<script setup lang="ts">
import { computed, ref } from "vue";
import type { InspectorControls, ModelGroup } from "../lib/types";

const props = defineProps<{
  controls: InspectorControls;
  onnxVersionText: string;
  statusText: string;
  statusTone: string;
  modelStatusLabel: string;
  modelStatusMeta: string;
  imageStatusText: string;
  predefinedModelGroups: ModelGroup[];
  isRunning: boolean;
  isModelLoading: boolean;
}>();

const emit = defineEmits<{
  modelFile: [file: File | null];
  imageFile: [file: File | null];
  reload: [];
  run: [];
  cancel: [];
  reset: [];
}>();

const modelInputRef = ref<HTMLInputElement | null>(null);
const imageInputRef = ref<HTMLInputElement | null>(null);
const controlsDisabled = computed(() => props.isRunning || props.isModelLoading);

function openModelPicker() {
  modelInputRef.value?.click();
}

function openImagePicker() {
  imageInputRef.value?.click();
}

function handleModelChange(event: Event) {
  const input = event.target as HTMLInputElement;
  emit("modelFile", input.files?.[0] || null);
  input.value = "";
}

function handleImageChange(event: Event) {
  const input = event.target as HTMLInputElement;
  emit("imageFile", input.files?.[0] || null);
  input.value = "";
}
</script>

