<!-- #region ExecutionMappingReview [C:3] [TYPE Component] [SEMANTICS dataset, review, execution-mapping, warning, override] -->
<!-- @BRIEF Component component: lib/components/dataset-review/ExecutionMappingReview.svelte -->
<!-- @LAYER UI -->
<!-- @SEMANTICS: dataset-review, execution-mapping, warning-approval, manual-override, required-values -->
<!-- @PURPOSE: Review imported-filter to template-variable mappings, surface effective values and blockers, and require explicit approval for warning-sensitive execution inputs before preview or launch. -->
<!-- @LAYER UI -->
<!-- @RELATION BINDS_TO ->[EXT:frontend:api_module] -->
<!-- @RELATION BINDS_TO ->[DatasetReviewWorkspace] -->
<!-- @PRE: Session id, execution mappings, imported filters, and template variables belong to the current ownership-scoped session payload. -->
<!-- @POST: Users can review effective mapping values, approve warning-sensitive transformations, or manually override them while unresolved required-value blockers remain visible. -->
<!-- @SIDE_EFFECT: Persists mapping approvals or manual overrides through dataset orchestration APIs and may invalidate the current preview truth for the route shell. -->
<!-- @DATA_CONTRACT: Input -> Dataset review execution payload { sessionId, mappings[], importedFilters[], templateVariables[] }; Output -> onupdated({ mapping | mappings, preview_state }) route-shell refresh payload. -->
<!-- @UX_STATE: Incomplete -> Required mapping values remain missing and blockers stay visible. -->
<!-- @UX_STATE: WarningApproval -> Mapping rows with transformation risk require explicit approval before execution can proceed. -->
<!-- @UX_STATE: Approved -> All launch-sensitive mappings are approved or no explicit approval is required. -->
<!-- @UX_FEEDBACK: Mapping approvals and manual overrides expose inline success, saving, and error feedback per row. -->
<!-- @UX_RECOVERY: Users can replace transformed values manually instead of approving them as-is and can retry failed mutations in place. -->
<!-- @UX_REACTIVITY: Uses $props, $state, and $derived only; no legacy reactive syntax. -->
<script lang="ts">
  import { t } from "$lib/i18n/index.svelte.js";
  import { requestDatasetReviewApi } from "$lib/api/datasetReview.js";

  let {
    sessionId = "",
    mappings = [],
    importedFilters = [],
    templateVariables = [],
    disabled = false,
    sessionVersion = null,
    focusTarget = null,
    onupdated = () => {},
    onaskai = () => {},
  } = $props();

  let editingMappingId = $state("");
  let overrideValueDraft = $state("");
  let overrideNoteDraft = $state("");
  let savingMappingId = $state("");
  let batchSaving = $state(false);
  let rowMessages = $state({});

  const filterLookup = $derived(
    Object.fromEntries((importedFilters || []).map((item) => [item.filter_id, item])),
  );
  const variableLookup = $derived(
    Object.fromEntries((templateVariables || []).map((item) => [item.variable_id, item])),
  );

  const sortedMappings = $derived(
    [...(mappings || [])].sort((left, right) => {
      const leftVariable = variableLookup[left.variable_id];
      const rightVariable = variableLookup[right.variable_id];
      const leftRequired = Number(Boolean(leftVariable?.is_required));
      const rightRequired = Number(Boolean(rightVariable?.is_required));
      if (leftRequired !== rightRequired) {
        return rightRequired - leftRequired;
      }

      const leftNeedsApproval = Number(
        Boolean(left.requires_explicit_approval && left.approval_state !== "approved"),
      );
      const rightNeedsApproval = Number(
        Boolean(right.requires_explicit_approval && right.approval_state !== "approved"),
      );
      if (leftNeedsApproval !== rightNeedsApproval) {
        return rightNeedsApproval - leftNeedsApproval;
      }

      return String(leftVariable?.variable_name || left.variable_id || "").localeCompare(
        String(rightVariable?.variable_name || right.variable_id || ""),
      );
    }),
  );

  const missingRequiredCount = $derived(
    sortedMappings.filter((mapping) => getRowState(mapping).missingRequiredValue).length,
  );
  const pendingApprovalCount = $derived(
    sortedMappings.filter((mapping) => getRowState(mapping).needsExplicitApproval).length,
  );
  const reviewState = $derived(
    missingRequiredCount > 0
      ? "Incomplete"
      : pendingApprovalCount > 0
        ? "WarningApproval"
        : "Approved",
  );

  function setRowMessage(mappingId, patch) {
    rowMessages = {
      ...rowMessages,
      [mappingId]: {
        ...(rowMessages[mappingId] || {}),
        ...patch,
      },
    };
  }

  function resetRowMessage(mappingId) {
    rowMessages = {
      ...rowMessages,
      [mappingId]: { status: "", text: "" },
    };
  }

  function getApprovalLabel(approvalState) {
    const normalized = String(approvalState || "pending");
    return $t.dataset_review?.mapping?.approval_state?.[normalized] || normalized;
  }

  function getWarningLabel(warningLevel) {
    const normalized = String(warningLevel || "none");
    return $t.dataset_review?.mapping?.warning_level?.[normalized] || normalized;
  }

  function getMethodLabel(method) {
    const normalized = String(method || "direct_match");
    return $t.dataset_review?.mapping?.method?.[normalized] || normalized;
  }

  function stringifyValue(value) {
    if (value === null || value === undefined || value === "") {
      return $t.common?.not_available || "N/A";
    }
    if (typeof value === "string") {
      return value;
    }
    try {
      return JSON.stringify(value);
    } catch (_error) {
      return String(value);
    }
  }

  function getEffectiveValue(mapping) {
    const importedFilter = filterLookup[mapping.filter_id];
    const templateVariable = variableLookup[mapping.variable_id];

    if (mapping.effective_value !== null && mapping.effective_value !== undefined) {
      return mapping.effective_value;
    }
    if (importedFilter?.normalized_value !== null && importedFilter?.normalized_value !== undefined) {
      return importedFilter.normalized_value;
    }
    if (importedFilter?.raw_value !== null && importedFilter?.raw_value !== undefined) {
      return importedFilter.raw_value;
    }
    if (templateVariable?.default_value !== null && templateVariable?.default_value !== undefined) {
      return templateVariable.default_value;
    }
    return null;
  }

  function getRowState(mapping) {
    const templateVariable = variableLookup[mapping.variable_id];
    const effectiveValue = getEffectiveValue(mapping);
    const missingRequiredValue = Boolean(templateVariable?.is_required) && effectiveValue === null;
    const needsExplicitApproval = Boolean(
      mapping.requires_explicit_approval && mapping.approval_state !== "approved",
    );
    return {
      templateVariable,
      importedFilter: filterLookup[mapping.filter_id],
      effectiveValue,
      missingRequiredValue,
      needsExplicitApproval,
    };
  }

  function startManualOverride(mapping) {
    const rowState = getRowState(mapping);
    editingMappingId = mapping.mapping_id;
    overrideValueDraft =
      rowState.effectiveValue === null ? "" : stringifyValue(rowState.effectiveValue);
    overrideNoteDraft = mapping.transformation_note || "";
    resetRowMessage(mapping.mapping_id);
  }

  function cancelManualOverride(mappingId) {
    if (editingMappingId !== mappingId) {
      return;
    }
    editingMappingId = "";
    overrideValueDraft = "";
    overrideNoteDraft = "";
    resetRowMessage(mappingId);
  }

  function normalizeOverrideValue() {
    const trimmed = String(overrideValueDraft || "").trim();
    if (!trimmed) {
      return null;
    }

    try {
      return JSON.parse(trimmed);
    } catch (_error) {
      return trimmed;
    }
  }

  async function approveMapping(mapping) {
    if (!sessionId || !mapping?.mapping_id || savingMappingId) {
      return;
    }

    savingMappingId = mapping.mapping_id;
    setRowMessage(mapping.mapping_id, { status: "saving", text: "" });

    try {
      const updatedMapping = await requestDatasetReviewApi(
        `/dataset-orchestration/sessions/${sessionId}/mappings/${mapping.mapping_id}/approve`,
        "POST",
        mapping.transformation_note ? { approval_note: mapping.transformation_note } : {},
        sessionVersion,
      );
      setRowMessage(mapping.mapping_id, {
        status: "success",
        text: $t.dataset_review?.mapping?.messages?.approval_saved,
      });
      onupdated({
        mapping: updatedMapping,
        preview_state: "unchanged",
      });
    } catch (error) {
      setRowMessage(mapping.mapping_id, {
        status: "error",
        text:
          (Number(error?.status) === 409
            ? error?.message ||
              "This session changed before the mapping approval completed. Reload and retry."
            : error?.message) ||
          $t.dataset_review?.mapping?.messages?.approval_failed ||
          $t.common?.error,
      });
    } finally {
      savingMappingId = "";
    }
  }

  async function approveAllMappings() {
    if (!sessionId || batchSaving || pendingApprovalCount === 0) {
      return;
    }

    batchSaving = true;
    try {
      const mappingIds = sortedMappings
        .filter((mapping) => getRowState(mapping).needsExplicitApproval)
        .map((mapping) => mapping.mapping_id);
      const updatedMappings = await requestDatasetReviewApi(
        `/dataset-orchestration/sessions/${sessionId}/mappings/approve-batch`,
        "POST",
        { mapping_ids: mappingIds },
        sessionVersion,
      );
      onupdated({
        mappings: updatedMappings,
        preview_state: "unchanged",
      });
    } catch (error) {
      const message =
        (Number(error?.status) === 409
          ? error?.message ||
            "This session changed before the mapping approval completed. Reload and retry."
          : error?.message) ||
        $t.dataset_review?.mapping?.messages?.approval_failed ||
        $t.common?.error;
      for (const mapping of sortedMappings.filter((item) => getRowState(item).needsExplicitApproval)) {
        setRowMessage(mapping.mapping_id, { status: "error", text: message });
      }
    } finally {
      batchSaving = false;
    }
  }

  async function saveManualOverride(mapping) {
    if (!sessionId || !mapping?.mapping_id || savingMappingId) {
      return;
    }

    const effectiveValue = normalizeOverrideValue();
    const templateVariable = variableLookup[mapping.variable_id];
    if (effectiveValue === null && templateVariable?.is_required) {
      setRowMessage(mapping.mapping_id, {
        status: "error",
        text: $t.dataset_review?.mapping?.messages?.required_value_missing,
      });
      return;
    }

    savingMappingId = mapping.mapping_id;
    setRowMessage(mapping.mapping_id, { status: "saving", text: "" });

    try {
      const updatedMapping = await requestDatasetReviewApi(
        `/dataset-orchestration/sessions/${sessionId}/mappings/${mapping.mapping_id}`,
        "PATCH",
        {
          effective_value: effectiveValue,
          mapping_method: "manual_override",
          transformation_note: String(overrideNoteDraft || "").trim() || null,
        },
        sessionVersion,
      );
      setRowMessage(mapping.mapping_id, {
        status: "success",
        text: $t.dataset_review?.mapping?.messages?.override_saved,
      });
      editingMappingId = "";
      overrideValueDraft = "";
      overrideNoteDraft = "";
      onupdated({
        mapping: updatedMapping,
        preview_state: "stale",
      });
    } catch (error) {
      setRowMessage(mapping.mapping_id, {
        status: "error",
        text:
          (Number(error?.status) === 409
            ? error?.message ||
              "This session changed before the manual mapping update completed. Reload and retry."
            : error?.message) ||
          $t.dataset_review?.mapping?.messages?.override_failed ||
          $t.common?.error,
      });
    } finally {
      savingMappingId = "";
    }
  }

  function isMappingFocused(mapping) {
    const target = String(focusTarget?.target || "");
    return target === `mapping:${mapping?.mapping_id}` || target === String(mapping?.mapping_id || "");
  }

  function askAiAboutMapping(mapping) {
    const rowState = getRowState(mapping);
    onaskai({
      target: `mapping:${mapping?.mapping_id}`,
      section: "mappings",
      label: rowState.templateVariable?.variable_name || mapping?.mapping_id,
      prompt:
        mapping?.transformation_note ||
        `${stringifyValue(rowState.importedFilter?.raw_value)} → ${stringifyValue(rowState.effectiveValue)}`,
      mapping,
    });
  }

  function improveMappingDraft(mapping) {
    const rowState = getRowState(mapping);
    onaskai({
      target: `mapping:${mapping?.mapping_id}`,
      section: "mappings",
      label: rowState.templateVariable?.variable_name || mapping?.mapping_id,
      prompt: `Improve mapping review guidance for ${rowState.templateVariable?.variable_name || mapping?.variable_id}. Preserve explicit approval gates and do not silently approve warning-level transformations.`,
      mode: "improve",
      mapping,
    });
  }
