<script lang="ts">
  import { onDestroy, onMount } from "svelte";
  import { open as openDialog } from "@tauri-apps/plugin-dialog";
  import { Cloud, Download, FolderOpen, GitBranch, Globe2, LoaderCircle, LockKeyhole, RefreshCw, Search, X } from "@lucide/svelte";
  import { listIntegrationRepositories } from "../git";
  import { configuredIntegrationSources } from "../integrations";
  import type { AppLanguage, GitIntegrationProvider, GitIntegrationRepository, GitIntegrationSettings, GitIntegrationSource } from "../types";

  type CloneSource = "url" | "integrations";

  interface Props {
    isBusy: boolean;
    error: string;
    language: AppLanguage;
    integrations: GitIntegrationSettings;
    onClone: (remoteUrl: string, parentPath: string, directoryName: string, provider?: GitIntegrationProvider, accountId?: string) => void;
    onClose: () => void;
  }

  let { isBusy = false, error = "", language = "en", integrations, onClone = () => {}, onClose = () => {} }: Props = $props();
  let source = $state<CloneSource>("url");
  let remoteUrl = $state("");
  let parentPath = $state("");
  let directoryName = $state("");
  let directoryNameEdited = $state(false);
  let directoryAutoName = $state("");
  let browseError = $state("");
  let visibleError = $state("");
  let errorHideTimer: ReturnType<typeof setTimeout> | undefined;
  let selectedSourceId = $state("");
  let selectedRepositoryId = $state("");
  let repositorySearch = $state("");
  let repositoriesBySource = $state<Record<string, GitIntegrationRepository[]>>({});
  let loadingSourceId = $state("");
  let repositoryError = $state("");
  let repositoryListElement = $state<HTMLDivElement>();
  let repositoryScrollbarElement = $state<HTMLDivElement>();
  let repositoryScrollbarVisible = $state(false);
  let repositoryScrollbarTop = $state(0);
  let repositoryScrollbarHeight = $state(28);
  let repositoryScrollTop = $state(0);
  let repositoryScrollMax = $state(0);
  let repositoryScrollbarPointerId = $state<number>();
  let repositoryScrollbarDragY = 0;
  let repositoryScrollbarDragScrollTop = 0;
  let repositoryScrollbarFrame: number | undefined;
  let repositoryRequestId = 0;

  const isGerman = $derived(language === "de");
  const configuredSources = $derived(configuredIntegrationSources(integrations));
  const activeSource = $derived(configuredSources.find((candidate) => candidate.id === selectedSourceId));
  const activeRepositories = $derived(activeSource ? repositoriesBySource[activeSource.id] ?? [] : []);
  const filteredRepositories = $derived.by(() => {
    const query = repositorySearch.trim().toLocaleLowerCase();
    if (!query) return activeRepositories;
    return activeRepositories.filter((repository) => `${repository.fullName} ${repository.description}`.toLocaleLowerCase().includes(query));
  });
  const selectedRepository = $derived(activeRepositories.find((repository) => repository.id === selectedRepositoryId));
  const directorySuggestion = $derived(directoryNameFromRemoteUrl(remoteUrl));
  const canSubmit = $derived(!isBusy && remoteUrl.trim().length > 0 && parentPath.trim().length > 0);

  $effect(() => {
    const nextError = error || browseError;
    if (errorHideTimer) clearTimeout(errorHideTimer);
    visibleError = nextError;
    if (nextError) errorHideTimer = setTimeout(() => { visibleError = ""; }, 6000);
  });

  $effect(() => {
    filteredRepositories.length;
    loadingSourceId;
    repositoryError;
    scheduleRepositoryScrollbarUpdate();
  });

  onMount(() => {
    window.addEventListener("resize", scheduleRepositoryScrollbarUpdate);
    return () => window.removeEventListener("resize", scheduleRepositoryScrollbarUpdate);
  });

  onDestroy(() => {
    if (errorHideTimer) clearTimeout(errorHideTimer);
    if (repositoryScrollbarFrame !== undefined) cancelAnimationFrame(repositoryScrollbarFrame);
  });

  function scheduleRepositoryScrollbarUpdate() {
    if (repositoryScrollbarFrame !== undefined) cancelAnimationFrame(repositoryScrollbarFrame);
    repositoryScrollbarFrame = requestAnimationFrame(() => {
      repositoryScrollbarFrame = undefined;
      updateRepositoryScrollbar();
    });
  }

  function updateRepositoryScrollbar() {
    const list = repositoryListElement;
    const track = repositoryScrollbarElement;
    if (!list || !track) {
      repositoryScrollbarVisible = false;
      return;
    }
    const scrollMax = Math.max(0, list.scrollHeight - list.clientHeight);
    const trackHeight = track.clientHeight;
    const thumbHeight = scrollMax > 0
      ? Math.max(28, trackHeight * (list.clientHeight / list.scrollHeight))
      : trackHeight;
    const thumbTravel = Math.max(0, trackHeight - thumbHeight);
    repositoryScrollTop = list.scrollTop;
    repositoryScrollMax = scrollMax;
    repositoryScrollbarHeight = thumbHeight;
    repositoryScrollbarTop = scrollMax > 0 ? (list.scrollTop / scrollMax) * thumbTravel : 0;
    repositoryScrollbarVisible = scrollMax > 1;
  }

  function startRepositoryScrollbarDrag(event: PointerEvent) {
    if (!repositoryListElement) return;
    event.preventDefault();
    event.stopPropagation();
    repositoryScrollbarPointerId = event.pointerId;
    repositoryScrollbarDragY = event.clientY;
    repositoryScrollbarDragScrollTop = repositoryListElement.scrollTop;
    (event.currentTarget as HTMLElement).setPointerCapture(event.pointerId);
  }

  function dragRepositoryScrollbar(event: PointerEvent) {
    if (repositoryScrollbarPointerId !== event.pointerId || !repositoryListElement || !repositoryScrollbarElement) return;
    const thumbTravel = repositoryScrollbarElement.clientHeight - repositoryScrollbarHeight;
    if (thumbTravel <= 0) return;
    repositoryListElement.scrollTop = repositoryScrollbarDragScrollTop
      + ((event.clientY - repositoryScrollbarDragY) / thumbTravel) * repositoryScrollMax;
  }

  function stopRepositoryScrollbarDrag(event: PointerEvent) {
    if (repositoryScrollbarPointerId !== event.pointerId) return;
    repositoryScrollbarPointerId = undefined;
    const target = event.currentTarget as HTMLElement;
    if (target.hasPointerCapture(event.pointerId)) target.releasePointerCapture(event.pointerId);
  }

  function jumpRepositoryScrollbar(event: MouseEvent) {
    if (event.target !== event.currentTarget || !repositoryListElement || !repositoryScrollbarElement) return;
    const track = repositoryScrollbarElement.getBoundingClientRect();
    const thumbTravel = track.height - repositoryScrollbarHeight;
    if (thumbTravel <= 0) return;
    const targetTop = Math.max(0, Math.min(thumbTravel, event.clientY - track.top - repositoryScrollbarHeight / 2));
    repositoryListElement.scrollTop = (targetTop / thumbTravel) * repositoryScrollMax;
  }

  function handleRepositoryScrollbarKey(event: KeyboardEvent) {
    if (!repositoryListElement) return;
    const page = repositoryListElement.clientHeight * 0.85;
    const changes: Record<string, number> = {
      ArrowUp: repositoryListElement.scrollTop - 40,
      ArrowDown: repositoryListElement.scrollTop + 40,
      PageUp: repositoryListElement.scrollTop - page,
      PageDown: repositoryListElement.scrollTop + page,
      Home: 0,
      End: repositoryScrollMax,
    };
    if (!(event.key in changes)) return;
    event.preventDefault();
    repositoryListElement.scrollTop = changes[event.key];
  }

  function directoryNameFromRemoteUrl(url: string): string {
    const trimmed = url.trim().split(/[?#]/, 1)[0]?.replace(/[\\/]+$/g, "") ?? "";
    const lastSegment = trimmed.split(/[\\/:]/).filter(Boolean).pop() ?? "";
    return lastSegment.replace(/\.git$/i, "").trim();
  }

  function errorToMessage(error: unknown): string {
    if (error instanceof Error) return error.message;
    if (typeof error === "string") return error;
    try { return JSON.stringify(error) ?? "Unknown error"; } catch { return "Unknown error"; }
  }

  async function chooseParentFolder() {
    if (isBusy) return;
    browseError = "";
    try {
      const selected = await openDialog({ title: isGerman ? "Zielordner zum Klonen auswählen" : "Select clone destination", directory: true, multiple: false, defaultPath: parentPath.trim() || undefined });
      if (typeof selected === "string") parentPath = selected;
    } catch (error) { browseError = errorToMessage(error); }
  }

  function setRemoteUrl(nextRemoteUrl: string) {
    remoteUrl = nextRemoteUrl;
    if (directoryNameEdited) return;
    directoryAutoName = directoryNameFromRemoteUrl(nextRemoteUrl);
    directoryName = directoryAutoName;
  }

  function handleRemoteInput(event: Event) {
    setRemoteUrl((event.currentTarget as HTMLInputElement).value);
    selectedRepositoryId = "";
  }

  function handleDirectoryInput(event: Event) {
    const nextDirectoryName = (event.currentTarget as HTMLInputElement).value;
    directoryNameEdited = nextDirectoryName.trim().length > 0 && nextDirectoryName !== directoryAutoName;
  }

  function selectRepository(repository: GitIntegrationRepository) {
    selectedRepositoryId = repository.id;
    setRemoteUrl(repository.cloneUrl);
  }

  function sortRepositories(repositories: GitIntegrationRepository[]): GitIntegrationRepository[] {
    return [...repositories].sort((left, right) => left.fullName.localeCompare(
      right.fullName,
      isGerman ? "de" : "en",
      { numeric: true, sensitivity: "base" },
    ));
  }

  async function loadRepositories(integrationSource: GitIntegrationSource, force = false) {
    selectedSourceId = integrationSource.id;
    selectedRepositoryId = "";
    repositorySearch = "";
    repositoryError = "";
    if (!force && repositoriesBySource[integrationSource.id]) return;
    const requestId = ++repositoryRequestId;
    loadingSourceId = integrationSource.id;
    try {
      const repositories = await listIntegrationRepositories(integrationSource.provider, integrationSource.baseUrl, integrationSource.accountId);
      if (requestId === repositoryRequestId) repositoriesBySource = { ...repositoriesBySource, [integrationSource.id]: sortRepositories(repositories) };
    } catch (error) {
      if (requestId === repositoryRequestId) repositoryError = errorToMessage(error);
    } finally {
      if (requestId === repositoryRequestId) loadingSourceId = "";
    }
  }

  function showIntegrations() {
    source = "integrations";
    const nextSource = configuredSources.find((candidate) => candidate.id === selectedSourceId) ?? configuredSources[0];
    if (nextSource) void loadRepositories(nextSource);
  }

  function showUrlInput() {
    source = "url";
    selectedRepositoryId = "";
  }

  function formatUpdatedAt(value: string): string {
    if (!value) return "";
    const date = new Date(value);
    return Number.isNaN(date.getTime()) ? "" : new Intl.DateTimeFormat(isGerman ? "de-DE" : "en-US", { dateStyle: "medium" }).format(date);
  }

  function submit(event: SubmitEvent) {
    event.preventDefault();
    if (canSubmit) onClone(remoteUrl.trim(), parentPath.trim(), directoryName.trim(), source === "integrations" ? activeSource?.provider : undefined, source === "integrations" ? activeSource?.accountId : undefined);
  }
</script>

<div class="dialog-backdrop" role="presentation">
  <div class="dialog clone-repository-dialog" role="dialog" aria-modal="true" aria-label={isGerman ? "Repository klonen" : "Clone repository"} tabindex="-1">
    <header class="dialog-header">
      <div><span class="eyebrow">Repository Management</span><h2 class="mt-0.5 text-ink text-base font-bold leading-tight">{isGerman ? "Repository klonen" : "Clone repository"}</h2></div>
      <button class="dialog-close" type="button" onclick={onClose} disabled={isBusy} title={isGerman ? "Schließen" : "Close"} aria-label={isGerman ? "Klonen schließen" : "Close clone dialog"}><X size={18} /></button>
    </header>

    <form class="clone-dialog-form" onsubmit={submit}>
      <div class="clone-source-tabs" role="tablist" aria-label={isGerman ? "Repository-Quelle" : "Repository source"}>
        <button type="button" role="tab" aria-selected={source === "url"} class:active={source === "url"} onclick={showUrlInput}><Globe2 size={15} />URL</button>
        <button type="button" role="tab" aria-selected={source === "integrations"} class:active={source === "integrations"} onclick={showIntegrations}><Cloud size={15} />{isGerman ? "Integrationen" : "Integrations"}{#if configuredSources.length}<em>{configuredSources.length}</em>{/if}</button>
      </div>

      {#if source === "url"}
        <label class="clone-dialog-field">
          <span>{isGerman ? "Remote-URL" : "Remote URL"}</span>
          <!-- svelte-ignore a11y_autofocus -->
          <input value={remoteUrl} oninput={handleRemoteInput} autocomplete="off" spellcheck="false" placeholder="https://gitlab.com/org/project.git" disabled={isBusy} autofocus />
        </label>
      {:else}
        <section class="integration-browser" aria-label={isGerman ? "Repositories aus Integrationen" : "Repositories from integrations"}>
          {#if configuredSources.length === 0}
            <div class="integration-empty"><Cloud size={26} /><strong>{isGerman ? "Keine aktive Integration" : "No active integration"}</strong><p>{isGerman ? "Richte unter Einstellungen → Integrationen zuerst GitHub, GitLab, Azure DevOps oder Gitea ein." : "Set up GitHub, GitLab, Azure DevOps, or Gitea under Settings → Integrations first."}</p></div>
          {:else}
            <div class="integration-provider-tabs" role="tablist" aria-label={isGerman ? "Konfigurierte Anbieter" : "Configured providers"}>
              {#each configuredSources as integrationSource}<button type="button" role="tab" aria-selected={selectedSourceId === integrationSource.id} class:active={selectedSourceId === integrationSource.id} onclick={() => loadRepositories(integrationSource)}>{integrationSource.provider === "azure-devops" ? `Azure · ${integrationSource.label}` : integrationSource.label}</button>{/each}
            </div>
            <div class="repository-toolbar">
              <label><Search size={14} /><input bind:value={repositorySearch} placeholder={isGerman ? "Repositories filtern…" : "Filter repositories…"} aria-label={isGerman ? "Repositories filtern" : "Filter repositories"} /></label>
              <button type="button" onclick={() => activeSource && loadRepositories(activeSource, true)} disabled={!activeSource || loadingSourceId.length > 0} title={isGerman ? "Neu laden" : "Refresh"} aria-label={isGerman ? "Repository-Liste neu laden" : "Refresh repository list"}><RefreshCw class={loadingSourceId ? "spin" : ""} size={14} /></button>
            </div>
            <div class="repository-list-shell">
              <div id="integration-repository-list" class="repository-list" bind:this={repositoryListElement} onscroll={updateRepositoryScrollbar} aria-live="polite">
                {#if loadingSourceId}
                  <div class="repository-state"><LoaderCircle class="spin" size={20} /><span>{isGerman ? "Repositories werden geladen…" : "Loading repositories…"}</span></div>
                {:else if repositoryError}
                  <div class="repository-state repository-state-error"><strong>{isGerman ? "Repositories konnten nicht geladen werden" : "Could not load repositories"}</strong><span>{repositoryError}</span></div>
                {:else if filteredRepositories.length === 0}
                  <div class="repository-state"><GitBranch size={20} /><span>{repositorySearch ? (isGerman ? "Keine passenden Repositories." : "No matching repositories.") : (isGerman ? "Keine Repositories gefunden." : "No repositories found.")}</span></div>
                {:else}
                  {#each filteredRepositories as repository (repository.id)}
                    <button type="button" class="repository-option" class:selected={selectedRepositoryId === repository.id} onclick={() => selectRepository(repository)}>
                      <span class="repository-option-icon"><GitBranch size={16} /></span>
                      <span class="repository-option-copy"><strong>{repository.fullName}</strong><small>{repository.description || repository.cloneUrl}</small></span>
                      <span class="repository-option-meta">{#if repository.private}<LockKeyhole size={12} aria-label={isGerman ? "Privat" : "Private"} />{/if}{formatUpdatedAt(repository.updatedAt)}</span>
                    </button>
                  {/each}
                {/if}
              </div>
              <div
                class="repository-scrollbar"
                class:visible={repositoryScrollbarVisible}
                class:dragging={repositoryScrollbarPointerId !== undefined}
                bind:this={repositoryScrollbarElement}
                role="scrollbar"
                tabindex={repositoryScrollbarVisible ? 0 : -1}
                aria-controls="integration-repository-list"
                aria-label={isGerman ? "Repository-Liste scrollen" : "Scroll repository list"}
                aria-orientation="vertical"
                aria-valuemin="0"
                aria-valuemax={repositoryScrollMax}
                aria-valuenow={repositoryScrollTop}
                onclick={jumpRepositoryScrollbar}
                onkeydown={handleRepositoryScrollbarKey}
              >
                <div
                  class="repository-scrollbar-thumb"
                  role="presentation"
                  style={`height:${repositoryScrollbarHeight}px;transform:translateY(${repositoryScrollbarTop}px)`}
                  onpointerdown={startRepositoryScrollbarDrag}
                  onpointermove={dragRepositoryScrollbar}
                  onpointerup={stopRepositoryScrollbarDrag}
                  onpointercancel={stopRepositoryScrollbarDrag}
                ></div>
              </div>
            </div>
            {#if selectedRepository}<div class="selected-repository"><span>{isGerman ? "Ausgewählt" : "Selected"}</span><strong>{selectedRepository.fullName}</strong><code>{selectedRepository.cloneUrl}</code></div>{/if}
          {/if}
        </section>
      {/if}

      <div class="clone-target-grid">
        <label class="clone-dialog-field"><span>{isGerman ? "Ziel" : "Destination"}</span><div class="clone-dialog-path-field"><input bind:value={parentPath} autocomplete="off" spellcheck="false" placeholder={isGerman ? "Übergeordneten Ordner auswählen" : "Choose parent folder"} disabled={isBusy} /><button class="btn-secondary" type="button" onclick={chooseParentFolder} disabled={isBusy}><FolderOpen size={14} />{isGerman ? "Durchsuchen" : "Browse"}</button></div></label>
        <label class="clone-dialog-field"><span>{isGerman ? "Ordnername" : "Folder name"}</span><input bind:value={directoryName} oninput={handleDirectoryInput} autocomplete="off" spellcheck="false" placeholder={directorySuggestion || "Optional"} disabled={isBusy} /></label>
      </div>

      {#if visibleError}<div class="clone-dialog-error" role="alert">{visibleError}</div>{/if}
      <div class="clone-dialog-actions"><button class="btn-secondary" type="button" onclick={onClose} disabled={isBusy}>{isGerman ? "Abbrechen" : "Cancel"}</button><button class="btn-primary" type="submit" disabled={!canSubmit}>{#if isBusy}<LoaderCircle class="spin" size={16} />{:else}<Download size={16} />{/if}{isGerman ? "Klonen" : "Clone"}</button></div>
    </form>
  </div>
</div>

<style>
  .clone-repository-dialog { width: min(760px, calc(100vw - 32px)); }
  .clone-source-tabs { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 4px; padding: 4px; border: 1px solid var(--color-border-subtle); border-radius: 9px; background: var(--app-settings-row-bg); }
  .clone-source-tabs button { min-height: 36px; border-color: transparent; color: var(--color-ink-dim); background: transparent; font-size: 11px; font-weight: 800; }
  .clone-source-tabs button.active { border-color: var(--color-border-input); color: var(--color-ink); background: var(--color-surface-raised); box-shadow: 0 2px 8px rgba(0,0,0,.12); }
  .clone-source-tabs button.active :global(svg) { color: var(--color-accent); }
  .clone-source-tabs em { display: grid; place-items: center; min-width: 19px; height: 18px; padding: 0 5px; border-radius: 9px; color: var(--color-accent); background: color-mix(in srgb, var(--color-accent) 12%, transparent); font-size: 9px; font-style: normal; }
  .integration-browser { display: grid; gap: 9px; min-height: 270px; padding: 11px; border: 1px solid var(--color-border-subtle); border-radius: 10px; background: color-mix(in srgb, var(--app-settings-row-bg) 72%, transparent); }
  .integration-provider-tabs { display: flex; gap: 5px; overflow-x: auto; }
  .integration-provider-tabs button { flex: 0 0 auto; min-height: 29px; padding: 0 9px; border-color: transparent; color: var(--color-ink-dim); background: transparent; font-size: 10px; font-weight: 750; }
  .integration-provider-tabs button.active { border-color: color-mix(in srgb, var(--color-accent) 30%, var(--color-border)); color: var(--color-ink); background: color-mix(in srgb, var(--color-accent) 8%, var(--color-surface-raised)); }
  .repository-toolbar { display: grid; grid-template-columns: minmax(0, 1fr) 32px; gap: 6px; }
  .repository-toolbar label { position: relative; min-width: 0; }
  .repository-toolbar label > :global(svg) { position: absolute; z-index: 1; top: 10px; left: 10px; color: var(--color-ink-faint); }
  .repository-toolbar input { height: 34px; padding-left: 31px; font-size: 11px; }
  .repository-toolbar button { min-height: 32px; padding: 0; }
  .repository-list-shell { position: relative; min-height: 162px; max-height: 250px; overflow: hidden; border: 1px solid var(--color-border-subtle); border-radius: 8px; background: var(--color-surface-raised); }
  .repository-list { min-height: 160px; max-height: 248px; padding-right: 8px; overflow: auto; scrollbar-width: none; border-radius: inherit; background: transparent; }
  .repository-list::-webkit-scrollbar { display: none; width: 0; height: 0; }
  .repository-scrollbar { position: absolute; z-index: 2; top: 3px; right: 1px; bottom: 3px; width: 7px; border-radius: 4px; opacity: 0; pointer-events: none; touch-action: none; transition: opacity 120ms ease; }
  .repository-scrollbar.visible { opacity: 1; pointer-events: auto; }
  .repository-scrollbar-thumb { position: absolute; top: 0; right: 2px; width: 3px; min-height: 28px; border-radius: 3px; background: var(--app-scrollbar-thumb); cursor: pointer; transition: width 100ms ease, background 100ms ease; }
  .repository-scrollbar:hover .repository-scrollbar-thumb,
  .repository-scrollbar:focus-visible .repository-scrollbar-thumb,
  .repository-scrollbar.dragging .repository-scrollbar-thumb { right: 1px; width: 4px; background: var(--app-scrollbar-thumb-hover); }
  .repository-scrollbar:focus-visible { outline: 1px solid color-mix(in srgb, var(--color-accent) 70%, transparent); outline-offset: 1px; }
  .repository-option { display: grid; grid-template-columns: auto minmax(0, 1fr) auto; align-items: center; gap: 9px; width: 100%; min-height: 52px; padding: 7px 9px; border: 0; border-bottom: 1px solid var(--color-border-subtle); border-radius: 0; color: var(--color-ink-dim); background: transparent; text-align: left; }
  .repository-option:last-child { border-bottom: 0; }
  .repository-option:hover { color: var(--color-ink); background: var(--color-surface-hover); }
  .repository-option.selected { color: var(--color-ink); background: color-mix(in srgb, var(--color-accent) 8%, var(--color-surface-hover)); box-shadow: inset 2px 0 0 var(--color-accent); }
  .repository-option-icon { display: grid; place-items: center; width: 30px; height: 30px; border: 1px solid var(--color-border-subtle); border-radius: 7px; color: var(--color-accent); background: color-mix(in srgb, var(--color-accent) 7%, transparent); }
  .repository-option-copy { display: grid; min-width: 0; gap: 3px; }
  .repository-option-copy strong, .repository-option-copy small { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .repository-option-copy strong { color: inherit; font-size: 10.5px; }
  .repository-option-copy small { color: var(--color-ink-faint); font-size: 9px; }
  .repository-option-meta { display: flex; align-items: center; gap: 5px; color: var(--color-ink-faint); font-size: 8.5px; }
  .repository-state, .integration-empty { display: grid; place-items: center; align-content: center; min-height: 160px; padding: 20px; color: var(--color-ink-faint); text-align: center; }
  .repository-state { gap: 7px; font-size: 10.5px; }
  .repository-state strong, .integration-empty strong { color: var(--color-ink); font-size: 11px; }
  .repository-state-error strong { color: #e86060; }
  .repository-state-error span { max-width: 520px; line-height: 1.45; }
  .integration-empty { min-height: 235px; gap: 8px; }
  .integration-empty :global(svg) { color: var(--color-accent); }
  .integration-empty p { max-width: 400px; margin: 0; color: var(--color-ink-faint); font-size: 10px; line-height: 1.5; }
  .selected-repository { display: grid; grid-template-columns: auto minmax(0, 1fr); align-items: center; gap: 3px 8px; min-width: 0; padding: 8px 9px; border-left: 2px solid var(--color-accent); background: color-mix(in srgb, var(--color-accent) 6%, transparent); }
  .selected-repository span { color: var(--color-accent); font-size: 8.5px; font-weight: 850; text-transform: uppercase; letter-spacing: .04em; }
  .selected-repository strong { overflow: hidden; color: var(--color-ink); font-size: 10px; text-overflow: ellipsis; white-space: nowrap; }
  .selected-repository code { grid-column: 2; overflow: hidden; color: var(--color-ink-faint); font: 8.5px var(--font-mono); text-overflow: ellipsis; white-space: nowrap; }
  .clone-target-grid { display: grid; grid-template-columns: minmax(0, 1.5fr) minmax(150px, .75fr); gap: 10px; }
  @media (max-width: 620px) { .clone-repository-dialog { width: min(620px, calc(100vw - 20px)); } .clone-target-grid { grid-template-columns: 1fr; } .repository-option-meta { display: none; } }
</style>