<template>
  <aside class="w-full lg:w-80 lg:shrink-0">
    <section class="flex flex-col gap-3 rounded-xl border border-stone-300 bg-white p-4 shadow-sm">
      <div class="flex flex-col gap-2">
        <div class="flex items-start justify-between gap-3">
          <div>
            <h1 class="m-0 text-lg font-semibold text-stone-900">ONNX in Browser</h1>
            <div class="mt-1 text-[11px] text-stone-500">{{ onnxVersionText }}</div>
          </div>
          <button
            type="button"
            class="shrink-0 text-[11px] font-normal text-stone-500 underline decoration-stone-300 underline-offset-2 transition hover:text-stone-700 disabled:cursor-not-allowed disabled:text-stone-300 disabled:decoration-stone-200"
            :disabled="controlsDisabled"
            @click="emit('reset')"
          >
            Reset
          </button>
        </div>
        <div
          :class="[
            'w-full px-3 py-2 text-center text-xs font-medium select-none',
            statusTone === 'success' && 'bg-emerald-100 text-emerald-900',
            statusTone === 'error' && 'bg-rose-100 text-rose-900',
            statusTone === 'busy' && 'bg-amber-100 text-amber-900',
            !statusTone && 'bg-stone-100 text-stone-600',
          ]"
        >
          {{ statusText }}
        </div>
        <button
          v-if="!isRunning"
          type="button"
          class="inline-flex w-full items-center justify-center rounded-md bg-stone-900 px-3.5 py-2.5 text-sm font-semibold text-white transition hover:bg-stone-800 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-stone-500 disabled:cursor-not-allowed disabled:bg-stone-300 disabled:text-stone-500"
          :disabled="isModelLoading"
          @click="emit('run')"
        >
          Run
        </button>
        <button
          v-else
          type="button"
          class="inline-flex w-full items-center justify-center rounded-md bg-stone-700 px-3.5 py-2.5 text-sm font-semibold text-white transition hover:bg-stone-600 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-stone-500 disabled:cursor-not-allowed disabled:bg-stone-300 disabled:text-stone-500"
          @click="emit('cancel')"
        >
          Cancel
        </button>
      </div>

      <div class="flex flex-col gap-2.5">
        <label class="flex flex-col gap-1">
          <span class="text-xs font-medium text-stone-600">Model</span>
          <div class="relative">
            <select
              v-model="props.controls.selectedPredefinedModelId"
              :disabled="controlsDisabled"
              class="w-full appearance-none rounded-lg border border-stone-300 bg-white px-3 py-2 pr-11 text-sm text-stone-800 outline-none transition focus:border-stone-500 disabled:cursor-not-allowed disabled:opacity-60"
            >
              <option value="">-- Select a model or choose a file --</option>
              <optgroup
                v-for="group in predefinedModelGroups"
                :key="group.label"
                :label="group.label"
              >
                <option
                  v-for="option in group.options"
                  :key="option.value"
                  :value="option.value"
                >
                  {{ option.label }}
                </option>
              </optgroup>
            </select>
            <svg
              class="pointer-events-none absolute right-3 top-1/2 h-4 w-4 -translate-y-1/2 text-stone-500"
              viewBox="0 0 16 16"
              fill="none"
              aria-hidden="true"
            >
              <path d="M4 6l4 4 4-4" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" />
            </svg>
          </div>
        </label>

        <label class="flex flex-col gap-1">
          <span class="flex w-full items-center justify-between gap-2 text-xs font-medium text-stone-600">
            <span>Model file</span>
            <a
              class="font-normal text-stone-500 underline decoration-stone-300 underline-offset-2 transition hover:text-stone-700"
              href="https://huggingface.co/spaces/notaneimu/pth2onnx-converter"
              target="_blank"
              rel="noopener noreferrer"
            >
              Convert from pth
            </a>
          </span>
          <div class="flex flex-col gap-1.5">
            <input
              ref="modelInputRef"
              class="sr-only"
              type="file"
              accept=".onnx,application/octet-stream"
              :disabled="controlsDisabled"
              @change="handleModelChange"
            />
            <button
              type="button"
              class="inline-flex w-full items-center justify-center rounded-md bg-white px-3 py-2 text-sm font-semibold text-stone-900 ring-1 ring-inset ring-stone-300 transition hover:bg-stone-50 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-stone-400 disabled:cursor-not-allowed disabled:bg-stone-100 disabled:text-stone-400"
              :disabled="controlsDisabled"
              @click="openModelPicker"
            >
              Choose model file
            </button>
          </div>
        </label>

        <div class="flex min-w-0 flex-col gap-0.5 rounded-xl border border-stone-300 bg-stone-50 px-3 py-2.5">
          <span class="min-w-0 break-words text-sm font-semibold text-stone-900">{{ modelStatusLabel }}</span>
          <span class="min-w-0 break-words text-[11px] text-stone-600">{{ modelStatusMeta }}</span>
        </div>

        <div class="flex flex-col gap-2.5">
          <label class="flex items-center justify-between rounded-lg border border-stone-200 bg-stone-50 px-3 py-2">
            <span class="text-xs font-medium text-stone-600">Auto loading</span>
            <input
              v-model="props.controls.autoLoadModel"
              type="checkbox"
              :disabled="controlsDisabled"
              class="h-4 w-4 accent-stone-700 disabled:opacity-60"
            />
          </label>
          <button
            type="button"
            class="inline-flex w-full items-center justify-center rounded-md bg-white px-3 py-2 text-sm font-semibold text-stone-900 ring-1 ring-inset ring-stone-300 transition hover:bg-stone-50 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-stone-400 disabled:cursor-not-allowed disabled:bg-stone-100 disabled:text-stone-400"
            :disabled="controlsDisabled"
            @click="emit('reload')"
          >
            Load model
          </button>
        </div>

        <label class="flex flex-col gap-1">
          <span class="text-xs font-medium text-stone-600">Image</span>
          <div class="flex flex-col gap-1.5">
            <input
              ref="imageInputRef"
              class="sr-only"
              type="file"
              accept="image/*"
              :disabled="controlsDisabled"
              @change="handleImageChange"
            />
            <button
              type="button"
              class="inline-flex w-full items-center justify-center rounded-md bg-white px-3 py-2 text-sm font-semibold text-stone-900 ring-1 ring-inset ring-stone-300 transition hover:bg-stone-50 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-stone-400 disabled:cursor-not-allowed disabled:bg-stone-100 disabled:text-stone-400"
              :disabled="controlsDisabled"
              @click="openImagePicker"
            >
              Choose image file
            </button>
            <p class="m-0 min-h-4 text-xs text-stone-500">{{ imageStatusText }}</p>
          </div>
        </label>

        <label class="flex flex-col gap-1">
          <span class="text-xs font-medium text-stone-600">Execution provider</span>
          <div class="relative">
            <select
              v-model="props.controls.provider"
              :disabled="controlsDisabled"
              class="w-full appearance-none rounded-lg border border-stone-300 bg-white px-3 py-2 pr-11 text-sm text-stone-800 outline-none transition focus:border-stone-500 disabled:cursor-not-allowed disabled:opacity-60"
            >
              <option value="webgpu">WebGPU (default)</option>
              <option value="wasm">WASM</option>
              <option value="webgl">WebGL</option>
            </select>
            <svg
              class="pointer-events-none absolute right-3 top-1/2 h-4 w-4 -translate-y-1/2 text-stone-500"
              viewBox="0 0 16 16"
              fill="none"
              aria-hidden="true"
            >
              <path d="M4 6l4 4 4-4" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" />
            </svg>
          </div>
        </label>

        <label class="flex flex-col gap-1">
          <span class="text-xs font-medium text-stone-600">Tile size</span>
          <input
            v-model="props.controls.tileSize"
            type="number"
            min="1"
            step="1"
            placeholder="(empty disables tiling)"
            :disabled="controlsDisabled"
            class="w-full rounded-lg border border-stone-300 bg-white px-3 py-2 text-sm text-stone-800 outline-none transition focus:border-stone-500 disabled:cursor-not-allowed disabled:opacity-60"
          />
        </label>

        <label class="flex items-center justify-between rounded-lg border border-stone-200 bg-stone-50 px-3 py-2">
          <span class="text-xs font-medium text-stone-600">Tile blending</span>
          <input
            v-model="props.controls.tileBlendingEnabled"
            type="checkbox"
            :disabled="controlsDisabled"
            class="h-4 w-4 accent-stone-700 disabled:opacity-60"
          />
        </label>

        <label class="flex flex-col gap-1">
          <span class="text-xs font-medium text-stone-600">Initial width</span>
          <input
            v-model="props.controls.width"
            type="number"
            min="1"
            step="1"
            placeholder="auto"
            :disabled="controlsDisabled"
            class="w-full rounded-lg border border-stone-300 bg-white px-3 py-2 text-sm text-stone-800 outline-none transition focus:border-stone-500 disabled:cursor-not-allowed disabled:opacity-60"
          />
        </label>

        <label class="flex flex-col gap-1">
          <span class="text-xs font-medium text-stone-600">Initial height</span>
          <input
            v-model="props.controls.height"
            type="number"
            min="1"
            step="1"
            placeholder="auto"
            :disabled="controlsDisabled"
            class="w-full rounded-lg border border-stone-300 bg-white px-3 py-2 text-sm text-stone-800 outline-none transition focus:border-stone-500 disabled:cursor-not-allowed disabled:opacity-60"
          />
        </label>

        <label class="flex flex-col gap-1">
          <span class="text-xs font-medium text-stone-600">Pre resize algorithm</span>
          <div class="relative">
            <select
              v-model="props.controls.preResizeAlgorithm"
              :disabled="controlsDisabled"
              class="w-full appearance-none rounded-lg border border-stone-300 bg-white px-3 py-2 pr-11 text-sm text-stone-800 outline-none transition focus:border-stone-500 disabled:cursor-not-allowed disabled:opacity-60"
            >
              <option value="lanczos">Lanczos</option>
              <option value="area">Area</option>
              <option value="bicubic">Bicubic</option>
              <option value="nearest">Nearest neighbor</option>
            </select>
            <svg
              class="pointer-events-none absolute right-3 top-1/2 h-4 w-4 -translate-y-1/2 text-stone-500"
              viewBox="0 0 16 16"
              fill="none"
              aria-hidden="true"
            >
              <path d="M4 6l4 4 4-4" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" />
            </svg>
          </div>
          <p class="m-0 text-xs italic leading-snug text-stone-500">Used when resizing the source image to the model input size.</p>
        </label>

        <label class="flex flex-col gap-1">
          <span class="text-xs font-medium text-stone-600">Final scale</span>
          <input
            v-model="props.controls.outputScale"
            type="number"
            min="1"
            max="4"
            step="0.1"
            placeholder="off (keep model output)"
            :disabled="controlsDisabled"
            class="w-full rounded-lg border border-stone-300 bg-white px-3 py-2 text-sm text-stone-800 outline-none transition focus:border-stone-500 disabled:cursor-not-allowed disabled:opacity-60"
          />
          <p class="m-0 text-xs italic leading-snug text-stone-500">Optional downscale after inference. Uses the input size as 1x and caps at the model output.</p>
        </label>

        <label class="flex flex-col gap-1">
          <span class="text-xs font-medium text-stone-600">Post resize algorithm</span>
          <div class="relative">
            <select
              v-model="props.controls.outputScaleAlgorithm"
              :disabled="controlsDisabled"
              class="w-full appearance-none rounded-lg border border-stone-300 bg-white px-3 py-2 pr-11 text-sm text-stone-800 outline-none transition focus:border-stone-500 disabled:cursor-not-allowed disabled:opacity-60"
            >
              <option value="lanczos">Lanczos</option>
              <option value="area">Area</option>
              <option value="bicubic">Bicubic</option>
              <option value="nearest">Nearest neighbor</option>
            </select>
            <svg
              class="pointer-events-none absolute right-3 top-1/2 h-4 w-4 -translate-y-1/2 text-stone-500"
              viewBox="0 0 16 16"
              fill="none"
              aria-hidden="true"
            >
              <path d="M4 6l4 4 4-4" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" />
            </svg>
          </div>
          <p class="m-0 text-xs italic leading-snug text-stone-500">Used only for the optional output resize after inference.</p>
        </label>

        <label class="flex items-center justify-between rounded-lg border border-stone-200 bg-stone-50 px-3 py-2">
          <span class="text-xs font-medium text-stone-600">Compare with classic upscale</span>
          <input
            v-model="props.controls.compareWithClassicUpscale"
            type="checkbox"
            :disabled="controlsDisabled"
            class="h-4 w-4 accent-stone-700 disabled:opacity-60"
          />
        </label>

        <label class="flex flex-col gap-1">
          <span class="text-xs font-medium text-stone-600">Classic compare algorithm</span>
          <div class="relative">
            <select
              v-model="props.controls.classicCompareAlgorithm"
              :disabled="controlsDisabled || !props.controls.compareWithClassicUpscale"
              class="w-full appearance-none rounded-lg border border-stone-300 bg-white px-3 py-2 pr-11 text-sm text-stone-800 outline-none transition focus:border-stone-500 disabled:cursor-not-allowed disabled:opacity-60"
            >
              <option value="lanczos">Lanczos</option>
              <option value="area">Area</option>
              <option value="bicubic">Bicubic</option>
              <option value="nearest">Nearest neighbor</option>
            </select>
            <svg
              class="pointer-events-none absolute right-3 top-1/2 h-4 w-4 -translate-y-1/2 text-stone-500"
              viewBox="0 0 16 16"
              fill="none"
              aria-hidden="true"
            >
              <path d="M4 6l4 4 4-4" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" />
            </svg>
          </div>
          <p class="m-0 text-xs italic leading-snug text-stone-500">Builds a non-AI baseline upscaled to the same final resolution as the model result.</p>
        </label>

        <details class="group">
          <summary class="flex cursor-pointer list-none items-center justify-between py-1 text-sm font-semibold text-stone-700">
            <span>Additional params</span>
            <span class="text-xs text-stone-500 group-open:hidden">▶</span>
            <span class="hidden text-xs text-stone-500 group-open:inline">▼</span>
          </summary>
          <div class="flex flex-col gap-2.5 pt-2">
            <label class="flex items-center justify-between rounded-lg border border-stone-200 bg-stone-50 px-3 py-2">
              <span class="text-xs font-medium text-stone-600">Color correct final image</span>
              <input
                v-model="props.controls.colorCorrectionEnabled"
                type="checkbox"
                :disabled="controlsDisabled"
                class="h-4 w-4 accent-stone-700 disabled:opacity-60"
              />
            </label>

            <label class="flex flex-col gap-1">
              <span class="text-xs font-medium text-stone-600">Color correction strength (%)</span>
              <input
                v-model="props.controls.colorCorrectionStrength"
                type="number"
                min="0"
                max="100"
                step="5"
                placeholder="100"
                :disabled="controlsDisabled || !props.controls.colorCorrectionEnabled"
                class="w-full rounded-lg border border-stone-300 bg-white px-3 py-2 text-sm text-stone-800 outline-none transition focus:border-stone-500 disabled:cursor-not-allowed disabled:opacity-60"
              />
              <p class="m-0 text-xs italic leading-snug text-stone-500">Matches RGB color balance and black/white levels back toward the source image.</p>
            </label>

            <label class="flex flex-col gap-1">
              <span class="text-xs font-medium text-stone-600">Black/white clip (%)</span>
              <input
                v-model="props.controls.colorCorrectionClip"
                type="number"
                min="0"
                max="10"
                step="0.1"
                placeholder="0.6"
                :disabled="controlsDisabled || !props.controls.colorCorrectionEnabled"
                class="w-full rounded-lg border border-stone-300 bg-white px-3 py-2 text-sm text-stone-800 outline-none transition focus:border-stone-500 disabled:cursor-not-allowed disabled:opacity-60"
              />
              <p class="m-0 text-xs italic leading-snug text-stone-500">Ignores tiny outliers when matching source black and white points.</p>
            </label>

            <label class="flex items-center justify-between rounded-lg border border-stone-200 bg-stone-50 px-3 py-2">
              <span class="text-xs font-medium text-stone-600">Add film grain</span>
              <input
                v-model="props.controls.filmGrainEnabled"
                type="checkbox"
                :disabled="controlsDisabled"
                class="h-4 w-4 accent-stone-700 disabled:opacity-60"
              />
            </label>

            <label class="flex flex-col gap-1">
              <span class="text-xs font-medium text-stone-600">Film grain amount (%)</span>
              <input
                v-model="props.controls.filmGrainAmount"
                type="number"
                min="0"
                max="100"
                step="1"
                placeholder="6"
                :disabled="controlsDisabled || !props.controls.filmGrainEnabled"
                class="w-full rounded-lg border border-stone-300 bg-white px-3 py-2 text-sm text-stone-800 outline-none transition focus:border-stone-500 disabled:cursor-not-allowed disabled:opacity-60"
              />
            </label>

            <label class="flex flex-col gap-1">
              <span class="text-xs font-medium text-stone-600">Film grain size (px)</span>
              <input
                v-model="props.controls.filmGrainSize"
                type="number"
                min="0.5"
                max="8"
                step="0.1"
                placeholder="1.2"
                :disabled="controlsDisabled || !props.controls.filmGrainEnabled"
                class="w-full rounded-lg border border-stone-300 bg-white px-3 py-2 text-sm text-stone-800 outline-none transition focus:border-stone-500 disabled:cursor-not-allowed disabled:opacity-60"
              />
            </label>

            <label class="flex items-center justify-between rounded-lg border border-stone-200 bg-stone-50 px-3 py-2">
              <span class="text-xs font-medium text-stone-600">Monochrome grain</span>
              <input
                v-model="props.controls.filmGrainMonochrome"
                type="checkbox"
                :disabled="controlsDisabled || !props.controls.filmGrainEnabled"
                class="h-4 w-4 accent-stone-700 disabled:opacity-60"
              />
            </label>

            <label class="flex flex-col gap-1">
              <span class="text-xs font-medium text-stone-600">Seam blend width (input px)</span>
              <input
                v-model="props.controls.seamBlendWidth"
                type="number"
                min="0"
                step="1"
                placeholder="auto"
                :disabled="controlsDisabled || !props.controls.tileBlendingEnabled"
                class="w-full rounded-lg border border-stone-300 bg-white px-3 py-2 text-sm text-stone-800 outline-none transition focus:border-stone-500 disabled:cursor-not-allowed disabled:opacity-60"
              />
              <p class="m-0 text-xs italic leading-snug text-stone-500">Blank uses auto seam width. Set 0 to disable seam feather blending.</p>
            </label>

            <label class="flex flex-col gap-1">
              <span class="text-xs font-medium text-stone-600">Seam correction strength (%)</span>
              <input
                v-model="props.controls.seamCorrectionStrength"
                type="number"
                min="0"
                max="300"
                step="5"
                placeholder="100"
                :disabled="controlsDisabled || !props.controls.tileBlendingEnabled"
                class="w-full rounded-lg border border-stone-300 bg-white px-3 py-2 text-sm text-stone-800 outline-none transition focus:border-stone-500 disabled:cursor-not-allowed disabled:opacity-60"
              />
              <p class="m-0 text-xs italic leading-snug text-stone-500">0 disables exposure matching. 100 is default, higher values apply stronger correction.</p>
            </label>

            <label class="flex flex-col gap-1">
              <span class="text-xs font-medium text-stone-600">Graph optimization</span>
              <div class="relative">
                <select
                  v-model="props.controls.optLevel"
                  :disabled="controlsDisabled"
                  class="w-full appearance-none rounded-lg border border-stone-300 bg-white px-3 py-2 pr-11 text-sm text-stone-800 outline-none transition focus:border-stone-500 disabled:cursor-not-allowed disabled:opacity-60"
                >
                  <option value="all">All (default)</option>
                  <option value="extended">Extended</option>
                  <option value="basic">Basic</option>
                  <option value="disabled">Disabled</option>
                </select>
                <svg
                  class="pointer-events-none absolute right-3 top-1/2 h-4 w-4 -translate-y-1/2 text-stone-500"
                  viewBox="0 0 16 16"
                  fill="none"
                  aria-hidden="true"
                >
                  <path d="M4 6l4 4 4-4" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" />
                </svg>
              </div>
            </label>

            <label class="flex flex-col gap-1">
              <span class="text-xs font-medium text-stone-600">WebGPU layout</span>
              <div class="relative">
                <select
                  v-model="props.controls.webgpuLayout"
                  :disabled="controlsDisabled"
                  class="w-full appearance-none rounded-lg border border-stone-300 bg-white px-3 py-2 pr-11 text-sm text-stone-800 outline-none transition focus:border-stone-500 disabled:cursor-not-allowed disabled:opacity-60"
                >
                  <option value="NCHW">NCHW (default)</option>
                  <option value="NHWC">NHWC</option>
                </select>
                <svg
                  class="pointer-events-none absolute right-3 top-1/2 h-4 w-4 -translate-y-1/2 text-stone-500"
                  viewBox="0 0 16 16"
                  fill="none"
                  aria-hidden="true"
                >
                  <path d="M4 6l4 4 4-4" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" />
                </svg>
              </div>
            </label>

            <label class="flex flex-col gap-1">
              <span class="text-xs font-medium text-stone-600">WebGPU validation</span>
              <div class="relative">
                <select
                  v-model="props.controls.webgpuValidation"
                  :disabled="controlsDisabled"
                  class="w-full appearance-none rounded-lg border border-stone-300 bg-white px-3 py-2 pr-11 text-sm text-stone-800 outline-none transition focus:border-stone-500 disabled:cursor-not-allowed disabled:opacity-60"
                >
                  <option value="basic">Basic (default)</option>
                  <option value="full">Full</option>
                  <option value="wgpuOnly">WebGPU-only</option>
                  <option value="disabled">Disabled</option>
                </select>
                <svg
                  class="pointer-events-none absolute right-3 top-1/2 h-4 w-4 -translate-y-1/2 text-stone-500"
                  viewBox="0 0 16 16"
                  fill="none"
                  aria-hidden="true"
                >
                  <path d="M4 6l4 4 4-4" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" />
                </svg>
              </div>
            </label>

            <label class="flex flex-col gap-1">
              <span class="text-xs font-medium text-stone-600">Input layout</span>
              <div class="relative">
                <select
                  v-model="props.controls.layout"
                  :disabled="controlsDisabled"
                  class="w-full appearance-none rounded-lg border border-stone-300 bg-white px-3 py-2 pr-11 text-sm text-stone-800 outline-none transition focus:border-stone-500 disabled:cursor-not-allowed disabled:opacity-60"
                >
                  <option value="nchw">NCHW</option>
                  <option value="nhwc">NHWC</option>
                </select>
                <svg
                  class="pointer-events-none absolute right-3 top-1/2 h-4 w-4 -translate-y-1/2 text-stone-500"
                  viewBox="0 0 16 16"
                  fill="none"
                  aria-hidden="true"
                >
                  <path d="M4 6l4 4 4-4" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" />
                </svg>
              </div>
            </label>

            <label class="flex flex-col gap-1">
              <span class="text-xs font-medium text-stone-600">Channel order</span>
              <div class="relative">
                <select
                  v-model="props.controls.channelOrder"
                  :disabled="controlsDisabled"
                  class="w-full appearance-none rounded-lg border border-stone-300 bg-white px-3 py-2 pr-11 text-sm text-stone-800 outline-none transition focus:border-stone-500 disabled:cursor-not-allowed disabled:opacity-60"
                >
                  <option value="rgb">RGB</option>
                  <option value="bgr">BGR</option>
                </select>
                <svg
                  class="pointer-events-none absolute right-3 top-1/2 h-4 w-4 -translate-y-1/2 text-stone-500"
                  viewBox="0 0 16 16"
                  fill="none"
                  aria-hidden="true"
                >
                  <path d="M4 6l4 4 4-4" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" />
                </svg>
              </div>
            </label>

            <label class="flex items-center justify-between rounded-lg border border-stone-200 bg-stone-50 px-3 py-2">
              <span class="text-xs font-medium text-stone-600">Scale pixels to 0..1</span>
              <input
                v-model="props.controls.normalize"
                type="checkbox"
                :disabled="controlsDisabled"
                class="h-4 w-4 accent-stone-700 disabled:opacity-60"
              />
            </label>

            <label class="flex flex-col gap-1">
              <span class="text-xs font-medium text-stone-600">Mean (comma separated)</span>
              <input
                v-model="props.controls.mean"
                type="text"
                :disabled="controlsDisabled"
                class="w-full rounded-lg border border-stone-300 bg-white px-3 py-2 text-sm text-stone-800 outline-none transition focus:border-stone-500 disabled:cursor-not-allowed disabled:opacity-60"
              />
            </label>

            <label class="flex flex-col gap-1">
              <span class="text-xs font-medium text-stone-600">Std (comma separated)</span>
              <input
                v-model="props.controls.std"
                type="text"
                :disabled="controlsDisabled"
                class="w-full rounded-lg border border-stone-300 bg-white px-3 py-2 text-sm text-stone-800 outline-none transition focus:border-stone-500 disabled:cursor-not-allowed disabled:opacity-60"
              />
            </label>
          </div>
        </details>
      </div>
    </section>
  </aside>
</template>