</script>

<section id="mapping" class="rounded-2xl border border-slate-200 bg-white p-5 shadow-sm">
  <div class="flex flex-col gap-3 md:flex-row md:items-start md:justify-between">
    <div>
      <p class="text-xs font-semibold uppercase tracking-wide text-slate-500">
        {$t.dataset_review?.mapping?.eyebrow}
      </p>
      <h2 class="text-xl font-semibold text-slate-900">
        {$t.dataset_review?.mapping?.title}
      </h2>
      <p class="mt-1 max-w-3xl text-sm text-slate-600">
        {$t.dataset_review?.mapping?.description}
      </p>
    </div>

    <div class="flex flex-wrap gap-2">
      <span
        class={`rounded-full px-3 py-1 text-xs font-medium ${
          reviewState === "Incomplete"
            ? "bg-red-100 text-red-700"
            : reviewState === "WarningApproval"
              ? "bg-amber-100 text-amber-700"
              : "bg-emerald-100 text-emerald-700"
        }`}
      >
        {$t.dataset_review?.mapping?.state_label}: {$t.dataset_review?.mapping?.state?.[reviewState]}
      </span>
      <span class="rounded-full bg-slate-100 px-3 py-1 text-xs font-medium text-slate-700">
        {$t.dataset_review?.mapping?.pending_approvals_label}: {pendingApprovalCount}
      </span>
      <span class="rounded-full bg-slate-100 px-3 py-1 text-xs font-medium text-slate-700">
        {$t.dataset_review?.mapping?.required_values_label}: {missingRequiredCount}
      </span>
      <button
        type="button"
        class="inline-flex items-center justify-center rounded-xl border border-slate-300 px-4 py-2 text-sm font-medium text-slate-700 transition hover:bg-slate-50 disabled:cursor-not-allowed disabled:opacity-50"
        onclick={approveAllMappings}
        disabled={disabled || batchSaving || pendingApprovalCount === 0}
      >
        {$t.dataset_review?.mapping?.approve_all_action}
      </button>
    </div>
  </div>

  {#if sortedMappings.length === 0}
    <div class="mt-5 rounded-xl border border-slate-200 bg-slate-50 px-4 py-4 text-sm text-slate-600">
      {$t.dataset_review?.mapping?.empty}
    </div>
  {:else}
    {#if missingRequiredCount > 0}
      <div class="mt-5 rounded-xl border border-destructive-light bg-destructive-light px-4 py-4 text-sm text-red-700">
        {$t.dataset_review?.mapping?.required_blockers_notice.replace(
          "{count}",
          String(missingRequiredCount),
        )}
      </div>
    {/if}

    {#if pendingApprovalCount > 0}
      <div class="mt-3 rounded-xl border border-amber-200 bg-amber-50 px-4 py-4 text-sm text-amber-800">
        {$t.dataset_review?.mapping?.approval_notice.replace(
          "{count}",
          String(pendingApprovalCount),
        )}
      </div>
    {/if}

    <div class="mt-5 space-y-4">
      {#each sortedMappings as mapping}
        {@const rowState = getRowState(mapping)}
        {@const templateVariable = rowState.templateVariable}
        {@const importedFilter = rowState.importedFilter}
        {@const isEditing = editingMappingId === mapping.mapping_id}
        {@const isSaving = savingMappingId === mapping.mapping_id}
        {@const rowMessage = rowMessages[mapping.mapping_id] || { status: "", text: "" }}

        <article
          class={`rounded-2xl border p-4 shadow-sm transition ${
            rowState.missingRequiredValue
              ? isMappingFocused(mapping)
                ? "border-violet-300 bg-violet-50 shadow-[0_0_0_3px_rgba(139,92,246,0.15)]"
                : "border-destructive-light bg-destructive-light"
              : rowState.needsExplicitApproval
                ? isMappingFocused(mapping)
                  ? "border-violet-300 bg-violet-50 shadow-[0_0_0_3px_rgba(139,92,246,0.15)]"
                  : "border-amber-200 bg-amber-50"
                : isMappingFocused(mapping)
                  ? "border-violet-300 bg-violet-50 shadow-[0_0_0_3px_rgba(139,92,246,0.15)]"
                  : "border-slate-200 bg-white"
          }`}
          data-focus-target={`mapping:${mapping.mapping_id}`}
        >
          <div class="flex flex-col gap-4 xl:flex-row xl:items-start xl:justify-between">
            <div class="min-w-0 flex-1">
              <div class="flex flex-wrap items-center gap-2">
                <h3 class="text-base font-semibold text-slate-900">
                  {importedFilter?.display_name || importedFilter?.filter_name || mapping.mapping_id}
                </h3>
                <span class="rounded-full bg-slate-100 px-2 py-0.5 text-xs text-slate-700">
                  {$t.dataset_review?.mapping?.to_variable_label}: {templateVariable?.variable_name ||
                    mapping.variable_id}
                </span>
                {#if templateVariable?.is_required}
                  <span class="rounded-full bg-red-100 px-2 py-0.5 text-xs text-red-700">
                    {$t.dataset_review?.mapping?.required_badge}
                  </span>
                {/if}
                {#if rowState.needsExplicitApproval}
                  <span class="rounded-full bg-amber-100 px-2 py-0.5 text-xs text-amber-800">
                    {$t.dataset_review?.mapping?.approval_required_badge}
                  </span>
                {/if}
                {#if mapping.approval_state === "approved"}
                  <span class="rounded-full bg-emerald-100 px-2 py-0.5 text-xs text-emerald-700">
                    {$t.dataset_review?.mapping?.approved_badge}
                  </span>
                {/if}
              </div>

              <div class="mt-3 grid gap-3 lg:grid-cols-2">
                <div class="rounded-xl border border-slate-200 bg-white p-3">
                  <div class="text-xs uppercase tracking-wide text-slate-500">
                    {$t.dataset_review?.mapping?.source_filter_label}
                  </div>
                  <div class="mt-1 text-sm font-medium text-slate-900">
                    {importedFilter?.filter_name || mapping.filter_id}
                  </div>
                  <div class="mt-2 flex flex-wrap gap-2 text-xs text-slate-600">
                    <span class="rounded-full bg-slate-100 px-2 py-1">
                      {$t.dataset_review?.mapping?.source_value_label}:
                      {stringifyValue(importedFilter?.raw_value)}
                    </span>
                    <span class="rounded-full bg-slate-100 px-2 py-1">
                      {$t.dataset_review?.mapping?.confidence_label}:
                      {importedFilter?.confidence_state || ($t.common?.unknown || "unknown")}
                    </span>
                    <span class="rounded-full bg-slate-100 px-2 py-1">
                      {$t.dataset_review?.mapping?.recovery_label}:
                      {importedFilter?.recovery_status || ($t.common?.unknown || "unknown")}
                    </span>
                  </div>
                </div>

                <div class="rounded-xl border border-slate-200 bg-white p-3">
                  <div class="text-xs uppercase tracking-wide text-slate-500">
                    {$t.dataset_review?.mapping?.effective_value_label}
                  </div>
                  <div class="mt-1 break-all text-sm font-medium text-slate-900">
                    {stringifyValue(rowState.effectiveValue)}
                  </div>
                  <div class="mt-2 flex flex-wrap gap-2 text-xs text-slate-600">
                    <span class="rounded-full bg-slate-100 px-2 py-1">
                      {$t.dataset_review?.mapping?.method_label}: {getMethodLabel(mapping.mapping_method)}
                    </span>
                    <span class="rounded-full bg-slate-100 px-2 py-1">
                      {$t.dataset_review?.mapping?.approval_label}: {getApprovalLabel(mapping.approval_state)}
                    </span>
                    {#if mapping.warning_level}
                      <span class="rounded-full bg-slate-100 px-2 py-1">
                        {$t.dataset_review?.mapping?.warning_label}: {getWarningLabel(mapping.warning_level)}
                      </span>
                    {/if}
                  </div>
                </div>
              </div>

              {#if mapping.transformation_note}
                <div class="mt-3 rounded-xl border border-slate-200 bg-slate-50 px-3 py-3 text-sm text-slate-700">
                  <span class="font-medium text-slate-900">
                    {$t.dataset_review?.mapping?.transformation_note_label}:
                  </span>
                  {mapping.transformation_note}
                </div>
              {/if}

              {#if rowState.missingRequiredValue}
                <div class="mt-3 rounded-xl border border-destructive-light bg-destructive-light px-3 py-3 text-sm text-red-700">
                  {$t.dataset_review?.mapping?.missing_required_value}
                </div>
              {/if}

              {#if isEditing}
                <div class="mt-4 grid gap-3">
                  <label class="space-y-1">
                    <span class="text-sm font-medium text-slate-700">
                      {$t.dataset_review?.mapping?.manual_value_label}
                    </span>
                    <input
                      class="w-full rounded-xl border border-slate-300 bg-white px-3 py-2 text-sm text-slate-900 shadow-sm outline-none transition focus-visible:ring-primary-ring focus-visible:border-primary-ring"
                      bind:value={overrideValueDraft}
                      disabled={disabled || isSaving}
                    />
                  </label>

                  <label class="space-y-1">
                    <span class="text-sm font-medium text-slate-700">
                      {$t.dataset_review?.mapping?.manual_note_label}
                    </span>
                    <textarea
                      class="min-h-24 w-full rounded-xl border border-slate-300 bg-white px-3 py-2 text-sm text-slate-900 shadow-sm outline-none transition focus-visible:ring-primary-ring focus-visible:border-primary-ring"
                      bind:value={overrideNoteDraft}
                      disabled={disabled || isSaving}
                    ></textarea>
                  </label>

                  <div class="flex flex-wrap gap-2">
                    <button
                      type="button"
                      class="inline-flex items-center justify-center rounded-xl bg-primary px-4 py-2 text-sm font-medium text-white transition hover:bg-primary-hover disabled:cursor-not-allowed disabled:bg-slate-300"
                      onclick={() => saveManualOverride(mapping)}
                      disabled={disabled || isSaving}
                    >
                      {$t.dataset_review?.mapping?.save_override_action}
                    </button>
                    <button
                      type="button"
                      class="inline-flex items-center justify-center rounded-xl border border-slate-300 px-4 py-2 text-sm font-medium text-slate-700 transition hover:bg-slate-50 disabled:cursor-not-allowed disabled:opacity-50"
                      onclick={() => cancelManualOverride(mapping.mapping_id)}
                      disabled={isSaving}
                    >
                      {$t.common?.cancel}
                    </button>
                  </div>
                </div>
              {/if}

              {#if rowMessage.text || rowMessage.status === "saving"}
                <div
                  class={`mt-4 rounded-xl px-3 py-3 text-sm ${
                    rowMessage.status === "error"
                      ? "border border-destructive-light bg-destructive-light text-red-700"
                      : rowMessage.status === "saving"
                        ? "border border-primary-ring bg-primary-light text-primary"
                        : "border border-emerald-200 bg-emerald-50 text-emerald-800"
                  }`}
                >
                  {rowMessage.status === "saving"
                    ? $t.dataset_review?.mapping?.messages?.saving
                    : rowMessage.text}
                </div>
              {/if}
            </div>

            <div class="flex shrink-0 flex-wrap gap-2 xl:w-56 xl:flex-col">
              <button
                type="button"
                class="inline-flex items-center justify-center rounded-xl border border-violet-300 bg-violet-50 px-4 py-2 text-sm font-medium text-violet-700 transition hover:bg-violet-100 disabled:cursor-not-allowed disabled:opacity-50"
                onclick={() => askAiAboutMapping(mapping)}
                disabled={disabled || isSaving}
              >
                {$t.dataset_review?.assistant?.ask_ai_action || "✨ Ask AI"}
              </button>
              <button
                type="button"
                class="inline-flex items-center justify-center rounded-xl border border-violet-300 bg-white px-4 py-2 text-sm font-medium text-violet-700 transition hover:bg-violet-50 disabled:cursor-not-allowed disabled:opacity-50"
                onclick={() => improveMappingDraft(mapping)}
                disabled={disabled || isSaving}
              >
                {$t.dataset_review?.assistant?.improve_action || "✨ Improve"}
              </button>
              <button
                type="button"
                class="inline-flex items-center justify-center rounded-xl border border-slate-300 px-4 py-2 text-sm font-medium text-slate-700 transition hover:bg-slate-50 disabled:cursor-not-allowed disabled:opacity-50"
                onclick={() => startManualOverride(mapping)}
                disabled={disabled || isSaving}
              >
                {$t.dataset_review?.mapping?.manual_override_action}
              </button>

              <button
                type="button"
                class="inline-flex items-center justify-center rounded-xl bg-amber-600 px-4 py-2 text-sm font-medium text-white transition hover:bg-amber-700 disabled:cursor-not-allowed disabled:bg-slate-300"
                onclick={() => approveMapping(mapping)}
                disabled={disabled || isSaving || !rowState.needsExplicitApproval}
              >
                {$t.dataset_review?.mapping?.approve_action}
              </button>
            </div>
          </div>
        </article>
      {/each}
    </div>
  {/if}
</section>

<!-- #endregion ExecutionMappingReview -->
