# Store Products Admin

> The merchant side of the catalogue: a product list with bulk edit, a product editor with a generated variant matrix, media manager and search preview, and a collections manager with manual and rule-based collections.

Source: https://docs.nasaqui.com/components/store-products-admin

## Install

```bash
npx shadcn@latest add https://docs.nasaqui.com/r/store-products-admin.json
```

Everything a merchant needs to manage the catalogue: a product list with search, filters and bulk edit of price, stock and status;
a product editor with pictures, price and margin, inventory, options that build a variant matrix, and a search listing preview;
and a collections manager where a collection is picked by hand or filled by rules with a live match preview.
Money is integer minor units. The components hold no data and call no API: you pass the catalogue and save in `on*` callbacks.

## When to use

- A store back office: products, variants, stock, collections.

## When not to use

- Showing products to shoppers: use `product-card`, `product-detail` and the listing components.
- Stock movements and warehouses: use `stock-ledger`.

## Import

```tsx
import { ProductAdminList, ProductEditor, CollectionsManager, productToDraft } from "@fadymondy/nasaq/web";
```

## Quick start

```tsx
<ProductAdminList
  products={products}
  currency="USD"
  onOpen={(p) => router.push(`/products/${p.id}`)}
  onCreate={() => router.push("/products/new")}
  onBulkEdit={async (ids, edit) => api.bulkEdit(ids, edit)}
/>

<ProductEditor
  initial={productToDraft(product, { cost: 4000 })}
  currency="USD"
  siteUrl="https://shop.example"
  onSave={async (draft) => api.saveProduct(draft)}
/>
```

## Anatomy

```
ProductAdminList   [data-slot=product-list]   DataTable + bulk edit dialog + delete confirm
ProductEditor      [data-slot=product-editor]       form of cards, sticky save bar
  MediaManager     [data-slot=media-manager]        sortable picture tiles [data-slot=media-tile]
  OptionsEditor    [data-slot=options-editor]
  VariantMatrix    [data-slot=variant-matrix]
CollectionsManager [data-slot=collections-manager]  cards + editor dialog with RuleBuilder and match preview
```

## API

### ProductAdminList

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `products` | `readonly CommerceProduct[]` | required | The catalogue. |
| `currency` | `string` | `"USD"` (`"SAR"` in Arabic) | ISO 4217 code. |
| `onOpen` | `(product) => void` | none | Row click, Enter, or Edit in the row menu. |
| `onCreate` | `() => void` | none | Shows "New product". |
| `onBulkEdit` | `(ids, edit: ProductBulkEdit) => Promise<ProductAdminResult>` | none | Without it the bulk button is hidden. |
| `onStatusChange` | `(product, status) => Promise<ProductAdminResult>` | none | Activate, draft, archive. |
| `onDelete` | `(product) => Promise<ProductAdminResult>` | none | Delete after confirmation. |
| `lowStockAt` | `number` | `5` | Stock at or below is low. |
| `loading`, `error`, `onRetry` | | | States. `error` is `true` or a message. |
| `labels` | `StoreProductsAdminLabels` | en / ar | Override any string. |

### ProductEditor

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `initial` | `ProductDraft` | empty draft | Build with `productToDraft(product, { cost, visibility, seoTitle, seoDescription })`. |
| `currency` | `string` | `"USD"` (`"SAR"` in Arabic) | ISO 4217 code. |
| `siteUrl` | `string` | `https://store.example` | Origin for the search preview URL. |
| `onSave` | `(draft) => Promise<ProductAdminResult>` | required | Resolve `{ error }` to keep the edits. |
| `onCancel` | `() => void` | none | Called when Discard is pressed with nothing changed. |
| `suggestions` | `{ brands?, categories?, tags? }` | none | Autocomplete lists. |
| `loading` | `boolean` | `false` | Skeleton. |
| `labels` | `StoreProductsAdminLabels` | en / ar | Strings. |

Changing options regenerates the variants with `generateVariants`: a variant whose option values still exist keeps its price, compare-at, SKU, stock and image. Removed combinations are named in a notice; the matrix is capped at 100.

### MediaManager, OptionsEditor, VariantMatrix

`MediaManager({ images, onImagesChange, maxImages = 12, disabled, labels })`,
`OptionsEditor({ options, onOptionsChange, maxOptions = 3, disabled, labels })`,
`VariantMatrix({ options, variants, onVariantsChange, currency, images, disabled, labels })`. All are controlled.

### CollectionsManager

| Prop | Type | Description |
| --- | --- | --- |
| `collections` | `readonly CollectionDef[]` | `{ id, title, kind: "manual" \| "rules", productIds?, conditions? }`. |
| `products` | `readonly CommerceProduct[]` | For the picker and live preview. |
| `currency` | `string` | Rule prices are typed in major units of it. |
| `onSave` | `(collection) => Promise<ProductAdminResult>` | New collections arrive with a fresh `id`. |
| `onDelete` | `(collection) => Promise<ProductAdminResult>` | Adds Delete. |
| `loading`, `error`, `onRetry`, `labels` | | |

### Logic (pure, also exported)

`generateVariants`, `bulkFillVariants`, `bulkEditProducts`, `bulkPrice`, `marginFromCost`, `priceForMargin`, `stockSummary`, `matchCollection`, `collectionsOfProduct`, `validateProductDraft`, `productToDraft`, `draftToProduct`, `draftChanged`, `emptyProductDraft`, `decimalToMinor`, `optionCombinations`, `variantLabel`, `duplicateSkus`. They use integer maths only.

## Examples

```tsx
// A rule collection: products tagged "summer" under 500
const collection: CollectionDef = {
  id: "c1",
  title: "Summer under 500",
  kind: "rules",
  conditions: { kind: "group", id: "g", join: "and", children: [
    { kind: "condition", id: "a", field: "tag", op: "is", value: "summer" },
    { kind: "condition", id: "b", field: "price", op: "lt", value: "500" },
  ] },
};
matchCollection(products, collection, { minorPerMajor: 100 });
```

## Accessibility

| Key | Action |
| --- | --- |
| Space, arrows, Space | Pick up, move and drop a picture (also the move earlier / later buttons). |
| Enter on a list row | Open the product. |
| Shift+F10, Menu key, context-click | Row actions. |

Moves are announced in a live region. Missing alt text is counted and flagged. Every icon-only button has a label.

## RTL & i18n

English and Arabic built in through `useOptionalNasaq()`. SKUs, prices and numbers stay LTR inside `dir="ltr"` or `<bdi>`. Chevrons flip in RTL.

## Styling & tokens

Uses `--nq-*` tokens only. Target `data-slot` names above; `data-dragging` marks a picture being dragged.

## Do / Don't

- Do pass prices in minor units. Don't pass floats.
- Do give every picture alt text.
- Don't rely on client validation alone: check again on the server.

## Related

- [store-settings](https://docs.nasaqui.com/components/store-settings)
- [data-table](https://docs.nasaqui.com/components/data-table)
- [rule-builder](https://docs.nasaqui.com/components/rule-builder)

## Lab

https://docs.nasaqui.com/?path=/docs/components-store-admin-store-products-admin--docs

## Code

### React

```tsx
<ProductAdminList
  products={products}
  currency="USD"
  onOpen={(p) => router.push(`/products/${p.id}`)}
  onCreate={() => router.push("/products/new")}
  onBulkEdit={async (ids, edit) => api.bulkEdit(ids, edit)}
/>

<ProductEditor
  initial={productToDraft(product, { cost: 4000 })}
  currency="USD"
  siteUrl="https://shop.example"
  onSave={async (draft) => api.saveProduct(draft)}
/>
```

### shadcn

```tsx
<ProductAdminList
  products={products}
  currency="USD"
  onOpen={(p) => router.push(`/products/${p.id}`)}
  onCreate={() => router.push("/products/new")}
  onBulkEdit={async (ids, edit) => api.bulkEdit(ids, edit)}
/>

<ProductEditor
  initial={productToDraft(product, { cost: 4000 })}
  currency="USD"
  siteUrl="https://shop.example"
  onSave={async (draft) => api.saveProduct(draft)}
/>
```

### Vue

```vue
<script setup lang="ts">
import {
  NqCollectionsManager,
  NqProductAdminList,
  NqProductEditor,
  NqTabs,
  NqTabsList,
  NqTabsPanel,
  NqTabsTab,
  bulkEditProducts,
  productToDraft,
  type CollectionDef,
  type ProductAdminProduct,
  type ProductBulkEdit,
} from "@fadymondy/nasaq/vue";
import { ref } from "vue";

const colour = { id: "colour", name: "Colour", values: [{ id: "red", label: "Red" }, { id: "blue", label: "Blue" }] };
const products = ref<ProductAdminProduct[]>([
  {
    id: "p1",
    name: "Linen shirt",
    brand: "Nile Basics",
    category: "Clothing",
    tags: ["summer", "new"],
    status: "active",
    images: [{ src: "/shirt.jpg", alt: "Linen shirt" }],
    options: [colour],
    variants: [
      { id: "v1", options: { colour: "red" }, price: 4900, stock: 12, sku: "SHIRT-RED" },
      { id: "v2", options: { colour: "blue" }, price: 4900, compareAt: 6900, stock: 2, sku: "SHIRT-BLUE" },
    ],
  },
  { id: "p2", name: "Canvas tote", brand: "Souk Goods", category: "Home", status: "draft", images: [], options: [], variants: [{ id: "v3", options: {}, price: 1900, stock: 0 }] },
]);
const collections = ref<CollectionDef[]>([
  { id: "c1", title: "Summer", kind: "manual", productIds: ["p1"] },
  { id: "c2", title: "Drafts", kind: "rules", conditions: { kind: "group", id: "g", join: "and", children: [{ kind: "condition", id: "r1", field: "status", op: "eq", value: "draft" }] } },
]);
const note = ref("");

async function onBulkEdit(ids: string[], edit: ProductBulkEdit) {
  products.value = bulkEditProducts(products.value, ids, edit);
}
async function onDelete(p: ProductAdminProduct) {
  products.value = products.value.filter((x) => x.id !== p.id);
}
async function onSaveCollection(c: CollectionDef) {
  collections.value = collections.value.some((x) => x.id === c.id) ? collections.value.map((x) => (x.id === c.id ? c : x)) : [...collections.value, c];
}
async function onSaveProduct() {
  note.value = "Saved.";
}
</script>

<template>
  <NqTabs default-value="products">
    <NqTabsList>
      <NqTabsTab value="products">Products</NqTabsTab>
      <NqTabsTab value="editor">Editor</NqTabsTab>
      <NqTabsTab value="collections">Collections</NqTabsTab>
    </NqTabsList>
    <NqTabsPanel value="products" class="pt-4">
      <NqProductAdminList :products="products" currency="USD" :on-open="(p) => (note = `Open ${p.name}`)" :on-create="() => (note = 'New product')" :on-bulk-edit="onBulkEdit" :on-delete="onDelete" />
    </NqTabsPanel>
    <NqTabsPanel value="editor" class="pt-4">
      <NqProductEditor :initial="productToDraft(products[0]!, { cost: 1500 })" currency="USD" site-url="https://shop.example" :suggestions="{ brands: ['Nile Basics'], categories: ['Clothing', 'Home'], tags: ['summer'] }" :on-save="onSaveProduct" />
      <p v-if="note" role="status">{{ note }}</p>
    </NqTabsPanel>
    <NqTabsPanel value="collections" class="pt-4">
      <NqCollectionsManager :collections="collections" :products="products" currency="USD" :on-save="onSaveCollection" />
    </NqTabsPanel>
  </NqTabs>
</template>
```

### Blade

```blade
@php
    $colour = ['id' => 'colour', 'name' => 'Colour', 'display' => 'button', 'values' => [['id' => 'red', 'label' => 'Red'], ['id' => 'blue', 'label' => 'Blue']]];
    $shirt = [
        'id' => 'p1', 'name' => 'Linen shirt', 'brand' => 'Nile', 'category' => 'Clothing', 'tags' => ['summer'], 'status' => 'active', 'slug' => 'linen-shirt',
        'images' => [['src' => '/img/shirt-a.jpg', 'alt' => 'Front'], ['src' => '/img/shirt-b.jpg', 'alt' => ''], ['src' => '/img/shirt-c.jpg', 'alt' => 'Back']],
        'options' => [$colour],
        'variants' => [
            ['id' => 'v1', 'options' => ['colour' => 'red'], 'price' => 4900, 'compareAt' => 5900, 'stock' => 12, 'sku' => 'LIN-RED'],
            ['id' => 'v2', 'options' => ['colour' => 'blue'], 'price' => 4900, 'stock' => 2, 'sku' => 'LIN-BLUE'],
        ],
    ];
    $tote = ['id' => 'p2', 'name' => 'Canvas tote', 'category' => 'Bags', 'tags' => ['summer', 'bag'], 'status' => 'draft', 'images' => [], 'options' => [], 'variants' => [['id' => 'v3', 'options' => [], 'price' => 1900, 'stock' => 0]]];
    $mug = ['id' => 'p3', 'name' => 'Clay mug', 'brand' => 'Nile', 'category' => 'Home', 'status' => 'active', 'images' => [['src' => '/img/mug.jpg', 'alt' => 'Mug']], 'options' => [], 'variants' => [['id' => 'v4', 'options' => [], 'price' => 1400, 'sku' => 'MUG-1']]];
    $products = [$shirt, $tote, $mug];
    $collections = [
        ['id' => 'c1', 'title' => 'Summer picks', 'kind' => 'manual', 'productIds' => ['p1', 'p2']],
        ['id' => 'c2', 'title' => 'Nile brand', 'kind' => 'rules', 'conditions' => ['kind' => 'group', 'id' => 'g-root', 'join' => 'and', 'children' => [['kind' => 'condition', 'id' => 'r-1', 'field' => 'brand', 'op' => 'is', 'value' => 'Nile']]]],
    ];
@endphp
<div class="flex flex-col gap-10">
    <x-nq::store-products-admin.product-list :products="$products" currency="USD" :page-size="10" />
    <x-nq::store-products-admin.product-editor :product="$shirt" :extra="['cost' => 2000]" currency="USD" can-cancel />
    <x-nq::store-products-admin.media-manager :images="$shirt['images']" />
    <x-nq::store-products-admin.options-editor :options="[$colour]" />
    <x-nq::store-products-admin.variant-matrix :options="[$colour]" :images="$shirt['images']" :variants="$shirt['variants']" currency="USD" />
    <x-nq::store-products-admin.collections-manager :collections="$collections" :products="$products" currency="USD" />
</div>
```

### HTML + Alpine

```html
<div class="flex flex-col gap-10">
    <div data-slot="product-list" x-data="nqProductAdminList(JSON.parse('{\u0022products\u0022:[{\u0022id\u0022:\u0022p1\u0022,\u0022name\u0022:\u0022Linen shirt\u0022,\u0022brand\u0022:\u0022Nile\u0022,\u0022category\u0022:\u0022Clothing\u0022,\u0022tags\u0022:[\u0022summer\u0022],\u0022status\u0022:\u0022active\u0022,\u0022slug\u0022:\u0022linen-shirt\u0022,\u0022images\u0022:[{\u0022src\u0022:\u0022\\\/img\\\/shirt-a.jpg\u0022,\u0022alt\u0022:\u0022Front\u0022},{\u0022src\u0022:\u0022\\\/img\\\/shirt-b.jpg\u0022,\u0022alt\u0022:\u0022\u0022},{\u0022src\u0022:\u0022\\\/img\\\/shirt-c.jpg\u0022,\u0022alt\u0022:\u0022Back\u0022}],\u0022options\u0022:[{\u0022id\u0022:\u0022colour\u0022,\u0022name\u0022:\u0022Colour\u0022,\u0022display\u0022:\u0022button\u0022,\u0022values\u0022:[{\u0022id\u0022:\u0022red\u0022,\u0022label\u0022:\u0022Red\u0022},{\u0022id\u0022:\u0022blue\u0022,\u0022label\u0022:\u0022Blue\u0022}]}],\u0022variants\u0022:[{\u0022id\u0022:\u0022v1\u0022,\u0022options\u0022:{\u0022colour\u0022:\u0022red\u0022},\u0022price\u0022:4900,\u0022compareAt\u0022:5900,\u0022stock\u0022:12,\u0022sku\u0022:\u0022LIN-RED\u0022},{\u0022id\u0022:\u0022v2\u0022,\u0022options\u0022:{\u0022colour\u0022:\u0022blue\u0022},\u0022price\u0022:4900,\u0022stock\u0022:2,\u0022sku\u0022:\u0022LIN-BLUE\u0022}]},{\u0022id\u0022:\u0022p2\u0022,\u0022name\u0022:\u0022Canvas tote\u0022,\u0022category\u0022:\u0022Bags\u0022,\u0022tags\u0022:[\u0022summer\u0022,\u0022bag\u0022],\u0022status\u0022:\u0022draft\u0022,\u0022images\u0022:[],\u0022options\u0022:[],\u0022variants\u0022:[{\u0022id\u0022:\u0022v3\u0022,\u0022options\u0022:[],\u0022price\u0022:1900,\u0022stock\u0022:0}]},{\u0022id\u0022:\u0022p3\u0022,\u0022name\u0022:\u0022Clay mug\u0022,\u0022brand\u0022:\u0022Nile\u0022,\u0022category\u0022:\u0022Home\u0022,\u0022status\u0022:\u0022active\u0022,\u0022images\u0022:[{\u0022src\u0022:\u0022\\\/img\\\/mug.jpg\u0022,\u0022alt\u0022:\u0022Mug\u0022}],\u0022options\u0022:[],\u0022variants\u0022:[{\u0022id\u0022:\u0022v4\u0022,\u0022options\u0022:[],\u0022price\u0022:1400,\u0022sku\u0022:\u0022MUG-1\u0022}]}],\u0022currency\u0022:\u0022USD\u0022,\u0022locale\u0022:\u0022en\u0022,\u0022t\u0022:{\u0022products\u0022:\u0022Products\u0022,\u0022newProduct\u0022:\u0022New product\u0022,\u0022searchProducts\u0022:\u0022Search products\u0022,\u0022productCol\u0022:\u0022Product\u0022,\u0022statusCol\u0022:\u0022Status\u0022,\u0022stockCol\u0022:\u0022Stock\u0022,\u0022priceCol\u0022:\u0022Price\u0022,\u0022variantsCol\u0022:\u0022Variants\u0022,\u0022categoryCol\u0022:\u0022Category\u0022,\u0022statuses.active\u0022:\u0022Active\u0022,\u0022statuses.draft\u0022:\u0022Draft\u0022,\u0022statuses.archived\u0022:\u0022Archived\u0022,\u0022stockLevels.in\u0022:\u0022In stock\u0022,\u0022stockLevels.low\u0022:\u0022Low stock\u0022,\u0022stockLevels.out\u0022:\u0022Out of stock\u0022,\u0022stockLevels.untracked\u0022:\u0022Not tracked\u0022,\u0022units\u0022:\u0022{0} in stock\u0022,\u0022variantCount\u0022:\u0022{0} variants\u0022,\u0022oneVariant\u0022:\u00221 variant\u0022,\u0022productListLabel\u0022:\u0022Products\u0022,\u0022noProducts\u0022:\u0022No products yet\u0022,\u0022noProductsHint\u0022:\u0022Add your first product to start selling.\u0022,\u0022loadFailed\u0022:\u0022Products did not load.\u0022,\u0022retry\u0022:\u0022Try again\u0022,\u0022edit\u0022:\u0022Edit\u0022,\u0022setActive\u0022:\u0022Set active\u0022,\u0022setDraft\u0022:\u0022Move to drafts\u0022,\u0022archive\u0022:\u0022Archive\u0022,\u0022delete\u0022:\u0022Delete\u0022,\u0022deleteTitle\u0022:\u0022Delete this product?\u0022,\u0022deleteDescription\u0022:\u0022{0} and its variants are removed. Past orders keep their copy.\u0022,\u0022selectedCount\u0022:\u0022{0} selected\u0022,\u0022bulkEdit\u0022:\u0022Bulk edit\u0022,\u0022bulkTitle\u0022:\u0022Edit {0} products\u0022,\u0022bulkDescription\u0022:\u0022Leave a section on Keep to leave it alone. Changes apply to every variant.\u0022,\u0022bulkPrice\u0022:\u0022Price\u0022,\u0022bulkStock\u0022:\u0022Stock\u0022,\u0022bulkStatus\u0022:\u0022Status\u0022,\u0022keep\u0022:\u0022Keep\u0022,\u0022priceModes.set\u0022:\u0022Set to\u0022,\u0022priceModes.increase-percent\u0022:\u0022Raise by percent\u0022,\u0022priceModes.decrease-percent\u0022:\u0022Lower by percent\u0022,\u0022priceModes.increase-amount\u0022:\u0022Raise by amount\u0022,\u0022priceModes.decrease-amount\u0022:\u0022Lower by amount\u0022,\u0022stockModes.set\u0022:\u0022Set to\u0022,\u0022stockModes.add\u0022:\u0022Add\u0022,\u0022stockModes.remove\u0022:\u0022Remove\u0022,\u0022alsoCompareAt\u0022:\u0022Move compare-at price the same way\u0022,\u0022percent\u0022:\u0022Percent\u0022,\u0022amount\u0022:\u0022Amount\u0022,\u0022quantity\u0022:\u0022Quantity\u0022,\u0022preview\u0022:\u0022Preview\u0022,\u0022previewEmpty\u0022:\u0022Nothing changes yet. Pick a change above.\u0022,\u0022previewRow\u0022:\u0022{0}\u0022,\u0022applyToProducts\u0022:\u0022Apply to {0} products\u0022,\u0022cancel\u0022:\u0022Cancel\u0022,\u0022actions\u0022:\u0022Actions\u0022,\u0022editProduct\u0022:\u0022Edit product\u0022,\u0022newProductTitle\u0022:\u0022New product\u0022,\u0022general\u0022:\u0022General\u0022,\u0022title\u0022:\u0022Title\u0022,\u0022description\u0022:\u0022Description\u0022,\u0022descriptionLabel\u0022:\u0022Product description\u0022,\u0022media\u0022:\u0022Media\u0022,\u0022pricing\u0022:\u0022Pricing\u0022,\u0022price\u0022:\u0022Price\u0022,\u0022compareAt\u0022:\u0022Compare-at price\u0022,\u0022compareAtHint\u0022:\u0022The old price shown struck through. Must be above the price.\u0022,\u0022cost\u0022:\u0022Cost per item\u0022,\u0022costHint\u0022:\u0022Only you see this.\u0022,\u0022margin\u0022:\u0022Margin\u0022,\u0022profit\u0022:\u0022Profit\u0022,\u0022markup\u0022:\u0022Markup\u0022,\u0022noMargin\u0022:\u0022Add a price and a cost to see the margin.\u0022,\u0022inventory\u0022:\u0022Inventory\u0022,\u0022sku\u0022:\u0022SKU\u0022,\u0022trackStock\u0022:\u0022Track stock\u0022,\u0022stockQty\u0022:\u0022In stock\u0022,\u0022backorder\u0022:\u0022Sell when out of stock\u0022,\u0022weight\u0022:\u0022Weight (grams)\u0022,\u0022organization\u0022:\u0022Organisation\u0022,\u0022brand\u0022:\u0022Brand\u0022,\u0022category\u0022:\u0022Category\u0022,\u0022tags\u0022:\u0022Tags\u0022,\u0022tagsPlaceholder\u0022:\u0022Add a tag\u0022,\u0022seo\u0022:\u0022Search listing\u0022,\u0022seoTitle\u0022:\u0022Page title\u0022,\u0022seoDescription\u0022:\u0022Meta description\u0022,\u0022slug\u0022:\u0022URL handle\u0022,\u0022slugHint\u0022:\u0022Lower-case letters, digits and dashes.\u0022,\u0022statusSection\u0022:\u0022Status and visibility\u0022,\u0022visibility\u0022:\u0022Visibility\u0022,\u0022visible\u0022:\u0022Visible in the store\u0022,\u0022hidden\u0022:\u0022Hidden from the store (link still works)\u0022,\u0022statusHint.active\u0022:\u0022Customers can buy it.\u0022,\u0022statusHint.draft\u0022:\u0022Only you can see it.\u0022,\u0022statusHint.archived\u0022:\u0022Kept for records, not sold.\u0022,\u0022save\u0022:\u0022Save product\u0022,\u0022saving\u0022:\u0022Saving\u0022,\u0022discard\u0022:\u0022Discard changes\u0022,\u0022unsaved\u0022:\u0022Unsaved changes\u0022,\u0022allSaved\u0022:\u0022All changes saved\u0022,\u0022saveFailed\u0022:\u0022That did not save. Try again.\u0022,\u0022fixIssues\u0022:\u0022{0} to fix before saving\u0022,\u0022issues.title\u0022:\u0022Add a title.\u0022,\u0022issues.price\u0022:\u0022Add a price.\u0022,\u0022issues.compare-at\u0022:\u0022Compare-at must be above the price.\u0022,\u0022issues.sku-duplicate\u0022:\u0022Two variants share a SKU.\u0022,\u0022issues.no-variants\u0022:\u0022Generate the variants for these options.\u0022,\u0022issues.too-many-variants\u0022:\u0022Too many variants. Remove an option value.\u0022,\u0022issues.slug\u0022:\u0022The URL handle has characters that are not allowed.\u0022,\u0022mediaLabel\u0022:\u0022Product images\u0022,\u0022addImage\u0022:\u0022Add image\u0022,\u0022imageUrl\u0022:\u0022Image URL\u0022,\u0022imageUrlPlaceholder\u0022:\u0022https:\\\/\\\/\\u2026\u0022,\u0022altText\u0022:\u0022Alt text\u0022,\u0022altHint\u0022:\u0022Describe the picture for people who cannot see it.\u0022,\u0022missingAlt\u0022:\u0022Alt text missing\u0022,\u0022primary\u0022:\u0022Main image\u0022,\u0022moveEarlier\u0022:\u0022Move earlier\u0022,\u0022moveLater\u0022:\u0022Move later\u0022,\u0022removeImage\u0022:\u0022Remove image\u0022,\u0022dragHandle\u0022:\u0022Reorder image {0}\u0022,\u0022movedTo\u0022:\u0022Image moved to position {0} of {1}\u0022,\u0022noImages\u0022:\u0022No images yet\u0022,\u0022noImagesHint\u0022:\u0022Add a picture by its URL. The first one is the main image.\u0022,\u0022imageFailed\u0022:\u0022Image did not load\u0022,\u0022optionsTitle\u0022:\u0022Options\u0022,\u0022optionsHint\u0022:\u0022Colour, size, material. Up to three options.\u0022,\u0022addOption\u0022:\u0022Add option\u0022,\u0022removeOption\u0022:\u0022Remove option\u0022,\u0022optionName\u0022:\u0022Option name\u0022,\u0022optionNamePlaceholder\u0022:\u0022Size\u0022,\u0022optionValues\u0022:\u0022Values\u0022,\u0022optionValuesPlaceholder\u0022:\u0022Add a value\u0022,\u0022variantsTitle\u0022:\u0022Variants\u0022,\u0022variantsSummary\u0022:\u0022{0} variants\u0022,\u0022variantsRemoved\u0022:\u0022{0} variants no longer match and were removed.\u0022,\u0022variantsTruncated\u0022:\u0022More than {0} combinations. Only the first {0} are created.\u0022,\u0022variantLabel\u0022:\u0022Variant\u0022,\u0022skuCol\u0022:\u0022SKU\u0022,\u0022priceCol2\u0022:\u0022Price\u0022,\u0022compareCol\u0022:\u0022Compare-at\u0022,\u0022stockCol2\u0022:\u0022Stock\u0022,\u0022imageCol\u0022:\u0022Image\u0022,\u0022noImage\u0022:\u0022No image\u0022,\u0022bulkFill\u0022:\u0022Fill selected variants\u0022,\u0022selectVariants\u0022:\u0022Select variants to fill them at once.\u0022,\u0022selectAll\u0022:\u0022Select all variants\u0022,\u0022selectVariant\u0022:\u0022Select {0}\u0022,\u0022fillPrice\u0022:\u0022Price\u0022,\u0022fillCompare\u0022:\u0022Compare-at\u0022,\u0022fillStock\u0022:\u0022Stock\u0022,\u0022fillAddStock\u0022:\u0022Add stock\u0022,\u0022fillSkuPrefix\u0022:\u0022SKU prefix\u0022,\u0022fillApply\u0022:\u0022Apply to selected\u0022,\u0022fillClear\u0022:\u0022Clear selection\u0022,\u0022variantsSelected\u0022:\u0022{0} selected\u0022,\u0022dupSku\u0022:\u0022Duplicate SKU\u0022,\u0022variantsEmpty\u0022:\u0022Add an option to create variants.\u0022,\u0022collections\u0022:\u0022Collections\u0022,\u0022newCollection\u0022:\u0022New collection\u0022,\u0022collectionsLabel\u0022:\u0022Collections\u0022,\u0022collectionTitle\u0022:\u0022Collection title\u0022,\u0022manual\u0022:\u0022Manual\u0022,\u0022rules\u0022:\u0022Rules\u0022,\u0022kindLabel\u0022:\u0022How products join\u0022,\u0022manualHint\u0022:\u0022Pick the products yourself, in the order you want them.\u0022,\u0022rulesHint\u0022:\u0022Products join on their own when they match the rules.\u0022,\u0022matchPreview\u0022:\u0022{0} products match\u0022,\u0022matchNone\u0022:\u0022No products match yet.\u0022,\u0022matchPreviewLabel\u0022:\u0022Products in this collection\u0022,\u0022addProducts\u0022:\u0022Add products\u0022,\u0022addProduct\u0022:\u0022Add a product\u0022,\u0022pickProduct\u0022:\u0022Choose a product\u0022,\u0022removeFromCollection\u0022:\u0022Remove from collection\u0022,\u0022moveUp\u0022:\u0022Move up\u0022,\u0022moveDown\u0022:\u0022Move down\u0022,\u0022saveCollection\u0022:\u0022Save collection\u0022,\u0022deleteCollection\u0022:\u0022Delete collection\u0022,\u0022deleteCollectionTitle\u0022:\u0022Delete this collection?\u0022,\u0022deleteCollectionDescription\u0022:\u0022{0} is removed. The products stay in your catalogue.\u0022,\u0022collectionsEmpty\u0022:\u0022No collections yet\u0022,\u0022collectionsEmptyHint\u0022:\u0022Group products so customers can browse them together.\u0022,\u0022productsCount\u0022:\u0022{0} products\u0022,\u0022ruleAnyProduct\u0022:\u0022any product\u0022,\u0022ruleAddIt\u0022:\u0022add it to this collection\u0022,\u0022ruleEventLabel\u0022:\u0022Applies to\u0022,\u0022ruleEventHelp\u0022:\u0022Every active product is checked against the conditions below.\u0022,\u0022ruleIfTitle\u0022:\u0022Products that match\u0022,\u0022ruleIfHelp\u0022:\u0022Add conditions. A product joins when they hold. With none, no product joins.\u0022,\u0022ruleThenTitle\u0022:\u0022Result\u0022,\u0022ruleThenHelp\u0022:\u0022Matching products are added to this collection.\u0022,\u0022ruleAction\u0022:\u0022Add it to this collection\u0022,\u0022ruleWhere\u0022:\u0022where\u0022,\u0022ruleSo\u0022:\u0022so\u0022,\u0022and\u0022:\u0022and\u0022,\u0022or\u0022:\u0022or\u0022,\u0022editCollection\u0022:\u0022Edit collection\u0022,\u0022fields.tag\u0022:\u0022Tag\u0022,\u0022fields.brand\u0022:\u0022Brand\u0022,\u0022fields.category\u0022:\u0022Category\u0022,\u0022fields.title\u0022:\u0022Title\u0022,\u0022fields.price\u0022:\u0022Price\u0022,\u0022fields.stock\u0022:\u0022Stock\u0022,\u0022fields.onSale\u0022:\u0022On sale\u0022,\u0022fields.status\u0022:\u0022Status\u0022,\u0022close\u0022:\u0022Close\u0022},\u0022lowStockAt\u0022:5,\u0022pageSize\u0022:10,\u0022loading\u0022:false,\u0022error\u0022:false,\u0022canCreate\u0022:true,\u0022canBulk\u0022:true,\u0022canStatus\u0022:true,\u0022canDelete\u0022:true}'))" class="flex min-w-0 flex-col gap-3">
    <div class="flex flex-wrap items-center justify-between gap-2">
        <h2 class="text-h3 text-foreground">Products</h2>
        <div x-show="canCreate">
            <button data-slot="button"
     type="button"                         x-on:click="create()" class="inline-flex shrink-0 select-none items-center justify-center gap-2 whitespace-nowrap rounded-control border border-transparent font-sans text-label transition-colors duration-150 ease-nq min-h-[var(--nq-touch-min,0px)] outline-none focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-nq-focus disabled:pointer-events-none disabled:opacity-50 data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0 bg-primary text-primary-foreground hover:bg-[color-mix(in_oklab,var(--nq-action)_88%,var(--nq-fg))] h-control px-[var(--nq-control-pad)]">
        <svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <path d="M5 12h14"/>
  <path d="M12 5v14"/>
</svg>                New product</button>
        </div>
    </div>
    <div data-slot="data-table-toolbar" class="flex flex-wrap items-center gap-2">
        <div class="relative w-full min-w-40 sm:w-64">
            <svg aria-hidden="true" class="pointer-events-none absolute inset-y-0 start-2.5 my-auto size-4 text-muted-foreground" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <path d="m21 21-4.34-4.34"/>
  <circle cx="11" cy="11" r="8"/>
</svg>            <input data-slot="input" type="search"
                    aria-label="Search products" placeholder="Search products" x-model="query" x-on:keydown.escape="query = &#039;&#039;" class="w-full min-w-0 rounded-control border border-input bg-card px-3 text-body text-foreground min-h-[var(--nq-touch-min,0px)] transition-colors duration-150 ease-nq outline-none placeholder:text-muted-foreground focus-visible:border-nq-focus focus-visible:outline-1 focus-visible:outline-nq-focus data-invalid:border-nq-danger aria-invalid:border-nq-danger disabled:cursor-not-allowed disabled:opacity-50 pointer-coarse:text-[16px] h-control-sm ps-8">
        </div>
        <div data-slot="dropdown-menu" x-data="nqDropdownMenu(false)" x-modelable="open" class="contents"><button data-slot="dropdown-menu-trigger"
     type="button"                         x-bind="trigger" x-ref="trigger" data-facet="status" class="inline-flex shrink-0 select-none items-center justify-center gap-2 whitespace-nowrap rounded-control border font-sans text-label transition-colors duration-150 ease-nq min-h-[var(--nq-touch-min,0px)] outline-none focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-nq-focus disabled:pointer-events-none disabled:opacity-50 data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0 border-border bg-card text-foreground hover:bg-nq-hover h-control-sm px-2.5">
        <svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <circle cx="12" cy="12" r="10"/>
  <path d="M8 12h8"/>
  <path d="M12 8v8"/>
</svg>                Status
                <span class="text-caption text-muted-foreground tabular-nums" x-show="on('status').length > 0" x-text="on('status').length"></span></button>
            <template x-teleport="body">
    <div data-slot="dropdown-menu-content" x-bind="popup" x-init="popupEl = $el" x-nq-presence="open" x-anchor.bottom-start.offset.4="$refs.trigger"
        class="z-50 overflow-hidden rounded-floating border border-border bg-popover p-1.5 text-popover-foreground shadow-floating outline-none max-h-[var(--available-height)] overflow-y-auto transition-opacity duration-150 ease-nq data-starting-style:opacity-0 data-ending-style:opacity-0 min-w-44"><div data-slot="dropdown-menu-checkbox-item" role="menuitemcheckbox" x-data="{ checked: false }" x-modelable="checked" x-bind="item"
    x-on:click="if (! $el.hasAttribute('data-disabled')) checked = ! checked"
    x-bind:aria-checked="checked ? 'true' : 'false'" x-bind:data-checked="checked ? '' : undefined" x-bind:data-unchecked="checked ? undefined : ''"
     data-keep-open         x-model="facet.status[&#039;active&#039;]" class="relative flex h-nav-row min-h-[var(--nq-touch-min,0px)] cursor-default select-none items-center gap-2.5 rounded-control px-2.5 text-body-sm text-foreground outline-none data-highlighted:bg-nq-selected data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:size-4 [&_svg]:shrink-0 [&_svg]:text-muted-foreground ps-8">
    <span aria-hidden="true" class="absolute start-2.5 inline-flex size-4 items-center justify-center">
        <span x-show="checked" class="contents"  style="display:none" ><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <path d="M20 6 9 17l-5-5"/>
</svg></span>
    </span>
    Active
</div>
                                    <div data-slot="dropdown-menu-checkbox-item" role="menuitemcheckbox" x-data="{ checked: false }" x-modelable="checked" x-bind="item"
    x-on:click="if (! $el.hasAttribute('data-disabled')) checked = ! checked"
    x-bind:aria-checked="checked ? 'true' : 'false'" x-bind:data-checked="checked ? '' : undefined" x-bind:data-unchecked="checked ? undefined : ''"
     data-keep-open         x-model="facet.status[&#039;draft&#039;]" class="relative flex h-nav-row min-h-[var(--nq-touch-min,0px)] cursor-default select-none items-center gap-2.5 rounded-control px-2.5 text-body-sm text-foreground outline-none data-highlighted:bg-nq-selected data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:size-4 [&_svg]:shrink-0 [&_svg]:text-muted-foreground ps-8">
    <span aria-hidden="true" class="absolute start-2.5 inline-flex size-4 items-center justify-center">
        <span x-show="checked" class="contents"  style="display:none" ><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <path d="M20 6 9 17l-5-5"/>
</svg></span>
    </span>
    Draft
</div>
                                    <div data-slot="dropdown-menu-checkbox-item" role="menuitemcheckbox" x-data="{ checked: false }" x-modelable="checked" x-bind="item"
    x-on:click="if (! $el.hasAttribute('data-disabled')) checked = ! checked"
    x-bind:aria-checked="checked ? 'true' : 'false'" x-bind:data-checked="checked ? '' : undefined" x-bind:data-unchecked="checked ? undefined : ''"
     data-keep-open         x-model="facet.status[&#039;archived&#039;]" class="relative flex h-nav-row min-h-[var(--nq-touch-min,0px)] cursor-default select-none items-center gap-2.5 rounded-control px-2.5 text-body-sm text-foreground outline-none data-highlighted:bg-nq-selected data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:size-4 [&_svg]:shrink-0 [&_svg]:text-muted-foreground ps-8">
    <span aria-hidden="true" class="absolute start-2.5 inline-flex size-4 items-center justify-center">
        <span x-show="checked" class="contents"  style="display:none" ><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <path d="M20 6 9 17l-5-5"/>
</svg></span>
    </span>
    Archived
</div></div>
</template></div>
        <div data-slot="dropdown-menu" x-data="nqDropdownMenu(false)" x-modelable="open" class="contents"><button data-slot="dropdown-menu-trigger"
     type="button"                         x-bind="trigger" x-ref="trigger" data-facet="stock" class="inline-flex shrink-0 select-none items-center justify-center gap-2 whitespace-nowrap rounded-control border font-sans text-label transition-colors duration-150 ease-nq min-h-[var(--nq-touch-min,0px)] outline-none focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-nq-focus disabled:pointer-events-none disabled:opacity-50 data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0 border-border bg-card text-foreground hover:bg-nq-hover h-control-sm px-2.5">
        <svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <circle cx="12" cy="12" r="10"/>
  <path d="M8 12h8"/>
  <path d="M12 8v8"/>
</svg>                Stock
                <span class="text-caption text-muted-foreground tabular-nums" x-show="on('stock').length > 0" x-text="on('stock').length"></span></button>
            <template x-teleport="body">
    <div data-slot="dropdown-menu-content" x-bind="popup" x-init="popupEl = $el" x-nq-presence="open" x-anchor.bottom-start.offset.4="$refs.trigger"
        class="z-50 overflow-hidden rounded-floating border border-border bg-popover p-1.5 text-popover-foreground shadow-floating outline-none max-h-[var(--available-height)] overflow-y-auto transition-opacity duration-150 ease-nq data-starting-style:opacity-0 data-ending-style:opacity-0 min-w-44"><div data-slot="dropdown-menu-checkbox-item" role="menuitemcheckbox" x-data="{ checked: false }" x-modelable="checked" x-bind="item"
    x-on:click="if (! $el.hasAttribute('data-disabled')) checked = ! checked"
    x-bind:aria-checked="checked ? 'true' : 'false'" x-bind:data-checked="checked ? '' : undefined" x-bind:data-unchecked="checked ? undefined : ''"
     data-keep-open         x-model="facet.stock[&#039;in&#039;]" class="relative flex h-nav-row min-h-[var(--nq-touch-min,0px)] cursor-default select-none items-center gap-2.5 rounded-control px-2.5 text-body-sm text-foreground outline-none data-highlighted:bg-nq-selected data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:size-4 [&_svg]:shrink-0 [&_svg]:text-muted-foreground ps-8">
    <span aria-hidden="true" class="absolute start-2.5 inline-flex size-4 items-center justify-center">
        <span x-show="checked" class="contents"  style="display:none" ><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <path d="M20 6 9 17l-5-5"/>
</svg></span>
    </span>
    In stock
</div>
                                    <div data-slot="dropdown-menu-checkbox-item" role="menuitemcheckbox" x-data="{ checked: false }" x-modelable="checked" x-bind="item"
    x-on:click="if (! $el.hasAttribute('data-disabled')) checked = ! checked"
    x-bind:aria-checked="checked ? 'true' : 'false'" x-bind:data-checked="checked ? '' : undefined" x-bind:data-unchecked="checked ? undefined : ''"
     data-keep-open         x-model="facet.stock[&#039;low&#039;]" class="relative flex h-nav-row min-h-[var(--nq-touch-min,0px)] cursor-default select-none items-center gap-2.5 rounded-control px-2.5 text-body-sm text-foreground outline-none data-highlighted:bg-nq-selected data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:size-4 [&_svg]:shrink-0 [&_svg]:text-muted-foreground ps-8">
    <span aria-hidden="true" class="absolute start-2.5 inline-flex size-4 items-center justify-center">
        <span x-show="checked" class="contents"  style="display:none" ><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <path d="M20 6 9 17l-5-5"/>
</svg></span>
    </span>
    Low stock
</div>
                                    <div data-slot="dropdown-menu-checkbox-item" role="menuitemcheckbox" x-data="{ checked: false }" x-modelable="checked" x-bind="item"
    x-on:click="if (! $el.hasAttribute('data-disabled')) checked = ! checked"
    x-bind:aria-checked="checked ? 'true' : 'false'" x-bind:data-checked="checked ? '' : undefined" x-bind:data-unchecked="checked ? undefined : ''"
     data-keep-open         x-model="facet.stock[&#039;out&#039;]" class="relative flex h-nav-row min-h-[var(--nq-touch-min,0px)] cursor-default select-none items-center gap-2.5 rounded-control px-2.5 text-body-sm text-foreground outline-none data-highlighted:bg-nq-selected data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:size-4 [&_svg]:shrink-0 [&_svg]:text-muted-foreground ps-8">
    <span aria-hidden="true" class="absolute start-2.5 inline-flex size-4 items-center justify-center">
        <span x-show="checked" class="contents"  style="display:none" ><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <path d="M20 6 9 17l-5-5"/>
</svg></span>
    </span>
    Out of stock
</div>
                                    <div data-slot="dropdown-menu-checkbox-item" role="menuitemcheckbox" x-data="{ checked: false }" x-modelable="checked" x-bind="item"
    x-on:click="if (! $el.hasAttribute('data-disabled')) checked = ! checked"
    x-bind:aria-checked="checked ? 'true' : 'false'" x-bind:data-checked="checked ? '' : undefined" x-bind:data-unchecked="checked ? undefined : ''"
     data-keep-open         x-model="facet.stock[&#039;untracked&#039;]" class="relative flex h-nav-row min-h-[var(--nq-touch-min,0px)] cursor-default select-none items-center gap-2.5 rounded-control px-2.5 text-body-sm text-foreground outline-none data-highlighted:bg-nq-selected data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:size-4 [&_svg]:shrink-0 [&_svg]:text-muted-foreground ps-8">
    <span aria-hidden="true" class="absolute start-2.5 inline-flex size-4 items-center justify-center">
        <span x-show="checked" class="contents"  style="display:none" ><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <path d="M20 6 9 17l-5-5"/>
</svg></span>
    </span>
    Not tracked
</div></div>
</template></div>
    </div>
    <div data-slot="data-table-bulk-actions" x-show="selected.length > 0 ? canBulk : false" class="flex flex-wrap items-center gap-2 rounded-card border border-border bg-secondary px-3 py-2">
        <span class="text-label text-foreground" x-text="tt(`selectedCount`, num(selected.length))"></span>
        <button data-slot="button"
     type="button"                         x-on:click="openBulk()" class="inline-flex shrink-0 select-none items-center justify-center gap-2 whitespace-nowrap rounded-control border font-sans text-label transition-colors duration-150 ease-nq min-h-[var(--nq-touch-min,0px)] outline-none focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-nq-focus disabled:pointer-events-none disabled:opacity-50 data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0 border-border bg-card text-foreground hover:bg-nq-hover h-control-sm px-2.5">
        <svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <path d="M21.174 6.812a1 1 0 0 0-3.986-3.987L3.842 16.174a2 2 0 0 0-.5.83l-1.321 4.352a.5.5 0 0 0 .623.622l4.353-1.32a2 2 0 0 0 .83-.497z"/>
  <path d="m15 5 4 4"/>
</svg>            Bulk edit</button>
    </div>
    <p x-show="notice ? ! (bulkOpen || delOpen) : false" role="alert" class="text-body-sm text-nq-danger-text" x-text="notice"></p>
    <template x-if="failed">
        <div class="flex flex-col items-center gap-3">
            <div data-slot="empty-state" class="flex flex-col items-center justify-center gap-3 border border-dashed border-border px-6 py-12 text-center rounded-card">
            <span data-slot="state-icon" class="inline-flex size-10 items-center justify-center rounded-control border border-border bg-card [&amp;_svg]:size-5 text-muted-foreground">
            <svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <path d="m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3"/>
  <path d="M12 9v4"/>
  <path d="M12 17h.01"/>
</svg>        </span>
        <div class="flex max-w-sm flex-col gap-1">
        <p class="text-label text-foreground">Products did not load.</p>
            </div>
    </div>
            <button data-slot="button"
     type="button"                         x-on:click="retry()" class="inline-flex shrink-0 select-none items-center justify-center gap-2 whitespace-nowrap rounded-control border font-sans text-label transition-colors duration-150 ease-nq min-h-[var(--nq-touch-min,0px)] outline-none focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-nq-focus disabled:pointer-events-none disabled:opacity-50 data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0 border-border bg-card text-foreground hover:bg-nq-hover h-control-sm px-2.5">
        Try again</button>
        </div>
    </template>
    <div x-show="loading" aria-busy="true" class="flex flex-col gap-2">
        <div data-slot="skeleton" aria-hidden="true" class="rounded-[4px] bg-secondary motion-safe:animate-pulse h-12"></div>
<div data-slot="skeleton" aria-hidden="true" class="rounded-[4px] bg-secondary motion-safe:animate-pulse h-12"></div>
<div data-slot="skeleton" aria-hidden="true" class="rounded-[4px] bg-secondary motion-safe:animate-pulse h-12"></div>
    </div>
    <template x-if="showEmpty">
        <div class="flex flex-col items-center gap-3">
            <div data-slot="empty-state" class="flex flex-col items-center justify-center gap-3 border border-dashed border-border px-6 py-12 text-center rounded-card">
            <span data-slot="state-icon" class="inline-flex size-10 items-center justify-center rounded-control border border-border bg-card [&amp;_svg]:size-5 text-muted-foreground">
            <svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <path d="M12 22v-9"/>
  <path d="M15.17 2.21a1.67 1.67 0 0 1 1.63 0L21 4.57a1.93 1.93 0 0 1 0 3.36L8.82 14.79a1.655 1.655 0 0 1-1.64 0L3 12.43a1.93 1.93 0 0 1 0-3.36z"/>
  <path d="M20 13v3.87a2.06 2.06 0 0 1-1.11 1.83l-6 3.08a1.93 1.93 0 0 1-1.78 0l-6-3.08A2.06 2.06 0 0 1 4 16.87V13"/>
  <path d="M21 12.43a1.93 1.93 0 0 0 0-3.36L8.83 2.2a1.64 1.64 0 0 0-1.63 0L3 4.57a1.93 1.93 0 0 0 0 3.36l12.18 6.86a1.636 1.636 0 0 0 1.63 0z"/>
</svg>        </span>
        <div class="flex max-w-sm flex-col gap-1">
        <p class="text-label text-foreground">No products yet</p>
                    <p class="text-body-sm text-muted-foreground">Add your first product to start selling.</p>
            </div>
    </div>
            <button data-slot="button"
     type="button"                         x-show="canCreate" x-on:click="create()" class="inline-flex shrink-0 select-none items-center justify-center gap-2 whitespace-nowrap rounded-control border font-sans text-label transition-colors duration-150 ease-nq min-h-[var(--nq-touch-min,0px)] outline-none focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-nq-focus disabled:pointer-events-none disabled:opacity-50 data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0 border-border bg-card text-foreground hover:bg-nq-hover h-control-sm px-2.5">
        New product</button>
        </div>
    </template>
    <template x-if="showNoMatch">
        <div class="flex flex-col items-center gap-3">
            <div data-slot="empty-state" class="flex flex-col items-center justify-center gap-3 border border-dashed border-border px-6 py-12 text-center rounded-card">
            <span data-slot="state-icon" class="inline-flex size-10 items-center justify-center rounded-control border border-border bg-card [&amp;_svg]:size-5 text-muted-foreground">
            <svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <path d="m13.5 8.5-5 5"/>
  <path d="m8.5 8.5 5 5"/>
  <circle cx="11" cy="11" r="8"/>
  <path d="m21 21-4.3-4.3"/>
</svg>        </span>
        <div class="flex max-w-sm flex-col gap-1">
        <p class="text-label text-foreground">No products match</p>
            </div>
    </div>
            <button data-slot="button"
     type="button"                         x-on:click="clear()" class="inline-flex shrink-0 select-none items-center justify-center gap-2 whitespace-nowrap rounded-control border font-sans text-label transition-colors duration-150 ease-nq min-h-[var(--nq-touch-min,0px)] outline-none focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-nq-focus disabled:pointer-events-none disabled:opacity-50 data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0 border-border bg-card text-foreground hover:bg-nq-hover h-control-sm px-2.5">
        Clear filters</button>
        </div>
    </template>
    <div x-show="showTable" data-slot="data-table" class="relative w-full overflow-x-auto rounded-card border border-border bg-card">
        <div role="table" aria-label="Products" class="table w-full min-w-[44rem] border-collapse">
            <div role="rowgroup" class="table-header-group border-b border-border">
                <div role="row" class="table-row">
                    <div role="columnheader" class="table-cell w-10 px-3">
                        <button type="button" role="checkbox" data-slot="checkbox" x-data="nqCheckbox(false, false)" x-modelable="checked" x-bind="root"
    aria-checked="false"
     data-unchecked                 aria-label="Products" x-on:click="toggleAll(! allOnPage)" x-bind:checked="allOnPage" class="relative inline-flex size-4 shrink-0 items-center justify-center rounded-[4px] border border-nq-line-strong bg-card text-primary-foreground outline-none transition-colors duration-150 ease-nq data-checked:border-primary data-checked:bg-primary data-indeterminate:border-primary data-indeterminate:bg-primary focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-nq-focus data-disabled:cursor-not-allowed data-disabled:opacity-50 after:absolute after:-inset-1">
    <span data-slot="checkbox-indicator" class="flex items-center justify-center [&_svg]:size-3 [&_svg]:stroke-3" x-show="checked || indeterminate"  style="display: none" >
        <svg aria-hidden="true" x-show="indeterminate" style="display: none" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <path d="M5 12h14"/>
</svg>        <svg aria-hidden="true" x-show="! indeterminate" style="" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <path d="M20 6 9 17l-5-5"/>
</svg>    </span>
    </button>
                    </div>
                                            <div role="columnheader" class="table-cell px-3 py-2 text-start text-caption font-medium text-muted-foreground " x-bind:aria-sort="ariaSort('product')">
                            <button type="button" class="inline-flex items-center gap-1 font-medium hover:text-foreground" x-on:click="sortBy('product')">Product</button>
                        </div>
                                            <div role="columnheader" class="table-cell px-3 py-2 text-start text-caption font-medium text-muted-foreground " x-bind:aria-sort="ariaSort('status')">
                            <button type="button" class="inline-flex items-center gap-1 font-medium hover:text-foreground" x-on:click="sortBy('status')">Status</button>
                        </div>
                                            <div role="columnheader" class="table-cell px-3 py-2 text-start text-caption font-medium text-muted-foreground " x-bind:aria-sort="ariaSort('stock')">
                            <button type="button" class="inline-flex items-center gap-1 font-medium hover:text-foreground" x-on:click="sortBy('stock')">Stock</button>
                        </div>
                                            <div role="columnheader" class="table-cell px-3 py-2 text-start text-caption font-medium text-muted-foreground " x-bind:aria-sort="ariaSort('variants')">
                            <button type="button" class="inline-flex items-center gap-1 font-medium hover:text-foreground" x-on:click="sortBy('variants')">Variants</button>
                        </div>
                                            <div role="columnheader" class="table-cell px-3 py-2 text-start text-caption font-medium text-muted-foreground text-end" x-bind:aria-sort="ariaSort('price')">
                            <button type="button" class="inline-flex items-center gap-1 font-medium hover:text-foreground" x-on:click="sortBy('price')">Price</button>
                        </div>
                                        <div role="columnheader" class="table-cell w-10"><span class="sr-only">Actions</span></div>
                </div>
            </div>
            <div role="rowgroup" class="table-row-group divide-y divide-border">
                <template x-for="p in rows" x-bind:key="p.id">
                    <div role="row" data-slot="product-row" x-data="nqContextMenu()" x-bind="trigger" x-bind:data-selected="sel[p.id] ? '' : null"
                        x-on:click="openProduct(p)" class="table-row cursor-pointer hover:bg-nq-hover data-[selected]:bg-nq-selected">
                        <div role="cell" class="table-cell px-3" x-on:click.stop>
                            <button type="button" role="checkbox" data-slot="checkbox" x-data="nqCheckbox(false, false)" x-modelable="checked" x-bind="root"
    aria-checked="false"
     data-unchecked                 x-model="sel[p.id]" x-bind:aria-label="p.name" class="relative inline-flex size-4 shrink-0 items-center justify-center rounded-[4px] border border-nq-line-strong bg-card text-primary-foreground outline-none transition-colors duration-150 ease-nq data-checked:border-primary data-checked:bg-primary data-indeterminate:border-primary data-indeterminate:bg-primary focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-nq-focus data-disabled:cursor-not-allowed data-disabled:opacity-50 after:absolute after:-inset-1">
    <span data-slot="checkbox-indicator" class="flex items-center justify-center [&_svg]:size-3 [&_svg]:stroke-3" x-show="checked || indeterminate"  style="display: none" >
        <svg aria-hidden="true" x-show="indeterminate" style="display: none" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <path d="M5 12h14"/>
</svg>        <svg aria-hidden="true" x-show="! indeterminate" style="" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <path d="M20 6 9 17l-5-5"/>
</svg>    </span>
    </button>
                        </div>
                        <div role="cell" class="table-cell px-3 py-2.5 text-body-sm text-foreground">
                            <span class="flex min-w-0 items-center gap-3">
                                <span data-slot="product-thumb" style="width: 40px; height: 40px"
    class="relative inline-flex shrink-0 items-center justify-center overflow-hidden rounded-control border border-border bg-secondary text-muted-foreground">
    <img alt="" x-show="imgOk(p.images[0]?.src)" x-bind:src="p.images[0]?.src" x-on:error="broken[p.images[0]?.src] = true" class="size-full object-cover" />
    <svg aria-hidden="true" x-show="! imgOk(p.images[0]?.src)" class="size-1/2" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <rect width="18" height="18" x="3" y="3" rx="2" ry="2"/>
  <circle cx="9" cy="9" r="2"/>
  <path d="m21 15-3.086-3.086a2 2 0 0 0-2.828 0L6 21"/>
</svg></span>
                                <span class="flex min-w-0 flex-col">
                                    <span class="truncate font-medium" x-text="p.name"></span>
                                    <span class="truncate text-caption text-muted-foreground" x-show="p.category" x-text="p.category"></span>
                                </span>
                            </span>
                        </div>
                        <div role="cell" class="table-cell px-3 py-2.5 text-body-sm text-foreground">
                            <span data-slot="badge" class="inline-flex h-5 shrink-0 items-center whitespace-nowrap rounded-[4px] border px-1.5 text-caption font-medium" x-bind:class="statusClass(p)" x-text="statusLabel(p)"></span>
                        </div>
                        <div role="cell" class="table-cell px-3 py-2.5 text-body-sm text-foreground">
                            <span class="flex flex-col items-start gap-0.5">
                                <span data-slot="badge" class="inline-flex h-5 shrink-0 items-center whitespace-nowrap rounded-[4px] border px-1.5 text-caption font-medium" x-bind:class="levelClass(p)" x-text="levelLabel(p)"></span>
                                <span class="text-caption text-muted-foreground tabular-nums" x-text="unitsText(p)"></span>
                            </span>
                        </div>
                        <div role="cell" class="table-cell px-3 py-2.5 text-body-sm text-foreground tabular-nums" x-text="variantsText(p)"></div>
                        <div role="cell" dir="ltr" class="table-cell px-3 py-2.5 text-body-sm text-foreground text-end tabular-nums" x-text="priceText(p)"></div>
                        <div role="cell" class="table-cell px-1" x-on:click.stop>
                            <div data-slot="dropdown-menu" x-data="nqDropdownMenu(false)" x-modelable="open" class="contents"><button data-slot="row-actions"
     type="button"                         x-bind="trigger" x-ref="trigger" x-bind:aria-label="`Actions, ${p.name}`" class="inline-flex shrink-0 select-none items-center justify-center gap-2 whitespace-nowrap rounded-control border border-transparent font-sans text-label transition-colors duration-150 ease-nq min-h-[var(--nq-touch-min,0px)] outline-none focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-nq-focus disabled:pointer-events-none disabled:opacity-50 data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0 hover:bg-nq-hover size-control-sm p-0 text-muted-foreground data-popup-open:text-foreground">
        <svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <circle cx="12" cy="12" r="1"/>
  <circle cx="19" cy="12" r="1"/>
  <circle cx="5" cy="12" r="1"/>
</svg></button>
                                <template x-teleport="body">
    <div data-slot="dropdown-menu-content" x-bind="popup" x-init="popupEl = $el" x-nq-presence="open" x-anchor.bottom-end.offset.4="$refs.trigger"
        class="z-50 overflow-hidden rounded-floating border border-border bg-popover p-1.5 text-popover-foreground shadow-floating outline-none max-h-[var(--available-height)] overflow-y-auto transition-opacity duration-150 ease-nq data-starting-style:opacity-0 data-ending-style:opacity-0 min-w-48"><div data-slot="dropdown-menu-item" role="menuitem" data-variant="default" x-bind="item"
        x-on:click="openProduct(p)" class="relative flex h-nav-row min-h-[var(--nq-touch-min,0px)] cursor-default select-none items-center gap-2.5 rounded-control px-2.5 text-body-sm text-foreground outline-none data-highlighted:bg-nq-selected data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:size-4 [&_svg]:shrink-0 [&_svg]:text-muted-foreground"><svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <path d="M21.174 6.812a1 1 0 0 0-3.986-3.987L3.842 16.174a2 2 0 0 0-.5.83l-1.321 4.352a.5.5 0 0 0 .623.622l4.353-1.32a2 2 0 0 0 .83-.497z"/>
  <path d="m15 5 4 4"/>
</svg>Edit</div>
                                    <div data-slot="dropdown-menu-item" role="menuitem" data-variant="default" x-bind="item"
        x-show="can(p, `active`)" x-on:click="setStatus(p, `active`)" class="relative flex h-nav-row min-h-[var(--nq-touch-min,0px)] cursor-default select-none items-center gap-2.5 rounded-control px-2.5 text-body-sm text-foreground outline-none data-highlighted:bg-nq-selected data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:size-4 [&_svg]:shrink-0 [&_svg]:text-muted-foreground"><svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <circle cx="12" cy="12" r="10"/>
  <path d="m9 12 2 2 4-4"/>
</svg>Set active</div>
                                    <div data-slot="dropdown-menu-item" role="menuitem" data-variant="default" x-bind="item"
        x-show="can(p, `draft`)" x-on:click="setStatus(p, `draft`)" class="relative flex h-nav-row min-h-[var(--nq-touch-min,0px)] cursor-default select-none items-center gap-2.5 rounded-control px-2.5 text-body-sm text-foreground outline-none data-highlighted:bg-nq-selected data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:size-4 [&_svg]:shrink-0 [&_svg]:text-muted-foreground"><svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <path d="M12.659 22H18a2 2 0 0 0 2-2V8a2.4 2.4 0 0 0-.706-1.706l-3.588-3.588A2.4 2.4 0 0 0 14 2H6a2 2 0 0 0-2 2v9.34"/>
  <path d="M14 2v5a1 1 0 0 0 1 1h5"/>
  <path d="M10.378 12.622a1 1 0 0 1 3 3.003L8.36 20.637a2 2 0 0 1-.854.506l-2.867.837a.5.5 0 0 1-.62-.62l.836-2.869a2 2 0 0 1 .506-.853z"/>
</svg>Move to drafts</div>
                                    <div data-slot="dropdown-menu-item" role="menuitem" data-variant="default" x-bind="item"
        x-show="can(p, `archived`)" x-on:click="setStatus(p, `archived`)" class="relative flex h-nav-row min-h-[var(--nq-touch-min,0px)] cursor-default select-none items-center gap-2.5 rounded-control px-2.5 text-body-sm text-foreground outline-none data-highlighted:bg-nq-selected data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:size-4 [&_svg]:shrink-0 [&_svg]:text-muted-foreground"><svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <rect width="20" height="5" x="2" y="3" rx="1"/>
  <path d="M4 8v11a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8"/>
  <path d="M10 12h4"/>
</svg>Archive</div>
                                    <div data-slot="dropdown-menu-separator" role="separator" aria-orientation="horizontal" x-show="canDelete" class="-mx-1.5 my-1.5 h-px bg-border"></div>
                                    <div data-slot="dropdown-menu-item" role="menuitem" data-variant="danger" x-bind="item"
        x-show="canDelete" x-on:click="askDelete(p)" class="relative flex h-nav-row min-h-[var(--nq-touch-min,0px)] cursor-default select-none items-center gap-2.5 rounded-control px-2.5 text-body-sm outline-none data-highlighted:bg-nq-selected data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:size-4 [&_svg]:shrink-0 text-nq-danger-text [&_svg]:text-current"><svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <path d="M10 11v6"/>
  <path d="M14 11v6"/>
  <path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6"/>
  <path d="M3 6h18"/>
  <path d="M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"/>
</svg>Delete</div></div>
</template></div>
                        </div>
                        <template x-teleport="body">
                            <div data-slot="context-menu-content" x-bind="popup" x-init="popupEl = $el" x-nq-presence="open"
                                class="fixed z-50 min-w-48 overflow-hidden rounded-floating border border-border bg-popover p-1.5 text-popover-foreground shadow-floating outline-none max-h-[var(--available-height)] overflow-y-auto transition-opacity duration-150 ease-nq data-starting-style:opacity-0 data-ending-style:opacity-0">
                                <div data-slot="context-menu-item" role="menuitem" data-variant="default" x-bind="item"
        x-on:click="openProduct(p)" class="relative flex h-nav-row min-h-[var(--nq-touch-min,0px)] cursor-default select-none items-center gap-2.5 rounded-control px-2.5 text-body-sm text-foreground outline-none data-highlighted:bg-nq-selected data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:size-4 [&_svg]:shrink-0 [&_svg]:text-muted-foreground"><svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <path d="M21.174 6.812a1 1 0 0 0-3.986-3.987L3.842 16.174a2 2 0 0 0-.5.83l-1.321 4.352a.5.5 0 0 0 .623.622l4.353-1.32a2 2 0 0 0 .83-.497z"/>
  <path d="m15 5 4 4"/>
</svg>Edit</div>
                                <div data-slot="context-menu-item" role="menuitem" data-variant="default" x-bind="item"
        x-show="can(p, `active`)" x-on:click="setStatus(p, `active`)" class="relative flex h-nav-row min-h-[var(--nq-touch-min,0px)] cursor-default select-none items-center gap-2.5 rounded-control px-2.5 text-body-sm text-foreground outline-none data-highlighted:bg-nq-selected data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:size-4 [&_svg]:shrink-0 [&_svg]:text-muted-foreground"><svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <circle cx="12" cy="12" r="10"/>
  <path d="m9 12 2 2 4-4"/>
</svg>Set active</div>
                                <div data-slot="context-menu-item" role="menuitem" data-variant="default" x-bind="item"
        x-show="can(p, `draft`)" x-on:click="setStatus(p, `draft`)" class="relative flex h-nav-row min-h-[var(--nq-touch-min,0px)] cursor-default select-none items-center gap-2.5 rounded-control px-2.5 text-body-sm text-foreground outline-none data-highlighted:bg-nq-selected data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:size-4 [&_svg]:shrink-0 [&_svg]:text-muted-foreground"><svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <path d="M12.659 22H18a2 2 0 0 0 2-2V8a2.4 2.4 0 0 0-.706-1.706l-3.588-3.588A2.4 2.4 0 0 0 14 2H6a2 2 0 0 0-2 2v9.34"/>
  <path d="M14 2v5a1 1 0 0 0 1 1h5"/>
  <path d="M10.378 12.622a1 1 0 0 1 3 3.003L8.36 20.637a2 2 0 0 1-.854.506l-2.867.837a.5.5 0 0 1-.62-.62l.836-2.869a2 2 0 0 1 .506-.853z"/>
</svg>Move to drafts</div>
                                <div data-slot="context-menu-item" role="menuitem" data-variant="default" x-bind="item"
        x-show="can(p, `archived`)" x-on:click="setStatus(p, `archived`)" class="relative flex h-nav-row min-h-[var(--nq-touch-min,0px)] cursor-default select-none items-center gap-2.5 rounded-control px-2.5 text-body-sm text-foreground outline-none data-highlighted:bg-nq-selected data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:size-4 [&_svg]:shrink-0 [&_svg]:text-muted-foreground"><svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <rect width="20" height="5" x="2" y="3" rx="1"/>
  <path d="M4 8v11a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8"/>
  <path d="M10 12h4"/>
</svg>Archive</div>
                                <div data-slot="context-menu-separator" role="separator" aria-orientation="horizontal" x-show="canDelete" class="-mx-1.5 my-1.5 h-px bg-border"></div>
                                <div data-slot="context-menu-item" role="menuitem" data-variant="danger" x-bind="item"
        x-show="canDelete" x-on:click="askDelete(p)" class="relative flex h-nav-row min-h-[var(--nq-touch-min,0px)] cursor-default select-none items-center gap-2.5 rounded-control px-2.5 text-body-sm outline-none data-highlighted:bg-nq-selected data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:size-4 [&_svg]:shrink-0 text-nq-danger-text [&_svg]:text-current"><svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <path d="M10 11v6"/>
  <path d="M14 11v6"/>
  <path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6"/>
  <path d="M3 6h18"/>
  <path d="M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"/>
</svg>Delete</div>
                            </div>
                        </template>
                    </div>
                </template>
            </div>
        </div>
    </div>
    <div x-show="showPager" class="flex items-center justify-between gap-2 text-body-sm text-muted-foreground">
        <span class="tabular-nums" x-text="num(Math.min(page, pages)) + ' / ' + num(pages)"></span>
        <div class="flex gap-2">
            <button data-slot="button"
     type="button"                         x-bind:disabled="page &lt;= 1" x-on:click="page = page - 1" class="inline-flex shrink-0 select-none items-center justify-center gap-2 whitespace-nowrap rounded-control border font-sans text-label transition-colors duration-150 ease-nq min-h-[var(--nq-touch-min,0px)] outline-none focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-nq-focus disabled:pointer-events-none disabled:opacity-50 data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0 border-border bg-card text-foreground hover:bg-nq-hover h-control-sm px-2.5">
        <svg aria-hidden="true" class="rtl:-scale-x-100" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <path d="m15 18-6-6 6-6"/>
</svg><span class="sr-only">Previous page</span></button>
            <button data-slot="button"
     type="button"                         x-bind:disabled="page &gt;= pages" x-on:click="page = page + 1" class="inline-flex shrink-0 select-none items-center justify-center gap-2 whitespace-nowrap rounded-control border font-sans text-label transition-colors duration-150 ease-nq min-h-[var(--nq-touch-min,0px)] outline-none focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-nq-focus disabled:pointer-events-none disabled:opacity-50 data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0 border-border bg-card text-foreground hover:bg-nq-hover h-control-sm px-2.5">
        <svg aria-hidden="true" class="rtl:-scale-x-100" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <path d="m9 18 6-6-6-6"/>
</svg><span class="sr-only">Next page</span></button>
        </div>
    </div>
    <div data-slot="dialog" x-data="nqDialog(false)" x-modelable="open" x-id="['nq-dialog']" x-model="bulkOpen" class="contents">
    <template x-teleport="body">
    <div data-slot="dialog-portal">
        <div data-slot="dialog-backdrop" x-nq-presence="open" x-on:click="close()" class="fixed inset-0 z-50 bg-nq-fg/15 dark:bg-nq-bg/60 transition-opacity duration-150 ease-nq data-starting-style:opacity-0 data-ending-style:opacity-0"></div>
        <div data-slot="product-bulk-edit" x-bind="popup" x-nq-presence="open" x-trap.noscroll="open"
            class="fixed inset-0 z-50 m-auto grid h-fit w-[calc(100%-2rem)] max-w-lg gap-4 rounded-floating border border-border bg-popover p-6 text-popover-foreground outline-none transition-opacity duration-150 ease-nq data-starting-style:opacity-0 data-ending-style:opacity-0 max-h-[92dvh] overflow-y-auto sm:max-w-xl">
            <form class="grid gap-4" x-on:submit.prevent="applyBulk()">
                <div data-slot="dialog-header" class="flex flex-col gap-1.5 pe-8 text-start"><h2 data-slot="dialog-title" :id="$id('nq-dialog', 'title')" class="text-h3 text-foreground"><span x-text="tt(`bulkTitle`, num(selected.length))"></span></h2>
                    <p data-slot="dialog-description" :id="$id('nq-dialog', 'description')" class="text-body-sm text-muted-foreground">Leave a section on Keep to leave it alone. Changes apply to every variant.</p></div>
                <fieldset class="grid gap-2">
                    <legend class="text-label text-foreground">Price</legend>
                    <div data-slot="native-select" class="relative w-full min-w-0">
    <select           class="w-full min-w-0 appearance-none rounded-control border border-input bg-card ps-3 pe-9 text-body text-foreground min-h-[var(--nq-touch-min,0px)] transition-colors duration-150 ease-nq outline-none focus-visible:border-nq-focus focus-visible:outline-1 focus-visible:outline-nq-focus data-invalid:border-nq-danger aria-invalid:border-nq-danger disabled:cursor-not-allowed disabled:opacity-50 pointer-coarse:text-[16px] h-control" aria-label="Price" x-model="priceMode">
                            <option value="keep"  >Keep</option>
                    <option value="set"  >Set to</option>
                    <option value="increase-percent"  >Raise by percent</option>
                    <option value="decrease-percent"  >Lower by percent</option>
                    <option value="increase-amount"  >Raise by amount</option>
                    <option value="decrease-amount"  >Lower by amount</option>
    </select>
    <svg aria-hidden="true" class="pointer-events-none absolute end-3 top-1/2 size-4 -translate-y-1/2 text-muted-foreground" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <path d="m6 9 6 6 6-6"/>
</svg></div>
                    <div x-show="percentMode">
                        <input data-slot="input" type="text"
                    inputmode="decimal" aria-label="Percent" placeholder="Percent" x-model="percentText" class="w-full min-w-0 rounded-control border border-input bg-card px-3 text-body text-foreground min-h-[var(--nq-touch-min,0px)] transition-colors duration-150 ease-nq outline-none placeholder:text-muted-foreground focus-visible:border-nq-focus focus-visible:outline-1 focus-visible:outline-nq-focus data-invalid:border-nq-danger aria-invalid:border-nq-danger disabled:cursor-not-allowed disabled:opacity-50 pointer-coarse:text-[16px] h-control">
                    </div>
                    <div x-show="priceMode !== 'keep' ? ! percentMode : false">
                        <div data-slot="currency-input" data-currency="USD" x-data="nqCurrencyInput(null, JSON.parse('{\u0022currency\u0022:\u0022USD\u0022,\u0022locale\u0022:\u0022en\u0022}'))" x-modelable="minor" x-id="['nq-currency']"
    x-model="amount" class="flex w-full min-w-0 flex-col gap-1">
    <div role="group" data-slot="input-group"
    x-bind="group" class="group/input-group flex h-control min-h-[var(--nq-touch-min,0px)] w-full min-w-0 items-center overflow-hidden rounded-control border border-input bg-card text-body text-foreground transition-colors duration-150 ease-nq focus-within:border-nq-focus focus-within:outline-1 focus-within:outline-nq-focus has-[[data-invalid]]:border-nq-danger has-[[aria-invalid=true]]:border-nq-danger has-[input:disabled]:cursor-not-allowed has-[input:disabled]:opacity-50"><div data-slot="currency-symbol" data-align="start" x-bind="symbolAddon"
            class="flex h-full shrink-0 items-center gap-1.5 text-body-sm text-muted-foreground [&amp;_svg]:size-4 order-first ps-3 pe-1">
            <span data-slot="input-group-text" class="select-none whitespace-nowrap"><bdi dir="ltr" x-text="mark()"></bdi></span>
        </div>
        <input data-slot="input-group-input" dir="ltr" x-bind="field" autocomplete="off" spellcheck="false"                           aria-label="Amount" class="h-full min-w-0 flex-1 border-0 bg-transparent px-3 text-body text-foreground outline-none placeholder:text-muted-foreground disabled:cursor-not-allowed pointer-coarse:text-[16px] text-start tabular-nums"></div>
    <span x-show="out()" x-cloak style="display: none" :id="rangeId()" class="sr-only">Amount out of range</span>
    </div>
                    </div>
                    <label x-show="priceMode !== 'keep'" class="flex items-center gap-2 text-body-sm text-foreground">
                        <button type="button" role="checkbox" data-slot="checkbox" x-data="nqCheckbox(false, false)" x-modelable="checked" x-bind="root"
    aria-checked="false"
     data-unchecked                 x-model="alsoCompare" class="relative inline-flex size-4 shrink-0 items-center justify-center rounded-[4px] border border-nq-line-strong bg-card text-primary-foreground outline-none transition-colors duration-150 ease-nq data-checked:border-primary data-checked:bg-primary data-indeterminate:border-primary data-indeterminate:bg-primary focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-nq-focus data-disabled:cursor-not-allowed data-disabled:opacity-50 after:absolute after:-inset-1">
    <span data-slot="checkbox-indicator" class="flex items-center justify-center [&_svg]:size-3 [&_svg]:stroke-3" x-show="checked || indeterminate"  style="display: none" >
        <svg aria-hidden="true" x-show="indeterminate" style="display: none" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <path d="M5 12h14"/>
</svg>        <svg aria-hidden="true" x-show="! indeterminate" style="" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <path d="M20 6 9 17l-5-5"/>
</svg>    </span>
    </button>
                        Move compare-at price the same way
                    </label>
                </fieldset>
                <fieldset class="grid gap-2">
                    <legend class="text-label text-foreground">Stock</legend>
                    <div data-slot="native-select" class="relative w-full min-w-0">
    <select           class="w-full min-w-0 appearance-none rounded-control border border-input bg-card ps-3 pe-9 text-body text-foreground min-h-[var(--nq-touch-min,0px)] transition-colors duration-150 ease-nq outline-none focus-visible:border-nq-focus focus-visible:outline-1 focus-visible:outline-nq-focus data-invalid:border-nq-danger aria-invalid:border-nq-danger disabled:cursor-not-allowed disabled:opacity-50 pointer-coarse:text-[16px] h-control" aria-label="Stock" x-model="stockMode">
                            <option value="keep"  >Keep</option>
                    <option value="set"  >Set to</option>
                    <option value="add"  >Add</option>
                    <option value="remove"  >Remove</option>
    </select>
    <svg aria-hidden="true" class="pointer-events-none absolute end-3 top-1/2 size-4 -translate-y-1/2 text-muted-foreground" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <path d="m6 9 6 6 6-6"/>
</svg></div>
                    <div x-show="stockMode !== 'keep'">
                        <input data-slot="input" type="text"
                    inputmode="numeric" aria-label="Quantity" placeholder="Quantity" x-model="stockText" class="w-full min-w-0 rounded-control border border-input bg-card px-3 text-body text-foreground min-h-[var(--nq-touch-min,0px)] transition-colors duration-150 ease-nq outline-none placeholder:text-muted-foreground focus-visible:border-nq-focus focus-visible:outline-1 focus-visible:outline-nq-focus data-invalid:border-nq-danger aria-invalid:border-nq-danger disabled:cursor-not-allowed disabled:opacity-50 pointer-coarse:text-[16px] h-control">
                    </div>
                </fieldset>
                <fieldset class="grid gap-2">
                    <legend class="text-label text-foreground">Status</legend>
                    <div data-slot="native-select" class="relative w-full min-w-0">
    <select           class="w-full min-w-0 appearance-none rounded-control border border-input bg-card ps-3 pe-9 text-body text-foreground min-h-[var(--nq-touch-min,0px)] transition-colors duration-150 ease-nq outline-none focus-visible:border-nq-focus focus-visible:outline-1 focus-visible:outline-nq-focus data-invalid:border-nq-danger aria-invalid:border-nq-danger disabled:cursor-not-allowed disabled:opacity-50 pointer-coarse:text-[16px] h-control" aria-label="Status" x-model="bulkStatus">
                            <option value="keep"  >Keep</option>
                    <option value="active"  >Active</option>
                    <option value="draft"  >Draft</option>
                    <option value="archived"  >Archived</option>
    </select>
    <svg aria-hidden="true" class="pointer-events-none absolute end-3 top-1/2 size-4 -translate-y-1/2 text-muted-foreground" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <path d="m6 9 6 6 6-6"/>
</svg></div>
                </fieldset>
                <div role="status" aria-live="polite" data-slot="bulk-preview" class="grid gap-2 rounded-card border border-border bg-nq-surface-soft p-3">
                    <p class="text-label text-foreground">Preview</p>
                    <p x-show="preview.length === 0" class="text-body-sm text-muted-foreground">Nothing changes yet. Pick a change above.</p>
                    <ul class="grid gap-1">
                        <template x-for="r in previewShown" x-bind:key="r.id">
                            <li class="flex flex-wrap items-center gap-x-3 text-body-sm">
                                <span class="min-w-0 flex-1 truncate" x-text="r.name"></span>
                                <span class="tabular-nums text-muted-foreground" dir="ltr" x-show="r.price" x-text="r.price"></span>
                                <span class="tabular-nums text-muted-foreground" dir="ltr" x-show="r.stock" x-text="r.stock"></span>
                                <span class="text-muted-foreground" x-show="r.status" x-text="r.status"></span>
                            </li>
                        </template>
                        <li class="text-caption text-muted-foreground" x-show="previewMore > 0" x-text="`+` + num(previewMore)"></li>
                    </ul>
                </div>
                <p x-show="notice" role="alert" class="text-body-sm text-nq-danger-text" x-text="notice"></p>
                <div data-slot="dialog-footer" class="flex flex-col-reverse gap-2 sm:flex-row sm:justify-end"><button data-slot="button"
     type="button"                         x-bind:disabled="busy" x-on:click="bulkOpen = false" class="inline-flex shrink-0 select-none items-center justify-center gap-2 whitespace-nowrap rounded-control border border-transparent font-sans text-label transition-colors duration-150 ease-nq min-h-[var(--nq-touch-min,0px)] outline-none focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-nq-focus disabled:pointer-events-none disabled:opacity-50 data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0 text-foreground hover:bg-nq-hover h-control px-[var(--nq-control-pad)]">
        Cancel</button>
                    <button data-slot="button"
     type="submit"                         x-bind:disabled="! hasChange || busy" class="inline-flex shrink-0 select-none items-center justify-center gap-2 whitespace-nowrap rounded-control border border-transparent font-sans text-label transition-colors duration-150 ease-nq min-h-[var(--nq-touch-min,0px)] outline-none focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-nq-focus disabled:pointer-events-none disabled:opacity-50 data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0 bg-primary text-primary-foreground hover:bg-[color-mix(in_oklab,var(--nq-action)_88%,var(--nq-fg))] h-control px-[var(--nq-control-pad)]">
        <span x-text="tt(`applyToProducts`, num(selected.length))"></span></button></div>
            </form>
                            <button type="button" data-slot="dialog-close" x-on:click="close()" aria-label="Close"
                    class="absolute end-3 top-3 inline-flex size-8 items-center justify-center rounded-control text-muted-foreground transition-colors duration-150 hover:bg-nq-hover hover:text-foreground focus-visible:outline-2 focus-visible:outline-nq-focus [&_svg]:size-4"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <path d="M18 6 6 18"/>
  <path d="m6 6 12 12"/>
</svg></button>
                    </div>
    </div>
</template>
</div>
    <div data-slot="dialog" x-data="nqDialog(false)" x-modelable="open" x-id="['nq-dialog']" x-model="delOpen" class="contents">
    <template x-teleport="body">
    <div data-slot="dialog-portal">
        <div data-slot="dialog-backdrop" x-nq-presence="open" x-on:click="close()" class="fixed inset-0 z-50 bg-nq-fg/15 dark:bg-nq-bg/60 transition-opacity duration-150 ease-nq data-starting-style:opacity-0 data-ending-style:opacity-0"></div>
        <div data-slot="product-delete" x-bind="popup" x-nq-presence="open" x-trap.noscroll="open"
            class="fixed inset-0 z-50 m-auto grid h-fit w-[calc(100%-2rem)] gap-4 rounded-floating border border-border bg-popover p-6 text-popover-foreground outline-none max-h-[calc(100dvh-2rem)] overflow-y-auto transition-opacity duration-150 ease-nq data-starting-style:opacity-0 data-ending-style:opacity-0 max-w-md">
            <div data-slot="dialog-header" class="flex flex-col gap-1.5 pe-8 text-start"><h2 data-slot="dialog-title" :id="$id('nq-dialog', 'title')" class="text-h3 text-foreground">Delete this product?</h2>
                <p data-slot="dialog-description" :id="$id('nq-dialog', 'description')" class="text-body-sm text-muted-foreground"><span x-text="tt(`deleteDescription`, deleting ? deleting.name : ``)"></span></p></div>
            <p x-show="notice" role="alert" class="text-body-sm text-nq-danger-text" x-text="notice"></p>
            <div data-slot="dialog-footer" class="flex flex-col-reverse gap-2 sm:flex-row sm:justify-end"><button data-slot="button"
     type="button"                         x-bind:disabled="busy" x-on:click="delOpen = false" class="inline-flex shrink-0 select-none items-center justify-center gap-2 whitespace-nowrap rounded-control border border-transparent font-sans text-label transition-colors duration-150 ease-nq min-h-[var(--nq-touch-min,0px)] outline-none focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-nq-focus disabled:pointer-events-none disabled:opacity-50 data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0 text-foreground hover:bg-nq-hover h-control px-[var(--nq-control-pad)]">
        Cancel</button>
                <button data-slot="button"
     type="button"                         x-bind:disabled="busy" x-on:click="confirmDelete()" class="inline-flex shrink-0 select-none items-center justify-center gap-2 whitespace-nowrap rounded-control border border-transparent font-sans text-label transition-colors duration-150 ease-nq min-h-[var(--nq-touch-min,0px)] outline-none focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-nq-focus disabled:pointer-events-none disabled:opacity-50 data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0 bg-destructive text-destructive-foreground hover:bg-[color-mix(in_oklab,var(--nq-danger-solid)_88%,var(--nq-fg))] h-control px-[var(--nq-control-pad)]">
        Delete</button></div>
                            <button type="button" data-slot="dialog-close" x-on:click="close()" aria-label="Close"
                    class="absolute end-3 top-3 inline-flex size-8 items-center justify-center rounded-control text-muted-foreground transition-colors duration-150 hover:bg-nq-hover hover:text-foreground focus-visible:outline-2 focus-visible:outline-nq-focus [&_svg]:size-4"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <path d="M18 6 6 18"/>
  <path d="m6 6 12 12"/>
</svg></button>
                    </div>
    </div>
</template>
</div>
</div>
    <form data-slot="product-editor" novalidate x-data="nqProductEditor(JSON.parse('{\u0022product\u0022:{\u0022id\u0022:\u0022p1\u0022,\u0022name\u0022:\u0022Linen shirt\u0022,\u0022brand\u0022:\u0022Nile\u0022,\u0022category\u0022:\u0022Clothing\u0022,\u0022tags\u0022:[\u0022summer\u0022],\u0022status\u0022:\u0022active\u0022,\u0022slug\u0022:\u0022linen-shirt\u0022,\u0022images\u0022:[{\u0022src\u0022:\u0022\\\/img\\\/shirt-a.jpg\u0022,\u0022alt\u0022:\u0022Front\u0022},{\u0022src\u0022:\u0022\\\/img\\\/shirt-b.jpg\u0022,\u0022alt\u0022:\u0022\u0022},{\u0022src\u0022:\u0022\\\/img\\\/shirt-c.jpg\u0022,\u0022alt\u0022:\u0022Back\u0022}],\u0022options\u0022:[{\u0022id\u0022:\u0022colour\u0022,\u0022name\u0022:\u0022Colour\u0022,\u0022display\u0022:\u0022button\u0022,\u0022values\u0022:[{\u0022id\u0022:\u0022red\u0022,\u0022label\u0022:\u0022Red\u0022},{\u0022id\u0022:\u0022blue\u0022,\u0022label\u0022:\u0022Blue\u0022}]}],\u0022variants\u0022:[{\u0022id\u0022:\u0022v1\u0022,\u0022options\u0022:{\u0022colour\u0022:\u0022red\u0022},\u0022price\u0022:4900,\u0022compareAt\u0022:5900,\u0022stock\u0022:12,\u0022sku\u0022:\u0022LIN-RED\u0022},{\u0022id\u0022:\u0022v2\u0022,\u0022options\u0022:{\u0022colour\u0022:\u0022blue\u0022},\u0022price\u0022:4900,\u0022stock\u0022:2,\u0022sku\u0022:\u0022LIN-BLUE\u0022}]},\u0022draft\u0022:null,\u0022extra\u0022:{\u0022cost\u0022:2000},\u0022currency\u0022:\u0022USD\u0022,\u0022locale\u0022:\u0022en\u0022,\u0022t\u0022:{\u0022products\u0022:\u0022Products\u0022,\u0022newProduct\u0022:\u0022New product\u0022,\u0022searchProducts\u0022:\u0022Search products\u0022,\u0022productCol\u0022:\u0022Product\u0022,\u0022statusCol\u0022:\u0022Status\u0022,\u0022stockCol\u0022:\u0022Stock\u0022,\u0022priceCol\u0022:\u0022Price\u0022,\u0022variantsCol\u0022:\u0022Variants\u0022,\u0022categoryCol\u0022:\u0022Category\u0022,\u0022statuses.active\u0022:\u0022Active\u0022,\u0022statuses.draft\u0022:\u0022Draft\u0022,\u0022statuses.archived\u0022:\u0022Archived\u0022,\u0022stockLevels.in\u0022:\u0022In stock\u0022,\u0022stockLevels.low\u0022:\u0022Low stock\u0022,\u0022stockLevels.out\u0022:\u0022Out of stock\u0022,\u0022stockLevels.untracked\u0022:\u0022Not tracked\u0022,\u0022units\u0022:\u0022{0} in stock\u0022,\u0022variantCount\u0022:\u0022{0} variants\u0022,\u0022oneVariant\u0022:\u00221 variant\u0022,\u0022productListLabel\u0022:\u0022Products\u0022,\u0022noProducts\u0022:\u0022No products yet\u0022,\u0022noProductsHint\u0022:\u0022Add your first product to start selling.\u0022,\u0022loadFailed\u0022:\u0022Products did not load.\u0022,\u0022retry\u0022:\u0022Try again\u0022,\u0022edit\u0022:\u0022Edit\u0022,\u0022setActive\u0022:\u0022Set active\u0022,\u0022setDraft\u0022:\u0022Move to drafts\u0022,\u0022archive\u0022:\u0022Archive\u0022,\u0022delete\u0022:\u0022Delete\u0022,\u0022deleteTitle\u0022:\u0022Delete this product?\u0022,\u0022deleteDescription\u0022:\u0022{0} and its variants are removed. Past orders keep their copy.\u0022,\u0022selectedCount\u0022:\u0022{0} selected\u0022,\u0022bulkEdit\u0022:\u0022Bulk edit\u0022,\u0022bulkTitle\u0022:\u0022Edit {0} products\u0022,\u0022bulkDescription\u0022:\u0022Leave a section on Keep to leave it alone. Changes apply to every variant.\u0022,\u0022bulkPrice\u0022:\u0022Price\u0022,\u0022bulkStock\u0022:\u0022Stock\u0022,\u0022bulkStatus\u0022:\u0022Status\u0022,\u0022keep\u0022:\u0022Keep\u0022,\u0022priceModes.set\u0022:\u0022Set to\u0022,\u0022priceModes.increase-percent\u0022:\u0022Raise by percent\u0022,\u0022priceModes.decrease-percent\u0022:\u0022Lower by percent\u0022,\u0022priceModes.increase-amount\u0022:\u0022Raise by amount\u0022,\u0022priceModes.decrease-amount\u0022:\u0022Lower by amount\u0022,\u0022stockModes.set\u0022:\u0022Set to\u0022,\u0022stockModes.add\u0022:\u0022Add\u0022,\u0022stockModes.remove\u0022:\u0022Remove\u0022,\u0022alsoCompareAt\u0022:\u0022Move compare-at price the same way\u0022,\u0022percent\u0022:\u0022Percent\u0022,\u0022amount\u0022:\u0022Amount\u0022,\u0022quantity\u0022:\u0022Quantity\u0022,\u0022preview\u0022:\u0022Preview\u0022,\u0022previewEmpty\u0022:\u0022Nothing changes yet. Pick a change above.\u0022,\u0022previewRow\u0022:\u0022{0}\u0022,\u0022applyToProducts\u0022:\u0022Apply to {0} products\u0022,\u0022cancel\u0022:\u0022Cancel\u0022,\u0022actions\u0022:\u0022Actions\u0022,\u0022editProduct\u0022:\u0022Edit product\u0022,\u0022newProductTitle\u0022:\u0022New product\u0022,\u0022general\u0022:\u0022General\u0022,\u0022title\u0022:\u0022Title\u0022,\u0022description\u0022:\u0022Description\u0022,\u0022descriptionLabel\u0022:\u0022Product description\u0022,\u0022media\u0022:\u0022Media\u0022,\u0022pricing\u0022:\u0022Pricing\u0022,\u0022price\u0022:\u0022Price\u0022,\u0022compareAt\u0022:\u0022Compare-at price\u0022,\u0022compareAtHint\u0022:\u0022The old price shown struck through. Must be above the price.\u0022,\u0022cost\u0022:\u0022Cost per item\u0022,\u0022costHint\u0022:\u0022Only you see this.\u0022,\u0022margin\u0022:\u0022Margin\u0022,\u0022profit\u0022:\u0022Profit\u0022,\u0022markup\u0022:\u0022Markup\u0022,\u0022noMargin\u0022:\u0022Add a price and a cost to see the margin.\u0022,\u0022inventory\u0022:\u0022Inventory\u0022,\u0022sku\u0022:\u0022SKU\u0022,\u0022trackStock\u0022:\u0022Track stock\u0022,\u0022stockQty\u0022:\u0022In stock\u0022,\u0022backorder\u0022:\u0022Sell when out of stock\u0022,\u0022weight\u0022:\u0022Weight (grams)\u0022,\u0022organization\u0022:\u0022Organisation\u0022,\u0022brand\u0022:\u0022Brand\u0022,\u0022category\u0022:\u0022Category\u0022,\u0022tags\u0022:\u0022Tags\u0022,\u0022tagsPlaceholder\u0022:\u0022Add a tag\u0022,\u0022seo\u0022:\u0022Search listing\u0022,\u0022seoTitle\u0022:\u0022Page title\u0022,\u0022seoDescription\u0022:\u0022Meta description\u0022,\u0022slug\u0022:\u0022URL handle\u0022,\u0022slugHint\u0022:\u0022Lower-case letters, digits and dashes.\u0022,\u0022statusSection\u0022:\u0022Status and visibility\u0022,\u0022visibility\u0022:\u0022Visibility\u0022,\u0022visible\u0022:\u0022Visible in the store\u0022,\u0022hidden\u0022:\u0022Hidden from the store (link still works)\u0022,\u0022statusHint.active\u0022:\u0022Customers can buy it.\u0022,\u0022statusHint.draft\u0022:\u0022Only you can see it.\u0022,\u0022statusHint.archived\u0022:\u0022Kept for records, not sold.\u0022,\u0022save\u0022:\u0022Save product\u0022,\u0022saving\u0022:\u0022Saving\u0022,\u0022discard\u0022:\u0022Discard changes\u0022,\u0022unsaved\u0022:\u0022Unsaved changes\u0022,\u0022allSaved\u0022:\u0022All changes saved\u0022,\u0022saveFailed\u0022:\u0022That did not save. Try again.\u0022,\u0022fixIssues\u0022:\u0022{0} to fix before saving\u0022,\u0022issues.title\u0022:\u0022Add a title.\u0022,\u0022issues.price\u0022:\u0022Add a price.\u0022,\u0022issues.compare-at\u0022:\u0022Compare-at must be above the price.\u0022,\u0022issues.sku-duplicate\u0022:\u0022Two variants share a SKU.\u0022,\u0022issues.no-variants\u0022:\u0022Generate the variants for these options.\u0022,\u0022issues.too-many-variants\u0022:\u0022Too many variants. Remove an option value.\u0022,\u0022issues.slug\u0022:\u0022The URL handle has characters that are not allowed.\u0022,\u0022mediaLabel\u0022:\u0022Product images\u0022,\u0022addImage\u0022:\u0022Add image\u0022,\u0022imageUrl\u0022:\u0022Image URL\u0022,\u0022imageUrlPlaceholder\u0022:\u0022https:\\\/\\\/\\u2026\u0022,\u0022altText\u0022:\u0022Alt text\u0022,\u0022altHint\u0022:\u0022Describe the picture for people who cannot see it.\u0022,\u0022missingAlt\u0022:\u0022Alt text missing\u0022,\u0022primary\u0022:\u0022Main image\u0022,\u0022moveEarlier\u0022:\u0022Move earlier\u0022,\u0022moveLater\u0022:\u0022Move later\u0022,\u0022removeImage\u0022:\u0022Remove image\u0022,\u0022dragHandle\u0022:\u0022Reorder image {0}\u0022,\u0022movedTo\u0022:\u0022Image moved to position {0} of {1}\u0022,\u0022noImages\u0022:\u0022No images yet\u0022,\u0022noImagesHint\u0022:\u0022Add a picture by its URL. The first one is the main image.\u0022,\u0022imageFailed\u0022:\u0022Image did not load\u0022,\u0022optionsTitle\u0022:\u0022Options\u0022,\u0022optionsHint\u0022:\u0022Colour, size, material. Up to three options.\u0022,\u0022addOption\u0022:\u0022Add option\u0022,\u0022removeOption\u0022:\u0022Remove option\u0022,\u0022optionName\u0022:\u0022Option name\u0022,\u0022optionNamePlaceholder\u0022:\u0022Size\u0022,\u0022optionValues\u0022:\u0022Values\u0022,\u0022optionValuesPlaceholder\u0022:\u0022Add a value\u0022,\u0022variantsTitle\u0022:\u0022Variants\u0022,\u0022variantsSummary\u0022:\u0022{0} variants\u0022,\u0022variantsRemoved\u0022:\u0022{0} variants no longer match and were removed.\u0022,\u0022variantsTruncated\u0022:\u0022More than {0} combinations. Only the first {0} are created.\u0022,\u0022variantLabel\u0022:\u0022Variant\u0022,\u0022skuCol\u0022:\u0022SKU\u0022,\u0022priceCol2\u0022:\u0022Price\u0022,\u0022compareCol\u0022:\u0022Compare-at\u0022,\u0022stockCol2\u0022:\u0022Stock\u0022,\u0022imageCol\u0022:\u0022Image\u0022,\u0022noImage\u0022:\u0022No image\u0022,\u0022bulkFill\u0022:\u0022Fill selected variants\u0022,\u0022selectVariants\u0022:\u0022Select variants to fill them at once.\u0022,\u0022selectAll\u0022:\u0022Select all variants\u0022,\u0022selectVariant\u0022:\u0022Select {0}\u0022,\u0022fillPrice\u0022:\u0022Price\u0022,\u0022fillCompare\u0022:\u0022Compare-at\u0022,\u0022fillStock\u0022:\u0022Stock\u0022,\u0022fillAddStock\u0022:\u0022Add stock\u0022,\u0022fillSkuPrefix\u0022:\u0022SKU prefix\u0022,\u0022fillApply\u0022:\u0022Apply to selected\u0022,\u0022fillClear\u0022:\u0022Clear selection\u0022,\u0022variantsSelected\u0022:\u0022{0} selected\u0022,\u0022dupSku\u0022:\u0022Duplicate SKU\u0022,\u0022variantsEmpty\u0022:\u0022Add an option to create variants.\u0022,\u0022collections\u0022:\u0022Collections\u0022,\u0022newCollection\u0022:\u0022New collection\u0022,\u0022collectionsLabel\u0022:\u0022Collections\u0022,\u0022collectionTitle\u0022:\u0022Collection title\u0022,\u0022manual\u0022:\u0022Manual\u0022,\u0022rules\u0022:\u0022Rules\u0022,\u0022kindLabel\u0022:\u0022How products join\u0022,\u0022manualHint\u0022:\u0022Pick the products yourself, in the order you want them.\u0022,\u0022rulesHint\u0022:\u0022Products join on their own when they match the rules.\u0022,\u0022matchPreview\u0022:\u0022{0} products match\u0022,\u0022matchNone\u0022:\u0022No products match yet.\u0022,\u0022matchPreviewLabel\u0022:\u0022Products in this collection\u0022,\u0022addProducts\u0022:\u0022Add products\u0022,\u0022addProduct\u0022:\u0022Add a product\u0022,\u0022pickProduct\u0022:\u0022Choose a product\u0022,\u0022removeFromCollection\u0022:\u0022Remove from collection\u0022,\u0022moveUp\u0022:\u0022Move up\u0022,\u0022moveDown\u0022:\u0022Move down\u0022,\u0022saveCollection\u0022:\u0022Save collection\u0022,\u0022deleteCollection\u0022:\u0022Delete collection\u0022,\u0022deleteCollectionTitle\u0022:\u0022Delete this collection?\u0022,\u0022deleteCollectionDescription\u0022:\u0022{0} is removed. The products stay in your catalogue.\u0022,\u0022collectionsEmpty\u0022:\u0022No collections yet\u0022,\u0022collectionsEmptyHint\u0022:\u0022Group products so customers can browse them together.\u0022,\u0022productsCount\u0022:\u0022{0} products\u0022,\u0022ruleAnyProduct\u0022:\u0022any product\u0022,\u0022ruleAddIt\u0022:\u0022add it to this collection\u0022,\u0022ruleEventLabel\u0022:\u0022Applies to\u0022,\u0022ruleEventHelp\u0022:\u0022Every active product is checked against the conditions below.\u0022,\u0022ruleIfTitle\u0022:\u0022Products that match\u0022,\u0022ruleIfHelp\u0022:\u0022Add conditions. A product joins when they hold. With none, no product joins.\u0022,\u0022ruleThenTitle\u0022:\u0022Result\u0022,\u0022ruleThenHelp\u0022:\u0022Matching products are added to this collection.\u0022,\u0022ruleAction\u0022:\u0022Add it to this collection\u0022,\u0022ruleWhere\u0022:\u0022where\u0022,\u0022ruleSo\u0022:\u0022so\u0022,\u0022and\u0022:\u0022and\u0022,\u0022or\u0022:\u0022or\u0022,\u0022editCollection\u0022:\u0022Edit collection\u0022,\u0022fields.tag\u0022:\u0022Tag\u0022,\u0022fields.brand\u0022:\u0022Brand\u0022,\u0022fields.category\u0022:\u0022Category\u0022,\u0022fields.title\u0022:\u0022Title\u0022,\u0022fields.price\u0022:\u0022Price\u0022,\u0022fields.stock\u0022:\u0022Stock\u0022,\u0022fields.onSale\u0022:\u0022On sale\u0022,\u0022fields.status\u0022:\u0022Status\u0022,\u0022close\u0022:\u0022Close\u0022},\u0022loading\u0022:false,\u0022canCancel\u0022:true}'))" x-on:submit.prevent="save()" x-bind:aria-busy="loading ? `true` : null"
    class="flex min-w-0 flex-col gap-4">
    <div x-show="loading" class="grid gap-3">
        <div data-slot="skeleton" aria-hidden="true" class="rounded-[4px] bg-secondary motion-safe:animate-pulse h-10"></div>
<div data-slot="skeleton" aria-hidden="true" class="rounded-[4px] bg-secondary motion-safe:animate-pulse h-40"></div>
<div data-slot="skeleton" aria-hidden="true" class="rounded-[4px] bg-secondary motion-safe:animate-pulse h-40"></div>
    </div>
    <div x-show="! loading" class="grid min-w-0 gap-4">
        <h2 class="text-h3 text-foreground" x-text="isNew ? t.newProductTitle : t.editProduct"></h2>
        <section class="grid gap-4 rounded-card border border-border bg-card p-4" aria-label="General">
            <h3 class="text-h4 text-foreground">General</h3>
            <div class="grid gap-1">
                <label class="text-label text-foreground" for="product-title">Title</label>
                <input data-slot="input" type="text"
                    id="product-title" x-model="draft.title" x-bind:aria-invalid="showTitleError ? `true` : null" class="w-full min-w-0 rounded-control border border-input bg-card px-3 text-body text-foreground min-h-[var(--nq-touch-min,0px)] transition-colors duration-150 ease-nq outline-none placeholder:text-muted-foreground focus-visible:border-nq-focus focus-visible:outline-1 focus-visible:outline-nq-focus data-invalid:border-nq-danger aria-invalid:border-nq-danger disabled:cursor-not-allowed disabled:opacity-50 pointer-coarse:text-[16px] h-control">
                <p x-show="showTitleError" class="text-body-sm text-nq-danger-text">Add a title.</p>
            </div>
            <div class="grid gap-1">
                <span class="text-label text-foreground">Description</span>
                                    <div data-slot="rich-text-editor" x-data="nqRichText('', JSON.parse('{\u0022ariaLabel\u0022:\u0022Product description\u0022}'))" x-modelable="value"     x-model="draft.description" class="flex min-w-0 flex-col overflow-hidden rounded-control border border-input bg-card text-foreground transition-colors duration-150 ease-nq focus-within:border-nq-focus focus-within:outline-1 focus-within:outline-nq-focus">
            <div role="toolbar" aria-label="Formatting" data-slot="rich-text-editor-toolbar" class="flex flex-wrap items-center gap-1 border-b border-border bg-card p-1.5">
                                            <div role="group" data-slot="toggle-group" data-multiple class="flex w-fit max-w-full rounded-control bg-transparent p-0">
                                            <button type="button" data-slot="toggle" aria-label="Bold" title="Bold" x-on:mousedown.prevent x-on:click="run('bold')"
                            :aria-pressed="on('bold') ? 'true' : 'false'" :data-pressed="on('bold') ? '' : undefined" :disabled="!ready" class="inline-flex size-control-sm shrink-0 items-center justify-center whitespace-nowrap rounded-[calc(var(--radius-control)-2px)] px-0 text-label text-muted-foreground outline-none transition-colors duration-150 ease-nq hover:text-foreground focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-nq-focus disabled:pointer-events-none disabled:opacity-50 data-pressed:bg-card data-pressed:text-foreground data-pressed:shadow-xs [&amp;_svg]:size-4 [&amp;_svg]:shrink-0">
                            <svg class="size-4" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <path d="M6 12h9a4 4 0 0 1 0 8H7a1 1 0 0 1-1-1V5a1 1 0 0 1 1-1h7a4 4 0 0 1 0 8"/>
</svg>                        </button>
                                            <button type="button" data-slot="toggle" aria-label="Italic" title="Italic" x-on:mousedown.prevent x-on:click="run('italic')"
                            :aria-pressed="on('italic') ? 'true' : 'false'" :data-pressed="on('italic') ? '' : undefined" :disabled="!ready" class="inline-flex size-control-sm shrink-0 items-center justify-center whitespace-nowrap rounded-[calc(var(--radius-control)-2px)] px-0 text-label text-muted-foreground outline-none transition-colors duration-150 ease-nq hover:text-foreground focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-nq-focus disabled:pointer-events-none disabled:opacity-50 data-pressed:bg-card data-pressed:text-foreground data-pressed:shadow-xs [&amp;_svg]:size-4 [&amp;_svg]:shrink-0">
                            <svg class="size-4" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <line x1="19" x2="10" y1="4" y2="4"/>
  <line x1="14" x2="5" y1="20" y2="20"/>
  <line x1="15" x2="9" y1="4" y2="20"/>
</svg>                        </button>
                                            <button type="button" data-slot="toggle" aria-label="Underline" title="Underline" x-on:mousedown.prevent x-on:click="run('underline')"
                            :aria-pressed="on('underline') ? 'true' : 'false'" :data-pressed="on('underline') ? '' : undefined" :disabled="!ready" class="inline-flex size-control-sm shrink-0 items-center justify-center whitespace-nowrap rounded-[calc(var(--radius-control)-2px)] px-0 text-label text-muted-foreground outline-none transition-colors duration-150 ease-nq hover:text-foreground focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-nq-focus disabled:pointer-events-none disabled:opacity-50 data-pressed:bg-card data-pressed:text-foreground data-pressed:shadow-xs [&amp;_svg]:size-4 [&amp;_svg]:shrink-0">
                            <svg class="size-4" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <path d="M6 4v6a6 6 0 0 0 12 0V4"/>
  <line x1="4" x2="20" y1="20" y2="20"/>
</svg>                        </button>
                                            <button type="button" data-slot="toggle" aria-label="Strikethrough" title="Strikethrough" x-on:mousedown.prevent x-on:click="run('strike')"
                            :aria-pressed="on('strike') ? 'true' : 'false'" :data-pressed="on('strike') ? '' : undefined" :disabled="!ready" class="inline-flex size-control-sm shrink-0 items-center justify-center whitespace-nowrap rounded-[calc(var(--radius-control)-2px)] px-0 text-label text-muted-foreground outline-none transition-colors duration-150 ease-nq hover:text-foreground focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-nq-focus disabled:pointer-events-none disabled:opacity-50 data-pressed:bg-card data-pressed:text-foreground data-pressed:shadow-xs [&amp;_svg]:size-4 [&amp;_svg]:shrink-0">
                            <svg class="size-4" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <path d="M16 4H9a3 3 0 0 0-2.83 4"/>
  <path d="M14 12a4 4 0 0 1 0 8H6"/>
  <line x1="4" x2="20" y1="12" y2="12"/>
</svg>                        </button>
                                            <button type="button" data-slot="toggle" aria-label="Code" title="Code" x-on:mousedown.prevent x-on:click="run('code')"
                            :aria-pressed="on('code') ? 'true' : 'false'" :data-pressed="on('code') ? '' : undefined" :disabled="!ready" class="inline-flex size-control-sm shrink-0 items-center justify-center whitespace-nowrap rounded-[calc(var(--radius-control)-2px)] px-0 text-label text-muted-foreground outline-none transition-colors duration-150 ease-nq hover:text-foreground focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-nq-focus disabled:pointer-events-none disabled:opacity-50 data-pressed:bg-card data-pressed:text-foreground data-pressed:shadow-xs [&amp;_svg]:size-4 [&amp;_svg]:shrink-0">
                            <svg class="size-4" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <path d="m16 18 6-6-6-6"/>
  <path d="m8 6-6 6 6 6"/>
</svg>                        </button>
                                    </div>
                            <div data-slot="separator" role="separator" data-orientation="vertical"
     aria-orientation="vertical"     class="shrink-0 bg-border h-4 w-px self-center"></div>
                <div role="group" data-slot="toggle-group" data-multiple class="flex w-fit max-w-full rounded-control bg-transparent p-0">
                                            <button type="button" data-slot="toggle" aria-label="Heading 1" title="Heading 1" x-on:mousedown.prevent x-on:click="run('h1')"
                            :aria-pressed="on('h1') ? 'true' : 'false'" :data-pressed="on('h1') ? '' : undefined" :disabled="!ready" class="inline-flex size-control-sm shrink-0 items-center justify-center whitespace-nowrap rounded-[calc(var(--radius-control)-2px)] px-0 text-label text-muted-foreground outline-none transition-colors duration-150 ease-nq hover:text-foreground focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-nq-focus disabled:pointer-events-none disabled:opacity-50 data-pressed:bg-card data-pressed:text-foreground data-pressed:shadow-xs [&amp;_svg]:size-4 [&amp;_svg]:shrink-0">
                            <svg class="size-4" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <path d="M4 12h8"/>
  <path d="M4 18V6"/>
  <path d="M12 18V6"/>
  <path d="m17 12 3-2v8"/>
</svg>                        </button>
                                            <button type="button" data-slot="toggle" aria-label="Heading 2" title="Heading 2" x-on:mousedown.prevent x-on:click="run('h2')"
                            :aria-pressed="on('h2') ? 'true' : 'false'" :data-pressed="on('h2') ? '' : undefined" :disabled="!ready" class="inline-flex size-control-sm shrink-0 items-center justify-center whitespace-nowrap rounded-[calc(var(--radius-control)-2px)] px-0 text-label text-muted-foreground outline-none transition-colors duration-150 ease-nq hover:text-foreground focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-nq-focus disabled:pointer-events-none disabled:opacity-50 data-pressed:bg-card data-pressed:text-foreground data-pressed:shadow-xs [&amp;_svg]:size-4 [&amp;_svg]:shrink-0">
                            <svg class="size-4" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <path d="M4 12h8"/>
  <path d="M4 18V6"/>
  <path d="M12 18V6"/>
  <path d="M21 18h-4c0-4 4-3 4-6 0-1.5-2-2.5-4-1"/>
</svg>                        </button>
                                            <button type="button" data-slot="toggle" aria-label="Heading 3" title="Heading 3" x-on:mousedown.prevent x-on:click="run('h3')"
                            :aria-pressed="on('h3') ? 'true' : 'false'" :data-pressed="on('h3') ? '' : undefined" :disabled="!ready" class="inline-flex size-control-sm shrink-0 items-center justify-center whitespace-nowrap rounded-[calc(var(--radius-control)-2px)] px-0 text-label text-muted-foreground outline-none transition-colors duration-150 ease-nq hover:text-foreground focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-nq-focus disabled:pointer-events-none disabled:opacity-50 data-pressed:bg-card data-pressed:text-foreground data-pressed:shadow-xs [&amp;_svg]:size-4 [&amp;_svg]:shrink-0">
                            <svg class="size-4" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <path d="M4 12h8"/>
  <path d="M4 18V6"/>
  <path d="M12 18V6"/>
  <path d="M17.5 10.5c1.7-1 3.5 0 3.5 1.5a2 2 0 0 1-2 2"/>
  <path d="M17 17.5c2 1.5 4 .3 4-1.5a2 2 0 0 0-2-2"/>
</svg>                        </button>
                                            <button type="button" data-slot="toggle" aria-label="Bulleted list" title="Bulleted list" x-on:mousedown.prevent x-on:click="run('bulletList')"
                            :aria-pressed="on('bulletList') ? 'true' : 'false'" :data-pressed="on('bulletList') ? '' : undefined" :disabled="!ready" class="inline-flex size-control-sm shrink-0 items-center justify-center whitespace-nowrap rounded-[calc(var(--radius-control)-2px)] px-0 text-label text-muted-foreground outline-none transition-colors duration-150 ease-nq hover:text-foreground focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-nq-focus disabled:pointer-events-none disabled:opacity-50 data-pressed:bg-card data-pressed:text-foreground data-pressed:shadow-xs [&amp;_svg]:size-4 [&amp;_svg]:shrink-0">
                            <svg class="size-4" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <path d="M3 5h.01"/>
  <path d="M3 12h.01"/>
  <path d="M3 19h.01"/>
  <path d="M8 5h13"/>
  <path d="M8 12h13"/>
  <path d="M8 19h13"/>
</svg>                        </button>
                                            <button type="button" data-slot="toggle" aria-label="Numbered list" title="Numbered list" x-on:mousedown.prevent x-on:click="run('orderedList')"
                            :aria-pressed="on('orderedList') ? 'true' : 'false'" :data-pressed="on('orderedList') ? '' : undefined" :disabled="!ready" class="inline-flex size-control-sm shrink-0 items-center justify-center whitespace-nowrap rounded-[calc(var(--radius-control)-2px)] px-0 text-label text-muted-foreground outline-none transition-colors duration-150 ease-nq hover:text-foreground focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-nq-focus disabled:pointer-events-none disabled:opacity-50 data-pressed:bg-card data-pressed:text-foreground data-pressed:shadow-xs [&amp;_svg]:size-4 [&amp;_svg]:shrink-0">
                            <svg class="size-4" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <path d="M11 5h10"/>
  <path d="M11 12h10"/>
  <path d="M11 19h10"/>
  <path d="M4 4h1v5"/>
  <path d="M4 9h2"/>
  <path d="M6.5 20H3.4c0-1 2.6-1.925 2.6-3.5a1.5 1.5 0 0 0-2.6-1.02"/>
</svg>                        </button>
                                            <button type="button" data-slot="toggle" aria-label="Quote" title="Quote" x-on:mousedown.prevent x-on:click="run('blockquote')"
                            :aria-pressed="on('blockquote') ? 'true' : 'false'" :data-pressed="on('blockquote') ? '' : undefined" :disabled="!ready" class="inline-flex size-control-sm shrink-0 items-center justify-center whitespace-nowrap rounded-[calc(var(--radius-control)-2px)] px-0 text-label text-muted-foreground outline-none transition-colors duration-150 ease-nq hover:text-foreground focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-nq-focus disabled:pointer-events-none disabled:opacity-50 data-pressed:bg-card data-pressed:text-foreground data-pressed:shadow-xs [&amp;_svg]:size-4 [&amp;_svg]:shrink-0">
                            <svg class="size-4" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <path d="M16 3a2 2 0 0 0-2 2v6a2 2 0 0 0 2 2 1 1 0 0 1 1 1v1a2 2 0 0 1-2 2 1 1 0 0 0-1 1v2a1 1 0 0 0 1 1 6 6 0 0 0 6-6V5a2 2 0 0 0-2-2z"/>
  <path d="M5 3a2 2 0 0 0-2 2v6a2 2 0 0 0 2 2 1 1 0 0 1 1 1v1a2 2 0 0 1-2 2 1 1 0 0 0-1 1v2a1 1 0 0 0 1 1 6 6 0 0 0 6-6V5a2 2 0 0 0-2-2z"/>
</svg>                        </button>
                                    </div>
                                        <div data-slot="separator" role="separator" data-orientation="vertical"
     aria-orientation="vertical"     class="shrink-0 bg-border h-4 w-px self-center"></div>
                <div class="relative flex items-center gap-0.5">
                                            <button data-slot="button"
     type="button"                         aria-label="Link" title="Link" :aria-pressed="on(&#039;link&#039;) ? &#039;true&#039; : &#039;false&#039;" :data-pressed="on(&#039;link&#039;) ? &#039;&#039; : undefined" :aria-expanded="linkOpen ? &#039;true&#039; : &#039;false&#039;" :disabled="!ready" x-on:mousedown.prevent="x-on:mousedown.prevent" x-on:click="toggleLink()" class="inline-flex shrink-0 select-none items-center justify-center gap-2 whitespace-nowrap rounded-control border border-transparent font-sans text-label transition-colors duration-150 ease-nq min-h-[var(--nq-touch-min,0px)] outline-none focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-nq-focus disabled:pointer-events-none disabled:opacity-50 data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0 text-foreground hover:bg-nq-hover size-control-sm p-0 data-pressed:bg-nq-selected">
        <svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <path d="M9 17H7A5 5 0 0 1 7 7h2"/>
  <path d="M15 7h2a5 5 0 1 1 0 10h-2"/>
  <line x1="8" x2="16" y1="12" y2="12"/>
</svg></button>
                                                                <button data-slot="button"
     type="button"                         aria-label="Undo" title="Undo" :disabled="!canUndo()" x-on:mousedown.prevent="x-on:mousedown.prevent" x-on:click="undo()" class="inline-flex shrink-0 select-none items-center justify-center gap-2 whitespace-nowrap rounded-control border border-transparent font-sans text-label transition-colors duration-150 ease-nq min-h-[var(--nq-touch-min,0px)] outline-none focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-nq-focus disabled:pointer-events-none disabled:opacity-50 data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0 text-foreground hover:bg-nq-hover size-control-sm p-0">
        <svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <path d="M9 14 4 9l5-5"/>
  <path d="M4 9h10.5a5.5 5.5 0 0 1 5.5 5.5a5.5 5.5 0 0 1-5.5 5.5H11"/>
</svg></button>
                                                                <button data-slot="button"
     type="button"                         aria-label="Redo" title="Redo" :disabled="!canRedo()" x-on:mousedown.prevent="x-on:mousedown.prevent" x-on:click="redo()" class="inline-flex shrink-0 select-none items-center justify-center gap-2 whitespace-nowrap rounded-control border border-transparent font-sans text-label transition-colors duration-150 ease-nq min-h-[var(--nq-touch-min,0px)] outline-none focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-nq-focus disabled:pointer-events-none disabled:opacity-50 data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0 text-foreground hover:bg-nq-hover size-control-sm p-0">
        <svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <path d="m15 14 5-5-5-5"/>
  <path d="M20 9H9.5A5.5 5.5 0 0 0 4 14.5A5.5 5.5 0 0 0 9.5 20H13"/>
</svg></button>
                                                                <form x-show="linkOpen" x-cloak style="display: none" x-on:submit.prevent="applyLink()" x-on:keydown.escape="linkOpen = false" data-slot="rich-text-editor-link"
                            class="absolute start-0 top-full z-50 mt-1 flex w-72 flex-col gap-2 rounded-card border border-border bg-card p-3 shadow-floating">
                            <input data-slot="input" type="text"
     dir="ltr"                 x-model="linkUrl" inputmode="url" placeholder="https://" aria-label="Link address" x-on:input="linkError = false" :aria-invalid="linkError ? &#039;true&#039; : undefined" class="w-full min-w-0 rounded-control border border-input bg-card px-3 text-body text-foreground min-h-[var(--nq-touch-min,0px)] transition-colors duration-150 ease-nq outline-none placeholder:text-muted-foreground focus-visible:border-nq-focus focus-visible:outline-1 focus-visible:outline-nq-focus data-invalid:border-nq-danger aria-invalid:border-nq-danger disabled:cursor-not-allowed disabled:opacity-50 pointer-coarse:text-[16px] h-control text-start">
                            <div class="flex justify-end gap-2">
                                <button data-slot="button"
     type="button"                         x-show="on(&#039;link&#039;)" x-on:click="removeLink()" class="inline-flex shrink-0 select-none items-center justify-center gap-2 whitespace-nowrap rounded-control border border-transparent font-sans text-label transition-colors duration-150 ease-nq min-h-[var(--nq-touch-min,0px)] outline-none focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-nq-focus disabled:pointer-events-none disabled:opacity-50 data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0 text-foreground hover:bg-nq-hover h-control-sm px-2.5">
        Remove link</button>
                                <button data-slot="button"
     type="submit"                         class="inline-flex shrink-0 select-none items-center justify-center gap-2 whitespace-nowrap rounded-control border border-transparent font-sans text-label transition-colors duration-150 ease-nq min-h-[var(--nq-touch-min,0px)] outline-none focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-nq-focus disabled:pointer-events-none disabled:opacity-50 data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0 bg-primary text-primary-foreground hover:bg-[color-mix(in_oklab,var(--nq-action)_88%,var(--nq-fg))] h-control-sm px-2.5">
        Apply</button>
                            </div>
                        </form>
                                    </div>
                    </div>
        <div x-ref="host" style="min-height: 10rem" class="min-w-0 flex-1 cursor-text px-3 py-2.5 [&amp;_.tiptap]:min-h-[inherit] [&amp;_.tiptap]:outline-none [&amp;_.tiptap]:flex [&amp;_.tiptap]:flex-col [&amp;_.tiptap]:gap-3 [&amp;_.tiptap]:text-body [&amp;_.tiptap]:text-nq-fg-body [&amp;_.tiptap_p]:text-start [&amp;_.tiptap_p]:min-h-[1lh] [&amp;_.tiptap_h1]:text-h1 [&amp;_.tiptap_h1]:text-foreground [&amp;_.tiptap_h1]:text-start [&amp;_.tiptap_h2]:text-h2 [&amp;_.tiptap_h2]:text-foreground [&amp;_.tiptap_h2]:text-start [&amp;_.tiptap_h3]:text-h3 [&amp;_.tiptap_h3]:text-foreground [&amp;_.tiptap_h3]:text-start [&amp;_.tiptap_ul]:list-disc [&amp;_.tiptap_ol]:list-decimal [&amp;_.tiptap_ul]:ps-6 [&amp;_.tiptap_ol]:ps-6 [&amp;_.tiptap_ul]:space-y-1 [&amp;_.tiptap_ol]:space-y-1 [&amp;_.tiptap_li]:text-start [&amp;_.tiptap_li]:marker:text-muted-foreground [&amp;_.tiptap_blockquote]:border-s-2 [&amp;_.tiptap_blockquote]:border-nq-line-strong [&amp;_.tiptap_blockquote]:ps-4 [&amp;_.tiptap_blockquote]:text-muted-foreground [&amp;_.tiptap_blockquote]:text-start [&amp;_.tiptap_a]:rounded-[2px] [&amp;_.tiptap_a]:text-foreground [&amp;_.tiptap_a]:underline [&amp;_.tiptap_a]:decoration-nq-line-strong [&amp;_.tiptap_a]:underline-offset-4 [&amp;_.tiptap_strong]:font-semibold [&amp;_.tiptap_strong]:text-foreground [&amp;_.tiptap_code]:rounded-[4px] [&amp;_.tiptap_code]:bg-secondary [&amp;_.tiptap_code]:px-1 [&amp;_.tiptap_code]:font-mono [&amp;_.tiptap_code]:text-code"></div>
</div>
                            </div>
        </section>
        <section class="grid gap-4 rounded-card border border-border bg-card p-4" aria-label="Media">
            <section data-slot="media-manager" aria-label="Product images" x-data="nqMediaManager(JSON.parse('{\u0022images\u0022:[],\u0022maxImages\u0022:12,\u0022disabled\u0022:false,\u0022currency\u0022:\u0022USD\u0022,\u0022locale\u0022:\u0022en\u0022,\u0022t\u0022:{\u0022products\u0022:\u0022Products\u0022,\u0022newProduct\u0022:\u0022New product\u0022,\u0022searchProducts\u0022:\u0022Search products\u0022,\u0022productCol\u0022:\u0022Product\u0022,\u0022statusCol\u0022:\u0022Status\u0022,\u0022stockCol\u0022:\u0022Stock\u0022,\u0022priceCol\u0022:\u0022Price\u0022,\u0022variantsCol\u0022:\u0022Variants\u0022,\u0022categoryCol\u0022:\u0022Category\u0022,\u0022statuses.active\u0022:\u0022Active\u0022,\u0022statuses.draft\u0022:\u0022Draft\u0022,\u0022statuses.archived\u0022:\u0022Archived\u0022,\u0022stockLevels.in\u0022:\u0022In stock\u0022,\u0022stockLevels.low\u0022:\u0022Low stock\u0022,\u0022stockLevels.out\u0022:\u0022Out of stock\u0022,\u0022stockLevels.untracked\u0022:\u0022Not tracked\u0022,\u0022units\u0022:\u0022{0} in stock\u0022,\u0022variantCount\u0022:\u0022{0} variants\u0022,\u0022oneVariant\u0022:\u00221 variant\u0022,\u0022productListLabel\u0022:\u0022Products\u0022,\u0022noProducts\u0022:\u0022No products yet\u0022,\u0022noProductsHint\u0022:\u0022Add your first product to start selling.\u0022,\u0022loadFailed\u0022:\u0022Products did not load.\u0022,\u0022retry\u0022:\u0022Try again\u0022,\u0022edit\u0022:\u0022Edit\u0022,\u0022setActive\u0022:\u0022Set active\u0022,\u0022setDraft\u0022:\u0022Move to drafts\u0022,\u0022archive\u0022:\u0022Archive\u0022,\u0022delete\u0022:\u0022Delete\u0022,\u0022deleteTitle\u0022:\u0022Delete this product?\u0022,\u0022deleteDescription\u0022:\u0022{0} and its variants are removed. Past orders keep their copy.\u0022,\u0022selectedCount\u0022:\u0022{0} selected\u0022,\u0022bulkEdit\u0022:\u0022Bulk edit\u0022,\u0022bulkTitle\u0022:\u0022Edit {0} products\u0022,\u0022bulkDescription\u0022:\u0022Leave a section on Keep to leave it alone. Changes apply to every variant.\u0022,\u0022bulkPrice\u0022:\u0022Price\u0022,\u0022bulkStock\u0022:\u0022Stock\u0022,\u0022bulkStatus\u0022:\u0022Status\u0022,\u0022keep\u0022:\u0022Keep\u0022,\u0022priceModes.set\u0022:\u0022Set to\u0022,\u0022priceModes.increase-percent\u0022:\u0022Raise by percent\u0022,\u0022priceModes.decrease-percent\u0022:\u0022Lower by percent\u0022,\u0022priceModes.increase-amount\u0022:\u0022Raise by amount\u0022,\u0022priceModes.decrease-amount\u0022:\u0022Lower by amount\u0022,\u0022stockModes.set\u0022:\u0022Set to\u0022,\u0022stockModes.add\u0022:\u0022Add\u0022,\u0022stockModes.remove\u0022:\u0022Remove\u0022,\u0022alsoCompareAt\u0022:\u0022Move compare-at price the same way\u0022,\u0022percent\u0022:\u0022Percent\u0022,\u0022amount\u0022:\u0022Amount\u0022,\u0022quantity\u0022:\u0022Quantity\u0022,\u0022preview\u0022:\u0022Preview\u0022,\u0022previewEmpty\u0022:\u0022Nothing changes yet. Pick a change above.\u0022,\u0022previewRow\u0022:\u0022{0}\u0022,\u0022applyToProducts\u0022:\u0022Apply to {0} products\u0022,\u0022cancel\u0022:\u0022Cancel\u0022,\u0022actions\u0022:\u0022Actions\u0022,\u0022editProduct\u0022:\u0022Edit product\u0022,\u0022newProductTitle\u0022:\u0022New product\u0022,\u0022general\u0022:\u0022General\u0022,\u0022title\u0022:\u0022Title\u0022,\u0022description\u0022:\u0022Description\u0022,\u0022descriptionLabel\u0022:\u0022Product description\u0022,\u0022media\u0022:\u0022Media\u0022,\u0022pricing\u0022:\u0022Pricing\u0022,\u0022price\u0022:\u0022Price\u0022,\u0022compareAt\u0022:\u0022Compare-at price\u0022,\u0022compareAtHint\u0022:\u0022The old price shown struck through. Must be above the price.\u0022,\u0022cost\u0022:\u0022Cost per item\u0022,\u0022costHint\u0022:\u0022Only you see this.\u0022,\u0022margin\u0022:\u0022Margin\u0022,\u0022profit\u0022:\u0022Profit\u0022,\u0022markup\u0022:\u0022Markup\u0022,\u0022noMargin\u0022:\u0022Add a price and a cost to see the margin.\u0022,\u0022inventory\u0022:\u0022Inventory\u0022,\u0022sku\u0022:\u0022SKU\u0022,\u0022trackStock\u0022:\u0022Track stock\u0022,\u0022stockQty\u0022:\u0022In stock\u0022,\u0022backorder\u0022:\u0022Sell when out of stock\u0022,\u0022weight\u0022:\u0022Weight (grams)\u0022,\u0022organization\u0022:\u0022Organisation\u0022,\u0022brand\u0022:\u0022Brand\u0022,\u0022category\u0022:\u0022Category\u0022,\u0022tags\u0022:\u0022Tags\u0022,\u0022tagsPlaceholder\u0022:\u0022Add a tag\u0022,\u0022seo\u0022:\u0022Search listing\u0022,\u0022seoTitle\u0022:\u0022Page title\u0022,\u0022seoDescription\u0022:\u0022Meta description\u0022,\u0022slug\u0022:\u0022URL handle\u0022,\u0022slugHint\u0022:\u0022Lower-case letters, digits and dashes.\u0022,\u0022statusSection\u0022:\u0022Status and visibility\u0022,\u0022visibility\u0022:\u0022Visibility\u0022,\u0022visible\u0022:\u0022Visible in the store\u0022,\u0022hidden\u0022:\u0022Hidden from the store (link still works)\u0022,\u0022statusHint.active\u0022:\u0022Customers can buy it.\u0022,\u0022statusHint.draft\u0022:\u0022Only you can see it.\u0022,\u0022statusHint.archived\u0022:\u0022Kept for records, not sold.\u0022,\u0022save\u0022:\u0022Save product\u0022,\u0022saving\u0022:\u0022Saving\u0022,\u0022discard\u0022:\u0022Discard changes\u0022,\u0022unsaved\u0022:\u0022Unsaved changes\u0022,\u0022allSaved\u0022:\u0022All changes saved\u0022,\u0022saveFailed\u0022:\u0022That did not save. Try again.\u0022,\u0022fixIssues\u0022:\u0022{0} to fix before saving\u0022,\u0022issues.title\u0022:\u0022Add a title.\u0022,\u0022issues.price\u0022:\u0022Add a price.\u0022,\u0022issues.compare-at\u0022:\u0022Compare-at must be above the price.\u0022,\u0022issues.sku-duplicate\u0022:\u0022Two variants share a SKU.\u0022,\u0022issues.no-variants\u0022:\u0022Generate the variants for these options.\u0022,\u0022issues.too-many-variants\u0022:\u0022Too many variants. Remove an option value.\u0022,\u0022issues.slug\u0022:\u0022The URL handle has characters that are not allowed.\u0022,\u0022mediaLabel\u0022:\u0022Product images\u0022,\u0022addImage\u0022:\u0022Add image\u0022,\u0022imageUrl\u0022:\u0022Image URL\u0022,\u0022imageUrlPlaceholder\u0022:\u0022https:\\\/\\\/\\u2026\u0022,\u0022altText\u0022:\u0022Alt text\u0022,\u0022altHint\u0022:\u0022Describe the picture for people who cannot see it.\u0022,\u0022missingAlt\u0022:\u0022Alt text missing\u0022,\u0022primary\u0022:\u0022Main image\u0022,\u0022moveEarlier\u0022:\u0022Move earlier\u0022,\u0022moveLater\u0022:\u0022Move later\u0022,\u0022removeImage\u0022:\u0022Remove image\u0022,\u0022dragHandle\u0022:\u0022Reorder image {0}\u0022,\u0022movedTo\u0022:\u0022Image moved to position {0} of {1}\u0022,\u0022noImages\u0022:\u0022No images yet\u0022,\u0022noImagesHint\u0022:\u0022Add a picture by its URL. The first one is the main image.\u0022,\u0022imageFailed\u0022:\u0022Image did not load\u0022,\u0022optionsTitle\u0022:\u0022Options\u0022,\u0022optionsHint\u0022:\u0022Colour, size, material. Up to three options.\u0022,\u0022addOption\u0022:\u0022Add option\u0022,\u0022removeOption\u0022:\u0022Remove option\u0022,\u0022optionName\u0022:\u0022Option name\u0022,\u0022optionNamePlaceholder\u0022:\u0022Size\u0022,\u0022optionValues\u0022:\u0022Values\u0022,\u0022optionValuesPlaceholder\u0022:\u0022Add a value\u0022,\u0022variantsTitle\u0022:\u0022Variants\u0022,\u0022variantsSummary\u0022:\u0022{0} variants\u0022,\u0022variantsRemoved\u0022:\u0022{0} variants no longer match and were removed.\u0022,\u0022variantsTruncated\u0022:\u0022More than {0} combinations. Only the first {0} are created.\u0022,\u0022variantLabel\u0022:\u0022Variant\u0022,\u0022skuCol\u0022:\u0022SKU\u0022,\u0022priceCol2\u0022:\u0022Price\u0022,\u0022compareCol\u0022:\u0022Compare-at\u0022,\u0022stockCol2\u0022:\u0022Stock\u0022,\u0022imageCol\u0022:\u0022Image\u0022,\u0022noImage\u0022:\u0022No image\u0022,\u0022bulkFill\u0022:\u0022Fill selected variants\u0022,\u0022selectVariants\u0022:\u0022Select variants to fill them at once.\u0022,\u0022selectAll\u0022:\u0022Select all variants\u0022,\u0022selectVariant\u0022:\u0022Select {0}\u0022,\u0022fillPrice\u0022:\u0022Price\u0022,\u0022fillCompare\u0022:\u0022Compare-at\u0022,\u0022fillStock\u0022:\u0022Stock\u0022,\u0022fillAddStock\u0022:\u0022Add stock\u0022,\u0022fillSkuPrefix\u0022:\u0022SKU prefix\u0022,\u0022fillApply\u0022:\u0022Apply to selected\u0022,\u0022fillClear\u0022:\u0022Clear selection\u0022,\u0022variantsSelected\u0022:\u0022{0} selected\u0022,\u0022dupSku\u0022:\u0022Duplicate SKU\u0022,\u0022variantsEmpty\u0022:\u0022Add an option to create variants.\u0022,\u0022collections\u0022:\u0022Collections\u0022,\u0022newCollection\u0022:\u0022New collection\u0022,\u0022collectionsLabel\u0022:\u0022Collections\u0022,\u0022collectionTitle\u0022:\u0022Collection title\u0022,\u0022manual\u0022:\u0022Manual\u0022,\u0022rules\u0022:\u0022Rules\u0022,\u0022kindLabel\u0022:\u0022How products join\u0022,\u0022manualHint\u0022:\u0022Pick the products yourself, in the order you want them.\u0022,\u0022rulesHint\u0022:\u0022Products join on their own when they match the rules.\u0022,\u0022matchPreview\u0022:\u0022{0} products match\u0022,\u0022matchNone\u0022:\u0022No products match yet.\u0022,\u0022matchPreviewLabel\u0022:\u0022Products in this collection\u0022,\u0022addProducts\u0022:\u0022Add products\u0022,\u0022addProduct\u0022:\u0022Add a product\u0022,\u0022pickProduct\u0022:\u0022Choose a product\u0022,\u0022removeFromCollection\u0022:\u0022Remove from collection\u0022,\u0022moveUp\u0022:\u0022Move up\u0022,\u0022moveDown\u0022:\u0022Move down\u0022,\u0022saveCollection\u0022:\u0022Save collection\u0022,\u0022deleteCollection\u0022:\u0022Delete collection\u0022,\u0022deleteCollectionTitle\u0022:\u0022Delete this collection?\u0022,\u0022deleteCollectionDescription\u0022:\u0022{0} is removed. The products stay in your catalogue.\u0022,\u0022collectionsEmpty\u0022:\u0022No collections yet\u0022,\u0022collectionsEmptyHint\u0022:\u0022Group products so customers can browse them together.\u0022,\u0022productsCount\u0022:\u0022{0} products\u0022,\u0022ruleAnyProduct\u0022:\u0022any product\u0022,\u0022ruleAddIt\u0022:\u0022add it to this collection\u0022,\u0022ruleEventLabel\u0022:\u0022Applies to\u0022,\u0022ruleEventHelp\u0022:\u0022Every active product is checked against the conditions below.\u0022,\u0022ruleIfTitle\u0022:\u0022Products that match\u0022,\u0022ruleIfHelp\u0022:\u0022Add conditions. A product joins when they hold. With none, no product joins.\u0022,\u0022ruleThenTitle\u0022:\u0022Result\u0022,\u0022ruleThenHelp\u0022:\u0022Matching products are added to this collection.\u0022,\u0022ruleAction\u0022:\u0022Add it to this collection\u0022,\u0022ruleWhere\u0022:\u0022where\u0022,\u0022ruleSo\u0022:\u0022so\u0022,\u0022and\u0022:\u0022and\u0022,\u0022or\u0022:\u0022or\u0022,\u0022editCollection\u0022:\u0022Edit collection\u0022,\u0022fields.tag\u0022:\u0022Tag\u0022,\u0022fields.brand\u0022:\u0022Brand\u0022,\u0022fields.category\u0022:\u0022Category\u0022,\u0022fields.title\u0022:\u0022Title\u0022,\u0022fields.price\u0022:\u0022Price\u0022,\u0022fields.stock\u0022:\u0022Stock\u0022,\u0022fields.onSale\u0022:\u0022On sale\u0022,\u0022fields.status\u0022:\u0022Status\u0022,\u0022close\u0022:\u0022Close\u0022}}'))" x-modelable="images"
    x-model="draft.images" class="flex min-w-0 flex-col gap-3">
    <div class="flex flex-wrap items-center justify-between gap-2">
        <h3 class="text-label text-foreground">Media</h3>
        <span class="inline-flex items-center gap-1 text-caption text-nq-warning-text" x-show="missing > 0">
            <svg aria-hidden="true" class="size-3.5" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <path d="m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3"/>
  <path d="M12 9v4"/>
  <path d="M12 17h.01"/>
</svg>            <span x-text="`${num(missing)} · Alt text missing`"></span>
        </span>
    </div>
    <template x-if="images.length === 0">
        <div data-slot="empty-state" class="flex flex-col items-center justify-center gap-3 border border-border px-6 py-12 text-center rounded-card border-dashed">
            <span data-slot="state-icon" class="inline-flex size-10 items-center justify-center rounded-control border border-border bg-card [&amp;_svg]:size-5 text-muted-foreground">
            <svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <rect width="18" height="18" x="3" y="3" rx="2" ry="2"/>
  <circle cx="9" cy="9" r="2"/>
  <path d="m21 15-3.086-3.086a2 2 0 0 0-2.828 0L6 21"/>
</svg>        </span>
        <div class="flex max-w-sm flex-col gap-1">
        <p class="text-label text-foreground">No images yet</p>
                    <p class="text-body-sm text-muted-foreground">Add a picture by its URL. The first one is the main image.</p>
            </div>
    </div>
    </template>
    <ol x-show="images.length > 0" aria-label="Product images" class="grid gap-3 sm:grid-cols-2 lg:grid-cols-3">
        <template x-for="(im, i) in images" x-bind:key="im.src">
            <li data-slot="media-tile" x-bind:data-dragging="isDragging(i) ? '' : null" x-bind:style="tileStyle(i)" x-bind:class="tileClass(i)"
                class="grid min-w-0 gap-2 rounded-card border border-border bg-card p-2 transition-colors">
                <div class="relative aspect-square w-full overflow-hidden rounded-control bg-secondary">
                    <img alt="" x-show="imgOk(im.src)" x-bind:src="im.src" x-on:error="broken[im.src] = true" class="size-full object-cover" draggable="false" />
                    <div x-show="! imgOk(im.src)" class="flex size-full flex-col items-center justify-center gap-1 text-caption text-muted-foreground">
                        <svg aria-hidden="true" class="size-5" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <line x1="2" x2="22" y1="2" y2="22"/>
  <path d="M10.41 10.41a2 2 0 1 1-2.83-2.83"/>
  <line x1="13.5" x2="6" y1="13.5" y2="21"/>
  <line x1="18" x2="21" y1="12" y2="15"/>
  <path d="M3.59 3.59A1.99 1.99 0 0 0 3 5v14a2 2 0 0 0 2 2h14c.55 0 1.052-.22 1.41-.59"/>
  <path d="M21 15V5a2 2 0 0 0-2-2H9"/>
</svg>                        Image did not load
                    </div>
                    <span x-show="i === 0" data-slot="badge" class="absolute start-1.5 top-1.5 inline-flex h-5 items-center rounded-[4px] border border-primary bg-card px-1.5 text-caption font-medium text-foreground">Main image</span>
                    <button type="button" data-slot="media-drag-handle" x-bind:disabled="off" x-bind:aria-label="tt(`dragHandle`, i + 1)"
                        x-on:pointerdown="dragStart(i, $event)" x-on:keydown="handleKey(i, $event)"
                        class="absolute end-1.5 top-1.5 inline-flex size-7 cursor-grab touch-none items-center justify-center rounded-control border border-border bg-card text-muted-foreground outline-none hover:text-foreground focus-visible:outline-2 focus-visible:outline-nq-focus active:cursor-grabbing">
                        <svg aria-hidden="true" class="size-4" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <circle cx="9" cy="12" r="1"/>
  <circle cx="9" cy="5" r="1"/>
  <circle cx="9" cy="19" r="1"/>
  <circle cx="15" cy="12" r="1"/>
  <circle cx="15" cy="5" r="1"/>
  <circle cx="15" cy="19" r="1"/>
</svg>                    </button>
                </div>
                <div class="flex items-center gap-1">
                    <button data-slot="button"
     type="button"                         x-bind:disabled="off ? true : i === 0" x-bind:aria-label="`Move earlier`" x-on:click="move(i, i - 1)" class="inline-flex shrink-0 select-none items-center justify-center gap-2 whitespace-nowrap rounded-control border border-transparent font-sans text-label transition-colors duration-150 ease-nq min-h-[var(--nq-touch-min,0px)] outline-none focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-nq-focus disabled:pointer-events-none disabled:opacity-50 data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0 text-foreground hover:bg-nq-hover size-control-sm p-0">
        <svg aria-hidden="true" class="rtl:-scale-x-100" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <path d="m12 19-7-7 7-7"/>
  <path d="M19 12H5"/>
</svg></button>
                    <button data-slot="button"
     type="button"                         x-bind:disabled="off ? true : i === images.length - 1" x-bind:aria-label="`Move later`" x-on:click="move(i, i + 1)" class="inline-flex shrink-0 select-none items-center justify-center gap-2 whitespace-nowrap rounded-control border border-transparent font-sans text-label transition-colors duration-150 ease-nq min-h-[var(--nq-touch-min,0px)] outline-none focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-nq-focus disabled:pointer-events-none disabled:opacity-50 data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0 text-foreground hover:bg-nq-hover size-control-sm p-0">
        <svg aria-hidden="true" class="rtl:-scale-x-100" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <path d="M5 12h14"/>
  <path d="m12 5 7 7-7 7"/>
</svg></button>
                    <button data-slot="button"
     type="button"                         x-bind:disabled="off" x-bind:aria-label="`Remove image`" x-on:click="remove(i)" class="inline-flex shrink-0 select-none items-center justify-center gap-2 whitespace-nowrap rounded-control border border-transparent font-sans text-label transition-colors duration-150 ease-nq min-h-[var(--nq-touch-min,0px)] outline-none focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-nq-focus disabled:pointer-events-none disabled:opacity-50 data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0 text-foreground hover:bg-nq-hover size-control-sm p-0 ms-auto">
        <svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <path d="M10 11v6"/>
  <path d="M14 11v6"/>
  <path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6"/>
  <path d="M3 6h18"/>
  <path d="M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"/>
</svg></button>
                </div>
                <input type="text" aria-label="Alt text" placeholder="Alt text" x-bind:value="im.alt" x-bind:disabled="off" x-on:input="setAlt(i, $event.target.value)"
                    x-bind:aria-invalid="im.alt ? null : `true`"
                    class="h-control-sm w-full min-w-0 rounded-control border border-input bg-card px-2 text-body-sm text-foreground outline-none focus-visible:border-nq-focus aria-invalid:border-nq-warning" />
            </li>
        </template>
    </ol>
    <div class="flex flex-wrap items-end gap-2" x-on:keydown.enter.prevent="add()">
        <div class="grid min-w-48 flex-1 gap-1">
            <label class="text-caption text-muted-foreground" for="media-url-url">Image URL</label>
            <input id="media-url-url" type="url" dir="ltr" placeholder="https://…" x-model="url" x-bind:disabled="off ? true : full"
                class="h-control w-full min-w-0 rounded-control border border-input bg-card px-3 text-body text-foreground outline-none focus-visible:border-nq-focus" />
        </div>
        <button data-slot="button"
     type="button"                         x-bind:disabled="! canAdd" x-on:click="add()" class="inline-flex shrink-0 select-none items-center justify-center gap-2 whitespace-nowrap rounded-control border font-sans text-label transition-colors duration-150 ease-nq min-h-[var(--nq-touch-min,0px)] outline-none focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-nq-focus disabled:pointer-events-none disabled:opacity-50 data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0 border-border bg-card text-foreground hover:bg-nq-hover h-control px-[var(--nq-control-pad)]">
        <svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <path d="M5 12h14"/>
  <path d="M12 5v14"/>
</svg>            Add image</button>
    </div>
    <p role="status" aria-live="polite" class="sr-only" x-text="announce"></p>
</section>
        </section>
        <template x-if="showSingle">
            <section class="grid gap-4 rounded-card border border-border bg-card p-4" aria-label="Pricing">
                <h3 class="text-h4 text-foreground">Pricing</h3>
                <div class="grid gap-4 sm:grid-cols-3">
                    <div class="grid gap-1">
                        <span class="text-label text-foreground">Price</span>
                        <div data-slot="currency-input" data-currency="USD" x-data="nqCurrencyInput(null, JSON.parse('{\u0022currency\u0022:\u0022USD\u0022,\u0022locale\u0022:\u0022en\u0022}'))" x-modelable="minor" x-id="['nq-currency']"
    x-model="single.price" class="flex w-full min-w-0 flex-col gap-1">
    <div role="group" data-slot="input-group"
    x-bind="group" class="group/input-group flex h-control min-h-[var(--nq-touch-min,0px)] w-full min-w-0 items-center overflow-hidden rounded-control border border-input bg-card text-body text-foreground transition-colors duration-150 ease-nq focus-within:border-nq-focus focus-within:outline-1 focus-within:outline-nq-focus has-[[data-invalid]]:border-nq-danger has-[[aria-invalid=true]]:border-nq-danger has-[input:disabled]:cursor-not-allowed has-[input:disabled]:opacity-50"><div data-slot="currency-symbol" data-align="start" x-bind="symbolAddon"
            class="flex h-full shrink-0 items-center gap-1.5 text-body-sm text-muted-foreground [&amp;_svg]:size-4 order-first ps-3 pe-1">
            <span data-slot="input-group-text" class="select-none whitespace-nowrap"><bdi dir="ltr" x-text="mark()"></bdi></span>
        </div>
        <input data-slot="input-group-input" dir="ltr" x-bind="field" autocomplete="off" spellcheck="false"                           aria-label="Price" class="h-full min-w-0 flex-1 border-0 bg-transparent px-3 text-body text-foreground outline-none placeholder:text-muted-foreground disabled:cursor-not-allowed pointer-coarse:text-[16px] text-start tabular-nums"></div>
    <span x-show="out()" x-cloak style="display: none" :id="rangeId()" class="sr-only">Amount out of range</span>
    </div>
                        <p x-show="showPriceError" class="text-body-sm text-nq-danger-text">Add a price.</p>
                    </div>
                    <div class="grid gap-1">
                        <span class="text-label text-foreground">Compare-at price</span>
                        <div data-slot="currency-input" data-currency="USD" x-data="nqCurrencyInput(null, JSON.parse('{\u0022currency\u0022:\u0022USD\u0022,\u0022locale\u0022:\u0022en\u0022}'))" x-modelable="minor" x-id="['nq-currency']"
    x-model="single.compareAt" class="flex w-full min-w-0 flex-col gap-1">
    <div role="group" data-slot="input-group"
    x-bind="group" class="group/input-group flex h-control min-h-[var(--nq-touch-min,0px)] w-full min-w-0 items-center overflow-hidden rounded-control border border-input bg-card text-body text-foreground transition-colors duration-150 ease-nq focus-within:border-nq-focus focus-within:outline-1 focus-within:outline-nq-focus has-[[data-invalid]]:border-nq-danger has-[[aria-invalid=true]]:border-nq-danger has-[input:disabled]:cursor-not-allowed has-[input:disabled]:opacity-50"><div data-slot="currency-symbol" data-align="start" x-bind="symbolAddon"
            class="flex h-full shrink-0 items-center gap-1.5 text-body-sm text-muted-foreground [&amp;_svg]:size-4 order-first ps-3 pe-1">
            <span data-slot="input-group-text" class="select-none whitespace-nowrap"><bdi dir="ltr" x-text="mark()"></bdi></span>
        </div>
        <input data-slot="input-group-input" dir="ltr" x-bind="field" autocomplete="off" spellcheck="false"                           aria-label="Compare-at price" class="h-full min-w-0 flex-1 border-0 bg-transparent px-3 text-body text-foreground outline-none placeholder:text-muted-foreground disabled:cursor-not-allowed pointer-coarse:text-[16px] text-start tabular-nums"></div>
    <span x-show="out()" x-cloak style="display: none" :id="rangeId()" class="sr-only">Amount out of range</span>
    </div>
                        <p class="text-caption text-muted-foreground" x-show="! has(`compare-at`)">The old price shown struck through. Must be above the price.</p>
                        <p x-show="has(`compare-at`)" class="text-body-sm text-nq-danger-text">Compare-at must be above the price.</p>
                    </div>
                    <div class="grid gap-1">
                        <span class="text-label text-foreground">Cost per item</span>
                        <div data-slot="currency-input" data-currency="USD" x-data="nqCurrencyInput(null, JSON.parse('{\u0022currency\u0022:\u0022USD\u0022,\u0022locale\u0022:\u0022en\u0022}'))" x-modelable="minor" x-id="['nq-currency']"
    x-model="draft.cost" class="flex w-full min-w-0 flex-col gap-1">
    <div role="group" data-slot="input-group"
    x-bind="group" class="group/input-group flex h-control min-h-[var(--nq-touch-min,0px)] w-full min-w-0 items-center overflow-hidden rounded-control border border-input bg-card text-body text-foreground transition-colors duration-150 ease-nq focus-within:border-nq-focus focus-within:outline-1 focus-within:outline-nq-focus has-[[data-invalid]]:border-nq-danger has-[[aria-invalid=true]]:border-nq-danger has-[input:disabled]:cursor-not-allowed has-[input:disabled]:opacity-50"><div data-slot="currency-symbol" data-align="start" x-bind="symbolAddon"
            class="flex h-full shrink-0 items-center gap-1.5 text-body-sm text-muted-foreground [&amp;_svg]:size-4 order-first ps-3 pe-1">
            <span data-slot="input-group-text" class="select-none whitespace-nowrap"><bdi dir="ltr" x-text="mark()"></bdi></span>
        </div>
        <input data-slot="input-group-input" dir="ltr" x-bind="field" autocomplete="off" spellcheck="false"                           aria-label="Cost per item" class="h-full min-w-0 flex-1 border-0 bg-transparent px-3 text-body text-foreground outline-none placeholder:text-muted-foreground disabled:cursor-not-allowed pointer-coarse:text-[16px] text-start tabular-nums"></div>
    <span x-show="out()" x-cloak style="display: none" :id="rangeId()" class="sr-only">Amount out of range</span>
    </div>
                        <p class="text-caption text-muted-foreground">Only you see this.</p>
                    </div>
                </div>
                <div data-slot="product-margin" role="status" aria-live="polite" class="grid gap-1 rounded-control bg-nq-surface-soft p-3 text-body-sm">
                    <p class="text-muted-foreground" x-show="! hasMargin">Add a price and a cost to see the margin.</p>
                    <dl class="grid grid-cols-3 gap-3" x-show="hasMargin">
                        <div><dt class="text-caption text-muted-foreground">Profit</dt><dd class="tabular-nums" dir="ltr" x-text="profitText"></dd></div>
                        <div><dt class="text-caption text-muted-foreground">Margin</dt><dd class="tabular-nums" dir="ltr" x-bind:class="marginNegative ? `text-nq-danger-text` : ``" x-text="marginText"></dd></div>
                        <div><dt class="text-caption text-muted-foreground">Markup</dt><dd class="tabular-nums" dir="ltr" x-text="markupText"></dd></div>
                    </dl>
                </div>
            </section>
        </template>
        <template x-if="showSingle">
            <section class="grid gap-4 rounded-card border border-border bg-card p-4" aria-label="Inventory">
                <h3 class="text-h4 text-foreground">Inventory</h3>
                <div class="grid gap-4 sm:grid-cols-2">
                    <div class="grid gap-1">
                        <label class="text-label text-foreground" for="product-sku">SKU</label>
                        <input data-slot="input" type="text"
                    id="product-sku" dir="ltr" x-model="single.sku" class="w-full min-w-0 rounded-control border border-input bg-card px-3 text-body text-foreground min-h-[var(--nq-touch-min,0px)] transition-colors duration-150 ease-nq outline-none placeholder:text-muted-foreground focus-visible:border-nq-focus focus-visible:outline-1 focus-visible:outline-nq-focus data-invalid:border-nq-danger aria-invalid:border-nq-danger disabled:cursor-not-allowed disabled:opacity-50 pointer-coarse:text-[16px] h-control">
                    </div>
                    <div class="grid gap-1">
                        <label class="text-label text-foreground" for="product-weight">Weight (grams)</label>
                        <input id="product-weight" type="text" inputmode="numeric" x-bind:value="single.weightGrams ?? ''" x-on:input="setWeight($event.target.value)"
                            class="h-control w-full min-w-0 rounded-control border border-input bg-card px-3 text-body text-foreground outline-none focus-visible:border-nq-focus" />
                    </div>
                </div>
                <label class="flex items-center gap-2 text-body text-foreground">
                    <button type="button" role="switch" data-slot="switch" x-data="nqSwitch(false)" x-modelable="checked" x-bind="root"
    aria-checked="false"
     data-unchecked                 x-model="tracked" class="relative inline-flex h-5 w-9 shrink-0 items-center rounded-full border border-transparent bg-nq-line-strong p-0.5 outline-none transition-colors duration-150 ease-nq data-checked:bg-primary focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-nq-focus data-disabled:cursor-not-allowed data-disabled:opacity-50">
    <span data-slot="switch-thumb"  data-unchecked         x-bind:data-checked="checked ? '' : undefined" x-bind:data-unchecked="checked ? undefined : ''"
        class="block size-4 rounded-full bg-background shadow-xs data-checked:bg-primary-foreground transition-[translate] duration-150 ease-nq data-checked:translate-x-3.5 rtl:data-checked:-translate-x-3.5"></span>
    </button>
                    Track stock
                </label>
                <div class="grid gap-4 sm:grid-cols-2" x-show="tracked">
                    <div class="grid gap-1">
                        <label class="text-label text-foreground" for="product-stock">In stock</label>
                        <input id="product-stock" type="text" inputmode="numeric" x-bind:value="single.stock ?? ''" x-on:input="setStock($event.target.value)"
                            class="h-control w-full min-w-0 rounded-control border border-input bg-card px-3 text-body tabular-nums text-foreground outline-none focus-visible:border-nq-focus" />
                    </div>
                    <label class="flex items-center gap-2 self-end pb-2 text-body text-foreground">
                        <button type="button" role="switch" data-slot="switch" x-data="nqSwitch(false)" x-modelable="checked" x-bind="root"
    aria-checked="false"
     data-unchecked                 x-model="single.allowBackorder" class="relative inline-flex h-5 w-9 shrink-0 items-center rounded-full border border-transparent bg-nq-line-strong p-0.5 outline-none transition-colors duration-150 ease-nq data-checked:bg-primary focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-nq-focus data-disabled:cursor-not-allowed data-disabled:opacity-50">
    <span data-slot="switch-thumb"  data-unchecked         x-bind:data-checked="checked ? '' : undefined" x-bind:data-unchecked="checked ? undefined : ''"
        class="block size-4 rounded-full bg-background shadow-xs data-checked:bg-primary-foreground transition-[translate] duration-150 ease-nq data-checked:translate-x-3.5 rtl:data-checked:-translate-x-3.5"></span>
    </button>
                        Sell when out of stock
                    </label>
                </div>
            </section>
        </template>
        <section class="grid gap-4 rounded-card border border-border bg-card p-4" aria-label="Options">
            <section data-slot="options-editor" aria-label="Options" x-data="nqOptionsEditor(JSON.parse('{\u0022options\u0022:[],\u0022maxOptions\u0022:3,\u0022disabled\u0022:false,\u0022currency\u0022:\u0022USD\u0022,\u0022locale\u0022:\u0022en\u0022,\u0022t\u0022:{\u0022products\u0022:\u0022Products\u0022,\u0022newProduct\u0022:\u0022New product\u0022,\u0022searchProducts\u0022:\u0022Search products\u0022,\u0022productCol\u0022:\u0022Product\u0022,\u0022statusCol\u0022:\u0022Status\u0022,\u0022stockCol\u0022:\u0022Stock\u0022,\u0022priceCol\u0022:\u0022Price\u0022,\u0022variantsCol\u0022:\u0022Variants\u0022,\u0022categoryCol\u0022:\u0022Category\u0022,\u0022statuses.active\u0022:\u0022Active\u0022,\u0022statuses.draft\u0022:\u0022Draft\u0022,\u0022statuses.archived\u0022:\u0022Archived\u0022,\u0022stockLevels.in\u0022:\u0022In stock\u0022,\u0022stockLevels.low\u0022:\u0022Low stock\u0022,\u0022stockLevels.out\u0022:\u0022Out of stock\u0022,\u0022stockLevels.untracked\u0022:\u0022Not tracked\u0022,\u0022units\u0022:\u0022{0} in stock\u0022,\u0022variantCount\u0022:\u0022{0} variants\u0022,\u0022oneVariant\u0022:\u00221 variant\u0022,\u0022productListLabel\u0022:\u0022Products\u0022,\u0022noProducts\u0022:\u0022No products yet\u0022,\u0022noProductsHint\u0022:\u0022Add your first product to start selling.\u0022,\u0022loadFailed\u0022:\u0022Products did not load.\u0022,\u0022retry\u0022:\u0022Try again\u0022,\u0022edit\u0022:\u0022Edit\u0022,\u0022setActive\u0022:\u0022Set active\u0022,\u0022setDraft\u0022:\u0022Move to drafts\u0022,\u0022archive\u0022:\u0022Archive\u0022,\u0022delete\u0022:\u0022Delete\u0022,\u0022deleteTitle\u0022:\u0022Delete this product?\u0022,\u0022deleteDescription\u0022:\u0022{0} and its variants are removed. Past orders keep their copy.\u0022,\u0022selectedCount\u0022:\u0022{0} selected\u0022,\u0022bulkEdit\u0022:\u0022Bulk edit\u0022,\u0022bulkTitle\u0022:\u0022Edit {0} products\u0022,\u0022bulkDescription\u0022:\u0022Leave a section on Keep to leave it alone. Changes apply to every variant.\u0022,\u0022bulkPrice\u0022:\u0022Price\u0022,\u0022bulkStock\u0022:\u0022Stock\u0022,\u0022bulkStatus\u0022:\u0022Status\u0022,\u0022keep\u0022:\u0022Keep\u0022,\u0022priceModes.set\u0022:\u0022Set to\u0022,\u0022priceModes.increase-percent\u0022:\u0022Raise by percent\u0022,\u0022priceModes.decrease-percent\u0022:\u0022Lower by percent\u0022,\u0022priceModes.increase-amount\u0022:\u0022Raise by amount\u0022,\u0022priceModes.decrease-amount\u0022:\u0022Lower by amount\u0022,\u0022stockModes.set\u0022:\u0022Set to\u0022,\u0022stockModes.add\u0022:\u0022Add\u0022,\u0022stockModes.remove\u0022:\u0022Remove\u0022,\u0022alsoCompareAt\u0022:\u0022Move compare-at price the same way\u0022,\u0022percent\u0022:\u0022Percent\u0022,\u0022amount\u0022:\u0022Amount\u0022,\u0022quantity\u0022:\u0022Quantity\u0022,\u0022preview\u0022:\u0022Preview\u0022,\u0022previewEmpty\u0022:\u0022Nothing changes yet. Pick a change above.\u0022,\u0022previewRow\u0022:\u0022{0}\u0022,\u0022applyToProducts\u0022:\u0022Apply to {0} products\u0022,\u0022cancel\u0022:\u0022Cancel\u0022,\u0022actions\u0022:\u0022Actions\u0022,\u0022editProduct\u0022:\u0022Edit product\u0022,\u0022newProductTitle\u0022:\u0022New product\u0022,\u0022general\u0022:\u0022General\u0022,\u0022title\u0022:\u0022Title\u0022,\u0022description\u0022:\u0022Description\u0022,\u0022descriptionLabel\u0022:\u0022Product description\u0022,\u0022media\u0022:\u0022Media\u0022,\u0022pricing\u0022:\u0022Pricing\u0022,\u0022price\u0022:\u0022Price\u0022,\u0022compareAt\u0022:\u0022Compare-at price\u0022,\u0022compareAtHint\u0022:\u0022The old price shown struck through. Must be above the price.\u0022,\u0022cost\u0022:\u0022Cost per item\u0022,\u0022costHint\u0022:\u0022Only you see this.\u0022,\u0022margin\u0022:\u0022Margin\u0022,\u0022profit\u0022:\u0022Profit\u0022,\u0022markup\u0022:\u0022Markup\u0022,\u0022noMargin\u0022:\u0022Add a price and a cost to see the margin.\u0022,\u0022inventory\u0022:\u0022Inventory\u0022,\u0022sku\u0022:\u0022SKU\u0022,\u0022trackStock\u0022:\u0022Track stock\u0022,\u0022stockQty\u0022:\u0022In stock\u0022,\u0022backorder\u0022:\u0022Sell when out of stock\u0022,\u0022weight\u0022:\u0022Weight (grams)\u0022,\u0022organization\u0022:\u0022Organisation\u0022,\u0022brand\u0022:\u0022Brand\u0022,\u0022category\u0022:\u0022Category\u0022,\u0022tags\u0022:\u0022Tags\u0022,\u0022tagsPlaceholder\u0022:\u0022Add a tag\u0022,\u0022seo\u0022:\u0022Search listing\u0022,\u0022seoTitle\u0022:\u0022Page title\u0022,\u0022seoDescription\u0022:\u0022Meta description\u0022,\u0022slug\u0022:\u0022URL handle\u0022,\u0022slugHint\u0022:\u0022Lower-case letters, digits and dashes.\u0022,\u0022statusSection\u0022:\u0022Status and visibility\u0022,\u0022visibility\u0022:\u0022Visibility\u0022,\u0022visible\u0022:\u0022Visible in the store\u0022,\u0022hidden\u0022:\u0022Hidden from the store (link still works)\u0022,\u0022statusHint.active\u0022:\u0022Customers can buy it.\u0022,\u0022statusHint.draft\u0022:\u0022Only you can see it.\u0022,\u0022statusHint.archived\u0022:\u0022Kept for records, not sold.\u0022,\u0022save\u0022:\u0022Save product\u0022,\u0022saving\u0022:\u0022Saving\u0022,\u0022discard\u0022:\u0022Discard changes\u0022,\u0022unsaved\u0022:\u0022Unsaved changes\u0022,\u0022allSaved\u0022:\u0022All changes saved\u0022,\u0022saveFailed\u0022:\u0022That did not save. Try again.\u0022,\u0022fixIssues\u0022:\u0022{0} to fix before saving\u0022,\u0022issues.title\u0022:\u0022Add a title.\u0022,\u0022issues.price\u0022:\u0022Add a price.\u0022,\u0022issues.compare-at\u0022:\u0022Compare-at must be above the price.\u0022,\u0022issues.sku-duplicate\u0022:\u0022Two variants share a SKU.\u0022,\u0022issues.no-variants\u0022:\u0022Generate the variants for these options.\u0022,\u0022issues.too-many-variants\u0022:\u0022Too many variants. Remove an option value.\u0022,\u0022issues.slug\u0022:\u0022The URL handle has characters that are not allowed.\u0022,\u0022mediaLabel\u0022:\u0022Product images\u0022,\u0022addImage\u0022:\u0022Add image\u0022,\u0022imageUrl\u0022:\u0022Image URL\u0022,\u0022imageUrlPlaceholder\u0022:\u0022https:\\\/\\\/\\u2026\u0022,\u0022altText\u0022:\u0022Alt text\u0022,\u0022altHint\u0022:\u0022Describe the picture for people who cannot see it.\u0022,\u0022missingAlt\u0022:\u0022Alt text missing\u0022,\u0022primary\u0022:\u0022Main image\u0022,\u0022moveEarlier\u0022:\u0022Move earlier\u0022,\u0022moveLater\u0022:\u0022Move later\u0022,\u0022removeImage\u0022:\u0022Remove image\u0022,\u0022dragHandle\u0022:\u0022Reorder image {0}\u0022,\u0022movedTo\u0022:\u0022Image moved to position {0} of {1}\u0022,\u0022noImages\u0022:\u0022No images yet\u0022,\u0022noImagesHint\u0022:\u0022Add a picture by its URL. The first one is the main image.\u0022,\u0022imageFailed\u0022:\u0022Image did not load\u0022,\u0022optionsTitle\u0022:\u0022Options\u0022,\u0022optionsHint\u0022:\u0022Colour, size, material. Up to three options.\u0022,\u0022addOption\u0022:\u0022Add option\u0022,\u0022removeOption\u0022:\u0022Remove option\u0022,\u0022optionName\u0022:\u0022Option name\u0022,\u0022optionNamePlaceholder\u0022:\u0022Size\u0022,\u0022optionValues\u0022:\u0022Values\u0022,\u0022optionValuesPlaceholder\u0022:\u0022Add a value\u0022,\u0022variantsTitle\u0022:\u0022Variants\u0022,\u0022variantsSummary\u0022:\u0022{0} variants\u0022,\u0022variantsRemoved\u0022:\u0022{0} variants no longer match and were removed.\u0022,\u0022variantsTruncated\u0022:\u0022More than {0} combinations. Only the first {0} are created.\u0022,\u0022variantLabel\u0022:\u0022Variant\u0022,\u0022skuCol\u0022:\u0022SKU\u0022,\u0022priceCol2\u0022:\u0022Price\u0022,\u0022compareCol\u0022:\u0022Compare-at\u0022,\u0022stockCol2\u0022:\u0022Stock\u0022,\u0022imageCol\u0022:\u0022Image\u0022,\u0022noImage\u0022:\u0022No image\u0022,\u0022bulkFill\u0022:\u0022Fill selected variants\u0022,\u0022selectVariants\u0022:\u0022Select variants to fill them at once.\u0022,\u0022selectAll\u0022:\u0022Select all variants\u0022,\u0022selectVariant\u0022:\u0022Select {0}\u0022,\u0022fillPrice\u0022:\u0022Price\u0022,\u0022fillCompare\u0022:\u0022Compare-at\u0022,\u0022fillStock\u0022:\u0022Stock\u0022,\u0022fillAddStock\u0022:\u0022Add stock\u0022,\u0022fillSkuPrefix\u0022:\u0022SKU prefix\u0022,\u0022fillApply\u0022:\u0022Apply to selected\u0022,\u0022fillClear\u0022:\u0022Clear selection\u0022,\u0022variantsSelected\u0022:\u0022{0} selected\u0022,\u0022dupSku\u0022:\u0022Duplicate SKU\u0022,\u0022variantsEmpty\u0022:\u0022Add an option to create variants.\u0022,\u0022collections\u0022:\u0022Collections\u0022,\u0022newCollection\u0022:\u0022New collection\u0022,\u0022collectionsLabel\u0022:\u0022Collections\u0022,\u0022collectionTitle\u0022:\u0022Collection title\u0022,\u0022manual\u0022:\u0022Manual\u0022,\u0022rules\u0022:\u0022Rules\u0022,\u0022kindLabel\u0022:\u0022How products join\u0022,\u0022manualHint\u0022:\u0022Pick the products yourself, in the order you want them.\u0022,\u0022rulesHint\u0022:\u0022Products join on their own when they match the rules.\u0022,\u0022matchPreview\u0022:\u0022{0} products match\u0022,\u0022matchNone\u0022:\u0022No products match yet.\u0022,\u0022matchPreviewLabel\u0022:\u0022Products in this collection\u0022,\u0022addProducts\u0022:\u0022Add products\u0022,\u0022addProduct\u0022:\u0022Add a product\u0022,\u0022pickProduct\u0022:\u0022Choose a product\u0022,\u0022removeFromCollection\u0022:\u0022Remove from collection\u0022,\u0022moveUp\u0022:\u0022Move up\u0022,\u0022moveDown\u0022:\u0022Move down\u0022,\u0022saveCollection\u0022:\u0022Save collection\u0022,\u0022deleteCollection\u0022:\u0022Delete collection\u0022,\u0022deleteCollectionTitle\u0022:\u0022Delete this collection?\u0022,\u0022deleteCollectionDescription\u0022:\u0022{0} is removed. The products stay in your catalogue.\u0022,\u0022collectionsEmpty\u0022:\u0022No collections yet\u0022,\u0022collectionsEmptyHint\u0022:\u0022Group products so customers can browse them together.\u0022,\u0022productsCount\u0022:\u0022{0} products\u0022,\u0022ruleAnyProduct\u0022:\u0022any product\u0022,\u0022ruleAddIt\u0022:\u0022add it to this collection\u0022,\u0022ruleEventLabel\u0022:\u0022Applies to\u0022,\u0022ruleEventHelp\u0022:\u0022Every active product is checked against the conditions below.\u0022,\u0022ruleIfTitle\u0022:\u0022Products that match\u0022,\u0022ruleIfHelp\u0022:\u0022Add conditions. A product joins when they hold. With none, no product joins.\u0022,\u0022ruleThenTitle\u0022:\u0022Result\u0022,\u0022ruleThenHelp\u0022:\u0022Matching products are added to this collection.\u0022,\u0022ruleAction\u0022:\u0022Add it to this collection\u0022,\u0022ruleWhere\u0022:\u0022where\u0022,\u0022ruleSo\u0022:\u0022so\u0022,\u0022and\u0022:\u0022and\u0022,\u0022or\u0022:\u0022or\u0022,\u0022editCollection\u0022:\u0022Edit collection\u0022,\u0022fields.tag\u0022:\u0022Tag\u0022,\u0022fields.brand\u0022:\u0022Brand\u0022,\u0022fields.category\u0022:\u0022Category\u0022,\u0022fields.title\u0022:\u0022Title\u0022,\u0022fields.price\u0022:\u0022Price\u0022,\u0022fields.stock\u0022:\u0022Stock\u0022,\u0022fields.onSale\u0022:\u0022On sale\u0022,\u0022fields.status\u0022:\u0022Status\u0022,\u0022close\u0022:\u0022Close\u0022}}'))" x-modelable="options"
    x-model="draft.options" x-on:nq-options-change="changeOptions($event.detail.options)" class="flex min-w-0 flex-col gap-3">
    <div class="flex flex-wrap items-center justify-between gap-2">
        <div class="grid gap-0.5">
            <h3 class="text-label text-foreground">Options</h3>
            <p class="text-caption text-muted-foreground">Colour, size, material. Up to three options.</p>
        </div>
        <button data-slot="button"
     type="button"                         x-bind:disabled="! canAdd" x-on:click="add()" class="inline-flex shrink-0 select-none items-center justify-center gap-2 whitespace-nowrap rounded-control border font-sans text-label transition-colors duration-150 ease-nq min-h-[var(--nq-touch-min,0px)] outline-none focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-nq-focus disabled:pointer-events-none disabled:opacity-50 data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0 border-border bg-card text-foreground hover:bg-nq-hover h-control-sm px-2.5">
        <svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <path d="M5 12h14"/>
  <path d="M12 5v14"/>
</svg>            Add option</button>
    </div>
    <div class="grid gap-3">
        <template x-for="o in options" x-bind:key="o.id">
            <div data-slot="option-row" class="grid gap-2 rounded-card border border-border bg-card p-3 sm:grid-cols-[12rem_1fr_auto] sm:items-end"
                x-data="{ labels: [] }" x-effect="labels = reconcile(o, labels)">
                <div class="grid gap-1">
                    <label class="text-caption text-muted-foreground" x-bind:for="`opt-name-` + o.id">Option name</label>
                    <input type="text" x-bind:id="`opt-name-` + o.id" placeholder="Size" x-bind:value="o.name" x-bind:disabled="off" x-on:input="setName(o.id, $event.target.value)"
                        class="h-control w-full min-w-0 rounded-control border border-input bg-card px-3 text-body text-foreground outline-none focus-visible:border-nq-focus" />
                </div>
                <div class="grid gap-1">
                    <span class="text-caption text-muted-foreground">Values</span>
                    <div data-slot="tag-input" x-data="nqTagInput([], {})" x-modelable="tags" x-bind="root"
         x-model="labels" class="relative w-full">
    <div data-slot="tag-input-box" x-bind="box"
        class="flex w-full min-w-0 flex-wrap items-center gap-1.5 rounded-control border border-input bg-card px-2 py-1 text-body text-foreground min-h-[max(var(--nq-control),var(--nq-touch-min,0px))] transition-colors duration-150 ease-nq focus-within:border-nq-focus focus-within:outline-1 focus-within:outline-nq-focus has-[[data-invalid]]:border-nq-danger has-[[aria-invalid=true]]:border-nq-danger">
        <template x-for="(tag, i) in tags" :key="tag">
            <span data-slot="tag-input-tag" data-variant="neutral" class="inline-flex w-fit shrink-0 items-center justify-center whitespace-nowrap rounded-control border border-transparent bg-muted px-2 py-0.5 font-medium text-foreground h-6 gap-0.5 ps-2 pe-0.5 text-body-sm">
                <bdi x-text="tag"></bdi>
                <button type="button"  :aria-label="'Remove' + ' ' + tag" @click.stop="removeAt(i)"
                    class="inline-flex size-5 items-center justify-center rounded-[3px] text-muted-foreground outline-none hover:bg-nq-hover hover:text-foreground focus-visible:outline-2 focus-visible:outline-nq-focus">
                    <span aria-hidden="true" class="flex [&_svg]:size-3"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <path d="M18 6 6 18"/>
  <path d="m6 6 12 12"/>
</svg></span>
                </button>
            </span>
        </template>
        <input data-slot="tag-input-field" x-ref="field" x-bind="field" autocomplete="off"             :placeholder="tags.length ? undefined : 'Add a value'"
                        aria-label="Values" class="h-7 min-w-24 flex-1 border-0 bg-transparent px-1 text-body outline-none placeholder:text-muted-foreground pointer-coarse:text-[16px]">
    </div>
        <p x-show="error" x-cloak style="display: none" role="alert" data-slot="tag-input-error" x-text="error" class="mt-1.5 text-caption text-nq-danger-text"></p>
    <span role="status" aria-live="polite" class="sr-only" x-text="message"></span>
    </div>
                </div>
                <button data-slot="button"
     type="button"                         x-bind:disabled="off" x-bind:aria-label="`Remove option: ${o.name}`" x-on:click="remove(o.id)" class="inline-flex shrink-0 select-none items-center justify-center gap-2 whitespace-nowrap rounded-control border border-transparent font-sans text-label transition-colors duration-150 ease-nq min-h-[var(--nq-touch-min,0px)] outline-none focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-nq-focus disabled:pointer-events-none disabled:opacity-50 data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0 text-foreground hover:bg-nq-hover size-control p-0">
        <svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <path d="M10 11v6"/>
  <path d="M14 11v6"/>
  <path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6"/>
  <path d="M3 6h18"/>
  <path d="M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"/>
</svg></button>
            </div>
        </template>
    </div>
</section>
            <p class="text-body-sm text-muted-foreground" x-show="note" role="status" x-text="note"></p>
            <div x-show="hasOptions" class="grid gap-2">
                <p class="text-caption text-muted-foreground" x-text="variantsSummary"></p>
                <section data-slot="variant-matrix" aria-label="Variants" x-data="nqVariantMatrix(JSON.parse('{\u0022options\u0022:[],\u0022variants\u0022:[],\u0022images\u0022:[],\u0022disabled\u0022:false,\u0022currency\u0022:\u0022USD\u0022,\u0022locale\u0022:\u0022en\u0022,\u0022t\u0022:{\u0022products\u0022:\u0022Products\u0022,\u0022newProduct\u0022:\u0022New product\u0022,\u0022searchProducts\u0022:\u0022Search products\u0022,\u0022productCol\u0022:\u0022Product\u0022,\u0022statusCol\u0022:\u0022Status\u0022,\u0022stockCol\u0022:\u0022Stock\u0022,\u0022priceCol\u0022:\u0022Price\u0022,\u0022variantsCol\u0022:\u0022Variants\u0022,\u0022categoryCol\u0022:\u0022Category\u0022,\u0022statuses.active\u0022:\u0022Active\u0022,\u0022statuses.draft\u0022:\u0022Draft\u0022,\u0022statuses.archived\u0022:\u0022Archived\u0022,\u0022stockLevels.in\u0022:\u0022In stock\u0022,\u0022stockLevels.low\u0022:\u0022Low stock\u0022,\u0022stockLevels.out\u0022:\u0022Out of stock\u0022,\u0022stockLevels.untracked\u0022:\u0022Not tracked\u0022,\u0022units\u0022:\u0022{0} in stock\u0022,\u0022variantCount\u0022:\u0022{0} variants\u0022,\u0022oneVariant\u0022:\u00221 variant\u0022,\u0022productListLabel\u0022:\u0022Products\u0022,\u0022noProducts\u0022:\u0022No products yet\u0022,\u0022noProductsHint\u0022:\u0022Add your first product to start selling.\u0022,\u0022loadFailed\u0022:\u0022Products did not load.\u0022,\u0022retry\u0022:\u0022Try again\u0022,\u0022edit\u0022:\u0022Edit\u0022,\u0022setActive\u0022:\u0022Set active\u0022,\u0022setDraft\u0022:\u0022Move to drafts\u0022,\u0022archive\u0022:\u0022Archive\u0022,\u0022delete\u0022:\u0022Delete\u0022,\u0022deleteTitle\u0022:\u0022Delete this product?\u0022,\u0022deleteDescription\u0022:\u0022{0} and its variants are removed. Past orders keep their copy.\u0022,\u0022selectedCount\u0022:\u0022{0} selected\u0022,\u0022bulkEdit\u0022:\u0022Bulk edit\u0022,\u0022bulkTitle\u0022:\u0022Edit {0} products\u0022,\u0022bulkDescription\u0022:\u0022Leave a section on Keep to leave it alone. Changes apply to every variant.\u0022,\u0022bulkPrice\u0022:\u0022Price\u0022,\u0022bulkStock\u0022:\u0022Stock\u0022,\u0022bulkStatus\u0022:\u0022Status\u0022,\u0022keep\u0022:\u0022Keep\u0022,\u0022priceModes.set\u0022:\u0022Set to\u0022,\u0022priceModes.increase-percent\u0022:\u0022Raise by percent\u0022,\u0022priceModes.decrease-percent\u0022:\u0022Lower by percent\u0022,\u0022priceModes.increase-amount\u0022:\u0022Raise by amount\u0022,\u0022priceModes.decrease-amount\u0022:\u0022Lower by amount\u0022,\u0022stockModes.set\u0022:\u0022Set to\u0022,\u0022stockModes.add\u0022:\u0022Add\u0022,\u0022stockModes.remove\u0022:\u0022Remove\u0022,\u0022alsoCompareAt\u0022:\u0022Move compare-at price the same way\u0022,\u0022percent\u0022:\u0022Percent\u0022,\u0022amount\u0022:\u0022Amount\u0022,\u0022quantity\u0022:\u0022Quantity\u0022,\u0022preview\u0022:\u0022Preview\u0022,\u0022previewEmpty\u0022:\u0022Nothing changes yet. Pick a change above.\u0022,\u0022previewRow\u0022:\u0022{0}\u0022,\u0022applyToProducts\u0022:\u0022Apply to {0} products\u0022,\u0022cancel\u0022:\u0022Cancel\u0022,\u0022actions\u0022:\u0022Actions\u0022,\u0022editProduct\u0022:\u0022Edit product\u0022,\u0022newProductTitle\u0022:\u0022New product\u0022,\u0022general\u0022:\u0022General\u0022,\u0022title\u0022:\u0022Title\u0022,\u0022description\u0022:\u0022Description\u0022,\u0022descriptionLabel\u0022:\u0022Product description\u0022,\u0022media\u0022:\u0022Media\u0022,\u0022pricing\u0022:\u0022Pricing\u0022,\u0022price\u0022:\u0022Price\u0022,\u0022compareAt\u0022:\u0022Compare-at price\u0022,\u0022compareAtHint\u0022:\u0022The old price shown struck through. Must be above the price.\u0022,\u0022cost\u0022:\u0022Cost per item\u0022,\u0022costHint\u0022:\u0022Only you see this.\u0022,\u0022margin\u0022:\u0022Margin\u0022,\u0022profit\u0022:\u0022Profit\u0022,\u0022markup\u0022:\u0022Markup\u0022,\u0022noMargin\u0022:\u0022Add a price and a cost to see the margin.\u0022,\u0022inventory\u0022:\u0022Inventory\u0022,\u0022sku\u0022:\u0022SKU\u0022,\u0022trackStock\u0022:\u0022Track stock\u0022,\u0022stockQty\u0022:\u0022In stock\u0022,\u0022backorder\u0022:\u0022Sell when out of stock\u0022,\u0022weight\u0022:\u0022Weight (grams)\u0022,\u0022organization\u0022:\u0022Organisation\u0022,\u0022brand\u0022:\u0022Brand\u0022,\u0022category\u0022:\u0022Category\u0022,\u0022tags\u0022:\u0022Tags\u0022,\u0022tagsPlaceholder\u0022:\u0022Add a tag\u0022,\u0022seo\u0022:\u0022Search listing\u0022,\u0022seoTitle\u0022:\u0022Page title\u0022,\u0022seoDescription\u0022:\u0022Meta description\u0022,\u0022slug\u0022:\u0022URL handle\u0022,\u0022slugHint\u0022:\u0022Lower-case letters, digits and dashes.\u0022,\u0022statusSection\u0022:\u0022Status and visibility\u0022,\u0022visibility\u0022:\u0022Visibility\u0022,\u0022visible\u0022:\u0022Visible in the store\u0022,\u0022hidden\u0022:\u0022Hidden from the store (link still works)\u0022,\u0022statusHint.active\u0022:\u0022Customers can buy it.\u0022,\u0022statusHint.draft\u0022:\u0022Only you can see it.\u0022,\u0022statusHint.archived\u0022:\u0022Kept for records, not sold.\u0022,\u0022save\u0022:\u0022Save product\u0022,\u0022saving\u0022:\u0022Saving\u0022,\u0022discard\u0022:\u0022Discard changes\u0022,\u0022unsaved\u0022:\u0022Unsaved changes\u0022,\u0022allSaved\u0022:\u0022All changes saved\u0022,\u0022saveFailed\u0022:\u0022That did not save. Try again.\u0022,\u0022fixIssues\u0022:\u0022{0} to fix before saving\u0022,\u0022issues.title\u0022:\u0022Add a title.\u0022,\u0022issues.price\u0022:\u0022Add a price.\u0022,\u0022issues.compare-at\u0022:\u0022Compare-at must be above the price.\u0022,\u0022issues.sku-duplicate\u0022:\u0022Two variants share a SKU.\u0022,\u0022issues.no-variants\u0022:\u0022Generate the variants for these options.\u0022,\u0022issues.too-many-variants\u0022:\u0022Too many variants. Remove an option value.\u0022,\u0022issues.slug\u0022:\u0022The URL handle has characters that are not allowed.\u0022,\u0022mediaLabel\u0022:\u0022Product images\u0022,\u0022addImage\u0022:\u0022Add image\u0022,\u0022imageUrl\u0022:\u0022Image URL\u0022,\u0022imageUrlPlaceholder\u0022:\u0022https:\\\/\\\/\\u2026\u0022,\u0022altText\u0022:\u0022Alt text\u0022,\u0022altHint\u0022:\u0022Describe the picture for people who cannot see it.\u0022,\u0022missingAlt\u0022:\u0022Alt text missing\u0022,\u0022primary\u0022:\u0022Main image\u0022,\u0022moveEarlier\u0022:\u0022Move earlier\u0022,\u0022moveLater\u0022:\u0022Move later\u0022,\u0022removeImage\u0022:\u0022Remove image\u0022,\u0022dragHandle\u0022:\u0022Reorder image {0}\u0022,\u0022movedTo\u0022:\u0022Image moved to position {0} of {1}\u0022,\u0022noImages\u0022:\u0022No images yet\u0022,\u0022noImagesHint\u0022:\u0022Add a picture by its URL. The first one is the main image.\u0022,\u0022imageFailed\u0022:\u0022Image did not load\u0022,\u0022optionsTitle\u0022:\u0022Options\u0022,\u0022optionsHint\u0022:\u0022Colour, size, material. Up to three options.\u0022,\u0022addOption\u0022:\u0022Add option\u0022,\u0022removeOption\u0022:\u0022Remove option\u0022,\u0022optionName\u0022:\u0022Option name\u0022,\u0022optionNamePlaceholder\u0022:\u0022Size\u0022,\u0022optionValues\u0022:\u0022Values\u0022,\u0022optionValuesPlaceholder\u0022:\u0022Add a value\u0022,\u0022variantsTitle\u0022:\u0022Variants\u0022,\u0022variantsSummary\u0022:\u0022{0} variants\u0022,\u0022variantsRemoved\u0022:\u0022{0} variants no longer match and were removed.\u0022,\u0022variantsTruncated\u0022:\u0022More than {0} combinations. Only the first {0} are created.\u0022,\u0022variantLabel\u0022:\u0022Variant\u0022,\u0022skuCol\u0022:\u0022SKU\u0022,\u0022priceCol2\u0022:\u0022Price\u0022,\u0022compareCol\u0022:\u0022Compare-at\u0022,\u0022stockCol2\u0022:\u0022Stock\u0022,\u0022imageCol\u0022:\u0022Image\u0022,\u0022noImage\u0022:\u0022No image\u0022,\u0022bulkFill\u0022:\u0022Fill selected variants\u0022,\u0022selectVariants\u0022:\u0022Select variants to fill them at once.\u0022,\u0022selectAll\u0022:\u0022Select all variants\u0022,\u0022selectVariant\u0022:\u0022Select {0}\u0022,\u0022fillPrice\u0022:\u0022Price\u0022,\u0022fillCompare\u0022:\u0022Compare-at\u0022,\u0022fillStock\u0022:\u0022Stock\u0022,\u0022fillAddStock\u0022:\u0022Add stock\u0022,\u0022fillSkuPrefix\u0022:\u0022SKU prefix\u0022,\u0022fillApply\u0022:\u0022Apply to selected\u0022,\u0022fillClear\u0022:\u0022Clear selection\u0022,\u0022variantsSelected\u0022:\u0022{0} selected\u0022,\u0022dupSku\u0022:\u0022Duplicate SKU\u0022,\u0022variantsEmpty\u0022:\u0022Add an option to create variants.\u0022,\u0022collections\u0022:\u0022Collections\u0022,\u0022newCollection\u0022:\u0022New collection\u0022,\u0022collectionsLabel\u0022:\u0022Collections\u0022,\u0022collectionTitle\u0022:\u0022Collection title\u0022,\u0022manual\u0022:\u0022Manual\u0022,\u0022rules\u0022:\u0022Rules\u0022,\u0022kindLabel\u0022:\u0022How products join\u0022,\u0022manualHint\u0022:\u0022Pick the products yourself, in the order you want them.\u0022,\u0022rulesHint\u0022:\u0022Products join on their own when they match the rules.\u0022,\u0022matchPreview\u0022:\u0022{0} products match\u0022,\u0022matchNone\u0022:\u0022No products match yet.\u0022,\u0022matchPreviewLabel\u0022:\u0022Products in this collection\u0022,\u0022addProducts\u0022:\u0022Add products\u0022,\u0022addProduct\u0022:\u0022Add a product\u0022,\u0022pickProduct\u0022:\u0022Choose a product\u0022,\u0022removeFromCollection\u0022:\u0022Remove from collection\u0022,\u0022moveUp\u0022:\u0022Move up\u0022,\u0022moveDown\u0022:\u0022Move down\u0022,\u0022saveCollection\u0022:\u0022Save collection\u0022,\u0022deleteCollection\u0022:\u0022Delete collection\u0022,\u0022deleteCollectionTitle\u0022:\u0022Delete this collection?\u0022,\u0022deleteCollectionDescription\u0022:\u0022{0} is removed. The products stay in your catalogue.\u0022,\u0022collectionsEmpty\u0022:\u0022No collections yet\u0022,\u0022collectionsEmptyHint\u0022:\u0022Group products so customers can browse them together.\u0022,\u0022productsCount\u0022:\u0022{0} products\u0022,\u0022ruleAnyProduct\u0022:\u0022any product\u0022,\u0022ruleAddIt\u0022:\u0022add it to this collection\u0022,\u0022ruleEventLabel\u0022:\u0022Applies to\u0022,\u0022ruleEventHelp\u0022:\u0022Every active product is checked against the conditions below.\u0022,\u0022ruleIfTitle\u0022:\u0022Products that match\u0022,\u0022ruleIfHelp\u0022:\u0022Add conditions. A product joins when they hold. With none, no product joins.\u0022,\u0022ruleThenTitle\u0022:\u0022Result\u0022,\u0022ruleThenHelp\u0022:\u0022Matching products are added to this collection.\u0022,\u0022ruleAction\u0022:\u0022Add it to this collection\u0022,\u0022ruleWhere\u0022:\u0022where\u0022,\u0022ruleSo\u0022:\u0022so\u0022,\u0022and\u0022:\u0022and\u0022,\u0022or\u0022:\u0022or\u0022,\u0022editCollection\u0022:\u0022Edit collection\u0022,\u0022fields.tag\u0022:\u0022Tag\u0022,\u0022fields.brand\u0022:\u0022Brand\u0022,\u0022fields.category\u0022:\u0022Category\u0022,\u0022fields.title\u0022:\u0022Title\u0022,\u0022fields.price\u0022:\u0022Price\u0022,\u0022fields.stock\u0022:\u0022Stock\u0022,\u0022fields.onSale\u0022:\u0022On sale\u0022,\u0022fields.status\u0022:\u0022Status\u0022,\u0022close\u0022:\u0022Close\u0022}}'))" x-modelable="variants"
    x-model="draft.variants" x-effect="setContext(activeOptions, draft.images)" class="flex min-w-0 flex-col gap-3">
    <h3 class="text-label text-foreground">Variants</h3>
    <template x-if="variants.length === 0">
        <div data-slot="empty-state" class="flex flex-col items-center justify-center gap-3 border border-border px-6 py-12 text-center rounded-card border-dashed">
            <span data-slot="state-icon" class="inline-flex size-10 items-center justify-center rounded-control border border-border bg-card [&amp;_svg]:size-5 text-muted-foreground">
            <svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <path d="M12.83 2.18a2 2 0 0 0-1.66 0L2.6 6.08a1 1 0 0 0 0 1.83l8.58 3.91a2 2 0 0 0 1.66 0l8.58-3.9a1 1 0 0 0 0-1.83z"/>
  <path d="M2 12a1 1 0 0 0 .58.91l8.6 3.91a2 2 0 0 0 1.65 0l8.58-3.9A1 1 0 0 0 22 12"/>
  <path d="M2 17a1 1 0 0 0 .58.91l8.6 3.91a2 2 0 0 0 1.65 0l8.58-3.9A1 1 0 0 0 22 17"/>
</svg>        </span>
        <div class="flex max-w-sm flex-col gap-1">
        <p class="text-label text-foreground">Add an option to create variants.</p>
            </div>
    </div>
    </template>
    <div x-show="variants.length > 0" data-slot="variant-fill" class="grid gap-2 rounded-card border border-border bg-nq-surface-soft p-3">
        <div class="flex flex-wrap items-center justify-between gap-2">
            <span class="text-label text-foreground">Fill selected variants</span>
            <span class="text-caption text-muted-foreground" role="status" aria-live="polite" x-text="selectedText"></span>
        </div>
        <div class="grid gap-2 sm:grid-cols-5">
            <div class="grid gap-1">
                <span class="text-caption text-muted-foreground">Price</span>
                <div data-slot="currency-input" data-currency="USD" x-data="nqCurrencyInput(null, JSON.parse('{\u0022currency\u0022:\u0022USD\u0022,\u0022locale\u0022:\u0022en\u0022}'))" x-modelable="minor" x-id="['nq-currency']"
    x-model="fill.price" class="flex w-full min-w-0 flex-col gap-1">
    <div role="group" data-slot="input-group"
    x-bind="group" class="group/input-group flex h-control min-h-[var(--nq-touch-min,0px)] w-full min-w-0 items-center overflow-hidden rounded-control border border-input bg-card text-body text-foreground transition-colors duration-150 ease-nq focus-within:border-nq-focus focus-within:outline-1 focus-within:outline-nq-focus has-[[data-invalid]]:border-nq-danger has-[[aria-invalid=true]]:border-nq-danger has-[input:disabled]:cursor-not-allowed has-[input:disabled]:opacity-50"><div data-slot="currency-symbol" data-align="start" x-bind="symbolAddon"
            class="flex h-full shrink-0 items-center gap-1.5 text-body-sm text-muted-foreground [&amp;_svg]:size-4 order-first ps-3 pe-1">
            <span data-slot="input-group-text" class="select-none whitespace-nowrap"><bdi dir="ltr" x-text="mark()"></bdi></span>
        </div>
        <input data-slot="input-group-input" dir="ltr" x-bind="field" autocomplete="off" spellcheck="false"                           aria-label="Price" class="h-full min-w-0 flex-1 border-0 bg-transparent px-3 text-body text-foreground outline-none placeholder:text-muted-foreground disabled:cursor-not-allowed pointer-coarse:text-[16px] text-start tabular-nums"></div>
    <span x-show="out()" x-cloak style="display: none" :id="rangeId()" class="sr-only">Amount out of range</span>
    </div>
            </div>
            <div class="grid gap-1">
                <span class="text-caption text-muted-foreground">Compare-at</span>
                <div data-slot="currency-input" data-currency="USD" x-data="nqCurrencyInput(null, JSON.parse('{\u0022currency\u0022:\u0022USD\u0022,\u0022locale\u0022:\u0022en\u0022}'))" x-modelable="minor" x-id="['nq-currency']"
    x-model="fill.compareAt" class="flex w-full min-w-0 flex-col gap-1">
    <div role="group" data-slot="input-group"
    x-bind="group" class="group/input-group flex h-control min-h-[var(--nq-touch-min,0px)] w-full min-w-0 items-center overflow-hidden rounded-control border border-input bg-card text-body text-foreground transition-colors duration-150 ease-nq focus-within:border-nq-focus focus-within:outline-1 focus-within:outline-nq-focus has-[[data-invalid]]:border-nq-danger has-[[aria-invalid=true]]:border-nq-danger has-[input:disabled]:cursor-not-allowed has-[input:disabled]:opacity-50"><div data-slot="currency-symbol" data-align="start" x-bind="symbolAddon"
            class="flex h-full shrink-0 items-center gap-1.5 text-body-sm text-muted-foreground [&amp;_svg]:size-4 order-first ps-3 pe-1">
            <span data-slot="input-group-text" class="select-none whitespace-nowrap"><bdi dir="ltr" x-text="mark()"></bdi></span>
        </div>
        <input data-slot="input-group-input" dir="ltr" x-bind="field" autocomplete="off" spellcheck="false"                           aria-label="Compare-at" class="h-full min-w-0 flex-1 border-0 bg-transparent px-3 text-body text-foreground outline-none placeholder:text-muted-foreground disabled:cursor-not-allowed pointer-coarse:text-[16px] text-start tabular-nums"></div>
    <span x-show="out()" x-cloak style="display: none" :id="rangeId()" class="sr-only">Amount out of range</span>
    </div>
            </div>
            <div class="grid gap-1">
                <span class="text-caption text-muted-foreground">Stock</span>
                <input data-slot="input" type="text"
                    inputmode="numeric" aria-label="Stock" x-model="fill.stock" class="w-full min-w-0 rounded-control border border-input bg-card px-3 text-body text-foreground min-h-[var(--nq-touch-min,0px)] transition-colors duration-150 ease-nq outline-none placeholder:text-muted-foreground focus-visible:border-nq-focus focus-visible:outline-1 focus-visible:outline-nq-focus data-invalid:border-nq-danger aria-invalid:border-nq-danger disabled:cursor-not-allowed disabled:opacity-50 pointer-coarse:text-[16px] h-control">
            </div>
            <div class="grid gap-1">
                <span class="text-caption text-muted-foreground">Add stock</span>
                <input data-slot="input" type="text"
                    inputmode="numeric" aria-label="Add stock" x-model="fill.add" class="w-full min-w-0 rounded-control border border-input bg-card px-3 text-body text-foreground min-h-[var(--nq-touch-min,0px)] transition-colors duration-150 ease-nq outline-none placeholder:text-muted-foreground focus-visible:border-nq-focus focus-visible:outline-1 focus-visible:outline-nq-focus data-invalid:border-nq-danger aria-invalid:border-nq-danger disabled:cursor-not-allowed disabled:opacity-50 pointer-coarse:text-[16px] h-control">
            </div>
            <div class="grid gap-1">
                <span class="text-caption text-muted-foreground">SKU prefix</span>
                <input data-slot="input" type="text"
                    dir="ltr" aria-label="SKU prefix" x-model="fill.sku" class="w-full min-w-0 rounded-control border border-input bg-card px-3 text-body text-foreground min-h-[var(--nq-touch-min,0px)] transition-colors duration-150 ease-nq outline-none placeholder:text-muted-foreground focus-visible:border-nq-focus focus-visible:outline-1 focus-visible:outline-nq-focus data-invalid:border-nq-danger aria-invalid:border-nq-danger disabled:cursor-not-allowed disabled:opacity-50 pointer-coarse:text-[16px] h-control">
            </div>
        </div>
        <div class="flex flex-wrap gap-2">
            <button data-slot="button"
     type="button"                         x-bind:disabled="! canFill" x-on:click="applyFill()" class="inline-flex shrink-0 select-none items-center justify-center gap-2 whitespace-nowrap rounded-control border font-sans text-label transition-colors duration-150 ease-nq min-h-[var(--nq-touch-min,0px)] outline-none focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-nq-focus disabled:pointer-events-none disabled:opacity-50 data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0 border-border bg-card text-foreground hover:bg-nq-hover h-control-sm px-2.5">
        Apply to selected</button>
            <button data-slot="button"
     type="button"                         x-bind:disabled="! some" x-on:click="clearSelection()" class="inline-flex shrink-0 select-none items-center justify-center gap-2 whitespace-nowrap rounded-control border border-transparent font-sans text-label transition-colors duration-150 ease-nq min-h-[var(--nq-touch-min,0px)] outline-none focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-nq-focus disabled:pointer-events-none disabled:opacity-50 data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0 text-foreground hover:bg-nq-hover h-control-sm px-2.5">
        Clear selection</button>
        </div>
    </div>
    <div x-show="variants.length > 0" class="relative w-full overflow-x-auto rounded-card border border-border bg-card">
        <div role="table" aria-label="Variants" class="table w-full min-w-[52rem] border-collapse">
            <div role="rowgroup" class="table-header-group border-b border-border">
                <div role="row" class="table-row">
                    <div role="columnheader" class="table-cell w-10 px-2">
                        <button type="button" role="checkbox" data-slot="checkbox" x-data="nqCheckbox(false, false)" x-modelable="checked" x-bind="root"
    aria-checked="false"
     data-unchecked                 aria-label="Select all variants" x-on:click="toggleAll(! all)" x-bind:checked="all" class="relative inline-flex size-4 shrink-0 items-center justify-center rounded-[4px] border border-nq-line-strong bg-card text-primary-foreground outline-none transition-colors duration-150 ease-nq data-checked:border-primary data-checked:bg-primary data-indeterminate:border-primary data-indeterminate:bg-primary focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-nq-focus data-disabled:cursor-not-allowed data-disabled:opacity-50 after:absolute after:-inset-1">
    <span data-slot="checkbox-indicator" class="flex items-center justify-center [&_svg]:size-3 [&_svg]:stroke-3" x-show="checked || indeterminate"  style="display: none" >
        <svg aria-hidden="true" x-show="indeterminate" style="display: none" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <path d="M5 12h14"/>
</svg>        <svg aria-hidden="true" x-show="! indeterminate" style="" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <path d="M20 6 9 17l-5-5"/>
</svg>    </span>
    </button>
                    </div>
                    <div role="columnheader" class="table-cell px-2 py-2 text-start text-caption font-medium text-muted-foreground">Variant</div>
                    <div role="columnheader" class="table-cell px-2 py-2 text-start text-caption font-medium text-muted-foreground">SKU</div>
                    <div role="columnheader" class="table-cell px-2 py-2 text-start text-caption font-medium text-muted-foreground">Price</div>
                    <div role="columnheader" class="table-cell px-2 py-2 text-start text-caption font-medium text-muted-foreground">Compare-at</div>
                    <div role="columnheader" class="table-cell px-2 py-2 text-start text-caption font-medium text-muted-foreground">Stock</div>
                    <div role="columnheader" class="table-cell px-2 py-2 text-start text-caption font-medium text-muted-foreground">Image</div>
                </div>
            </div>
            <div role="rowgroup" class="table-row-group divide-y divide-border">
                <template x-for="(v, i) in variants" x-bind:key="v.id">
                    <div role="row" data-slot="variant-row" x-bind:data-selected="selected[v.id] ? '' : null" class="table-row data-[selected]:bg-nq-selected">
                        <div role="cell" class="table-cell px-2 py-2 align-middle text-body-sm text-foreground">
                            <button type="button" role="checkbox" data-slot="checkbox" x-data="nqCheckbox(false, false)" x-modelable="checked" x-bind="root"
    aria-checked="false"
     data-unchecked                 x-model="selected[v.id]" x-bind:aria-label="tt(`selectVariant`, label(v, i))" class="relative inline-flex size-4 shrink-0 items-center justify-center rounded-[4px] border border-nq-line-strong bg-card text-primary-foreground outline-none transition-colors duration-150 ease-nq data-checked:border-primary data-checked:bg-primary data-indeterminate:border-primary data-indeterminate:bg-primary focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-nq-focus data-disabled:cursor-not-allowed data-disabled:opacity-50 after:absolute after:-inset-1">
    <span data-slot="checkbox-indicator" class="flex items-center justify-center [&_svg]:size-3 [&_svg]:stroke-3" x-show="checked || indeterminate"  style="display: none" >
        <svg aria-hidden="true" x-show="indeterminate" style="display: none" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <path d="M5 12h14"/>
</svg>        <svg aria-hidden="true" x-show="! indeterminate" style="" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <path d="M20 6 9 17l-5-5"/>
</svg>    </span>
    </button>
                        </div>
                        <div role="cell" class="table-cell px-2 py-2 align-middle text-body-sm text-foreground font-medium" x-text="label(v, i)"></div>
                        <div role="cell" class="table-cell px-2 py-2 align-middle text-body-sm text-foreground">
                            <input type="text" dir="ltr" x-model="v.sku" x-bind:disabled="off" x-bind:aria-label="`SKU: ${label(v, i)}`" x-bind:aria-invalid="isDup(v) ? `true` : null"
                                class="h-control-sm w-full min-w-24 rounded-control border border-input bg-card px-2 text-body-sm text-foreground outline-none focus-visible:border-nq-focus aria-invalid:border-nq-danger" />
                            <span class="mt-0.5 block text-caption text-nq-danger-text" x-show="isDup(v)">Duplicate SKU</span>
                        </div>
                        <div role="cell" class="table-cell px-2 py-2 align-middle text-body-sm text-foreground">
                            <div data-slot="currency-input" data-currency="USD" x-data="nqCurrencyInput(null, JSON.parse('{\u0022currency\u0022:\u0022USD\u0022,\u0022locale\u0022:\u0022en\u0022}'))" x-modelable="minor" x-id="['nq-currency']"
    x-model="v.price" class="flex w-full min-w-0 flex-col gap-1">
    <div role="group" data-slot="input-group"
    x-bind="group" class="group/input-group flex h-control min-h-[var(--nq-touch-min,0px)] w-full min-w-0 items-center overflow-hidden rounded-control border border-input bg-card text-body text-foreground transition-colors duration-150 ease-nq focus-within:border-nq-focus focus-within:outline-1 focus-within:outline-nq-focus has-[[data-invalid]]:border-nq-danger has-[[aria-invalid=true]]:border-nq-danger has-[input:disabled]:cursor-not-allowed has-[input:disabled]:opacity-50"><div data-slot="currency-symbol" data-align="start" x-bind="symbolAddon"
            class="flex h-full shrink-0 items-center gap-1.5 text-body-sm text-muted-foreground [&amp;_svg]:size-4 order-first ps-3 pe-1">
            <span data-slot="input-group-text" class="select-none whitespace-nowrap"><bdi dir="ltr" x-text="mark()"></bdi></span>
        </div>
        <input data-slot="input-group-input" dir="ltr" x-bind="field" autocomplete="off" spellcheck="false"                           x-bind:aria-label="`Price: ${label(v, i)}`" class="h-full min-w-0 flex-1 border-0 bg-transparent px-3 text-body text-foreground outline-none placeholder:text-muted-foreground disabled:cursor-not-allowed pointer-coarse:text-[16px] text-start tabular-nums"></div>
    <span x-show="out()" x-cloak style="display: none" :id="rangeId()" class="sr-only">Amount out of range</span>
    </div>
                        </div>
                        <div role="cell" class="table-cell px-2 py-2 align-middle text-body-sm text-foreground">
                            <div data-slot="currency-input" data-currency="USD" x-data="nqCurrencyInput(null, JSON.parse('{\u0022currency\u0022:\u0022USD\u0022,\u0022locale\u0022:\u0022en\u0022}'))" x-modelable="minor" x-id="['nq-currency']"
    x-model="v.compareAt" class="flex w-full min-w-0 flex-col gap-1">
    <div role="group" data-slot="input-group"
    x-bind="group" class="group/input-group flex h-control min-h-[var(--nq-touch-min,0px)] w-full min-w-0 items-center overflow-hidden rounded-control border border-input bg-card text-body text-foreground transition-colors duration-150 ease-nq focus-within:border-nq-focus focus-within:outline-1 focus-within:outline-nq-focus has-[[data-invalid]]:border-nq-danger has-[[aria-invalid=true]]:border-nq-danger has-[input:disabled]:cursor-not-allowed has-[input:disabled]:opacity-50"><div data-slot="currency-symbol" data-align="start" x-bind="symbolAddon"
            class="flex h-full shrink-0 items-center gap-1.5 text-body-sm text-muted-foreground [&amp;_svg]:size-4 order-first ps-3 pe-1">
            <span data-slot="input-group-text" class="select-none whitespace-nowrap"><bdi dir="ltr" x-text="mark()"></bdi></span>
        </div>
        <input data-slot="input-group-input" dir="ltr" x-bind="field" autocomplete="off" spellcheck="false"                           x-bind:aria-label="`Compare-at: ${label(v, i)}`" class="h-full min-w-0 flex-1 border-0 bg-transparent px-3 text-body text-foreground outline-none placeholder:text-muted-foreground disabled:cursor-not-allowed pointer-coarse:text-[16px] text-start tabular-nums"></div>
    <span x-show="out()" x-cloak style="display: none" :id="rangeId()" class="sr-only">Amount out of range</span>
    </div>
                            <span class="mt-0.5 block text-caption text-nq-danger-text" x-show="badCompare(v)">Compare-at must be above the price.</span>
                        </div>
                        <div role="cell" class="table-cell px-2 py-2 align-middle text-body-sm text-foreground">
                            <input type="text" inputmode="numeric" x-bind:value="v.stock ?? ''" x-on:input="setStock(v, $event.target.value)" x-bind:disabled="off" x-bind:aria-label="`Stock: ${label(v, i)}`"
                                class="h-control-sm w-20 rounded-control border border-input bg-card px-2 text-body-sm tabular-nums text-foreground outline-none focus-visible:border-nq-focus" />
                        </div>
                        <div role="cell" class="table-cell px-2 py-2 align-middle text-body-sm text-foreground">
                            <div data-slot="native-select" class="relative w-full min-w-0">
    <select           class="w-full min-w-0 appearance-none rounded-control border border-input bg-card ps-3 pe-9 text-body text-foreground min-h-[var(--nq-touch-min,0px)] transition-colors duration-150 ease-nq outline-none focus-visible:border-nq-focus focus-visible:outline-1 focus-visible:outline-nq-focus data-invalid:border-nq-danger aria-invalid:border-nq-danger disabled:cursor-not-allowed disabled:opacity-50 pointer-coarse:text-[16px] h-control-sm" x-model="v.image" x-bind:disabled="off ? true : images.length === 0" x-bind:aria-label="`Image: ${label(v, i)}`">
                        <option value="" x-bind:selected="! v.image">No image</option>
                                <template x-for="(im, k) in images" x-bind:key="im.src">
                                    <option x-bind:value="im.src" x-bind:selected="v.image === im.src" x-text="imageAlt(im, k)"></option>
                                </template>
    </select>
    <svg aria-hidden="true" class="pointer-events-none absolute end-3 top-1/2 size-4 -translate-y-1/2 text-muted-foreground" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <path d="m6 9 6 6 6-6"/>
</svg></div>
                        </div>
                    </div>
                </template>
            </div>
        </div>
    </div>
</section>
            </div>
            <p x-show="has(`no-variants`)" class="text-body-sm text-nq-danger-text">Generate the variants for these options.</p>
        </section>
        <section class="grid gap-4 rounded-card border border-border bg-card p-4" aria-label="Organisation">
            <h3 class="text-h4 text-foreground">Organisation</h3>
            <div class="grid gap-4 sm:grid-cols-2">
                <div class="grid gap-1">
                    <label class="text-label text-foreground" for="product-brand">Brand</label>
                    <input data-slot="input" type="text"
                    id="product-brand" x-model="draft.brand" class="w-full min-w-0 rounded-control border border-input bg-card px-3 text-body text-foreground min-h-[var(--nq-touch-min,0px)] transition-colors duration-150 ease-nq outline-none placeholder:text-muted-foreground focus-visible:border-nq-focus focus-visible:outline-1 focus-visible:outline-nq-focus data-invalid:border-nq-danger aria-invalid:border-nq-danger disabled:cursor-not-allowed disabled:opacity-50 pointer-coarse:text-[16px] h-control">
                </div>
                <div class="grid gap-1">
                    <label class="text-label text-foreground" for="product-category">Category</label>
                    <input data-slot="input" type="text"
                    id="product-category" x-model="draft.category" class="w-full min-w-0 rounded-control border border-input bg-card px-3 text-body text-foreground min-h-[var(--nq-touch-min,0px)] transition-colors duration-150 ease-nq outline-none placeholder:text-muted-foreground focus-visible:border-nq-focus focus-visible:outline-1 focus-visible:outline-nq-focus data-invalid:border-nq-danger aria-invalid:border-nq-danger disabled:cursor-not-allowed disabled:opacity-50 pointer-coarse:text-[16px] h-control">
                </div>
            </div>
            <div class="grid gap-1">
                <span class="text-label text-foreground">Tags</span>
                <div data-slot="tag-input" x-data="nqTagInput([], {})" x-modelable="tags" x-bind="root"
         x-model="draft.tags" class="relative w-full">
    <div data-slot="tag-input-box" x-bind="box"
        class="flex w-full min-w-0 flex-wrap items-center gap-1.5 rounded-control border border-input bg-card px-2 py-1 text-body text-foreground min-h-[max(var(--nq-control),var(--nq-touch-min,0px))] transition-colors duration-150 ease-nq focus-within:border-nq-focus focus-within:outline-1 focus-within:outline-nq-focus has-[[data-invalid]]:border-nq-danger has-[[aria-invalid=true]]:border-nq-danger">
        <template x-for="(tag, i) in tags" :key="tag">
            <span data-slot="tag-input-tag" data-variant="neutral" class="inline-flex w-fit shrink-0 items-center justify-center whitespace-nowrap rounded-control border border-transparent bg-muted px-2 py-0.5 font-medium text-foreground h-6 gap-0.5 ps-2 pe-0.5 text-body-sm">
                <bdi x-text="tag"></bdi>
                <button type="button"  :aria-label="'Remove' + ' ' + tag" @click.stop="removeAt(i)"
                    class="inline-flex size-5 items-center justify-center rounded-[3px] text-muted-foreground outline-none hover:bg-nq-hover hover:text-foreground focus-visible:outline-2 focus-visible:outline-nq-focus">
                    <span aria-hidden="true" class="flex [&_svg]:size-3"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <path d="M18 6 6 18"/>
  <path d="m6 6 12 12"/>
</svg></span>
                </button>
            </span>
        </template>
        <input data-slot="tag-input-field" x-ref="field" x-bind="field" autocomplete="off"             :placeholder="tags.length ? undefined : 'Add a tag'"
                        aria-label="Tags" class="h-7 min-w-24 flex-1 border-0 bg-transparent px-1 text-body outline-none placeholder:text-muted-foreground pointer-coarse:text-[16px]">
    </div>
        <p x-show="error" x-cloak style="display: none" role="alert" data-slot="tag-input-error" x-text="error" class="mt-1.5 text-caption text-nq-danger-text"></p>
    <span role="status" aria-live="polite" class="sr-only" x-text="message"></span>
    </div>
            </div>
        </section>
        <section class="grid gap-4 rounded-card border border-border bg-card p-4" aria-label="Search listing">
            <h3 class="text-h4 text-foreground">Search listing</h3>
            <div class="grid gap-1">
                <label class="text-label text-foreground" for="product-slug">URL handle</label>
                <input id="product-slug" type="text" dir="ltr" x-model="draft.slug" x-bind:placeholder="slugHolder" x-bind:aria-invalid="has(`slug`) ? `true` : null"
                    class="h-control w-full min-w-0 rounded-control border border-input bg-card px-3 text-body text-foreground outline-none focus-visible:border-nq-focus aria-invalid:border-nq-danger" />
                <p class="text-caption text-muted-foreground" x-show="! has(`slug`)">Lower-case letters, digits and dashes.</p>
                <p class="text-body-sm text-nq-danger-text" x-show="has(`slug`)">The URL handle has characters that are not allowed.</p>
            </div>
            <div data-slot="seo-preview" x-on:nq-seo-preview-change="setSeo($event.detail)" class="flex flex-col gap-4 rounded-card border border-border bg-card py-4 text-card-foreground"><div data-slot="card-header" class="grid auto-rows-min items-start gap-1 px-4 has-data-[slot=card-action]:grid-cols-[1fr_auto]"><h3 data-slot="card-title" class="text-label text-foreground">Search listing</h3>
        <div data-slot="card-description" class="text-body-sm text-muted-foreground">How this page looks in search results and when it is shared.</div></div>
    <div data-slot="card-content" class="px-4 flex flex-col gap-5"><div x-data="nqSeoPreview(JSON.parse('{\u0022title\u0022:\u0022Linen shirt\u0022,\u0022description\u0022:\u0022\u0022,\u0022url\u0022:\u0022\u0022}'), JSON.parse('{\u0022length\u0022:\u0022{n} of {max} characters\u0022,\u0022empty\u0022:\u0022Empty\u0022,\u0022short\u0022:\u0022Too short\u0022,\u0022good\u0022:\u0022Good length\u0022,\u0022longOne\u0022:\u00221 character too long\u0022,\u0022longMany\u0022:\u0022{n} characters too long\u0022,\u0022noTitle\u0022:\u0022Untitled page\u0022,\u0022noDescription\u0022:\u0022No description. Search engines will pick text from the page.\u0022,\u0022siteFallback\u0022:\u0022Your site\u0022}'))" class="flex flex-col gap-5">
            <div data-slot="tabs" data-orientation="horizontal" x-data="nqTabs('google')" x-modelable="value" x-id="['nq-tabs']" class="flex flex-col gap-4">
    <div data-slot="tabs-list" data-variant="underline" aria-orientation="horizontal" x-bind="list"
    class="relative z-0 flex max-w-full overflow-x-auto [scrollbar-width:none] [&::-webkit-scrollbar]:hidden gap-4 border-b border-border">
    <button type="button" data-slot="tabs-tab" x-bind="tab('google')"
     data-active aria-selected="true"         class="inline-flex shrink-0 items-center gap-1.5 whitespace-nowrap text-label text-muted-foreground outline-none transition-colors duration-150 ease-nq hover:text-foreground data-active:text-foreground [&_svg]:size-4 [&_svg]:shrink-0 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-nq-focus data-disabled:pointer-events-none data-disabled:opacity-50 h-9 px-0.5">Google</button>
                                            <button type="button" data-slot="tabs-tab" x-bind="tab('open-graph')"
            class="inline-flex shrink-0 items-center gap-1.5 whitespace-nowrap text-label text-muted-foreground outline-none transition-colors duration-150 ease-nq hover:text-foreground data-active:text-foreground [&_svg]:size-4 [&_svg]:shrink-0 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-nq-focus data-disabled:pointer-events-none data-disabled:opacity-50 h-9 px-0.5">Open Graph</button>
                                            <button type="button" data-slot="tabs-tab" x-bind="tab('x')"
            class="inline-flex shrink-0 items-center gap-1.5 whitespace-nowrap text-label text-muted-foreground outline-none transition-colors duration-150 ease-nq hover:text-foreground data-active:text-foreground [&_svg]:size-4 [&_svg]:shrink-0 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-nq-focus data-disabled:pointer-events-none data-disabled:opacity-50 h-9 px-0.5">X</button>
                                            <button type="button" data-slot="tabs-tab" x-bind="tab('whatsapp')"
            class="inline-flex shrink-0 items-center gap-1.5 whitespace-nowrap text-label text-muted-foreground outline-none transition-colors duration-150 ease-nq hover:text-foreground data-active:text-foreground [&_svg]:size-4 [&_svg]:shrink-0 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-nq-focus data-disabled:pointer-events-none data-disabled:opacity-50 h-9 px-0.5">WhatsApp</button>
                                            <button type="button" data-slot="tabs-tab" x-bind="tab('linkedin')"
            class="inline-flex shrink-0 items-center gap-1.5 whitespace-nowrap text-label text-muted-foreground outline-none transition-colors duration-150 ease-nq hover:text-foreground data-active:text-foreground [&_svg]:size-4 [&_svg]:shrink-0 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-nq-focus data-disabled:pointer-events-none data-disabled:opacity-50 h-9 px-0.5">LinkedIn</button>
                                        <span data-slot="tabs-indicator" aria-hidden="true"
    class="absolute -z-10 transition-[left,width] duration-200 ease-nq left-[var(--active-tab-left)] w-[var(--active-tab-width)] bottom-0 h-0.5 rounded-full bg-primary"></span>
</div>
                <div data-slot="tabs-panel" x-bind="panel('google')"
        class="outline-none focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-nq-focus flex flex-col gap-3 pt-4"><div role="group" data-slot="toggle-group" data-variant="segmented" data-orientation="horizontal"
    x-data="nqToggleGroup(JSON.parse('[\u0022desktop\u0022]'), false)" x-modelable="value" x-bind="root"
            x-model="device" aria-label="Device" class="flex w-fit max-w-full gap-0.5 rounded-control bg-secondary p-0.5">
    <button type="button" data-slot="toggle" aria-pressed="true"
     x-bind="toggle('desktop')"      data-pressed         class="inline-flex h-7 shrink-0 items-center justify-center gap-1.5 whitespace-nowrap px-3 text-label text-muted-foreground outline-none transition-colors duration-150 ease-nq hover:text-foreground [&_svg]:size-4 [&_svg]:shrink-0 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-nq-focus data-disabled:pointer-events-none data-disabled:opacity-50 rounded-[calc(var(--radius-control)-2px)] data-pressed:bg-card data-pressed:text-foreground data-pressed:shadow-xs"><svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <rect width="20" height="14" x="2" y="3" rx="2"/>
  <line x1="8" x2="16" y1="21" y2="21"/>
  <line x1="12" x2="12" y1="17" y2="21"/>
</svg>Desktop</button>
                        <button type="button" data-slot="toggle" aria-pressed="false"
     x-bind="toggle('mobile')"             class="inline-flex h-7 shrink-0 items-center justify-center gap-1.5 whitespace-nowrap px-3 text-label text-muted-foreground outline-none transition-colors duration-150 ease-nq hover:text-foreground [&_svg]:size-4 [&_svg]:shrink-0 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-nq-focus data-disabled:pointer-events-none data-disabled:opacity-50 rounded-[calc(var(--radius-control)-2px)] data-pressed:bg-card data-pressed:text-foreground data-pressed:shadow-xs"><svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <rect width="14" height="20" x="5" y="2" rx="2" ry="2"/>
  <path d="M12 18h.01"/>
</svg>Mobile</button>
</div>
                    <div data-slot="seo-google" x-bind:data-device="mobile ? 'mobile' : 'desktop'" data-device="desktop"
                        x-bind:class="mobile ? 'w-full max-w-[22rem]' : 'max-w-[41rem]'" class="flex max-w-[41rem] flex-col gap-1 rounded-card border border-border bg-card p-4">
                        <div class="flex items-center gap-2.5">
                            <img x-show="favicon" x-bind:src="favicon || null" alt="" class="size-7 shrink-0 rounded-full border border-border" style="display: none">
                            <span x-show="! favicon" aria-hidden="true" x-text="firstLetter" class="flex size-[18px] shrink-0 items-center justify-center rounded-full bg-secondary text-[10px] font-semibold uppercase text-muted-foreground size-7 border border-border"></span>
                            <div class="flex min-w-0 flex-col leading-tight">
                                <span class="truncate text-body-sm text-foreground" dir="auto" x-text="site"></span>
                                <span dir="ltr" class="flex min-w-0 items-center gap-1 text-caption text-muted-foreground">
                                    <template x-for="(c, i) in crumbs" x-bind:key="i + c">
                                        <span class="flex min-w-0 items-center gap-1">
                                            <svg aria-hidden="true" x-show="i > 0" class="size-3 shrink-0" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <path d="m9 18 6-6-6-6"/>
</svg>                                            <span class="truncate" x-text="c"></span>
                                        </span>
                                    </template>
                                </span>
                            </div>
                        </div>
                        <p dir="auto" x-bind:class="mobile ? 'line-clamp-2 text-body' : 'line-clamp-1 text-h5'" x-text="googleTitle" class="mt-1 line-clamp-1 text-h5 font-medium text-nq-info-text"></p>
                        <p dir="auto" x-bind:class="mobile ? 'line-clamp-3' : 'line-clamp-2'" x-text="googleDescription" class="line-clamp-2 text-body-sm text-muted-foreground"></p>
                    </div></div>
                <div data-slot="tabs-panel" x-bind="panel('open-graph')"
     hidden     class="outline-none focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-nq-focus pt-4"><div data-slot="seo-open-graph" class="w-full max-w-[32rem] overflow-hidden rounded-card border border-border bg-card">
                        <img x-show="image" x-bind:src="image || null" alt="" class="aspect-[1.91/1] w-full object-cover" style="display: none">
                        <div x-show="! image" class="flex flex-col items-center justify-center gap-1 bg-secondary text-caption text-muted-foreground aspect-[1.91/1] w-full"><svg aria-hidden="true" class="size-6" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <rect width="18" height="18" x="3" y="3" rx="2" ry="2"/>
  <circle cx="9" cy="9" r="2"/>
  <path d="m21 15-3.086-3.086a2 2 0 0 0-2.828 0L6 21"/>
</svg>No share image</div>
                        <div class="flex flex-col gap-0.5 border-t border-border bg-secondary/50 p-3">
                            <span dir="ltr" class="truncate text-start text-caption uppercase text-muted-foreground" x-text="host"></span>
                            <p dir="auto" class="line-clamp-2 text-label text-foreground" x-text="shownTitle"></p>
                            <p dir="auto" class="line-clamp-2 text-caption text-muted-foreground" x-text="shownDescription"></p>
                        </div>
                    </div></div>
                <div data-slot="tabs-panel" x-bind="panel('x')"
     hidden     class="outline-none focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-nq-focus pt-4"><div data-slot="seo-x" class="w-full max-w-[32rem]">
                        <div class="relative overflow-hidden rounded-2xl border border-border bg-card">
                            <img x-show="image" x-bind:src="image || null" alt="" class="aspect-[2/1] w-full object-cover" style="display: none">
                            <div x-show="! image" class="flex flex-col items-center justify-center gap-1 bg-secondary text-caption text-muted-foreground aspect-[2/1] w-full"><svg aria-hidden="true" class="size-6" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <rect width="18" height="18" x="3" y="3" rx="2" ry="2"/>
  <circle cx="9" cy="9" r="2"/>
  <path d="m21 15-3.086-3.086a2 2 0 0 0-2.828 0L6 21"/>
</svg>No share image</div>
                            <span dir="auto" class="absolute bottom-2 start-2 max-w-[80%] truncate rounded-md bg-foreground/70 px-1.5 py-0.5 text-caption text-background" x-text="shownTitle"></span>
                        </div>
                        <p dir="ltr" class="mt-1 px-1 text-start text-caption text-muted-foreground" x-text="host"></p>
                    </div></div>
                <div data-slot="tabs-panel" x-bind="panel('whatsapp')"
     hidden     class="outline-none focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-nq-focus pt-4"><div data-slot="seo-whatsapp" class="flex w-full max-w-[24rem] flex-col gap-1 rounded-card bg-secondary p-2">
                        <div class="overflow-hidden rounded-md bg-card">
                            <img x-show="image" x-bind:src="image || null" alt="" class="aspect-[1.91/1] w-full object-cover" style="display: none">
                            <div x-show="! image" class="flex flex-col items-center justify-center gap-1 bg-secondary text-caption text-muted-foreground aspect-[1.91/1] w-full"><svg aria-hidden="true" class="size-6" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <rect width="18" height="18" x="3" y="3" rx="2" ry="2"/>
  <circle cx="9" cy="9" r="2"/>
  <path d="m21 15-3.086-3.086a2 2 0 0 0-2.828 0L6 21"/>
</svg>No share image</div>
                            <div class="flex flex-col gap-0.5 p-2.5">
                                <p dir="auto" class="line-clamp-2 text-label text-foreground" x-text="shownTitle"></p>
                                <p dir="auto" class="line-clamp-2 text-caption text-muted-foreground" x-text="shownDescription"></p>
                                <span dir="ltr" class="truncate text-start text-caption text-muted-foreground" x-text="host"></span>
                            </div>
                        </div>
                        <span dir="ltr" class="truncate px-1 text-start text-caption text-nq-info-text" x-text="url"></span>
                    </div></div>
                <div data-slot="tabs-panel" x-bind="panel('linkedin')"
     hidden     class="outline-none focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-nq-focus pt-4"><div data-slot="seo-linkedin" class="w-full max-w-[32rem] overflow-hidden rounded-card border border-border bg-card">
                        <img x-show="image" x-bind:src="image || null" alt="" class="aspect-[1.91/1] w-full object-cover" style="display: none">
                        <div x-show="! image" class="flex flex-col items-center justify-center gap-1 bg-secondary text-caption text-muted-foreground aspect-[1.91/1] w-full"><svg aria-hidden="true" class="size-6" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <rect width="18" height="18" x="3" y="3" rx="2" ry="2"/>
  <circle cx="9" cy="9" r="2"/>
  <path d="m21 15-3.086-3.086a2 2 0 0 0-2.828 0L6 21"/>
</svg>No share image</div>
                        <div class="flex flex-col gap-0.5 p-3">
                            <p dir="auto" class="line-clamp-2 text-label text-foreground" x-text="shownTitle"></p>
                            <span dir="ltr" class="truncate text-start text-caption text-muted-foreground" x-text="host"></span>
                        </div>
                    </div></div>
</div>
            <div class="grid gap-4 md:grid-cols-2">
                                    <div data-slot="field" x-data="nqField(false)" x-modelable="invalid" x-id="['nq-field']"
         data-valid     class="flex flex-col gap-1.5">
    <label data-slot="field-label"  class="text-label text-foreground data-disabled:opacity-50">Title</label>
                        <input data-slot="input" type="text"
                    dir="auto" x-model="title" x-on:input="changed()" class="w-full min-w-0 rounded-control border border-input bg-card px-3 text-body text-foreground min-h-[var(--nq-touch-min,0px)] transition-colors duration-150 ease-nq outline-none placeholder:text-muted-foreground focus-visible:border-nq-focus focus-visible:outline-1 focus-visible:outline-nq-focus data-invalid:border-nq-danger aria-invalid:border-nq-danger disabled:cursor-not-allowed disabled:opacity-50 pointer-coarse:text-[16px] h-control">
</div>
                    <div data-slot="field" x-data="nqField(false)" x-modelable="invalid" x-id="['nq-field']"
         data-valid     class="flex flex-col gap-1.5">
    <label data-slot="field-label"  class="text-label text-foreground data-disabled:opacity-50">Page URL</label>
                        <input data-slot="input" type="text"
     dir="ltr"                 x-model="url" x-on:input="changed()" class="w-full min-w-0 rounded-control border border-input bg-card px-3 text-body text-foreground min-h-[var(--nq-touch-min,0px)] transition-colors duration-150 ease-nq outline-none placeholder:text-muted-foreground focus-visible:border-nq-focus focus-visible:outline-1 focus-visible:outline-nq-focus data-invalid:border-nq-danger aria-invalid:border-nq-danger disabled:cursor-not-allowed disabled:opacity-50 pointer-coarse:text-[16px] h-control text-start">
</div>
                    <div data-slot="field" x-data="nqField(false)" x-modelable="invalid" x-id="['nq-field']"
         data-valid     class="flex flex-col gap-1.5 md:col-span-2">
    <label data-slot="field-label"  class="text-label text-foreground data-disabled:opacity-50">Meta description</label>
                        <textarea data-slot="textarea"
                dir="auto" rows="3" x-model="description" x-on:input="changed()" class="w-full min-w-0 rounded-control border border-input bg-card px-3 text-body text-foreground transition-colors duration-150 ease-nq outline-none placeholder:text-muted-foreground focus-visible:border-nq-focus focus-visible:outline-1 focus-visible:outline-nq-focus data-invalid:border-nq-danger aria-invalid:border-nq-danger disabled:cursor-not-allowed disabled:opacity-50 pointer-coarse:text-[16px] min-h-20 py-2"></textarea>
</div>
                    <div data-slot="field" x-data="nqField(false)" x-modelable="invalid" x-id="['nq-field']"
         data-valid     class="flex flex-col gap-1.5 md:col-span-2">
    <label data-slot="field-label"  class="text-label text-foreground data-disabled:opacity-50">Share image URL</label>
                        <input data-slot="input" type="text"
     dir="ltr"                 x-model="image" x-on:input="changed()" class="w-full min-w-0 rounded-control border border-input bg-card px-3 text-body text-foreground min-h-[var(--nq-touch-min,0px)] transition-colors duration-150 ease-nq outline-none placeholder:text-muted-foreground focus-visible:border-nq-focus focus-visible:outline-1 focus-visible:outline-nq-focus data-invalid:border-nq-danger aria-invalid:border-nq-danger disabled:cursor-not-allowed disabled:opacity-50 pointer-coarse:text-[16px] h-control text-start">
</div>
                                                    <div data-slot="length-meter" x-bind:data-status="titleMeter.status" class="flex flex-col gap-1.5">
                        <div class="flex items-baseline justify-between gap-3 text-caption">
                            <span class="min-w-0 truncate text-muted-foreground">Title</span>
                            <bdi class="shrink-0 tabular-nums text-muted-foreground" x-text="titleMeter.text"></bdi>
                        </div>
                        <div data-slot="meter" role="meter" aria-label="Title length" aria-valuemin="0" x-bind:aria-valuemax="titleMeter.max" x-bind:aria-valuenow="titleMeter.length" x-bind:aria-valuetext="titleMeter.text" x-bind:data-tone="titleMeter.tone === 'neutral' ? 'default' : titleMeter.tone" class="flex w-full flex-col gap-1.5">
                            <div data-slot="meter-track" class="relative block h-1 w-full overflow-hidden rounded-full bg-nq-surface-soft">
                                <div data-slot="meter-indicator" style="inset-inline-start:0;width:0%" x-bind:style="'inset-inline-start:0;width:' + titleMeter.percent + '%'"
                                    x-bind:class="{  'bg-primary': titleMeter.tone === 'neutral',  'bg-nq-warning': titleMeter.tone === 'warning',  'bg-nq-success': titleMeter.tone === 'success',  'bg-nq-danger': titleMeter.tone === 'danger',  }" class="block h-full rounded-full bg-primary transition-[width] duration-300 ease-nq motion-reduce:transition-none"></div>
                            </div>
                        </div>
                        <span data-slot="status" x-bind:data-tone="titleMeter.tone" class="inline-flex min-w-0 items-center gap-1.5 text-body-sm text-caption"
                            x-bind:class="{  'text-muted-foreground': titleMeter.tone === 'neutral',  'text-nq-warning-text': titleMeter.tone === 'warning',  'text-nq-success-text': titleMeter.tone === 'success',  'text-nq-danger-text': titleMeter.tone === 'danger',  }"><span class="truncate" x-text="titleMeter.verdict"></span></span>
                    </div>
                                    <div data-slot="length-meter" x-bind:data-status="descMeter.status" class="flex flex-col gap-1.5">
                        <div class="flex items-baseline justify-between gap-3 text-caption">
                            <span class="min-w-0 truncate text-muted-foreground">Meta description</span>
                            <bdi class="shrink-0 tabular-nums text-muted-foreground" x-text="descMeter.text"></bdi>
                        </div>
                        <div data-slot="meter" role="meter" aria-label="Meta description length" aria-valuemin="0" x-bind:aria-valuemax="descMeter.max" x-bind:aria-valuenow="descMeter.length" x-bind:aria-valuetext="descMeter.text" x-bind:data-tone="descMeter.tone === 'neutral' ? 'default' : descMeter.tone" class="flex w-full flex-col gap-1.5">
                            <div data-slot="meter-track" class="relative block h-1 w-full overflow-hidden rounded-full bg-nq-surface-soft">
                                <div data-slot="meter-indicator" style="inset-inline-start:0;width:0%" x-bind:style="'inset-inline-start:0;width:' + descMeter.percent + '%'"
                                    x-bind:class="{  'bg-primary': descMeter.tone === 'neutral',  'bg-nq-warning': descMeter.tone === 'warning',  'bg-nq-success': descMeter.tone === 'success',  'bg-nq-danger': descMeter.tone === 'danger',  }" class="block h-full rounded-full bg-primary transition-[width] duration-300 ease-nq motion-reduce:transition-none"></div>
                            </div>
                        </div>
                        <span data-slot="status" x-bind:data-tone="descMeter.tone" class="inline-flex min-w-0 items-center gap-1.5 text-body-sm text-caption"
                            x-bind:class="{  'text-muted-foreground': descMeter.tone === 'neutral',  'text-nq-warning-text': descMeter.tone === 'warning',  'text-nq-success-text': descMeter.tone === 'success',  'text-nq-danger-text': descMeter.tone === 'danger',  }"><span class="truncate" x-text="descMeter.verdict"></span></span>
                    </div>
                            </div>
        </div></div></div>
        </section>
        <section class="grid gap-4 rounded-card border border-border bg-card p-4" aria-label="Status and visibility">
            <h3 class="text-h4 text-foreground">Status and visibility</h3>
            <div class="grid gap-4 sm:grid-cols-2">
                <div class="grid gap-1">
                    <label class="text-label text-foreground" for="product-status">Status</label>
                    <div data-slot="native-select" class="relative w-full min-w-0">
    <select           class="w-full min-w-0 appearance-none rounded-control border border-input bg-card ps-3 pe-9 text-body text-foreground min-h-[var(--nq-touch-min,0px)] transition-colors duration-150 ease-nq outline-none focus-visible:border-nq-focus focus-visible:outline-1 focus-visible:outline-nq-focus data-invalid:border-nq-danger aria-invalid:border-nq-danger disabled:cursor-not-allowed disabled:opacity-50 pointer-coarse:text-[16px] h-control" id="product-status" x-model="draft.status">
                            <option value="active"  >Active</option>
                    <option value="draft"  >Draft</option>
                    <option value="archived"  >Archived</option>
    </select>
    <svg aria-hidden="true" class="pointer-events-none absolute end-3 top-1/2 size-4 -translate-y-1/2 text-muted-foreground" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <path d="m6 9 6 6 6-6"/>
</svg></div>
                    <p class="text-caption text-muted-foreground" x-text="t[`statusHint.${draft.status}`]"></p>
                </div>
                <div class="grid gap-1">
                    <label class="text-label text-foreground" for="product-visibility">Visibility</label>
                    <div data-slot="native-select" class="relative w-full min-w-0">
    <select           class="w-full min-w-0 appearance-none rounded-control border border-input bg-card ps-3 pe-9 text-body text-foreground min-h-[var(--nq-touch-min,0px)] transition-colors duration-150 ease-nq outline-none focus-visible:border-nq-focus focus-visible:outline-1 focus-visible:outline-nq-focus data-invalid:border-nq-danger aria-invalid:border-nq-danger disabled:cursor-not-allowed disabled:opacity-50 pointer-coarse:text-[16px] h-control" id="product-visibility" x-model="draft.visibility">
                            <option value="visible"  >Visible in the store</option>
                    <option value="hidden"  >Hidden from the store (link still works)</option>
    </select>
    <svg aria-hidden="true" class="pointer-events-none absolute end-3 top-1/2 size-4 -translate-y-1/2 text-muted-foreground" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <path d="m6 9 6 6 6-6"/>
</svg></div>
                </div>
            </div>
        </section>
        <div data-slot="product-editor-bar" class="sticky bottom-0 z-10 flex flex-wrap items-center justify-between gap-3 rounded-card border border-border bg-card p-3 shadow-floating">
            <p role="status" aria-live="polite" class="min-w-0 text-body-sm text-muted-foreground">
                <span x-show="error" class="text-body-sm text-nq-danger-text" x-text="error"></span>
                <span x-show="showFix" class="text-body-sm text-nq-danger-text" x-text="fixText"></span>
                <span x-show="showUnsaved" x-text="t.unsaved"></span>
                <span x-show="showSaved" class="text-nq-success-text" x-text="t.allSaved"></span>
            </p>
            <div class="flex gap-2">
                <button data-slot="button"
     type="button"                         x-bind:disabled="discardOff" x-on:click="discard()" class="inline-flex shrink-0 select-none items-center justify-center gap-2 whitespace-nowrap rounded-control border border-transparent font-sans text-label transition-colors duration-150 ease-nq min-h-[var(--nq-touch-min,0px)] outline-none focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-nq-focus disabled:pointer-events-none disabled:opacity-50 data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0 text-foreground hover:bg-nq-hover h-control px-[var(--nq-control-pad)]">
        Discard changes</button>
                <button data-slot="button"
     type="submit"                         x-bind:disabled="saveOff ? true : saving" class="inline-flex shrink-0 select-none items-center justify-center gap-2 whitespace-nowrap rounded-control border border-transparent font-sans text-label transition-colors duration-150 ease-nq min-h-[var(--nq-touch-min,0px)] outline-none focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-nq-focus disabled:pointer-events-none disabled:opacity-50 data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0 bg-primary text-primary-foreground hover:bg-[color-mix(in_oklab,var(--nq-action)_88%,var(--nq-fg))] h-control px-[var(--nq-control-pad)]">
        <span x-text="saving ? t.saving : t.save"></span></button>
            </div>
        </div>
    </div>
</form>
    <section data-slot="media-manager" aria-label="Product images" x-data="nqMediaManager(JSON.parse('{\u0022images\u0022:[{\u0022src\u0022:\u0022\\\/img\\\/shirt-a.jpg\u0022,\u0022alt\u0022:\u0022Front\u0022},{\u0022src\u0022:\u0022\\\/img\\\/shirt-b.jpg\u0022,\u0022alt\u0022:\u0022\u0022},{\u0022src\u0022:\u0022\\\/img\\\/shirt-c.jpg\u0022,\u0022alt\u0022:\u0022Back\u0022}],\u0022maxImages\u0022:12,\u0022disabled\u0022:false,\u0022currency\u0022:\u0022USD\u0022,\u0022locale\u0022:\u0022en\u0022,\u0022t\u0022:{\u0022products\u0022:\u0022Products\u0022,\u0022newProduct\u0022:\u0022New product\u0022,\u0022searchProducts\u0022:\u0022Search products\u0022,\u0022productCol\u0022:\u0022Product\u0022,\u0022statusCol\u0022:\u0022Status\u0022,\u0022stockCol\u0022:\u0022Stock\u0022,\u0022priceCol\u0022:\u0022Price\u0022,\u0022variantsCol\u0022:\u0022Variants\u0022,\u0022categoryCol\u0022:\u0022Category\u0022,\u0022statuses.active\u0022:\u0022Active\u0022,\u0022statuses.draft\u0022:\u0022Draft\u0022,\u0022statuses.archived\u0022:\u0022Archived\u0022,\u0022stockLevels.in\u0022:\u0022In stock\u0022,\u0022stockLevels.low\u0022:\u0022Low stock\u0022,\u0022stockLevels.out\u0022:\u0022Out of stock\u0022,\u0022stockLevels.untracked\u0022:\u0022Not tracked\u0022,\u0022units\u0022:\u0022{0} in stock\u0022,\u0022variantCount\u0022:\u0022{0} variants\u0022,\u0022oneVariant\u0022:\u00221 variant\u0022,\u0022productListLabel\u0022:\u0022Products\u0022,\u0022noProducts\u0022:\u0022No products yet\u0022,\u0022noProductsHint\u0022:\u0022Add your first product to start selling.\u0022,\u0022loadFailed\u0022:\u0022Products did not load.\u0022,\u0022retry\u0022:\u0022Try again\u0022,\u0022edit\u0022:\u0022Edit\u0022,\u0022setActive\u0022:\u0022Set active\u0022,\u0022setDraft\u0022:\u0022Move to drafts\u0022,\u0022archive\u0022:\u0022Archive\u0022,\u0022delete\u0022:\u0022Delete\u0022,\u0022deleteTitle\u0022:\u0022Delete this product?\u0022,\u0022deleteDescription\u0022:\u0022{0} and its variants are removed. Past orders keep their copy.\u0022,\u0022selectedCount\u0022:\u0022{0} selected\u0022,\u0022bulkEdit\u0022:\u0022Bulk edit\u0022,\u0022bulkTitle\u0022:\u0022Edit {0} products\u0022,\u0022bulkDescription\u0022:\u0022Leave a section on Keep to leave it alone. Changes apply to every variant.\u0022,\u0022bulkPrice\u0022:\u0022Price\u0022,\u0022bulkStock\u0022:\u0022Stock\u0022,\u0022bulkStatus\u0022:\u0022Status\u0022,\u0022keep\u0022:\u0022Keep\u0022,\u0022priceModes.set\u0022:\u0022Set to\u0022,\u0022priceModes.increase-percent\u0022:\u0022Raise by percent\u0022,\u0022priceModes.decrease-percent\u0022:\u0022Lower by percent\u0022,\u0022priceModes.increase-amount\u0022:\u0022Raise by amount\u0022,\u0022priceModes.decrease-amount\u0022:\u0022Lower by amount\u0022,\u0022stockModes.set\u0022:\u0022Set to\u0022,\u0022stockModes.add\u0022:\u0022Add\u0022,\u0022stockModes.remove\u0022:\u0022Remove\u0022,\u0022alsoCompareAt\u0022:\u0022Move compare-at price the same way\u0022,\u0022percent\u0022:\u0022Percent\u0022,\u0022amount\u0022:\u0022Amount\u0022,\u0022quantity\u0022:\u0022Quantity\u0022,\u0022preview\u0022:\u0022Preview\u0022,\u0022previewEmpty\u0022:\u0022Nothing changes yet. Pick a change above.\u0022,\u0022previewRow\u0022:\u0022{0}\u0022,\u0022applyToProducts\u0022:\u0022Apply to {0} products\u0022,\u0022cancel\u0022:\u0022Cancel\u0022,\u0022actions\u0022:\u0022Actions\u0022,\u0022editProduct\u0022:\u0022Edit product\u0022,\u0022newProductTitle\u0022:\u0022New product\u0022,\u0022general\u0022:\u0022General\u0022,\u0022title\u0022:\u0022Title\u0022,\u0022description\u0022:\u0022Description\u0022,\u0022descriptionLabel\u0022:\u0022Product description\u0022,\u0022media\u0022:\u0022Media\u0022,\u0022pricing\u0022:\u0022Pricing\u0022,\u0022price\u0022:\u0022Price\u0022,\u0022compareAt\u0022:\u0022Compare-at price\u0022,\u0022compareAtHint\u0022:\u0022The old price shown struck through. Must be above the price.\u0022,\u0022cost\u0022:\u0022Cost per item\u0022,\u0022costHint\u0022:\u0022Only you see this.\u0022,\u0022margin\u0022:\u0022Margin\u0022,\u0022profit\u0022:\u0022Profit\u0022,\u0022markup\u0022:\u0022Markup\u0022,\u0022noMargin\u0022:\u0022Add a price and a cost to see the margin.\u0022,\u0022inventory\u0022:\u0022Inventory\u0022,\u0022sku\u0022:\u0022SKU\u0022,\u0022trackStock\u0022:\u0022Track stock\u0022,\u0022stockQty\u0022:\u0022In stock\u0022,\u0022backorder\u0022:\u0022Sell when out of stock\u0022,\u0022weight\u0022:\u0022Weight (grams)\u0022,\u0022organization\u0022:\u0022Organisation\u0022,\u0022brand\u0022:\u0022Brand\u0022,\u0022category\u0022:\u0022Category\u0022,\u0022tags\u0022:\u0022Tags\u0022,\u0022tagsPlaceholder\u0022:\u0022Add a tag\u0022,\u0022seo\u0022:\u0022Search listing\u0022,\u0022seoTitle\u0022:\u0022Page title\u0022,\u0022seoDescription\u0022:\u0022Meta description\u0022,\u0022slug\u0022:\u0022URL handle\u0022,\u0022slugHint\u0022:\u0022Lower-case letters, digits and dashes.\u0022,\u0022statusSection\u0022:\u0022Status and visibility\u0022,\u0022visibility\u0022:\u0022Visibility\u0022,\u0022visible\u0022:\u0022Visible in the store\u0022,\u0022hidden\u0022:\u0022Hidden from the store (link still works)\u0022,\u0022statusHint.active\u0022:\u0022Customers can buy it.\u0022,\u0022statusHint.draft\u0022:\u0022Only you can see it.\u0022,\u0022statusHint.archived\u0022:\u0022Kept for records, not sold.\u0022,\u0022save\u0022:\u0022Save product\u0022,\u0022saving\u0022:\u0022Saving\u0022,\u0022discard\u0022:\u0022Discard changes\u0022,\u0022unsaved\u0022:\u0022Unsaved changes\u0022,\u0022allSaved\u0022:\u0022All changes saved\u0022,\u0022saveFailed\u0022:\u0022That did not save. Try again.\u0022,\u0022fixIssues\u0022:\u0022{0} to fix before saving\u0022,\u0022issues.title\u0022:\u0022Add a title.\u0022,\u0022issues.price\u0022:\u0022Add a price.\u0022,\u0022issues.compare-at\u0022:\u0022Compare-at must be above the price.\u0022,\u0022issues.sku-duplicate\u0022:\u0022Two variants share a SKU.\u0022,\u0022issues.no-variants\u0022:\u0022Generate the variants for these options.\u0022,\u0022issues.too-many-variants\u0022:\u0022Too many variants. Remove an option value.\u0022,\u0022issues.slug\u0022:\u0022The URL handle has characters that are not allowed.\u0022,\u0022mediaLabel\u0022:\u0022Product images\u0022,\u0022addImage\u0022:\u0022Add image\u0022,\u0022imageUrl\u0022:\u0022Image URL\u0022,\u0022imageUrlPlaceholder\u0022:\u0022https:\\\/\\\/\\u2026\u0022,\u0022altText\u0022:\u0022Alt text\u0022,\u0022altHint\u0022:\u0022Describe the picture for people who cannot see it.\u0022,\u0022missingAlt\u0022:\u0022Alt text missing\u0022,\u0022primary\u0022:\u0022Main image\u0022,\u0022moveEarlier\u0022:\u0022Move earlier\u0022,\u0022moveLater\u0022:\u0022Move later\u0022,\u0022removeImage\u0022:\u0022Remove image\u0022,\u0022dragHandle\u0022:\u0022Reorder image {0}\u0022,\u0022movedTo\u0022:\u0022Image moved to position {0} of {1}\u0022,\u0022noImages\u0022:\u0022No images yet\u0022,\u0022noImagesHint\u0022:\u0022Add a picture by its URL. The first one is the main image.\u0022,\u0022imageFailed\u0022:\u0022Image did not load\u0022,\u0022optionsTitle\u0022:\u0022Options\u0022,\u0022optionsHint\u0022:\u0022Colour, size, material. Up to three options.\u0022,\u0022addOption\u0022:\u0022Add option\u0022,\u0022removeOption\u0022:\u0022Remove option\u0022,\u0022optionName\u0022:\u0022Option name\u0022,\u0022optionNamePlaceholder\u0022:\u0022Size\u0022,\u0022optionValues\u0022:\u0022Values\u0022,\u0022optionValuesPlaceholder\u0022:\u0022Add a value\u0022,\u0022variantsTitle\u0022:\u0022Variants\u0022,\u0022variantsSummary\u0022:\u0022{0} variants\u0022,\u0022variantsRemoved\u0022:\u0022{0} variants no longer match and were removed.\u0022,\u0022variantsTruncated\u0022:\u0022More than {0} combinations. Only the first {0} are created.\u0022,\u0022variantLabel\u0022:\u0022Variant\u0022,\u0022skuCol\u0022:\u0022SKU\u0022,\u0022priceCol2\u0022:\u0022Price\u0022,\u0022compareCol\u0022:\u0022Compare-at\u0022,\u0022stockCol2\u0022:\u0022Stock\u0022,\u0022imageCol\u0022:\u0022Image\u0022,\u0022noImage\u0022:\u0022No image\u0022,\u0022bulkFill\u0022:\u0022Fill selected variants\u0022,\u0022selectVariants\u0022:\u0022Select variants to fill them at once.\u0022,\u0022selectAll\u0022:\u0022Select all variants\u0022,\u0022selectVariant\u0022:\u0022Select {0}\u0022,\u0022fillPrice\u0022:\u0022Price\u0022,\u0022fillCompare\u0022:\u0022Compare-at\u0022,\u0022fillStock\u0022:\u0022Stock\u0022,\u0022fillAddStock\u0022:\u0022Add stock\u0022,\u0022fillSkuPrefix\u0022:\u0022SKU prefix\u0022,\u0022fillApply\u0022:\u0022Apply to selected\u0022,\u0022fillClear\u0022:\u0022Clear selection\u0022,\u0022variantsSelected\u0022:\u0022{0} selected\u0022,\u0022dupSku\u0022:\u0022Duplicate SKU\u0022,\u0022variantsEmpty\u0022:\u0022Add an option to create variants.\u0022,\u0022collections\u0022:\u0022Collections\u0022,\u0022newCollection\u0022:\u0022New collection\u0022,\u0022collectionsLabel\u0022:\u0022Collections\u0022,\u0022collectionTitle\u0022:\u0022Collection title\u0022,\u0022manual\u0022:\u0022Manual\u0022,\u0022rules\u0022:\u0022Rules\u0022,\u0022kindLabel\u0022:\u0022How products join\u0022,\u0022manualHint\u0022:\u0022Pick the products yourself, in the order you want them.\u0022,\u0022rulesHint\u0022:\u0022Products join on their own when they match the rules.\u0022,\u0022matchPreview\u0022:\u0022{0} products match\u0022,\u0022matchNone\u0022:\u0022No products match yet.\u0022,\u0022matchPreviewLabel\u0022:\u0022Products in this collection\u0022,\u0022addProducts\u0022:\u0022Add products\u0022,\u0022addProduct\u0022:\u0022Add a product\u0022,\u0022pickProduct\u0022:\u0022Choose a product\u0022,\u0022removeFromCollection\u0022:\u0022Remove from collection\u0022,\u0022moveUp\u0022:\u0022Move up\u0022,\u0022moveDown\u0022:\u0022Move down\u0022,\u0022saveCollection\u0022:\u0022Save collection\u0022,\u0022deleteCollection\u0022:\u0022Delete collection\u0022,\u0022deleteCollectionTitle\u0022:\u0022Delete this collection?\u0022,\u0022deleteCollectionDescription\u0022:\u0022{0} is removed. The products stay in your catalogue.\u0022,\u0022collectionsEmpty\u0022:\u0022No collections yet\u0022,\u0022collectionsEmptyHint\u0022:\u0022Group products so customers can browse them together.\u0022,\u0022productsCount\u0022:\u0022{0} products\u0022,\u0022ruleAnyProduct\u0022:\u0022any product\u0022,\u0022ruleAddIt\u0022:\u0022add it to this collection\u0022,\u0022ruleEventLabel\u0022:\u0022Applies to\u0022,\u0022ruleEventHelp\u0022:\u0022Every active product is checked against the conditions below.\u0022,\u0022ruleIfTitle\u0022:\u0022Products that match\u0022,\u0022ruleIfHelp\u0022:\u0022Add conditions. A product joins when they hold. With none, no product joins.\u0022,\u0022ruleThenTitle\u0022:\u0022Result\u0022,\u0022ruleThenHelp\u0022:\u0022Matching products are added to this collection.\u0022,\u0022ruleAction\u0022:\u0022Add it to this collection\u0022,\u0022ruleWhere\u0022:\u0022where\u0022,\u0022ruleSo\u0022:\u0022so\u0022,\u0022and\u0022:\u0022and\u0022,\u0022or\u0022:\u0022or\u0022,\u0022editCollection\u0022:\u0022Edit collection\u0022,\u0022fields.tag\u0022:\u0022Tag\u0022,\u0022fields.brand\u0022:\u0022Brand\u0022,\u0022fields.category\u0022:\u0022Category\u0022,\u0022fields.title\u0022:\u0022Title\u0022,\u0022fields.price\u0022:\u0022Price\u0022,\u0022fields.stock\u0022:\u0022Stock\u0022,\u0022fields.onSale\u0022:\u0022On sale\u0022,\u0022fields.status\u0022:\u0022Status\u0022,\u0022close\u0022:\u0022Close\u0022}}'))" x-modelable="images"
    class="flex min-w-0 flex-col gap-3">
    <div class="flex flex-wrap items-center justify-between gap-2">
        <h3 class="text-label text-foreground">Media</h3>
        <span class="inline-flex items-center gap-1 text-caption text-nq-warning-text" x-show="missing > 0">
            <svg aria-hidden="true" class="size-3.5" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <path d="m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3"/>
  <path d="M12 9v4"/>
  <path d="M12 17h.01"/>
</svg>            <span x-text="`${num(missing)} · Alt text missing`"></span>
        </span>
    </div>
    <template x-if="images.length === 0">
        <div data-slot="empty-state" class="flex flex-col items-center justify-center gap-3 border border-border px-6 py-12 text-center rounded-card border-dashed">
            <span data-slot="state-icon" class="inline-flex size-10 items-center justify-center rounded-control border border-border bg-card [&amp;_svg]:size-5 text-muted-foreground">
            <svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <rect width="18" height="18" x="3" y="3" rx="2" ry="2"/>
  <circle cx="9" cy="9" r="2"/>
  <path d="m21 15-3.086-3.086a2 2 0 0 0-2.828 0L6 21"/>
</svg>        </span>
        <div class="flex max-w-sm flex-col gap-1">
        <p class="text-label text-foreground">No images yet</p>
                    <p class="text-body-sm text-muted-foreground">Add a picture by its URL. The first one is the main image.</p>
            </div>
    </div>
    </template>
    <ol x-show="images.length > 0" aria-label="Product images" class="grid gap-3 sm:grid-cols-2 lg:grid-cols-3">
        <template x-for="(im, i) in images" x-bind:key="im.src">
            <li data-slot="media-tile" x-bind:data-dragging="isDragging(i) ? '' : null" x-bind:style="tileStyle(i)" x-bind:class="tileClass(i)"
                class="grid min-w-0 gap-2 rounded-card border border-border bg-card p-2 transition-colors">
                <div class="relative aspect-square w-full overflow-hidden rounded-control bg-secondary">
                    <img alt="" x-show="imgOk(im.src)" x-bind:src="im.src" x-on:error="broken[im.src] = true" class="size-full object-cover" draggable="false" />
                    <div x-show="! imgOk(im.src)" class="flex size-full flex-col items-center justify-center gap-1 text-caption text-muted-foreground">
                        <svg aria-hidden="true" class="size-5" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <line x1="2" x2="22" y1="2" y2="22"/>
  <path d="M10.41 10.41a2 2 0 1 1-2.83-2.83"/>
  <line x1="13.5" x2="6" y1="13.5" y2="21"/>
  <line x1="18" x2="21" y1="12" y2="15"/>
  <path d="M3.59 3.59A1.99 1.99 0 0 0 3 5v14a2 2 0 0 0 2 2h14c.55 0 1.052-.22 1.41-.59"/>
  <path d="M21 15V5a2 2 0 0 0-2-2H9"/>
</svg>                        Image did not load
                    </div>
                    <span x-show="i === 0" data-slot="badge" class="absolute start-1.5 top-1.5 inline-flex h-5 items-center rounded-[4px] border border-primary bg-card px-1.5 text-caption font-medium text-foreground">Main image</span>
                    <button type="button" data-slot="media-drag-handle" x-bind:disabled="off" x-bind:aria-label="tt(`dragHandle`, i + 1)"
                        x-on:pointerdown="dragStart(i, $event)" x-on:keydown="handleKey(i, $event)"
                        class="absolute end-1.5 top-1.5 inline-flex size-7 cursor-grab touch-none items-center justify-center rounded-control border border-border bg-card text-muted-foreground outline-none hover:text-foreground focus-visible:outline-2 focus-visible:outline-nq-focus active:cursor-grabbing">
                        <svg aria-hidden="true" class="size-4" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <circle cx="9" cy="12" r="1"/>
  <circle cx="9" cy="5" r="1"/>
  <circle cx="9" cy="19" r="1"/>
  <circle cx="15" cy="12" r="1"/>
  <circle cx="15" cy="5" r="1"/>
  <circle cx="15" cy="19" r="1"/>
</svg>                    </button>
                </div>
                <div class="flex items-center gap-1">
                    <button data-slot="button"
     type="button"                         x-bind:disabled="off ? true : i === 0" x-bind:aria-label="`Move earlier`" x-on:click="move(i, i - 1)" class="inline-flex shrink-0 select-none items-center justify-center gap-2 whitespace-nowrap rounded-control border border-transparent font-sans text-label transition-colors duration-150 ease-nq min-h-[var(--nq-touch-min,0px)] outline-none focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-nq-focus disabled:pointer-events-none disabled:opacity-50 data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0 text-foreground hover:bg-nq-hover size-control-sm p-0">
        <svg aria-hidden="true" class="rtl:-scale-x-100" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <path d="m12 19-7-7 7-7"/>
  <path d="M19 12H5"/>
</svg></button>
                    <button data-slot="button"
     type="button"                         x-bind:disabled="off ? true : i === images.length - 1" x-bind:aria-label="`Move later`" x-on:click="move(i, i + 1)" class="inline-flex shrink-0 select-none items-center justify-center gap-2 whitespace-nowrap rounded-control border border-transparent font-sans text-label transition-colors duration-150 ease-nq min-h-[var(--nq-touch-min,0px)] outline-none focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-nq-focus disabled:pointer-events-none disabled:opacity-50 data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0 text-foreground hover:bg-nq-hover size-control-sm p-0">
        <svg aria-hidden="true" class="rtl:-scale-x-100" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <path d="M5 12h14"/>
  <path d="m12 5 7 7-7 7"/>
</svg></button>
                    <button data-slot="button"
     type="button"                         x-bind:disabled="off" x-bind:aria-label="`Remove image`" x-on:click="remove(i)" class="inline-flex shrink-0 select-none items-center justify-center gap-2 whitespace-nowrap rounded-control border border-transparent font-sans text-label transition-colors duration-150 ease-nq min-h-[var(--nq-touch-min,0px)] outline-none focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-nq-focus disabled:pointer-events-none disabled:opacity-50 data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0 text-foreground hover:bg-nq-hover size-control-sm p-0 ms-auto">
        <svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <path d="M10 11v6"/>
  <path d="M14 11v6"/>
  <path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6"/>
  <path d="M3 6h18"/>
  <path d="M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"/>
</svg></button>
                </div>
                <input type="text" aria-label="Alt text" placeholder="Alt text" x-bind:value="im.alt" x-bind:disabled="off" x-on:input="setAlt(i, $event.target.value)"
                    x-bind:aria-invalid="im.alt ? null : `true`"
                    class="h-control-sm w-full min-w-0 rounded-control border border-input bg-card px-2 text-body-sm text-foreground outline-none focus-visible:border-nq-focus aria-invalid:border-nq-warning" />
            </li>
        </template>
    </ol>
    <div class="flex flex-wrap items-end gap-2" x-on:keydown.enter.prevent="add()">
        <div class="grid min-w-48 flex-1 gap-1">
            <label class="text-caption text-muted-foreground" for="media-url-url">Image URL</label>
            <input id="media-url-url" type="url" dir="ltr" placeholder="https://…" x-model="url" x-bind:disabled="off ? true : full"
                class="h-control w-full min-w-0 rounded-control border border-input bg-card px-3 text-body text-foreground outline-none focus-visible:border-nq-focus" />
        </div>
        <button data-slot="button"
     type="button"                         x-bind:disabled="! canAdd" x-on:click="add()" class="inline-flex shrink-0 select-none items-center justify-center gap-2 whitespace-nowrap rounded-control border font-sans text-label transition-colors duration-150 ease-nq min-h-[var(--nq-touch-min,0px)] outline-none focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-nq-focus disabled:pointer-events-none disabled:opacity-50 data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0 border-border bg-card text-foreground hover:bg-nq-hover h-control px-[var(--nq-control-pad)]">
        <svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <path d="M5 12h14"/>
  <path d="M12 5v14"/>
</svg>            Add image</button>
    </div>
    <p role="status" aria-live="polite" class="sr-only" x-text="announce"></p>
</section>
    <section data-slot="options-editor" aria-label="Options" x-data="nqOptionsEditor(JSON.parse('{\u0022options\u0022:[{\u0022id\u0022:\u0022colour\u0022,\u0022name\u0022:\u0022Colour\u0022,\u0022display\u0022:\u0022button\u0022,\u0022values\u0022:[{\u0022id\u0022:\u0022red\u0022,\u0022label\u0022:\u0022Red\u0022},{\u0022id\u0022:\u0022blue\u0022,\u0022label\u0022:\u0022Blue\u0022}]}],\u0022maxOptions\u0022:3,\u0022disabled\u0022:false,\u0022currency\u0022:\u0022USD\u0022,\u0022locale\u0022:\u0022en\u0022,\u0022t\u0022:{\u0022products\u0022:\u0022Products\u0022,\u0022newProduct\u0022:\u0022New product\u0022,\u0022searchProducts\u0022:\u0022Search products\u0022,\u0022productCol\u0022:\u0022Product\u0022,\u0022statusCol\u0022:\u0022Status\u0022,\u0022stockCol\u0022:\u0022Stock\u0022,\u0022priceCol\u0022:\u0022Price\u0022,\u0022variantsCol\u0022:\u0022Variants\u0022,\u0022categoryCol\u0022:\u0022Category\u0022,\u0022statuses.active\u0022:\u0022Active\u0022,\u0022statuses.draft\u0022:\u0022Draft\u0022,\u0022statuses.archived\u0022:\u0022Archived\u0022,\u0022stockLevels.in\u0022:\u0022In stock\u0022,\u0022stockLevels.low\u0022:\u0022Low stock\u0022,\u0022stockLevels.out\u0022:\u0022Out of stock\u0022,\u0022stockLevels.untracked\u0022:\u0022Not tracked\u0022,\u0022units\u0022:\u0022{0} in stock\u0022,\u0022variantCount\u0022:\u0022{0} variants\u0022,\u0022oneVariant\u0022:\u00221 variant\u0022,\u0022productListLabel\u0022:\u0022Products\u0022,\u0022noProducts\u0022:\u0022No products yet\u0022,\u0022noProductsHint\u0022:\u0022Add your first product to start selling.\u0022,\u0022loadFailed\u0022:\u0022Products did not load.\u0022,\u0022retry\u0022:\u0022Try again\u0022,\u0022edit\u0022:\u0022Edit\u0022,\u0022setActive\u0022:\u0022Set active\u0022,\u0022setDraft\u0022:\u0022Move to drafts\u0022,\u0022archive\u0022:\u0022Archive\u0022,\u0022delete\u0022:\u0022Delete\u0022,\u0022deleteTitle\u0022:\u0022Delete this product?\u0022,\u0022deleteDescription\u0022:\u0022{0} and its variants are removed. Past orders keep their copy.\u0022,\u0022selectedCount\u0022:\u0022{0} selected\u0022,\u0022bulkEdit\u0022:\u0022Bulk edit\u0022,\u0022bulkTitle\u0022:\u0022Edit {0} products\u0022,\u0022bulkDescription\u0022:\u0022Leave a section on Keep to leave it alone. Changes apply to every variant.\u0022,\u0022bulkPrice\u0022:\u0022Price\u0022,\u0022bulkStock\u0022:\u0022Stock\u0022,\u0022bulkStatus\u0022:\u0022Status\u0022,\u0022keep\u0022:\u0022Keep\u0022,\u0022priceModes.set\u0022:\u0022Set to\u0022,\u0022priceModes.increase-percent\u0022:\u0022Raise by percent\u0022,\u0022priceModes.decrease-percent\u0022:\u0022Lower by percent\u0022,\u0022priceModes.increase-amount\u0022:\u0022Raise by amount\u0022,\u0022priceModes.decrease-amount\u0022:\u0022Lower by amount\u0022,\u0022stockModes.set\u0022:\u0022Set to\u0022,\u0022stockModes.add\u0022:\u0022Add\u0022,\u0022stockModes.remove\u0022:\u0022Remove\u0022,\u0022alsoCompareAt\u0022:\u0022Move compare-at price the same way\u0022,\u0022percent\u0022:\u0022Percent\u0022,\u0022amount\u0022:\u0022Amount\u0022,\u0022quantity\u0022:\u0022Quantity\u0022,\u0022preview\u0022:\u0022Preview\u0022,\u0022previewEmpty\u0022:\u0022Nothing changes yet. Pick a change above.\u0022,\u0022previewRow\u0022:\u0022{0}\u0022,\u0022applyToProducts\u0022:\u0022Apply to {0} products\u0022,\u0022cancel\u0022:\u0022Cancel\u0022,\u0022actions\u0022:\u0022Actions\u0022,\u0022editProduct\u0022:\u0022Edit product\u0022,\u0022newProductTitle\u0022:\u0022New product\u0022,\u0022general\u0022:\u0022General\u0022,\u0022title\u0022:\u0022Title\u0022,\u0022description\u0022:\u0022Description\u0022,\u0022descriptionLabel\u0022:\u0022Product description\u0022,\u0022media\u0022:\u0022Media\u0022,\u0022pricing\u0022:\u0022Pricing\u0022,\u0022price\u0022:\u0022Price\u0022,\u0022compareAt\u0022:\u0022Compare-at price\u0022,\u0022compareAtHint\u0022:\u0022The old price shown struck through. Must be above the price.\u0022,\u0022cost\u0022:\u0022Cost per item\u0022,\u0022costHint\u0022:\u0022Only you see this.\u0022,\u0022margin\u0022:\u0022Margin\u0022,\u0022profit\u0022:\u0022Profit\u0022,\u0022markup\u0022:\u0022Markup\u0022,\u0022noMargin\u0022:\u0022Add a price and a cost to see the margin.\u0022,\u0022inventory\u0022:\u0022Inventory\u0022,\u0022sku\u0022:\u0022SKU\u0022,\u0022trackStock\u0022:\u0022Track stock\u0022,\u0022stockQty\u0022:\u0022In stock\u0022,\u0022backorder\u0022:\u0022Sell when out of stock\u0022,\u0022weight\u0022:\u0022Weight (grams)\u0022,\u0022organization\u0022:\u0022Organisation\u0022,\u0022brand\u0022:\u0022Brand\u0022,\u0022category\u0022:\u0022Category\u0022,\u0022tags\u0022:\u0022Tags\u0022,\u0022tagsPlaceholder\u0022:\u0022Add a tag\u0022,\u0022seo\u0022:\u0022Search listing\u0022,\u0022seoTitle\u0022:\u0022Page title\u0022,\u0022seoDescription\u0022:\u0022Meta description\u0022,\u0022slug\u0022:\u0022URL handle\u0022,\u0022slugHint\u0022:\u0022Lower-case letters, digits and dashes.\u0022,\u0022statusSection\u0022:\u0022Status and visibility\u0022,\u0022visibility\u0022:\u0022Visibility\u0022,\u0022visible\u0022:\u0022Visible in the store\u0022,\u0022hidden\u0022:\u0022Hidden from the store (link still works)\u0022,\u0022statusHint.active\u0022:\u0022Customers can buy it.\u0022,\u0022statusHint.draft\u0022:\u0022Only you can see it.\u0022,\u0022statusHint.archived\u0022:\u0022Kept for records, not sold.\u0022,\u0022save\u0022:\u0022Save product\u0022,\u0022saving\u0022:\u0022Saving\u0022,\u0022discard\u0022:\u0022Discard changes\u0022,\u0022unsaved\u0022:\u0022Unsaved changes\u0022,\u0022allSaved\u0022:\u0022All changes saved\u0022,\u0022saveFailed\u0022:\u0022That did not save. Try again.\u0022,\u0022fixIssues\u0022:\u0022{0} to fix before saving\u0022,\u0022issues.title\u0022:\u0022Add a title.\u0022,\u0022issues.price\u0022:\u0022Add a price.\u0022,\u0022issues.compare-at\u0022:\u0022Compare-at must be above the price.\u0022,\u0022issues.sku-duplicate\u0022:\u0022Two variants share a SKU.\u0022,\u0022issues.no-variants\u0022:\u0022Generate the variants for these options.\u0022,\u0022issues.too-many-variants\u0022:\u0022Too many variants. Remove an option value.\u0022,\u0022issues.slug\u0022:\u0022The URL handle has characters that are not allowed.\u0022,\u0022mediaLabel\u0022:\u0022Product images\u0022,\u0022addImage\u0022:\u0022Add image\u0022,\u0022imageUrl\u0022:\u0022Image URL\u0022,\u0022imageUrlPlaceholder\u0022:\u0022https:\\\/\\\/\\u2026\u0022,\u0022altText\u0022:\u0022Alt text\u0022,\u0022altHint\u0022:\u0022Describe the picture for people who cannot see it.\u0022,\u0022missingAlt\u0022:\u0022Alt text missing\u0022,\u0022primary\u0022:\u0022Main image\u0022,\u0022moveEarlier\u0022:\u0022Move earlier\u0022,\u0022moveLater\u0022:\u0022Move later\u0022,\u0022removeImage\u0022:\u0022Remove image\u0022,\u0022dragHandle\u0022:\u0022Reorder image {0}\u0022,\u0022movedTo\u0022:\u0022Image moved to position {0} of {1}\u0022,\u0022noImages\u0022:\u0022No images yet\u0022,\u0022noImagesHint\u0022:\u0022Add a picture by its URL. The first one is the main image.\u0022,\u0022imageFailed\u0022:\u0022Image did not load\u0022,\u0022optionsTitle\u0022:\u0022Options\u0022,\u0022optionsHint\u0022:\u0022Colour, size, material. Up to three options.\u0022,\u0022addOption\u0022:\u0022Add option\u0022,\u0022removeOption\u0022:\u0022Remove option\u0022,\u0022optionName\u0022:\u0022Option name\u0022,\u0022optionNamePlaceholder\u0022:\u0022Size\u0022,\u0022optionValues\u0022:\u0022Values\u0022,\u0022optionValuesPlaceholder\u0022:\u0022Add a value\u0022,\u0022variantsTitle\u0022:\u0022Variants\u0022,\u0022variantsSummary\u0022:\u0022{0} variants\u0022,\u0022variantsRemoved\u0022:\u0022{0} variants no longer match and were removed.\u0022,\u0022variantsTruncated\u0022:\u0022More than {0} combinations. Only the first {0} are created.\u0022,\u0022variantLabel\u0022:\u0022Variant\u0022,\u0022skuCol\u0022:\u0022SKU\u0022,\u0022priceCol2\u0022:\u0022Price\u0022,\u0022compareCol\u0022:\u0022Compare-at\u0022,\u0022stockCol2\u0022:\u0022Stock\u0022,\u0022imageCol\u0022:\u0022Image\u0022,\u0022noImage\u0022:\u0022No image\u0022,\u0022bulkFill\u0022:\u0022Fill selected variants\u0022,\u0022selectVariants\u0022:\u0022Select variants to fill them at once.\u0022,\u0022selectAll\u0022:\u0022Select all variants\u0022,\u0022selectVariant\u0022:\u0022Select {0}\u0022,\u0022fillPrice\u0022:\u0022Price\u0022,\u0022fillCompare\u0022:\u0022Compare-at\u0022,\u0022fillStock\u0022:\u0022Stock\u0022,\u0022fillAddStock\u0022:\u0022Add stock\u0022,\u0022fillSkuPrefix\u0022:\u0022SKU prefix\u0022,\u0022fillApply\u0022:\u0022Apply to selected\u0022,\u0022fillClear\u0022:\u0022Clear selection\u0022,\u0022variantsSelected\u0022:\u0022{0} selected\u0022,\u0022dupSku\u0022:\u0022Duplicate SKU\u0022,\u0022variantsEmpty\u0022:\u0022Add an option to create variants.\u0022,\u0022collections\u0022:\u0022Collections\u0022,\u0022newCollection\u0022:\u0022New collection\u0022,\u0022collectionsLabel\u0022:\u0022Collections\u0022,\u0022collectionTitle\u0022:\u0022Collection title\u0022,\u0022manual\u0022:\u0022Manual\u0022,\u0022rules\u0022:\u0022Rules\u0022,\u0022kindLabel\u0022:\u0022How products join\u0022,\u0022manualHint\u0022:\u0022Pick the products yourself, in the order you want them.\u0022,\u0022rulesHint\u0022:\u0022Products join on their own when they match the rules.\u0022,\u0022matchPreview\u0022:\u0022{0} products match\u0022,\u0022matchNone\u0022:\u0022No products match yet.\u0022,\u0022matchPreviewLabel\u0022:\u0022Products in this collection\u0022,\u0022addProducts\u0022:\u0022Add products\u0022,\u0022addProduct\u0022:\u0022Add a product\u0022,\u0022pickProduct\u0022:\u0022Choose a product\u0022,\u0022removeFromCollection\u0022:\u0022Remove from collection\u0022,\u0022moveUp\u0022:\u0022Move up\u0022,\u0022moveDown\u0022:\u0022Move down\u0022,\u0022saveCollection\u0022:\u0022Save collection\u0022,\u0022deleteCollection\u0022:\u0022Delete collection\u0022,\u0022deleteCollectionTitle\u0022:\u0022Delete this collection?\u0022,\u0022deleteCollectionDescription\u0022:\u0022{0} is removed. The products stay in your catalogue.\u0022,\u0022collectionsEmpty\u0022:\u0022No collections yet\u0022,\u0022collectionsEmptyHint\u0022:\u0022Group products so customers can browse them together.\u0022,\u0022productsCount\u0022:\u0022{0} products\u0022,\u0022ruleAnyProduct\u0022:\u0022any product\u0022,\u0022ruleAddIt\u0022:\u0022add it to this collection\u0022,\u0022ruleEventLabel\u0022:\u0022Applies to\u0022,\u0022ruleEventHelp\u0022:\u0022Every active product is checked against the conditions below.\u0022,\u0022ruleIfTitle\u0022:\u0022Products that match\u0022,\u0022ruleIfHelp\u0022:\u0022Add conditions. A product joins when they hold. With none, no product joins.\u0022,\u0022ruleThenTitle\u0022:\u0022Result\u0022,\u0022ruleThenHelp\u0022:\u0022Matching products are added to this collection.\u0022,\u0022ruleAction\u0022:\u0022Add it to this collection\u0022,\u0022ruleWhere\u0022:\u0022where\u0022,\u0022ruleSo\u0022:\u0022so\u0022,\u0022and\u0022:\u0022and\u0022,\u0022or\u0022:\u0022or\u0022,\u0022editCollection\u0022:\u0022Edit collection\u0022,\u0022fields.tag\u0022:\u0022Tag\u0022,\u0022fields.brand\u0022:\u0022Brand\u0022,\u0022fields.category\u0022:\u0022Category\u0022,\u0022fields.title\u0022:\u0022Title\u0022,\u0022fields.price\u0022:\u0022Price\u0022,\u0022fields.stock\u0022:\u0022Stock\u0022,\u0022fields.onSale\u0022:\u0022On sale\u0022,\u0022fields.status\u0022:\u0022Status\u0022,\u0022close\u0022:\u0022Close\u0022}}'))" x-modelable="options"
    class="flex min-w-0 flex-col gap-3">
    <div class="flex flex-wrap items-center justify-between gap-2">
        <div class="grid gap-0.5">
            <h3 class="text-label text-foreground">Options</h3>
            <p class="text-caption text-muted-foreground">Colour, size, material. Up to three options.</p>
        </div>
        <button data-slot="button"
     type="button"                         x-bind:disabled="! canAdd" x-on:click="add()" class="inline-flex shrink-0 select-none items-center justify-center gap-2 whitespace-nowrap rounded-control border font-sans text-label transition-colors duration-150 ease-nq min-h-[var(--nq-touch-min,0px)] outline-none focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-nq-focus disabled:pointer-events-none disabled:opacity-50 data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0 border-border bg-card text-foreground hover:bg-nq-hover h-control-sm px-2.5">
        <svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <path d="M5 12h14"/>
  <path d="M12 5v14"/>
</svg>            Add option</button>
    </div>
    <div class="grid gap-3">
        <template x-for="o in options" x-bind:key="o.id">
            <div data-slot="option-row" class="grid gap-2 rounded-card border border-border bg-card p-3 sm:grid-cols-[12rem_1fr_auto] sm:items-end"
                x-data="{ labels: [] }" x-effect="labels = reconcile(o, labels)">
                <div class="grid gap-1">
                    <label class="text-caption text-muted-foreground" x-bind:for="`opt-name-` + o.id">Option name</label>
                    <input type="text" x-bind:id="`opt-name-` + o.id" placeholder="Size" x-bind:value="o.name" x-bind:disabled="off" x-on:input="setName(o.id, $event.target.value)"
                        class="h-control w-full min-w-0 rounded-control border border-input bg-card px-3 text-body text-foreground outline-none focus-visible:border-nq-focus" />
                </div>
                <div class="grid gap-1">
                    <span class="text-caption text-muted-foreground">Values</span>
                    <div data-slot="tag-input" x-data="nqTagInput([], {})" x-modelable="tags" x-bind="root"
         x-model="labels" class="relative w-full">
    <div data-slot="tag-input-box" x-bind="box"
        class="flex w-full min-w-0 flex-wrap items-center gap-1.5 rounded-control border border-input bg-card px-2 py-1 text-body text-foreground min-h-[max(var(--nq-control),var(--nq-touch-min,0px))] transition-colors duration-150 ease-nq focus-within:border-nq-focus focus-within:outline-1 focus-within:outline-nq-focus has-[[data-invalid]]:border-nq-danger has-[[aria-invalid=true]]:border-nq-danger">
        <template x-for="(tag, i) in tags" :key="tag">
            <span data-slot="tag-input-tag" data-variant="neutral" class="inline-flex w-fit shrink-0 items-center justify-center whitespace-nowrap rounded-control border border-transparent bg-muted px-2 py-0.5 font-medium text-foreground h-6 gap-0.5 ps-2 pe-0.5 text-body-sm">
                <bdi x-text="tag"></bdi>
                <button type="button"  :aria-label="'Remove' + ' ' + tag" @click.stop="removeAt(i)"
                    class="inline-flex size-5 items-center justify-center rounded-[3px] text-muted-foreground outline-none hover:bg-nq-hover hover:text-foreground focus-visible:outline-2 focus-visible:outline-nq-focus">
                    <span aria-hidden="true" class="flex [&_svg]:size-3"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <path d="M18 6 6 18"/>
  <path d="m6 6 12 12"/>
</svg></span>
                </button>
            </span>
        </template>
        <input data-slot="tag-input-field" x-ref="field" x-bind="field" autocomplete="off"             :placeholder="tags.length ? undefined : 'Add a value'"
                        aria-label="Values" class="h-7 min-w-24 flex-1 border-0 bg-transparent px-1 text-body outline-none placeholder:text-muted-foreground pointer-coarse:text-[16px]">
    </div>
        <p x-show="error" x-cloak style="display: none" role="alert" data-slot="tag-input-error" x-text="error" class="mt-1.5 text-caption text-nq-danger-text"></p>
    <span role="status" aria-live="polite" class="sr-only" x-text="message"></span>
    </div>
                </div>
                <button data-slot="button"
     type="button"                         x-bind:disabled="off" x-bind:aria-label="`Remove option: ${o.name}`" x-on:click="remove(o.id)" class="inline-flex shrink-0 select-none items-center justify-center gap-2 whitespace-nowrap rounded-control border border-transparent font-sans text-label transition-colors duration-150 ease-nq min-h-[var(--nq-touch-min,0px)] outline-none focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-nq-focus disabled:pointer-events-none disabled:opacity-50 data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0 text-foreground hover:bg-nq-hover size-control p-0">
        <svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <path d="M10 11v6"/>
  <path d="M14 11v6"/>
  <path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6"/>
  <path d="M3 6h18"/>
  <path d="M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"/>
</svg></button>
            </div>
        </template>
    </div>
</section>
    <section data-slot="variant-matrix" aria-label="Variants" x-data="nqVariantMatrix(JSON.parse('{\u0022options\u0022:[{\u0022id\u0022:\u0022colour\u0022,\u0022name\u0022:\u0022Colour\u0022,\u0022display\u0022:\u0022button\u0022,\u0022values\u0022:[{\u0022id\u0022:\u0022red\u0022,\u0022label\u0022:\u0022Red\u0022},{\u0022id\u0022:\u0022blue\u0022,\u0022label\u0022:\u0022Blue\u0022}]}],\u0022variants\u0022:[{\u0022id\u0022:\u0022v1\u0022,\u0022options\u0022:{\u0022colour\u0022:\u0022red\u0022},\u0022price\u0022:4900,\u0022compareAt\u0022:5900,\u0022stock\u0022:12,\u0022sku\u0022:\u0022LIN-RED\u0022},{\u0022id\u0022:\u0022v2\u0022,\u0022options\u0022:{\u0022colour\u0022:\u0022blue\u0022},\u0022price\u0022:4900,\u0022stock\u0022:2,\u0022sku\u0022:\u0022LIN-BLUE\u0022}],\u0022images\u0022:[{\u0022src\u0022:\u0022\\\/img\\\/shirt-a.jpg\u0022,\u0022alt\u0022:\u0022Front\u0022},{\u0022src\u0022:\u0022\\\/img\\\/shirt-b.jpg\u0022,\u0022alt\u0022:\u0022\u0022},{\u0022src\u0022:\u0022\\\/img\\\/shirt-c.jpg\u0022,\u0022alt\u0022:\u0022Back\u0022}],\u0022disabled\u0022:false,\u0022currency\u0022:\u0022USD\u0022,\u0022locale\u0022:\u0022en\u0022,\u0022t\u0022:{\u0022products\u0022:\u0022Products\u0022,\u0022newProduct\u0022:\u0022New product\u0022,\u0022searchProducts\u0022:\u0022Search products\u0022,\u0022productCol\u0022:\u0022Product\u0022,\u0022statusCol\u0022:\u0022Status\u0022,\u0022stockCol\u0022:\u0022Stock\u0022,\u0022priceCol\u0022:\u0022Price\u0022,\u0022variantsCol\u0022:\u0022Variants\u0022,\u0022categoryCol\u0022:\u0022Category\u0022,\u0022statuses.active\u0022:\u0022Active\u0022,\u0022statuses.draft\u0022:\u0022Draft\u0022,\u0022statuses.archived\u0022:\u0022Archived\u0022,\u0022stockLevels.in\u0022:\u0022In stock\u0022,\u0022stockLevels.low\u0022:\u0022Low stock\u0022,\u0022stockLevels.out\u0022:\u0022Out of stock\u0022,\u0022stockLevels.untracked\u0022:\u0022Not tracked\u0022,\u0022units\u0022:\u0022{0} in stock\u0022,\u0022variantCount\u0022:\u0022{0} variants\u0022,\u0022oneVariant\u0022:\u00221 variant\u0022,\u0022productListLabel\u0022:\u0022Products\u0022,\u0022noProducts\u0022:\u0022No products yet\u0022,\u0022noProductsHint\u0022:\u0022Add your first product to start selling.\u0022,\u0022loadFailed\u0022:\u0022Products did not load.\u0022,\u0022retry\u0022:\u0022Try again\u0022,\u0022edit\u0022:\u0022Edit\u0022,\u0022setActive\u0022:\u0022Set active\u0022,\u0022setDraft\u0022:\u0022Move to drafts\u0022,\u0022archive\u0022:\u0022Archive\u0022,\u0022delete\u0022:\u0022Delete\u0022,\u0022deleteTitle\u0022:\u0022Delete this product?\u0022,\u0022deleteDescription\u0022:\u0022{0} and its variants are removed. Past orders keep their copy.\u0022,\u0022selectedCount\u0022:\u0022{0} selected\u0022,\u0022bulkEdit\u0022:\u0022Bulk edit\u0022,\u0022bulkTitle\u0022:\u0022Edit {0} products\u0022,\u0022bulkDescription\u0022:\u0022Leave a section on Keep to leave it alone. Changes apply to every variant.\u0022,\u0022bulkPrice\u0022:\u0022Price\u0022,\u0022bulkStock\u0022:\u0022Stock\u0022,\u0022bulkStatus\u0022:\u0022Status\u0022,\u0022keep\u0022:\u0022Keep\u0022,\u0022priceModes.set\u0022:\u0022Set to\u0022,\u0022priceModes.increase-percent\u0022:\u0022Raise by percent\u0022,\u0022priceModes.decrease-percent\u0022:\u0022Lower by percent\u0022,\u0022priceModes.increase-amount\u0022:\u0022Raise by amount\u0022,\u0022priceModes.decrease-amount\u0022:\u0022Lower by amount\u0022,\u0022stockModes.set\u0022:\u0022Set to\u0022,\u0022stockModes.add\u0022:\u0022Add\u0022,\u0022stockModes.remove\u0022:\u0022Remove\u0022,\u0022alsoCompareAt\u0022:\u0022Move compare-at price the same way\u0022,\u0022percent\u0022:\u0022Percent\u0022,\u0022amount\u0022:\u0022Amount\u0022,\u0022quantity\u0022:\u0022Quantity\u0022,\u0022preview\u0022:\u0022Preview\u0022,\u0022previewEmpty\u0022:\u0022Nothing changes yet. Pick a change above.\u0022,\u0022previewRow\u0022:\u0022{0}\u0022,\u0022applyToProducts\u0022:\u0022Apply to {0} products\u0022,\u0022cancel\u0022:\u0022Cancel\u0022,\u0022actions\u0022:\u0022Actions\u0022,\u0022editProduct\u0022:\u0022Edit product\u0022,\u0022newProductTitle\u0022:\u0022New product\u0022,\u0022general\u0022:\u0022General\u0022,\u0022title\u0022:\u0022Title\u0022,\u0022description\u0022:\u0022Description\u0022,\u0022descriptionLabel\u0022:\u0022Product description\u0022,\u0022media\u0022:\u0022Media\u0022,\u0022pricing\u0022:\u0022Pricing\u0022,\u0022price\u0022:\u0022Price\u0022,\u0022compareAt\u0022:\u0022Compare-at price\u0022,\u0022compareAtHint\u0022:\u0022The old price shown struck through. Must be above the price.\u0022,\u0022cost\u0022:\u0022Cost per item\u0022,\u0022costHint\u0022:\u0022Only you see this.\u0022,\u0022margin\u0022:\u0022Margin\u0022,\u0022profit\u0022:\u0022Profit\u0022,\u0022markup\u0022:\u0022Markup\u0022,\u0022noMargin\u0022:\u0022Add a price and a cost to see the margin.\u0022,\u0022inventory\u0022:\u0022Inventory\u0022,\u0022sku\u0022:\u0022SKU\u0022,\u0022trackStock\u0022:\u0022Track stock\u0022,\u0022stockQty\u0022:\u0022In stock\u0022,\u0022backorder\u0022:\u0022Sell when out of stock\u0022,\u0022weight\u0022:\u0022Weight (grams)\u0022,\u0022organization\u0022:\u0022Organisation\u0022,\u0022brand\u0022:\u0022Brand\u0022,\u0022category\u0022:\u0022Category\u0022,\u0022tags\u0022:\u0022Tags\u0022,\u0022tagsPlaceholder\u0022:\u0022Add a tag\u0022,\u0022seo\u0022:\u0022Search listing\u0022,\u0022seoTitle\u0022:\u0022Page title\u0022,\u0022seoDescription\u0022:\u0022Meta description\u0022,\u0022slug\u0022:\u0022URL handle\u0022,\u0022slugHint\u0022:\u0022Lower-case letters, digits and dashes.\u0022,\u0022statusSection\u0022:\u0022Status and visibility\u0022,\u0022visibility\u0022:\u0022Visibility\u0022,\u0022visible\u0022:\u0022Visible in the store\u0022,\u0022hidden\u0022:\u0022Hidden from the store (link still works)\u0022,\u0022statusHint.active\u0022:\u0022Customers can buy it.\u0022,\u0022statusHint.draft\u0022:\u0022Only you can see it.\u0022,\u0022statusHint.archived\u0022:\u0022Kept for records, not sold.\u0022,\u0022save\u0022:\u0022Save product\u0022,\u0022saving\u0022:\u0022Saving\u0022,\u0022discard\u0022:\u0022Discard changes\u0022,\u0022unsaved\u0022:\u0022Unsaved changes\u0022,\u0022allSaved\u0022:\u0022All changes saved\u0022,\u0022saveFailed\u0022:\u0022That did not save. Try again.\u0022,\u0022fixIssues\u0022:\u0022{0} to fix before saving\u0022,\u0022issues.title\u0022:\u0022Add a title.\u0022,\u0022issues.price\u0022:\u0022Add a price.\u0022,\u0022issues.compare-at\u0022:\u0022Compare-at must be above the price.\u0022,\u0022issues.sku-duplicate\u0022:\u0022Two variants share a SKU.\u0022,\u0022issues.no-variants\u0022:\u0022Generate the variants for these options.\u0022,\u0022issues.too-many-variants\u0022:\u0022Too many variants. Remove an option value.\u0022,\u0022issues.slug\u0022:\u0022The URL handle has characters that are not allowed.\u0022,\u0022mediaLabel\u0022:\u0022Product images\u0022,\u0022addImage\u0022:\u0022Add image\u0022,\u0022imageUrl\u0022:\u0022Image URL\u0022,\u0022imageUrlPlaceholder\u0022:\u0022https:\\\/\\\/\\u2026\u0022,\u0022altText\u0022:\u0022Alt text\u0022,\u0022altHint\u0022:\u0022Describe the picture for people who cannot see it.\u0022,\u0022missingAlt\u0022:\u0022Alt text missing\u0022,\u0022primary\u0022:\u0022Main image\u0022,\u0022moveEarlier\u0022:\u0022Move earlier\u0022,\u0022moveLater\u0022:\u0022Move later\u0022,\u0022removeImage\u0022:\u0022Remove image\u0022,\u0022dragHandle\u0022:\u0022Reorder image {0}\u0022,\u0022movedTo\u0022:\u0022Image moved to position {0} of {1}\u0022,\u0022noImages\u0022:\u0022No images yet\u0022,\u0022noImagesHint\u0022:\u0022Add a picture by its URL. The first one is the main image.\u0022,\u0022imageFailed\u0022:\u0022Image did not load\u0022,\u0022optionsTitle\u0022:\u0022Options\u0022,\u0022optionsHint\u0022:\u0022Colour, size, material. Up to three options.\u0022,\u0022addOption\u0022:\u0022Add option\u0022,\u0022removeOption\u0022:\u0022Remove option\u0022,\u0022optionName\u0022:\u0022Option name\u0022,\u0022optionNamePlaceholder\u0022:\u0022Size\u0022,\u0022optionValues\u0022:\u0022Values\u0022,\u0022optionValuesPlaceholder\u0022:\u0022Add a value\u0022,\u0022variantsTitle\u0022:\u0022Variants\u0022,\u0022variantsSummary\u0022:\u0022{0} variants\u0022,\u0022variantsRemoved\u0022:\u0022{0} variants no longer match and were removed.\u0022,\u0022variantsTruncated\u0022:\u0022More than {0} combinations. Only the first {0} are created.\u0022,\u0022variantLabel\u0022:\u0022Variant\u0022,\u0022skuCol\u0022:\u0022SKU\u0022,\u0022priceCol2\u0022:\u0022Price\u0022,\u0022compareCol\u0022:\u0022Compare-at\u0022,\u0022stockCol2\u0022:\u0022Stock\u0022,\u0022imageCol\u0022:\u0022Image\u0022,\u0022noImage\u0022:\u0022No image\u0022,\u0022bulkFill\u0022:\u0022Fill selected variants\u0022,\u0022selectVariants\u0022:\u0022Select variants to fill them at once.\u0022,\u0022selectAll\u0022:\u0022Select all variants\u0022,\u0022selectVariant\u0022:\u0022Select {0}\u0022,\u0022fillPrice\u0022:\u0022Price\u0022,\u0022fillCompare\u0022:\u0022Compare-at\u0022,\u0022fillStock\u0022:\u0022Stock\u0022,\u0022fillAddStock\u0022:\u0022Add stock\u0022,\u0022fillSkuPrefix\u0022:\u0022SKU prefix\u0022,\u0022fillApply\u0022:\u0022Apply to selected\u0022,\u0022fillClear\u0022:\u0022Clear selection\u0022,\u0022variantsSelected\u0022:\u0022{0} selected\u0022,\u0022dupSku\u0022:\u0022Duplicate SKU\u0022,\u0022variantsEmpty\u0022:\u0022Add an option to create variants.\u0022,\u0022collections\u0022:\u0022Collections\u0022,\u0022newCollection\u0022:\u0022New collection\u0022,\u0022collectionsLabel\u0022:\u0022Collections\u0022,\u0022collectionTitle\u0022:\u0022Collection title\u0022,\u0022manual\u0022:\u0022Manual\u0022,\u0022rules\u0022:\u0022Rules\u0022,\u0022kindLabel\u0022:\u0022How products join\u0022,\u0022manualHint\u0022:\u0022Pick the products yourself, in the order you want them.\u0022,\u0022rulesHint\u0022:\u0022Products join on their own when they match the rules.\u0022,\u0022matchPreview\u0022:\u0022{0} products match\u0022,\u0022matchNone\u0022:\u0022No products match yet.\u0022,\u0022matchPreviewLabel\u0022:\u0022Products in this collection\u0022,\u0022addProducts\u0022:\u0022Add products\u0022,\u0022addProduct\u0022:\u0022Add a product\u0022,\u0022pickProduct\u0022:\u0022Choose a product\u0022,\u0022removeFromCollection\u0022:\u0022Remove from collection\u0022,\u0022moveUp\u0022:\u0022Move up\u0022,\u0022moveDown\u0022:\u0022Move down\u0022,\u0022saveCollection\u0022:\u0022Save collection\u0022,\u0022deleteCollection\u0022:\u0022Delete collection\u0022,\u0022deleteCollectionTitle\u0022:\u0022Delete this collection?\u0022,\u0022deleteCollectionDescription\u0022:\u0022{0} is removed. The products stay in your catalogue.\u0022,\u0022collectionsEmpty\u0022:\u0022No collections yet\u0022,\u0022collectionsEmptyHint\u0022:\u0022Group products so customers can browse them together.\u0022,\u0022productsCount\u0022:\u0022{0} products\u0022,\u0022ruleAnyProduct\u0022:\u0022any product\u0022,\u0022ruleAddIt\u0022:\u0022add it to this collection\u0022,\u0022ruleEventLabel\u0022:\u0022Applies to\u0022,\u0022ruleEventHelp\u0022:\u0022Every active product is checked against the conditions below.\u0022,\u0022ruleIfTitle\u0022:\u0022Products that match\u0022,\u0022ruleIfHelp\u0022:\u0022Add conditions. A product joins when they hold. With none, no product joins.\u0022,\u0022ruleThenTitle\u0022:\u0022Result\u0022,\u0022ruleThenHelp\u0022:\u0022Matching products are added to this collection.\u0022,\u0022ruleAction\u0022:\u0022Add it to this collection\u0022,\u0022ruleWhere\u0022:\u0022where\u0022,\u0022ruleSo\u0022:\u0022so\u0022,\u0022and\u0022:\u0022and\u0022,\u0022or\u0022:\u0022or\u0022,\u0022editCollection\u0022:\u0022Edit collection\u0022,\u0022fields.tag\u0022:\u0022Tag\u0022,\u0022fields.brand\u0022:\u0022Brand\u0022,\u0022fields.category\u0022:\u0022Category\u0022,\u0022fields.title\u0022:\u0022Title\u0022,\u0022fields.price\u0022:\u0022Price\u0022,\u0022fields.stock\u0022:\u0022Stock\u0022,\u0022fields.onSale\u0022:\u0022On sale\u0022,\u0022fields.status\u0022:\u0022Status\u0022,\u0022close\u0022:\u0022Close\u0022}}'))" x-modelable="variants"
    class="flex min-w-0 flex-col gap-3">
    <h3 class="text-label text-foreground">Variants</h3>
    <template x-if="variants.length === 0">
        <div data-slot="empty-state" class="flex flex-col items-center justify-center gap-3 border border-border px-6 py-12 text-center rounded-card border-dashed">
            <span data-slot="state-icon" class="inline-flex size-10 items-center justify-center rounded-control border border-border bg-card [&amp;_svg]:size-5 text-muted-foreground">
            <svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <path d="M12.83 2.18a2 2 0 0 0-1.66 0L2.6 6.08a1 1 0 0 0 0 1.83l8.58 3.91a2 2 0 0 0 1.66 0l8.58-3.9a1 1 0 0 0 0-1.83z"/>
  <path d="M2 12a1 1 0 0 0 .58.91l8.6 3.91a2 2 0 0 0 1.65 0l8.58-3.9A1 1 0 0 0 22 12"/>
  <path d="M2 17a1 1 0 0 0 .58.91l8.6 3.91a2 2 0 0 0 1.65 0l8.58-3.9A1 1 0 0 0 22 17"/>
</svg>        </span>
        <div class="flex max-w-sm flex-col gap-1">
        <p class="text-label text-foreground">Add an option to create variants.</p>
            </div>
    </div>
    </template>
    <div x-show="variants.length > 0" data-slot="variant-fill" class="grid gap-2 rounded-card border border-border bg-nq-surface-soft p-3">
        <div class="flex flex-wrap items-center justify-between gap-2">
            <span class="text-label text-foreground">Fill selected variants</span>
            <span class="text-caption text-muted-foreground" role="status" aria-live="polite" x-text="selectedText"></span>
        </div>
        <div class="grid gap-2 sm:grid-cols-5">
            <div class="grid gap-1">
                <span class="text-caption text-muted-foreground">Price</span>
                <div data-slot="currency-input" data-currency="USD" x-data="nqCurrencyInput(null, JSON.parse('{\u0022currency\u0022:\u0022USD\u0022,\u0022locale\u0022:\u0022en\u0022}'))" x-modelable="minor" x-id="['nq-currency']"
    x-model="fill.price" class="flex w-full min-w-0 flex-col gap-1">
    <div role="group" data-slot="input-group"
    x-bind="group" class="group/input-group flex h-control min-h-[var(--nq-touch-min,0px)] w-full min-w-0 items-center overflow-hidden rounded-control border border-input bg-card text-body text-foreground transition-colors duration-150 ease-nq focus-within:border-nq-focus focus-within:outline-1 focus-within:outline-nq-focus has-[[data-invalid]]:border-nq-danger has-[[aria-invalid=true]]:border-nq-danger has-[input:disabled]:cursor-not-allowed has-[input:disabled]:opacity-50"><div data-slot="currency-symbol" data-align="start" x-bind="symbolAddon"
            class="flex h-full shrink-0 items-center gap-1.5 text-body-sm text-muted-foreground [&amp;_svg]:size-4 order-first ps-3 pe-1">
            <span data-slot="input-group-text" class="select-none whitespace-nowrap"><bdi dir="ltr" x-text="mark()"></bdi></span>
        </div>
        <input data-slot="input-group-input" dir="ltr" x-bind="field" autocomplete="off" spellcheck="false"                           aria-label="Price" class="h-full min-w-0 flex-1 border-0 bg-transparent px-3 text-body text-foreground outline-none placeholder:text-muted-foreground disabled:cursor-not-allowed pointer-coarse:text-[16px] text-start tabular-nums"></div>
    <span x-show="out()" x-cloak style="display: none" :id="rangeId()" class="sr-only">Amount out of range</span>
    </div>
            </div>
            <div class="grid gap-1">
                <span class="text-caption text-muted-foreground">Compare-at</span>
                <div data-slot="currency-input" data-currency="USD" x-data="nqCurrencyInput(null, JSON.parse('{\u0022currency\u0022:\u0022USD\u0022,\u0022locale\u0022:\u0022en\u0022}'))" x-modelable="minor" x-id="['nq-currency']"
    x-model="fill.compareAt" class="flex w-full min-w-0 flex-col gap-1">
    <div role="group" data-slot="input-group"
    x-bind="group" class="group/input-group flex h-control min-h-[var(--nq-touch-min,0px)] w-full min-w-0 items-center overflow-hidden rounded-control border border-input bg-card text-body text-foreground transition-colors duration-150 ease-nq focus-within:border-nq-focus focus-within:outline-1 focus-within:outline-nq-focus has-[[data-invalid]]:border-nq-danger has-[[aria-invalid=true]]:border-nq-danger has-[input:disabled]:cursor-not-allowed has-[input:disabled]:opacity-50"><div data-slot="currency-symbol" data-align="start" x-bind="symbolAddon"
            class="flex h-full shrink-0 items-center gap-1.5 text-body-sm text-muted-foreground [&amp;_svg]:size-4 order-first ps-3 pe-1">
            <span data-slot="input-group-text" class="select-none whitespace-nowrap"><bdi dir="ltr" x-text="mark()"></bdi></span>
        </div>
        <input data-slot="input-group-input" dir="ltr" x-bind="field" autocomplete="off" spellcheck="false"                           aria-label="Compare-at" class="h-full min-w-0 flex-1 border-0 bg-transparent px-3 text-body text-foreground outline-none placeholder:text-muted-foreground disabled:cursor-not-allowed pointer-coarse:text-[16px] text-start tabular-nums"></div>
    <span x-show="out()" x-cloak style="display: none" :id="rangeId()" class="sr-only">Amount out of range</span>
    </div>
            </div>
            <div class="grid gap-1">
                <span class="text-caption text-muted-foreground">Stock</span>
                <input data-slot="input" type="text"
                    inputmode="numeric" aria-label="Stock" x-model="fill.stock" class="w-full min-w-0 rounded-control border border-input bg-card px-3 text-body text-foreground min-h-[var(--nq-touch-min,0px)] transition-colors duration-150 ease-nq outline-none placeholder:text-muted-foreground focus-visible:border-nq-focus focus-visible:outline-1 focus-visible:outline-nq-focus data-invalid:border-nq-danger aria-invalid:border-nq-danger disabled:cursor-not-allowed disabled:opacity-50 pointer-coarse:text-[16px] h-control">
            </div>
            <div class="grid gap-1">
                <span class="text-caption text-muted-foreground">Add stock</span>
                <input data-slot="input" type="text"
                    inputmode="numeric" aria-label="Add stock" x-model="fill.add" class="w-full min-w-0 rounded-control border border-input bg-card px-3 text-body text-foreground min-h-[var(--nq-touch-min,0px)] transition-colors duration-150 ease-nq outline-none placeholder:text-muted-foreground focus-visible:border-nq-focus focus-visible:outline-1 focus-visible:outline-nq-focus data-invalid:border-nq-danger aria-invalid:border-nq-danger disabled:cursor-not-allowed disabled:opacity-50 pointer-coarse:text-[16px] h-control">
            </div>
            <div class="grid gap-1">
                <span class="text-caption text-muted-foreground">SKU prefix</span>
                <input data-slot="input" type="text"
                    dir="ltr" aria-label="SKU prefix" x-model="fill.sku" class="w-full min-w-0 rounded-control border border-input bg-card px-3 text-body text-foreground min-h-[var(--nq-touch-min,0px)] transition-colors duration-150 ease-nq outline-none placeholder:text-muted-foreground focus-visible:border-nq-focus focus-visible:outline-1 focus-visible:outline-nq-focus data-invalid:border-nq-danger aria-invalid:border-nq-danger disabled:cursor-not-allowed disabled:opacity-50 pointer-coarse:text-[16px] h-control">
            </div>
        </div>
        <div class="flex flex-wrap gap-2">
            <button data-slot="button"
     type="button"                         x-bind:disabled="! canFill" x-on:click="applyFill()" class="inline-flex shrink-0 select-none items-center justify-center gap-2 whitespace-nowrap rounded-control border font-sans text-label transition-colors duration-150 ease-nq min-h-[var(--nq-touch-min,0px)] outline-none focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-nq-focus disabled:pointer-events-none disabled:opacity-50 data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0 border-border bg-card text-foreground hover:bg-nq-hover h-control-sm px-2.5">
        Apply to selected</button>
            <button data-slot="button"
     type="button"                         x-bind:disabled="! some" x-on:click="clearSelection()" class="inline-flex shrink-0 select-none items-center justify-center gap-2 whitespace-nowrap rounded-control border border-transparent font-sans text-label transition-colors duration-150 ease-nq min-h-[var(--nq-touch-min,0px)] outline-none focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-nq-focus disabled:pointer-events-none disabled:opacity-50 data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0 text-foreground hover:bg-nq-hover h-control-sm px-2.5">
        Clear selection</button>
        </div>
    </div>
    <div x-show="variants.length > 0" class="relative w-full overflow-x-auto rounded-card border border-border bg-card">
        <div role="table" aria-label="Variants" class="table w-full min-w-[52rem] border-collapse">
            <div role="rowgroup" class="table-header-group border-b border-border">
                <div role="row" class="table-row">
                    <div role="columnheader" class="table-cell w-10 px-2">
                        <button type="button" role="checkbox" data-slot="checkbox" x-data="nqCheckbox(false, false)" x-modelable="checked" x-bind="root"
    aria-checked="false"
     data-unchecked                 aria-label="Select all variants" x-on:click="toggleAll(! all)" x-bind:checked="all" class="relative inline-flex size-4 shrink-0 items-center justify-center rounded-[4px] border border-nq-line-strong bg-card text-primary-foreground outline-none transition-colors duration-150 ease-nq data-checked:border-primary data-checked:bg-primary data-indeterminate:border-primary data-indeterminate:bg-primary focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-nq-focus data-disabled:cursor-not-allowed data-disabled:opacity-50 after:absolute after:-inset-1">
    <span data-slot="checkbox-indicator" class="flex items-center justify-center [&_svg]:size-3 [&_svg]:stroke-3" x-show="checked || indeterminate"  style="display: none" >
        <svg aria-hidden="true" x-show="indeterminate" style="display: none" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <path d="M5 12h14"/>
</svg>        <svg aria-hidden="true" x-show="! indeterminate" style="" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <path d="M20 6 9 17l-5-5"/>
</svg>    </span>
    </button>
                    </div>
                    <div role="columnheader" class="table-cell px-2 py-2 text-start text-caption font-medium text-muted-foreground">Variant</div>
                    <div role="columnheader" class="table-cell px-2 py-2 text-start text-caption font-medium text-muted-foreground">SKU</div>
                    <div role="columnheader" class="table-cell px-2 py-2 text-start text-caption font-medium text-muted-foreground">Price</div>
                    <div role="columnheader" class="table-cell px-2 py-2 text-start text-caption font-medium text-muted-foreground">Compare-at</div>
                    <div role="columnheader" class="table-cell px-2 py-2 text-start text-caption font-medium text-muted-foreground">Stock</div>
                    <div role="columnheader" class="table-cell px-2 py-2 text-start text-caption font-medium text-muted-foreground">Image</div>
                </div>
            </div>
            <div role="rowgroup" class="table-row-group divide-y divide-border">
                <template x-for="(v, i) in variants" x-bind:key="v.id">
                    <div role="row" data-slot="variant-row" x-bind:data-selected="selected[v.id] ? '' : null" class="table-row data-[selected]:bg-nq-selected">
                        <div role="cell" class="table-cell px-2 py-2 align-middle text-body-sm text-foreground">
                            <button type="button" role="checkbox" data-slot="checkbox" x-data="nqCheckbox(false, false)" x-modelable="checked" x-bind="root"
    aria-checked="false"
     data-unchecked                 x-model="selected[v.id]" x-bind:aria-label="tt(`selectVariant`, label(v, i))" class="relative inline-flex size-4 shrink-0 items-center justify-center rounded-[4px] border border-nq-line-strong bg-card text-primary-foreground outline-none transition-colors duration-150 ease-nq data-checked:border-primary data-checked:bg-primary data-indeterminate:border-primary data-indeterminate:bg-primary focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-nq-focus data-disabled:cursor-not-allowed data-disabled:opacity-50 after:absolute after:-inset-1">
    <span data-slot="checkbox-indicator" class="flex items-center justify-center [&_svg]:size-3 [&_svg]:stroke-3" x-show="checked || indeterminate"  style="display: none" >
        <svg aria-hidden="true" x-show="indeterminate" style="display: none" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <path d="M5 12h14"/>
</svg>        <svg aria-hidden="true" x-show="! indeterminate" style="" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <path d="M20 6 9 17l-5-5"/>
</svg>    </span>
    </button>
                        </div>
                        <div role="cell" class="table-cell px-2 py-2 align-middle text-body-sm text-foreground font-medium" x-text="label(v, i)"></div>
                        <div role="cell" class="table-cell px-2 py-2 align-middle text-body-sm text-foreground">
                            <input type="text" dir="ltr" x-model="v.sku" x-bind:disabled="off" x-bind:aria-label="`SKU: ${label(v, i)}`" x-bind:aria-invalid="isDup(v) ? `true` : null"
                                class="h-control-sm w-full min-w-24 rounded-control border border-input bg-card px-2 text-body-sm text-foreground outline-none focus-visible:border-nq-focus aria-invalid:border-nq-danger" />
                            <span class="mt-0.5 block text-caption text-nq-danger-text" x-show="isDup(v)">Duplicate SKU</span>
                        </div>
                        <div role="cell" class="table-cell px-2 py-2 align-middle text-body-sm text-foreground">
                            <div data-slot="currency-input" data-currency="USD" x-data="nqCurrencyInput(null, JSON.parse('{\u0022currency\u0022:\u0022USD\u0022,\u0022locale\u0022:\u0022en\u0022}'))" x-modelable="minor" x-id="['nq-currency']"
    x-model="v.price" class="flex w-full min-w-0 flex-col gap-1">
    <div role="group" data-slot="input-group"
    x-bind="group" class="group/input-group flex h-control min-h-[var(--nq-touch-min,0px)] w-full min-w-0 items-center overflow-hidden rounded-control border border-input bg-card text-body text-foreground transition-colors duration-150 ease-nq focus-within:border-nq-focus focus-within:outline-1 focus-within:outline-nq-focus has-[[data-invalid]]:border-nq-danger has-[[aria-invalid=true]]:border-nq-danger has-[input:disabled]:cursor-not-allowed has-[input:disabled]:opacity-50"><div data-slot="currency-symbol" data-align="start" x-bind="symbolAddon"
            class="flex h-full shrink-0 items-center gap-1.5 text-body-sm text-muted-foreground [&amp;_svg]:size-4 order-first ps-3 pe-1">
            <span data-slot="input-group-text" class="select-none whitespace-nowrap"><bdi dir="ltr" x-text="mark()"></bdi></span>
        </div>
        <input data-slot="input-group-input" dir="ltr" x-bind="field" autocomplete="off" spellcheck="false"                           x-bind:aria-label="`Price: ${label(v, i)}`" class="h-full min-w-0 flex-1 border-0 bg-transparent px-3 text-body text-foreground outline-none placeholder:text-muted-foreground disabled:cursor-not-allowed pointer-coarse:text-[16px] text-start tabular-nums"></div>
    <span x-show="out()" x-cloak style="display: none" :id="rangeId()" class="sr-only">Amount out of range</span>
    </div>
                        </div>
                        <div role="cell" class="table-cell px-2 py-2 align-middle text-body-sm text-foreground">
                            <div data-slot="currency-input" data-currency="USD" x-data="nqCurrencyInput(null, JSON.parse('{\u0022currency\u0022:\u0022USD\u0022,\u0022locale\u0022:\u0022en\u0022}'))" x-modelable="minor" x-id="['nq-currency']"
    x-model="v.compareAt" class="flex w-full min-w-0 flex-col gap-1">
    <div role="group" data-slot="input-group"
    x-bind="group" class="group/input-group flex h-control min-h-[var(--nq-touch-min,0px)] w-full min-w-0 items-center overflow-hidden rounded-control border border-input bg-card text-body text-foreground transition-colors duration-150 ease-nq focus-within:border-nq-focus focus-within:outline-1 focus-within:outline-nq-focus has-[[data-invalid]]:border-nq-danger has-[[aria-invalid=true]]:border-nq-danger has-[input:disabled]:cursor-not-allowed has-[input:disabled]:opacity-50"><div data-slot="currency-symbol" data-align="start" x-bind="symbolAddon"
            class="flex h-full shrink-0 items-center gap-1.5 text-body-sm text-muted-foreground [&amp;_svg]:size-4 order-first ps-3 pe-1">
            <span data-slot="input-group-text" class="select-none whitespace-nowrap"><bdi dir="ltr" x-text="mark()"></bdi></span>
        </div>
        <input data-slot="input-group-input" dir="ltr" x-bind="field" autocomplete="off" spellcheck="false"                           x-bind:aria-label="`Compare-at: ${label(v, i)}`" class="h-full min-w-0 flex-1 border-0 bg-transparent px-3 text-body text-foreground outline-none placeholder:text-muted-foreground disabled:cursor-not-allowed pointer-coarse:text-[16px] text-start tabular-nums"></div>
    <span x-show="out()" x-cloak style="display: none" :id="rangeId()" class="sr-only">Amount out of range</span>
    </div>
                            <span class="mt-0.5 block text-caption text-nq-danger-text" x-show="badCompare(v)">Compare-at must be above the price.</span>
                        </div>
                        <div role="cell" class="table-cell px-2 py-2 align-middle text-body-sm text-foreground">
                            <input type="text" inputmode="numeric" x-bind:value="v.stock ?? ''" x-on:input="setStock(v, $event.target.value)" x-bind:disabled="off" x-bind:aria-label="`Stock: ${label(v, i)}`"
                                class="h-control-sm w-20 rounded-control border border-input bg-card px-2 text-body-sm tabular-nums text-foreground outline-none focus-visible:border-nq-focus" />
                        </div>
                        <div role="cell" class="table-cell px-2 py-2 align-middle text-body-sm text-foreground">
                            <div data-slot="native-select" class="relative w-full min-w-0">
    <select           class="w-full min-w-0 appearance-none rounded-control border border-input bg-card ps-3 pe-9 text-body text-foreground min-h-[var(--nq-touch-min,0px)] transition-colors duration-150 ease-nq outline-none focus-visible:border-nq-focus focus-visible:outline-1 focus-visible:outline-nq-focus data-invalid:border-nq-danger aria-invalid:border-nq-danger disabled:cursor-not-allowed disabled:opacity-50 pointer-coarse:text-[16px] h-control-sm" x-model="v.image" x-bind:disabled="off ? true : images.length === 0" x-bind:aria-label="`Image: ${label(v, i)}`">
                        <option value="" x-bind:selected="! v.image">No image</option>
                                <template x-for="(im, k) in images" x-bind:key="im.src">
                                    <option x-bind:value="im.src" x-bind:selected="v.image === im.src" x-text="imageAlt(im, k)"></option>
                                </template>
    </select>
    <svg aria-hidden="true" class="pointer-events-none absolute end-3 top-1/2 size-4 -translate-y-1/2 text-muted-foreground" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <path d="m6 9 6 6 6-6"/>
</svg></div>
                        </div>
                    </div>
                </template>
            </div>
        </div>
    </div>
</section>
    <section data-slot="collections-manager" aria-label="Collections" x-data="nqCollectionsManager(JSON.parse('{\u0022collections\u0022:[{\u0022id\u0022:\u0022c1\u0022,\u0022title\u0022:\u0022Summer picks\u0022,\u0022kind\u0022:\u0022manual\u0022,\u0022productIds\u0022:[\u0022p1\u0022,\u0022p2\u0022]},{\u0022id\u0022:\u0022c2\u0022,\u0022title\u0022:\u0022Nile brand\u0022,\u0022kind\u0022:\u0022rules\u0022,\u0022conditions\u0022:{\u0022kind\u0022:\u0022group\u0022,\u0022id\u0022:\u0022g-root\u0022,\u0022join\u0022:\u0022and\u0022,\u0022children\u0022:[{\u0022kind\u0022:\u0022condition\u0022,\u0022id\u0022:\u0022r-1\u0022,\u0022field\u0022:\u0022brand\u0022,\u0022op\u0022:\u0022is\u0022,\u0022value\u0022:\u0022Nile\u0022}]}}],\u0022products\u0022:[{\u0022id\u0022:\u0022p1\u0022,\u0022name\u0022:\u0022Linen shirt\u0022,\u0022brand\u0022:\u0022Nile\u0022,\u0022category\u0022:\u0022Clothing\u0022,\u0022tags\u0022:[\u0022summer\u0022],\u0022status\u0022:\u0022active\u0022,\u0022slug\u0022:\u0022linen-shirt\u0022,\u0022images\u0022:[{\u0022src\u0022:\u0022\\\/img\\\/shirt-a.jpg\u0022,\u0022alt\u0022:\u0022Front\u0022},{\u0022src\u0022:\u0022\\\/img\\\/shirt-b.jpg\u0022,\u0022alt\u0022:\u0022\u0022},{\u0022src\u0022:\u0022\\\/img\\\/shirt-c.jpg\u0022,\u0022alt\u0022:\u0022Back\u0022}],\u0022options\u0022:[{\u0022id\u0022:\u0022colour\u0022,\u0022name\u0022:\u0022Colour\u0022,\u0022display\u0022:\u0022button\u0022,\u0022values\u0022:[{\u0022id\u0022:\u0022red\u0022,\u0022label\u0022:\u0022Red\u0022},{\u0022id\u0022:\u0022blue\u0022,\u0022label\u0022:\u0022Blue\u0022}]}],\u0022variants\u0022:[{\u0022id\u0022:\u0022v1\u0022,\u0022options\u0022:{\u0022colour\u0022:\u0022red\u0022},\u0022price\u0022:4900,\u0022compareAt\u0022:5900,\u0022stock\u0022:12,\u0022sku\u0022:\u0022LIN-RED\u0022},{\u0022id\u0022:\u0022v2\u0022,\u0022options\u0022:{\u0022colour\u0022:\u0022blue\u0022},\u0022price\u0022:4900,\u0022stock\u0022:2,\u0022sku\u0022:\u0022LIN-BLUE\u0022}]},{\u0022id\u0022:\u0022p2\u0022,\u0022name\u0022:\u0022Canvas tote\u0022,\u0022category\u0022:\u0022Bags\u0022,\u0022tags\u0022:[\u0022summer\u0022,\u0022bag\u0022],\u0022status\u0022:\u0022draft\u0022,\u0022images\u0022:[],\u0022options\u0022:[],\u0022variants\u0022:[{\u0022id\u0022:\u0022v3\u0022,\u0022options\u0022:[],\u0022price\u0022:1900,\u0022stock\u0022:0}]},{\u0022id\u0022:\u0022p3\u0022,\u0022name\u0022:\u0022Clay mug\u0022,\u0022brand\u0022:\u0022Nile\u0022,\u0022category\u0022:\u0022Home\u0022,\u0022status\u0022:\u0022active\u0022,\u0022images\u0022:[{\u0022src\u0022:\u0022\\\/img\\\/mug.jpg\u0022,\u0022alt\u0022:\u0022Mug\u0022}],\u0022options\u0022:[],\u0022variants\u0022:[{\u0022id\u0022:\u0022v4\u0022,\u0022options\u0022:[],\u0022price\u0022:1400,\u0022sku\u0022:\u0022MUG-1\u0022}]}],\u0022currency\u0022:\u0022USD\u0022,\u0022locale\u0022:\u0022en\u0022,\u0022t\u0022:{\u0022products\u0022:\u0022Products\u0022,\u0022newProduct\u0022:\u0022New product\u0022,\u0022searchProducts\u0022:\u0022Search products\u0022,\u0022productCol\u0022:\u0022Product\u0022,\u0022statusCol\u0022:\u0022Status\u0022,\u0022stockCol\u0022:\u0022Stock\u0022,\u0022priceCol\u0022:\u0022Price\u0022,\u0022variantsCol\u0022:\u0022Variants\u0022,\u0022categoryCol\u0022:\u0022Category\u0022,\u0022statuses.active\u0022:\u0022Active\u0022,\u0022statuses.draft\u0022:\u0022Draft\u0022,\u0022statuses.archived\u0022:\u0022Archived\u0022,\u0022stockLevels.in\u0022:\u0022In stock\u0022,\u0022stockLevels.low\u0022:\u0022Low stock\u0022,\u0022stockLevels.out\u0022:\u0022Out of stock\u0022,\u0022stockLevels.untracked\u0022:\u0022Not tracked\u0022,\u0022units\u0022:\u0022{0} in stock\u0022,\u0022variantCount\u0022:\u0022{0} variants\u0022,\u0022oneVariant\u0022:\u00221 variant\u0022,\u0022productListLabel\u0022:\u0022Products\u0022,\u0022noProducts\u0022:\u0022No products yet\u0022,\u0022noProductsHint\u0022:\u0022Add your first product to start selling.\u0022,\u0022loadFailed\u0022:\u0022Products did not load.\u0022,\u0022retry\u0022:\u0022Try again\u0022,\u0022edit\u0022:\u0022Edit\u0022,\u0022setActive\u0022:\u0022Set active\u0022,\u0022setDraft\u0022:\u0022Move to drafts\u0022,\u0022archive\u0022:\u0022Archive\u0022,\u0022delete\u0022:\u0022Delete\u0022,\u0022deleteTitle\u0022:\u0022Delete this product?\u0022,\u0022deleteDescription\u0022:\u0022{0} and its variants are removed. Past orders keep their copy.\u0022,\u0022selectedCount\u0022:\u0022{0} selected\u0022,\u0022bulkEdit\u0022:\u0022Bulk edit\u0022,\u0022bulkTitle\u0022:\u0022Edit {0} products\u0022,\u0022bulkDescription\u0022:\u0022Leave a section on Keep to leave it alone. Changes apply to every variant.\u0022,\u0022bulkPrice\u0022:\u0022Price\u0022,\u0022bulkStock\u0022:\u0022Stock\u0022,\u0022bulkStatus\u0022:\u0022Status\u0022,\u0022keep\u0022:\u0022Keep\u0022,\u0022priceModes.set\u0022:\u0022Set to\u0022,\u0022priceModes.increase-percent\u0022:\u0022Raise by percent\u0022,\u0022priceModes.decrease-percent\u0022:\u0022Lower by percent\u0022,\u0022priceModes.increase-amount\u0022:\u0022Raise by amount\u0022,\u0022priceModes.decrease-amount\u0022:\u0022Lower by amount\u0022,\u0022stockModes.set\u0022:\u0022Set to\u0022,\u0022stockModes.add\u0022:\u0022Add\u0022,\u0022stockModes.remove\u0022:\u0022Remove\u0022,\u0022alsoCompareAt\u0022:\u0022Move compare-at price the same way\u0022,\u0022percent\u0022:\u0022Percent\u0022,\u0022amount\u0022:\u0022Amount\u0022,\u0022quantity\u0022:\u0022Quantity\u0022,\u0022preview\u0022:\u0022Preview\u0022,\u0022previewEmpty\u0022:\u0022Nothing changes yet. Pick a change above.\u0022,\u0022previewRow\u0022:\u0022{0}\u0022,\u0022applyToProducts\u0022:\u0022Apply to {0} products\u0022,\u0022cancel\u0022:\u0022Cancel\u0022,\u0022actions\u0022:\u0022Actions\u0022,\u0022editProduct\u0022:\u0022Edit product\u0022,\u0022newProductTitle\u0022:\u0022New product\u0022,\u0022general\u0022:\u0022General\u0022,\u0022title\u0022:\u0022Title\u0022,\u0022description\u0022:\u0022Description\u0022,\u0022descriptionLabel\u0022:\u0022Product description\u0022,\u0022media\u0022:\u0022Media\u0022,\u0022pricing\u0022:\u0022Pricing\u0022,\u0022price\u0022:\u0022Price\u0022,\u0022compareAt\u0022:\u0022Compare-at price\u0022,\u0022compareAtHint\u0022:\u0022The old price shown struck through. Must be above the price.\u0022,\u0022cost\u0022:\u0022Cost per item\u0022,\u0022costHint\u0022:\u0022Only you see this.\u0022,\u0022margin\u0022:\u0022Margin\u0022,\u0022profit\u0022:\u0022Profit\u0022,\u0022markup\u0022:\u0022Markup\u0022,\u0022noMargin\u0022:\u0022Add a price and a cost to see the margin.\u0022,\u0022inventory\u0022:\u0022Inventory\u0022,\u0022sku\u0022:\u0022SKU\u0022,\u0022trackStock\u0022:\u0022Track stock\u0022,\u0022stockQty\u0022:\u0022In stock\u0022,\u0022backorder\u0022:\u0022Sell when out of stock\u0022,\u0022weight\u0022:\u0022Weight (grams)\u0022,\u0022organization\u0022:\u0022Organisation\u0022,\u0022brand\u0022:\u0022Brand\u0022,\u0022category\u0022:\u0022Category\u0022,\u0022tags\u0022:\u0022Tags\u0022,\u0022tagsPlaceholder\u0022:\u0022Add a tag\u0022,\u0022seo\u0022:\u0022Search listing\u0022,\u0022seoTitle\u0022:\u0022Page title\u0022,\u0022seoDescription\u0022:\u0022Meta description\u0022,\u0022slug\u0022:\u0022URL handle\u0022,\u0022slugHint\u0022:\u0022Lower-case letters, digits and dashes.\u0022,\u0022statusSection\u0022:\u0022Status and visibility\u0022,\u0022visibility\u0022:\u0022Visibility\u0022,\u0022visible\u0022:\u0022Visible in the store\u0022,\u0022hidden\u0022:\u0022Hidden from the store (link still works)\u0022,\u0022statusHint.active\u0022:\u0022Customers can buy it.\u0022,\u0022statusHint.draft\u0022:\u0022Only you can see it.\u0022,\u0022statusHint.archived\u0022:\u0022Kept for records, not sold.\u0022,\u0022save\u0022:\u0022Save product\u0022,\u0022saving\u0022:\u0022Saving\u0022,\u0022discard\u0022:\u0022Discard changes\u0022,\u0022unsaved\u0022:\u0022Unsaved changes\u0022,\u0022allSaved\u0022:\u0022All changes saved\u0022,\u0022saveFailed\u0022:\u0022That did not save. Try again.\u0022,\u0022fixIssues\u0022:\u0022{0} to fix before saving\u0022,\u0022issues.title\u0022:\u0022Add a title.\u0022,\u0022issues.price\u0022:\u0022Add a price.\u0022,\u0022issues.compare-at\u0022:\u0022Compare-at must be above the price.\u0022,\u0022issues.sku-duplicate\u0022:\u0022Two variants share a SKU.\u0022,\u0022issues.no-variants\u0022:\u0022Generate the variants for these options.\u0022,\u0022issues.too-many-variants\u0022:\u0022Too many variants. Remove an option value.\u0022,\u0022issues.slug\u0022:\u0022The URL handle has characters that are not allowed.\u0022,\u0022mediaLabel\u0022:\u0022Product images\u0022,\u0022addImage\u0022:\u0022Add image\u0022,\u0022imageUrl\u0022:\u0022Image URL\u0022,\u0022imageUrlPlaceholder\u0022:\u0022https:\\\/\\\/\\u2026\u0022,\u0022altText\u0022:\u0022Alt text\u0022,\u0022altHint\u0022:\u0022Describe the picture for people who cannot see it.\u0022,\u0022missingAlt\u0022:\u0022Alt text missing\u0022,\u0022primary\u0022:\u0022Main image\u0022,\u0022moveEarlier\u0022:\u0022Move earlier\u0022,\u0022moveLater\u0022:\u0022Move later\u0022,\u0022removeImage\u0022:\u0022Remove image\u0022,\u0022dragHandle\u0022:\u0022Reorder image {0}\u0022,\u0022movedTo\u0022:\u0022Image moved to position {0} of {1}\u0022,\u0022noImages\u0022:\u0022No images yet\u0022,\u0022noImagesHint\u0022:\u0022Add a picture by its URL. The first one is the main image.\u0022,\u0022imageFailed\u0022:\u0022Image did not load\u0022,\u0022optionsTitle\u0022:\u0022Options\u0022,\u0022optionsHint\u0022:\u0022Colour, size, material. Up to three options.\u0022,\u0022addOption\u0022:\u0022Add option\u0022,\u0022removeOption\u0022:\u0022Remove option\u0022,\u0022optionName\u0022:\u0022Option name\u0022,\u0022optionNamePlaceholder\u0022:\u0022Size\u0022,\u0022optionValues\u0022:\u0022Values\u0022,\u0022optionValuesPlaceholder\u0022:\u0022Add a value\u0022,\u0022variantsTitle\u0022:\u0022Variants\u0022,\u0022variantsSummary\u0022:\u0022{0} variants\u0022,\u0022variantsRemoved\u0022:\u0022{0} variants no longer match and were removed.\u0022,\u0022variantsTruncated\u0022:\u0022More than {0} combinations. Only the first {0} are created.\u0022,\u0022variantLabel\u0022:\u0022Variant\u0022,\u0022skuCol\u0022:\u0022SKU\u0022,\u0022priceCol2\u0022:\u0022Price\u0022,\u0022compareCol\u0022:\u0022Compare-at\u0022,\u0022stockCol2\u0022:\u0022Stock\u0022,\u0022imageCol\u0022:\u0022Image\u0022,\u0022noImage\u0022:\u0022No image\u0022,\u0022bulkFill\u0022:\u0022Fill selected variants\u0022,\u0022selectVariants\u0022:\u0022Select variants to fill them at once.\u0022,\u0022selectAll\u0022:\u0022Select all variants\u0022,\u0022selectVariant\u0022:\u0022Select {0}\u0022,\u0022fillPrice\u0022:\u0022Price\u0022,\u0022fillCompare\u0022:\u0022Compare-at\u0022,\u0022fillStock\u0022:\u0022Stock\u0022,\u0022fillAddStock\u0022:\u0022Add stock\u0022,\u0022fillSkuPrefix\u0022:\u0022SKU prefix\u0022,\u0022fillApply\u0022:\u0022Apply to selected\u0022,\u0022fillClear\u0022:\u0022Clear selection\u0022,\u0022variantsSelected\u0022:\u0022{0} selected\u0022,\u0022dupSku\u0022:\u0022Duplicate SKU\u0022,\u0022variantsEmpty\u0022:\u0022Add an option to create variants.\u0022,\u0022collections\u0022:\u0022Collections\u0022,\u0022newCollection\u0022:\u0022New collection\u0022,\u0022collectionsLabel\u0022:\u0022Collections\u0022,\u0022collectionTitle\u0022:\u0022Collection title\u0022,\u0022manual\u0022:\u0022Manual\u0022,\u0022rules\u0022:\u0022Rules\u0022,\u0022kindLabel\u0022:\u0022How products join\u0022,\u0022manualHint\u0022:\u0022Pick the products yourself, in the order you want them.\u0022,\u0022rulesHint\u0022:\u0022Products join on their own when they match the rules.\u0022,\u0022matchPreview\u0022:\u0022{0} products match\u0022,\u0022matchNone\u0022:\u0022No products match yet.\u0022,\u0022matchPreviewLabel\u0022:\u0022Products in this collection\u0022,\u0022addProducts\u0022:\u0022Add products\u0022,\u0022addProduct\u0022:\u0022Add a product\u0022,\u0022pickProduct\u0022:\u0022Choose a product\u0022,\u0022removeFromCollection\u0022:\u0022Remove from collection\u0022,\u0022moveUp\u0022:\u0022Move up\u0022,\u0022moveDown\u0022:\u0022Move down\u0022,\u0022saveCollection\u0022:\u0022Save collection\u0022,\u0022deleteCollection\u0022:\u0022Delete collection\u0022,\u0022deleteCollectionTitle\u0022:\u0022Delete this collection?\u0022,\u0022deleteCollectionDescription\u0022:\u0022{0} is removed. The products stay in your catalogue.\u0022,\u0022collectionsEmpty\u0022:\u0022No collections yet\u0022,\u0022collectionsEmptyHint\u0022:\u0022Group products so customers can browse them together.\u0022,\u0022productsCount\u0022:\u0022{0} products\u0022,\u0022ruleAnyProduct\u0022:\u0022any product\u0022,\u0022ruleAddIt\u0022:\u0022add it to this collection\u0022,\u0022ruleEventLabel\u0022:\u0022Applies to\u0022,\u0022ruleEventHelp\u0022:\u0022Every active product is checked against the conditions below.\u0022,\u0022ruleIfTitle\u0022:\u0022Products that match\u0022,\u0022ruleIfHelp\u0022:\u0022Add conditions. A product joins when they hold. With none, no product joins.\u0022,\u0022ruleThenTitle\u0022:\u0022Result\u0022,\u0022ruleThenHelp\u0022:\u0022Matching products are added to this collection.\u0022,\u0022ruleAction\u0022:\u0022Add it to this collection\u0022,\u0022ruleWhere\u0022:\u0022where\u0022,\u0022ruleSo\u0022:\u0022so\u0022,\u0022and\u0022:\u0022and\u0022,\u0022or\u0022:\u0022or\u0022,\u0022editCollection\u0022:\u0022Edit collection\u0022,\u0022fields.tag\u0022:\u0022Tag\u0022,\u0022fields.brand\u0022:\u0022Brand\u0022,\u0022fields.category\u0022:\u0022Category\u0022,\u0022fields.title\u0022:\u0022Title\u0022,\u0022fields.price\u0022:\u0022Price\u0022,\u0022fields.stock\u0022:\u0022Stock\u0022,\u0022fields.onSale\u0022:\u0022On sale\u0022,\u0022fields.status\u0022:\u0022Status\u0022,\u0022close\u0022:\u0022Close\u0022},\u0022loading\u0022:false,\u0022error\u0022:false}'))"
    class="flex min-w-0 flex-col gap-4">
    <div class="flex flex-wrap items-center justify-between gap-2">
        <h2 class="text-h3 text-foreground">Collections</h2>
        <button data-slot="button"
     type="button"                         x-on:click="create()" class="inline-flex shrink-0 select-none items-center justify-center gap-2 whitespace-nowrap rounded-control border border-transparent font-sans text-label transition-colors duration-150 ease-nq min-h-[var(--nq-touch-min,0px)] outline-none focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-nq-focus disabled:pointer-events-none disabled:opacity-50 data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0 bg-primary text-primary-foreground hover:bg-[color-mix(in_oklab,var(--nq-action)_88%,var(--nq-fg))] h-control px-[var(--nq-control-pad)]">
        <svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <path d="M5 12h14"/>
  <path d="M12 5v14"/>
</svg>            New collection</button>
    </div>
    <p x-show="notice ? ! (editOpen || delOpen) : false" role="alert" class="text-body-sm text-nq-danger-text" x-text="notice"></p>
    <template x-if="failed">
        <div data-slot="empty-state" class="flex flex-col items-center justify-center gap-3 border border-dashed border-border px-6 py-12 text-center rounded-card">
            <span data-slot="state-icon" class="inline-flex size-10 items-center justify-center rounded-control border border-border bg-card [&amp;_svg]:size-5 text-muted-foreground">
            <svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <path d="m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3"/>
  <path d="M12 9v4"/>
  <path d="M12 17h.01"/>
</svg>        </span>
        <div class="flex max-w-sm flex-col gap-1">
        <p class="text-label text-foreground">Products did not load.</p>
            </div>
    </div>
    </template>
    <div x-show="loading" aria-busy="true" class="grid gap-3 sm:grid-cols-2 xl:grid-cols-3">
        <div data-slot="skeleton" aria-hidden="true" class="rounded-[4px] bg-secondary motion-safe:animate-pulse h-28"></div>
<div data-slot="skeleton" aria-hidden="true" class="rounded-[4px] bg-secondary motion-safe:animate-pulse h-28"></div>
<div data-slot="skeleton" aria-hidden="true" class="rounded-[4px] bg-secondary motion-safe:animate-pulse h-28"></div>
    </div>
    <template x-if="showEmpty">
        <div class="flex flex-col items-center gap-3">
            <div data-slot="empty-state" class="flex flex-col items-center justify-center gap-3 border border-dashed border-border px-6 py-12 text-center rounded-card">
            <span data-slot="state-icon" class="inline-flex size-10 items-center justify-center rounded-control border border-border bg-card [&amp;_svg]:size-5 text-muted-foreground">
            <svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <path d="M12.83 2.18a2 2 0 0 0-1.66 0L2.6 6.08a1 1 0 0 0 0 1.83l8.58 3.91a2 2 0 0 0 1.66 0l8.58-3.9a1 1 0 0 0 0-1.83z"/>
  <path d="M2 12a1 1 0 0 0 .58.91l8.6 3.91a2 2 0 0 0 1.65 0l8.58-3.9A1 1 0 0 0 22 12"/>
  <path d="M2 17a1 1 0 0 0 .58.91l8.6 3.91a2 2 0 0 0 1.65 0l8.58-3.9A1 1 0 0 0 22 17"/>
</svg>        </span>
        <div class="flex max-w-sm flex-col gap-1">
        <p class="text-label text-foreground">No collections yet</p>
                    <p class="text-body-sm text-muted-foreground">Group products so customers can browse them together.</p>
            </div>
    </div>
            <button data-slot="button"
     type="button"                         x-on:click="create()" class="inline-flex shrink-0 select-none items-center justify-center gap-2 whitespace-nowrap rounded-control border font-sans text-label transition-colors duration-150 ease-nq min-h-[var(--nq-touch-min,0px)] outline-none focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-nq-focus disabled:pointer-events-none disabled:opacity-50 data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0 border-border bg-card text-foreground hover:bg-nq-hover h-control px-[var(--nq-control-pad)]">
        New collection</button>
        </div>
    </template>
    <ul x-show="showList" class="grid gap-3 sm:grid-cols-2 xl:grid-cols-3">
        <template x-for="c in collections" x-bind:key="c.id">
            <li data-slot="collection-card" x-data="nqContextMenu()" x-bind="trigger" class="min-w-0">
                <div data-slot="card" class="flex flex-col gap-4 rounded-card border border-border bg-card py-4 text-card-foreground h-full w-full"><div data-slot="card-header" class="grid auto-rows-min items-start gap-1 px-4 has-data-[slot=card-action]:grid-cols-[1fr_auto]"><h3 data-slot="card-title" class="text-label text-foreground flex min-w-0 items-center justify-between gap-2"><span class="truncate" x-text="c.title"></span>
                            <span class="flex shrink-0 items-center gap-1">
                                <span data-slot="badge" class="inline-flex h-5 items-center whitespace-nowrap rounded-[4px] border px-1.5 text-caption font-medium"
                                    x-bind:class="chip(c.kind === 'rules' ? 'info' : 'neutral')" x-text="c.kind === 'rules' ? t.rules : t.manual"></span>
                                <div data-slot="dropdown-menu" x-data="nqDropdownMenu(false)" x-modelable="open" class="contents"><button data-slot="row-actions"
     type="button"                         x-bind="trigger" x-ref="trigger" x-bind:aria-label="`Actions, ${c.title}`" class="inline-flex shrink-0 select-none items-center justify-center gap-2 whitespace-nowrap rounded-control border border-transparent font-sans text-label transition-colors duration-150 ease-nq min-h-[var(--nq-touch-min,0px)] outline-none focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-nq-focus disabled:pointer-events-none disabled:opacity-50 data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0 hover:bg-nq-hover size-control-sm p-0 text-muted-foreground data-popup-open:text-foreground">
        <svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <circle cx="12" cy="12" r="1"/>
  <circle cx="19" cy="12" r="1"/>
  <circle cx="5" cy="12" r="1"/>
</svg></button>
                                    <template x-teleport="body">
    <div data-slot="dropdown-menu-content" x-bind="popup" x-init="popupEl = $el" x-nq-presence="open" x-anchor.bottom-end.offset.4="$refs.trigger"
        class="z-50 overflow-hidden rounded-floating border border-border bg-popover p-1.5 text-popover-foreground shadow-floating outline-none max-h-[var(--available-height)] overflow-y-auto transition-opacity duration-150 ease-nq data-starting-style:opacity-0 data-ending-style:opacity-0 min-w-44"><div data-slot="dropdown-menu-item" role="menuitem" data-variant="default" x-bind="item"
        x-on:click="edit(c)" class="relative flex h-nav-row min-h-[var(--nq-touch-min,0px)] cursor-default select-none items-center gap-2.5 rounded-control px-2.5 text-body-sm text-foreground outline-none data-highlighted:bg-nq-selected data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:size-4 [&_svg]:shrink-0 [&_svg]:text-muted-foreground"><svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <path d="M21.174 6.812a1 1 0 0 0-3.986-3.987L3.842 16.174a2 2 0 0 0-.5.83l-1.321 4.352a.5.5 0 0 0 .623.622l4.353-1.32a2 2 0 0 0 .83-.497z"/>
  <path d="m15 5 4 4"/>
</svg>Edit</div>
                                        <div data-slot="dropdown-menu-separator" role="separator" aria-orientation="horizontal" class="-mx-1.5 my-1.5 h-px bg-border"></div>
                                        <div data-slot="dropdown-menu-item" role="menuitem" data-variant="danger" x-bind="item"
        x-on:click="askDelete(c)" class="relative flex h-nav-row min-h-[var(--nq-touch-min,0px)] cursor-default select-none items-center gap-2.5 rounded-control px-2.5 text-body-sm outline-none data-highlighted:bg-nq-selected data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:size-4 [&_svg]:shrink-0 text-nq-danger-text [&_svg]:text-current"><svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <path d="M10 11v6"/>
  <path d="M14 11v6"/>
  <path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6"/>
  <path d="M3 6h18"/>
  <path d="M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"/>
</svg>Delete collection</div></div>
</template></div>
                            </span></h3></div>
                    <div data-slot="card-content" class="px-4 grid gap-3"><div class="flex -space-x-2 rtl:space-x-reverse" aria-hidden="true">
                            <template x-for="m in cardMatches(c).slice(0, 5)" x-bind:key="m.id">
                                <span data-slot="product-thumb" style="width: 32px; height: 32px"
    class="relative inline-flex shrink-0 items-center justify-center overflow-hidden border border-border bg-secondary text-muted-foreground rounded-full ring-2 ring-card">
    <img alt="" x-show="imgOk(m.images[0]?.src)" x-bind:src="m.images[0]?.src" x-on:error="broken[m.images[0]?.src] = true" class="size-full object-cover" />
    <svg aria-hidden="true" x-show="! imgOk(m.images[0]?.src)" class="size-1/2" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <rect width="18" height="18" x="3" y="3" rx="2" ry="2"/>
  <circle cx="9" cy="9" r="2"/>
  <path d="m21 15-3.086-3.086a2 2 0 0 0-2.828 0L6 21"/>
</svg></span>
                            </template>
                        </div>
                        <div class="flex items-center justify-between gap-2">
                            <span class="text-body-sm text-muted-foreground" x-text="countText(c)"></span>
                            <button data-slot="button"
     type="button"                         x-on:click="edit(c)" class="inline-flex shrink-0 select-none items-center justify-center gap-2 whitespace-nowrap rounded-control border font-sans text-label transition-colors duration-150 ease-nq min-h-[var(--nq-touch-min,0px)] outline-none focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-nq-focus disabled:pointer-events-none disabled:opacity-50 data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0 border-border bg-card text-foreground hover:bg-nq-hover h-control-sm px-2.5">
        <svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <path d="M21.174 6.812a1 1 0 0 0-3.986-3.987L3.842 16.174a2 2 0 0 0-.5.83l-1.321 4.352a.5.5 0 0 0 .623.622l4.353-1.32a2 2 0 0 0 .83-.497z"/>
  <path d="m15 5 4 4"/>
</svg>                                Edit</button>
                        </div></div></div>
                <template x-teleport="body">
                    <div data-slot="context-menu-content" x-bind="popup" x-init="popupEl = $el" x-nq-presence="open"
                        class="fixed z-50 min-w-44 overflow-hidden rounded-floating border border-border bg-popover p-1.5 text-popover-foreground shadow-floating outline-none max-h-[var(--available-height)] overflow-y-auto transition-opacity duration-150 ease-nq data-starting-style:opacity-0 data-ending-style:opacity-0">
                        <div data-slot="context-menu-item" role="menuitem" data-variant="default" x-bind="item"
        x-on:click="edit(c)" class="relative flex h-nav-row min-h-[var(--nq-touch-min,0px)] cursor-default select-none items-center gap-2.5 rounded-control px-2.5 text-body-sm text-foreground outline-none data-highlighted:bg-nq-selected data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:size-4 [&_svg]:shrink-0 [&_svg]:text-muted-foreground"><svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <path d="M21.174 6.812a1 1 0 0 0-3.986-3.987L3.842 16.174a2 2 0 0 0-.5.83l-1.321 4.352a.5.5 0 0 0 .623.622l4.353-1.32a2 2 0 0 0 .83-.497z"/>
  <path d="m15 5 4 4"/>
</svg>Edit</div>
                        <div data-slot="context-menu-separator" role="separator" aria-orientation="horizontal" class="-mx-1.5 my-1.5 h-px bg-border"></div>
                        <div data-slot="context-menu-item" role="menuitem" data-variant="danger" x-bind="item"
        x-on:click="askDelete(c)" class="relative flex h-nav-row min-h-[var(--nq-touch-min,0px)] cursor-default select-none items-center gap-2.5 rounded-control px-2.5 text-body-sm outline-none data-highlighted:bg-nq-selected data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:size-4 [&_svg]:shrink-0 text-nq-danger-text [&_svg]:text-current"><svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <path d="M10 11v6"/>
  <path d="M14 11v6"/>
  <path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6"/>
  <path d="M3 6h18"/>
  <path d="M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"/>
</svg>Delete collection</div>
                    </div>
                </template>
            </li>
        </template>
    </ul>
    <div data-slot="dialog" x-data="nqDialog(false)" x-modelable="open" x-id="['nq-dialog']" x-model="editOpen" class="contents">
    <template x-teleport="body">
    <div data-slot="dialog-portal">
        <div data-slot="dialog-backdrop" x-nq-presence="open" x-on:click="close()" class="fixed inset-0 z-50 bg-nq-fg/15 dark:bg-nq-bg/60 transition-opacity duration-150 ease-nq data-starting-style:opacity-0 data-ending-style:opacity-0"></div>
        <div data-slot="collection-editor" x-bind="popup" x-nq-presence="open" x-trap.noscroll="open"
            class="fixed inset-0 z-50 m-auto grid h-fit w-[calc(100%-2rem)] max-w-lg gap-4 rounded-floating border border-border bg-popover p-6 text-popover-foreground outline-none transition-opacity duration-150 ease-nq data-starting-style:opacity-0 data-ending-style:opacity-0 max-h-[92dvh] overflow-y-auto sm:max-w-3xl">
            <form class="grid gap-4" novalidate x-on:submit.prevent="saveCollection()">
                <div data-slot="dialog-header" class="flex flex-col gap-1.5 pe-8 text-start"><h2 data-slot="dialog-title" :id="$id('nq-dialog', 'title')" class="text-h3 text-foreground"><span x-text="dialogTitle"></span></h2>
                    <p data-slot="dialog-description" :id="$id('nq-dialog', 'description')" class="text-body-sm text-muted-foreground"><span x-text="dialogHint"></span></p></div>
                <div class="grid gap-1">
                    <label class="text-label text-foreground" for="collection-title">Collection title</label>
                    <input data-slot="input" type="text"
                    id="collection-title" x-model="ctitle" x-bind:aria-invalid="titleBad ? `true` : null" class="w-full min-w-0 rounded-control border border-input bg-card px-3 text-body text-foreground min-h-[var(--nq-touch-min,0px)] transition-colors duration-150 ease-nq outline-none placeholder:text-muted-foreground focus-visible:border-nq-focus focus-visible:outline-1 focus-visible:outline-nq-focus data-invalid:border-nq-danger aria-invalid:border-nq-danger disabled:cursor-not-allowed disabled:opacity-50 pointer-coarse:text-[16px] h-control">
                </div>
                <div data-slot="tabs" data-orientation="horizontal" x-data="nqTabs(null)" x-modelable="value" x-id="['nq-tabs']" x-model="kind" class="flex flex-col gap-4">
    <div data-slot="tabs-list" data-variant="segmented" aria-orientation="horizontal" x-bind="list"
    aria-label="How products join" class="relative z-0 flex max-w-full overflow-x-auto [scrollbar-width:none] [&::-webkit-scrollbar]:hidden w-fit gap-0.5 rounded-control bg-secondary p-0.5">
    <button type="button" data-slot="tabs-tab" x-bind="tab('manual')"
            class="inline-flex shrink-0 items-center gap-1.5 whitespace-nowrap text-label text-muted-foreground outline-none transition-colors duration-150 ease-nq hover:text-foreground data-active:text-foreground [&_svg]:size-4 [&_svg]:shrink-0 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-nq-focus data-disabled:pointer-events-none data-disabled:opacity-50 h-7 rounded-[calc(var(--radius-control)-2px)] px-3">Manual</button>
                        <button type="button" data-slot="tabs-tab" x-bind="tab('rules')"
            class="inline-flex shrink-0 items-center gap-1.5 whitespace-nowrap text-label text-muted-foreground outline-none transition-colors duration-150 ease-nq hover:text-foreground data-active:text-foreground [&_svg]:size-4 [&_svg]:shrink-0 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-nq-focus data-disabled:pointer-events-none data-disabled:opacity-50 h-7 rounded-[calc(var(--radius-control)-2px)] px-3">Rules</button>
</div>
                    <div data-slot="tabs-panel" x-bind="panel('manual')"
        class="outline-none focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-nq-focus grid gap-3 pt-3"><div data-slot="dropdown-menu" x-data="nqDropdownMenu(false)" x-modelable="open" class="contents"><button data-slot="collection-pick"
     type="button"                         x-bind="trigger" x-ref="trigger" aria-label="Add a product" class="inline-flex shrink-0 select-none items-center justify-center gap-2 whitespace-nowrap rounded-control border font-sans text-label transition-colors duration-150 ease-nq min-h-[var(--nq-touch-min,0px)] outline-none focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-nq-focus disabled:pointer-events-none disabled:opacity-50 data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0 border-border bg-card text-foreground hover:bg-nq-hover h-control px-[var(--nq-control-pad)]">
        <svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <path d="M5 12h14"/>
  <path d="M12 5v14"/>
</svg>                                Choose a product</button>
                            <template x-teleport="body">
    <div data-slot="dropdown-menu-content" x-bind="popup" x-init="popupEl = $el" x-nq-presence="open" x-anchor.bottom-start.offset.4="$refs.trigger"
        class="z-50 overflow-hidden rounded-floating border border-border bg-popover p-1.5 text-popover-foreground shadow-floating outline-none transition-opacity duration-150 ease-nq data-starting-style:opacity-0 data-ending-style:opacity-0 max-h-64 min-w-56 overflow-y-auto"><template x-for="pr in available" x-bind:key="pr.id">
                                    <div data-slot="dropdown-menu-item" role="menuitem" data-variant="default" x-bind="item"
        x-on:click="addProduct(pr.id)" class="relative flex h-nav-row min-h-[var(--nq-touch-min,0px)] cursor-default select-none items-center gap-2.5 rounded-control px-2.5 text-body-sm text-foreground outline-none data-highlighted:bg-nq-selected data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:size-4 [&_svg]:shrink-0 [&_svg]:text-muted-foreground"><span x-text="pr.name"></span></div>
                                </template></div>
</template></div>
                        <p x-show="ids.length === 0" class="rounded-card border border-dashed border-border p-3 text-center text-body-sm text-muted-foreground">No products match yet.</p>
                        <ol x-show="ids.length > 0" aria-label="Products in this collection" class="grid gap-1.5">
                            <template x-for="(it, i) in picked" x-bind:key="it.id">
                                <li class="flex min-w-0 items-center gap-2 rounded-control border border-border bg-card p-1.5">
                                    <span data-slot="product-thumb" style="width: 32px; height: 32px"
    class="relative inline-flex shrink-0 items-center justify-center overflow-hidden rounded-control border border-border bg-secondary text-muted-foreground">
    <img alt="" x-show="imgOk(it.src)" x-bind:src="it.src" x-on:error="broken[it.src] = true" class="size-full object-cover" />
    <svg aria-hidden="true" x-show="! imgOk(it.src)" class="size-1/2" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <rect width="18" height="18" x="3" y="3" rx="2" ry="2"/>
  <circle cx="9" cy="9" r="2"/>
  <path d="m21 15-3.086-3.086a2 2 0 0 0-2.828 0L6 21"/>
</svg></span>
                                    <span class="min-w-0 flex-1 truncate text-body-sm" x-text="it.name"></span>
                                    <button data-slot="button"
     type="button"                         aria-label="Move up" x-bind:disabled="i === 0" x-on:click="moveBy(i, -1)" class="inline-flex shrink-0 select-none items-center justify-center gap-2 whitespace-nowrap rounded-control border border-transparent font-sans text-label transition-colors duration-150 ease-nq min-h-[var(--nq-touch-min,0px)] outline-none focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-nq-focus disabled:pointer-events-none disabled:opacity-50 data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0 text-foreground hover:bg-nq-hover size-control-sm p-0">
        <svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <path d="m5 12 7-7 7 7"/>
  <path d="M12 19V5"/>
</svg></button>
                                    <button data-slot="button"
     type="button"                         aria-label="Move down" x-bind:disabled="i === ids.length - 1" x-on:click="moveBy(i, 1)" class="inline-flex shrink-0 select-none items-center justify-center gap-2 whitespace-nowrap rounded-control border border-transparent font-sans text-label transition-colors duration-150 ease-nq min-h-[var(--nq-touch-min,0px)] outline-none focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-nq-focus disabled:pointer-events-none disabled:opacity-50 data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0 text-foreground hover:bg-nq-hover size-control-sm p-0">
        <svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <path d="M12 5v14"/>
  <path d="m19 12-7 7-7-7"/>
</svg></button>
                                    <button data-slot="button"
     type="button"                         aria-label="Remove from collection" x-on:click="removeId(it.id)" class="inline-flex shrink-0 select-none items-center justify-center gap-2 whitespace-nowrap rounded-control border border-transparent font-sans text-label transition-colors duration-150 ease-nq min-h-[var(--nq-touch-min,0px)] outline-none focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-nq-focus disabled:pointer-events-none disabled:opacity-50 data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0 text-foreground hover:bg-nq-hover size-control-sm p-0">
        <svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <path d="M18 6 6 18"/>
  <path d="m6 6 12 12"/>
</svg></button>
                                </li>
                            </template>
                        </ol></div>
                    <div data-slot="tabs-panel" x-bind="panel('rules')"
        class="outline-none focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-nq-focus grid gap-3 pt-3"><div data-slot="rule-builder" x-data="nqRuleBuilder(JSON.parse('{\u0022events\u0022:[{\u0022id\u0022:\u0022product\u0022,\u0022label\u0022:\u0022any product\u0022}],\u0022fields\u0022:[{\u0022id\u0022:\u0022tag\u0022,\u0022label\u0022:\u0022Tag\u0022,\u0022kind\u0022:\u0022text\u0022},{\u0022id\u0022:\u0022brand\u0022,\u0022label\u0022:\u0022Brand\u0022,\u0022kind\u0022:\u0022text\u0022},{\u0022id\u0022:\u0022category\u0022,\u0022label\u0022:\u0022Category\u0022,\u0022kind\u0022:\u0022text\u0022},{\u0022id\u0022:\u0022title\u0022,\u0022label\u0022:\u0022Title\u0022,\u0022kind\u0022:\u0022text\u0022},{\u0022id\u0022:\u0022price\u0022,\u0022label\u0022:\u0022Price\u0022,\u0022kind\u0022:\u0022number\u0022},{\u0022id\u0022:\u0022stock\u0022,\u0022label\u0022:\u0022Stock\u0022,\u0022kind\u0022:\u0022number\u0022},{\u0022id\u0022:\u0022onSale\u0022,\u0022label\u0022:\u0022On sale\u0022,\u0022kind\u0022:\u0022boolean\u0022},{\u0022id\u0022:\u0022status\u0022,\u0022label\u0022:\u0022Status\u0022,\u0022kind\u0022:\u0022select\u0022,\u0022options\u0022:[{\u0022value\u0022:\u0022active\u0022,\u0022label\u0022:\u0022Active\u0022},{\u0022value\u0022:\u0022draft\u0022,\u0022label\u0022:\u0022Draft\u0022},{\u0022value\u0022:\u0022archived\u0022,\u0022label\u0022:\u0022Archived\u0022}]}],\u0022actionTypes\u0022:[{\u0022id\u0022:\u0022add\u0022,\u0022label\u0022:\u0022Add it to this collection\u0022}],\u0022actionTypesFrom\u0022:null,\u0022value\u0022:null,\u0022maxDepth\u0022:3,\u0022disabled\u0022:false,\u0022t\u0022:{\u0022whenHelp\u0022:\u0022Every active product is checked against the conditions below.\u0022,\u0022matchAll\u0022:\u0022All of these\u0022,\u0022matchAny\u0022:\u0022Any of these\u0022,\u0022groupLabel\u0022:\u0022Group: {join}\u0022,\u0022chooseField\u0022:\u0022Choose a field\u0022,\u0022yes\u0022:\u0022True\u0022,\u0022no\u0022:\u0022False\u0022,\u0022actionRow\u0022:\u0022Action {n}\u0022,\u0022problems\u0022:\u0022{n} to fix\u0022,\u0022issueEvent\u0022:\u0022Choose the event that starts the rule\u0022,\u0022issueActions\u0022:\u0022Add at least one action\u0022,\u0022issueField\u0022:\u0022A condition has no field\u0022,\u0022issueValue\u0022:\u0022A condition has no value\u0022,\u0022issueActionField\u0022:\u0022An action is missing \\u0022{field}\\u0022\u0022,\u0022sentence\u0022:{\u0022when\u0022:\u0022Applies to {event}\u0022,\u0022ifWord\u0022:\u0022where\u0022,\u0022then\u0022:\u0022so\u0022,\u0022noConditions\u0022:\u0022No products match yet.\u0022,\u0022and\u0022:\u0022and\u0022,\u0022or\u0022:\u0022or\u0022},\u0022ops\u0022:{\u0022is\u0022:\u0022is\u0022,\u0022isNot\u0022:\u0022is not\u0022,\u0022contains\u0022:\u0022contains\u0022,\u0022startsWith\u0022:\u0022starts with\u0022,\u0022isEmpty\u0022:\u0022is empty\u0022,\u0022isNotEmpty\u0022:\u0022is not empty\u0022,\u0022gt\u0022:\u0022is greater than\u0022,\u0022gte\u0022:\u0022is at least\u0022,\u0022lt\u0022:\u0022is less than\u0022,\u0022lte\u0022:\u0022is at most\u0022}}}'))" x-modelable="rule" x-model="ruleDoc" class="flex min-w-0 flex-col gap-4">
    <section aria-label="This rule" data-slot="rule-summary" class="rounded-card border border-border bg-nq-surface-soft p-4">
        <p class="flex items-start gap-2 text-body text-foreground" aria-live="polite">
            <svg aria-hidden="true" class="mt-0.5 size-4 shrink-0 text-primary" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <path d="M15.914 4a1.5 1.5 0 00-2.474-1.561l-9 9A1.5 1.5 0 005.5 14h4.002a.5.5 0 01.471.666L8.086 20a1.5 1.5 0 002.475 1.56l9-9A1.5 1.5 0 0018.5 10h-3.997a.5.5 0 01-.472-.667z"/>
</svg>            <span dir="auto" x-text="sentence()"></span>
        </p>
            </section>
    <div data-slot="alert" data-tone="warning" role="alert" x-show="messages().length" style="display: none"
        class="relative grid grid-cols-[auto_1fr_auto] items-start gap-x-3 rounded-card border p-3 text-start border-nq-warning/30 bg-nq-warning-soft">
        <svg aria-hidden="true" data-slot="alert-icon" class="mt-0.5 size-4 text-nq-warning-text" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <circle cx="12" cy="12" r="10"/>
  <line x1="12" x2="12" y1="8" y2="12"/>
  <line x1="12" x2="12.01" y1="16" y2="16"/>
</svg>        <div data-slot="alert-body" class="flex min-w-0 flex-col gap-0.5">
            <div data-slot="alert-title" class="text-label text-foreground" x-text="problemsTitle()"></div>
            <div data-slot="alert-description" class="text-body-sm text-muted-foreground">
                <ul class="mt-1 list-disc ps-5 text-body-sm">
                    <template x-for="m in messages()" x-bind:key="m"><li x-text="m"></li></template>
                </ul>
            </div>
        </div>
    </div>
    <section aria-labelledby="nq-rule-000001-when" class="flex flex-col gap-2 rounded-card border border-border bg-card p-4">
        <div class="flex items-center gap-2">
            <span data-slot="badge"     class="inline-flex h-5 shrink-0 items-center gap-1 whitespace-nowrap rounded-[4px] border px-1.5 text-caption font-medium [&_svg]:size-3 border-nq-brand/40 bg-[color-mix(in_oklab,var(--nq-brand)_14%,transparent)] text-foreground">1</span>
            <h3 id="nq-rule-000001-when" class="text-h4 text-foreground">Applies to</h3>
        </div>
        <div data-slot="field" x-data="nqField(false)" x-modelable="invalid" x-id="['nq-field']"
         data-valid     x-model="evInvalid" class="flex flex-col gap-1.5">
    <label data-slot="field-label"  class="text-label text-foreground data-disabled:opacity-50 sr-only">Applies to</label>
            <div data-slot="select" x-data="nqSelect(null, false)" x-modelable="value" x-id="['nq-select']" x-model="rule.event" class="contents">
    <button data-slot="select-trigger" x-ref="trigger" x-bind="trigger"
        aria-label="Applies to" x-bind:disabled="disabled" class="flex h-control w-full min-w-0 items-center justify-between gap-2 rounded-control border border-input bg-card px-3 text-body text-foreground min-h-[var(--nq-touch-min,0px)] cursor-default select-none outline-none transition-colors duration-150 ease-nq focus-visible:border-nq-focus focus-visible:outline-1 focus-visible:outline-nq-focus data-popup-open:border-nq-focus data-invalid:border-nq-danger disabled:cursor-not-allowed disabled:opacity-50 pointer-coarse:text-[16px]">
    <span data-slot="select-value" x-text="label() ?? 'Choose an event'" :data-placeholder="empty() ? '' : undefined"
    class="min-w-0 flex-1 truncate text-start data-placeholder:text-muted-foreground"></span>
    <span class="flex shrink-0 text-muted-foreground [&_svg]:size-4"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <path d="m7 15 5 5 5-5"/>
  <path d="m7 9 5-5 5 5"/>
</svg></span>
</button>
                <template x-teleport="body">
    <div data-slot="select-content" x-ref="popup" x-bind="popup" x-nq-presence="open" x-anchor.bottom-start.offset.4="$refs.trigger"
        class="z-50 min-w-[var(--anchor-width)] max-h-[var(--available-height)] overflow-y-auto rounded-floating border border-border bg-popover p-1.5 text-popover-foreground shadow-floating outline-none transition-opacity duration-150 ease-nq data-starting-style:opacity-0 data-ending-style:opacity-0">
        <div data-slot="select-item" x-bind="item('product', false)"
    class="relative flex h-nav-row min-h-[var(--nq-touch-min,0px)] cursor-default select-none items-center gap-2.5 rounded-control ps-8 pe-2.5 text-body-sm text-foreground outline-none data-highlighted:bg-nq-selected data-disabled:pointer-events-none data-disabled:opacity-50">
    <span aria-hidden="true" class="absolute start-2.5 inline-flex size-4 items-center justify-center">
        <span x-show="isSelected('product')" x-cloak class="contents"><svg class="size-4" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <path d="M20 6 9 17l-5-5"/>
</svg></span>
    </span>
    <span data-slot="select-item-text" class="min-w-0 flex-1 truncate">any product</span>
</div>
    </div>
</template>
    </div>
            <p data-slot="field-description" x-text="eventHelp()" class="text-caption text-muted-foreground">Every active product is checked against the conditions below.</p>
</div>
    </section>
    <section aria-labelledby="nq-rule-000001-if" class="flex flex-col gap-2 rounded-card border border-border bg-card p-4">
        <div class="flex items-center gap-2">
            <span data-slot="badge"     class="inline-flex h-5 shrink-0 items-center gap-1 whitespace-nowrap rounded-[4px] border px-1.5 text-caption font-medium [&_svg]:size-3 border-nq-brand/40 bg-[color-mix(in_oklab,var(--nq-brand)_14%,transparent)] text-foreground">2</span>
            <h3 id="nq-rule-000001-if" class="text-h4 text-foreground">Products that match</h3>
            <span class="text-caption text-muted-foreground tabular-nums" x-text="conditionCount()">0</span>
        </div>
        <p class="text-body-sm text-muted-foreground">Add conditions. A product joins when they hold. With none, no product joins.</p>
        <div x-bind:data-group="rule.conditions.id" role="group" x-bind:aria-label="groupLabel(rule.conditions)"
    class="flex flex-col gap-3 rounded-control border border-border p-3 ">
    <div class="flex flex-wrap items-center gap-2">
        <span class="text-label text-muted-foreground">Match</span>
        <div role="group" data-slot="toggle-group" data-variant="segmented" data-orientation="horizontal" aria-label="Match" x-bind:data-disabled="disabled ? '' : null"
            class="flex w-fit max-w-full gap-0.5 rounded-control bg-secondary p-0.5">
            <button type="button" data-slot="toggle" class="inline-flex h-7 shrink-0 items-center justify-center gap-1.5 whitespace-nowrap px-3 text-label text-muted-foreground outline-none transition-colors duration-150 ease-nq hover:text-foreground [&amp;_svg]:size-4 [&amp;_svg]:shrink-0 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-nq-focus data-disabled:pointer-events-none data-disabled:opacity-50 rounded-[calc(var(--radius-control)-2px)] data-pressed:bg-card data-pressed:text-foreground data-pressed:shadow-xs" x-bind:aria-pressed="rule.conditions.join === 'and' ? 'true' : 'false'" x-bind:data-pressed="rule.conditions.join === 'and' ? '' : null"
                x-bind:disabled="disabled" x-bind:data-disabled="disabled ? '' : null" x-on:click="setJoin(rule.conditions, 'and')">All of these</button>
            <button type="button" data-slot="toggle" class="inline-flex h-7 shrink-0 items-center justify-center gap-1.5 whitespace-nowrap px-3 text-label text-muted-foreground outline-none transition-colors duration-150 ease-nq hover:text-foreground [&amp;_svg]:size-4 [&amp;_svg]:shrink-0 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-nq-focus data-disabled:pointer-events-none data-disabled:opacity-50 rounded-[calc(var(--radius-control)-2px)] data-pressed:bg-card data-pressed:text-foreground data-pressed:shadow-xs" x-bind:aria-pressed="rule.conditions.join === 'or' ? 'true' : 'false'" x-bind:data-pressed="rule.conditions.join === 'or' ? '' : null"
                x-bind:disabled="disabled" x-bind:data-disabled="disabled ? '' : null" x-on:click="setJoin(rule.conditions, 'or')">Any of these</button>
        </div>
            </div>
    <p class="text-body-sm text-muted-foreground" x-show="rule.conditions.children.length === 0" style="display: none">Products join on their own when they match the rules.</p>
    <ul class="flex flex-col gap-3">
        <template x-for="n1 in rule.conditions.children" x-bind:key="n1.id">
            <li x-bind:data-condition="n1.kind === 'condition' ? n1.id : null"
                x-bind:class="n1.kind === 'condition' ? 'grid grid-cols-[minmax(0,1fr)_auto] items-start gap-2 sm:grid-cols-[minmax(0,1fr)_minmax(0,10rem)_minmax(0,1fr)_auto]' : ''">
                <template x-if="n1.kind === 'group'">
                    <div>
                                                    <div x-bind:data-group="n1.id" role="group" x-bind:aria-label="groupLabel(n1)"
    class="flex flex-col gap-3 rounded-control border border-border p-3 bg-nq-surface-soft">
    <div class="flex flex-wrap items-center gap-2">
        <span class="text-label text-muted-foreground">Match</span>
        <div role="group" data-slot="toggle-group" data-variant="segmented" data-orientation="horizontal" aria-label="Match" x-bind:data-disabled="disabled ? '' : null"
            class="flex w-fit max-w-full gap-0.5 rounded-control bg-secondary p-0.5">
            <button type="button" data-slot="toggle" class="inline-flex h-7 shrink-0 items-center justify-center gap-1.5 whitespace-nowrap px-3 text-label text-muted-foreground outline-none transition-colors duration-150 ease-nq hover:text-foreground [&amp;_svg]:size-4 [&amp;_svg]:shrink-0 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-nq-focus data-disabled:pointer-events-none data-disabled:opacity-50 rounded-[calc(var(--radius-control)-2px)] data-pressed:bg-card data-pressed:text-foreground data-pressed:shadow-xs" x-bind:aria-pressed="n1.join === 'and' ? 'true' : 'false'" x-bind:data-pressed="n1.join === 'and' ? '' : null"
                x-bind:disabled="disabled" x-bind:data-disabled="disabled ? '' : null" x-on:click="setJoin(n1, 'and')">All of these</button>
            <button type="button" data-slot="toggle" class="inline-flex h-7 shrink-0 items-center justify-center gap-1.5 whitespace-nowrap px-3 text-label text-muted-foreground outline-none transition-colors duration-150 ease-nq hover:text-foreground [&amp;_svg]:size-4 [&amp;_svg]:shrink-0 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-nq-focus data-disabled:pointer-events-none data-disabled:opacity-50 rounded-[calc(var(--radius-control)-2px)] data-pressed:bg-card data-pressed:text-foreground data-pressed:shadow-xs" x-bind:aria-pressed="n1.join === 'or' ? 'true' : 'false'" x-bind:data-pressed="n1.join === 'or' ? '' : null"
                x-bind:disabled="disabled" x-bind:data-disabled="disabled ? '' : null" x-on:click="setJoin(n1, 'or')">Any of these</button>
        </div>
                    <button data-slot="button"
     type="button"                         x-on:click="removeNode(n1.id)" x-bind:disabled="disabled" x-bind:data-disabled="disabled ? &#039;&#039; : null" class="inline-flex shrink-0 select-none items-center justify-center gap-2 whitespace-nowrap rounded-control border border-transparent font-sans text-label transition-colors duration-150 ease-nq min-h-[var(--nq-touch-min,0px)] outline-none focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-nq-focus disabled:pointer-events-none disabled:opacity-50 data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0 text-foreground hover:bg-nq-hover h-control-sm px-2.5 ms-auto">
        <svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <path d="M10 11v6"/>
  <path d="M14 11v6"/>
  <path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6"/>
  <path d="M3 6h18"/>
  <path d="M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"/>
</svg>                Remove group</button>
            </div>
    <p class="text-body-sm text-muted-foreground" x-show="n1.children.length === 0" style="display: none">Products join on their own when they match the rules.</p>
    <ul class="flex flex-col gap-3">
        <template x-for="n2 in n1.children" x-bind:key="n2.id">
            <li x-bind:data-condition="n2.kind === 'condition' ? n2.id : null"
                x-bind:class="n2.kind === 'condition' ? 'grid grid-cols-[minmax(0,1fr)_auto] items-start gap-2 sm:grid-cols-[minmax(0,1fr)_minmax(0,10rem)_minmax(0,1fr)_auto]' : ''">
                <template x-if="n2.kind === 'group'">
                    <div>
                                                    <div x-bind:data-group="n2.id" role="group" x-bind:aria-label="groupLabel(n2)"
    class="flex flex-col gap-3 rounded-control border border-border p-3 bg-nq-surface-soft">
    <div class="flex flex-wrap items-center gap-2">
        <span class="text-label text-muted-foreground">Match</span>
        <div role="group" data-slot="toggle-group" data-variant="segmented" data-orientation="horizontal" aria-label="Match" x-bind:data-disabled="disabled ? '' : null"
            class="flex w-fit max-w-full gap-0.5 rounded-control bg-secondary p-0.5">
            <button type="button" data-slot="toggle" class="inline-flex h-7 shrink-0 items-center justify-center gap-1.5 whitespace-nowrap px-3 text-label text-muted-foreground outline-none transition-colors duration-150 ease-nq hover:text-foreground [&amp;_svg]:size-4 [&amp;_svg]:shrink-0 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-nq-focus data-disabled:pointer-events-none data-disabled:opacity-50 rounded-[calc(var(--radius-control)-2px)] data-pressed:bg-card data-pressed:text-foreground data-pressed:shadow-xs" x-bind:aria-pressed="n2.join === 'and' ? 'true' : 'false'" x-bind:data-pressed="n2.join === 'and' ? '' : null"
                x-bind:disabled="disabled" x-bind:data-disabled="disabled ? '' : null" x-on:click="setJoin(n2, 'and')">All of these</button>
            <button type="button" data-slot="toggle" class="inline-flex h-7 shrink-0 items-center justify-center gap-1.5 whitespace-nowrap px-3 text-label text-muted-foreground outline-none transition-colors duration-150 ease-nq hover:text-foreground [&amp;_svg]:size-4 [&amp;_svg]:shrink-0 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-nq-focus data-disabled:pointer-events-none data-disabled:opacity-50 rounded-[calc(var(--radius-control)-2px)] data-pressed:bg-card data-pressed:text-foreground data-pressed:shadow-xs" x-bind:aria-pressed="n2.join === 'or' ? 'true' : 'false'" x-bind:data-pressed="n2.join === 'or' ? '' : null"
                x-bind:disabled="disabled" x-bind:data-disabled="disabled ? '' : null" x-on:click="setJoin(n2, 'or')">Any of these</button>
        </div>
                    <button data-slot="button"
     type="button"                         x-on:click="removeNode(n2.id)" x-bind:disabled="disabled" x-bind:data-disabled="disabled ? &#039;&#039; : null" class="inline-flex shrink-0 select-none items-center justify-center gap-2 whitespace-nowrap rounded-control border border-transparent font-sans text-label transition-colors duration-150 ease-nq min-h-[var(--nq-touch-min,0px)] outline-none focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-nq-focus disabled:pointer-events-none disabled:opacity-50 data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0 text-foreground hover:bg-nq-hover h-control-sm px-2.5 ms-auto">
        <svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <path d="M10 11v6"/>
  <path d="M14 11v6"/>
  <path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6"/>
  <path d="M3 6h18"/>
  <path d="M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"/>
</svg>                Remove group</button>
            </div>
    <p class="text-body-sm text-muted-foreground" x-show="n2.children.length === 0" style="display: none">Products join on their own when they match the rules.</p>
    <ul class="flex flex-col gap-3">
        <template x-for="n3 in n2.children" x-bind:key="n3.id">
            <li x-bind:data-condition="n3.kind === 'condition' ? n3.id : null"
                x-bind:class="n3.kind === 'condition' ? 'grid grid-cols-[minmax(0,1fr)_auto] items-start gap-2 sm:grid-cols-[minmax(0,1fr)_minmax(0,10rem)_minmax(0,1fr)_auto]' : ''">
                <template x-if="n3.kind === 'group'">
                    <div>
                                            </div>
                </template>
                <template x-if="n3.kind === 'condition'">
                    <div class="contents">
                        <select data-slot="select" aria-label="Field" x-bind:disabled="disabled" x-bind:data-invalid="bad(n3, 'no-field') ? '' : null"
                            x-bind:aria-invalid="bad(n3, 'no-field') ? 'true' : null" class="w-full min-w-0 rounded-control border border-input bg-card px-3 text-body text-foreground min-h-[var(--nq-touch-min,0px)] transition-colors duration-150 ease-nq outline-none placeholder:text-muted-foreground focus-visible:border-nq-focus focus-visible:outline-1 focus-visible:outline-nq-focus data-invalid:border-nq-danger aria-invalid:border-nq-danger disabled:cursor-not-allowed disabled:opacity-50 pointer-coarse:text-[16px] h-control" x-on:change="setField(n3, $event.target.value)">
                            <option value="" x-bind:selected="! n3.field">Choose a field</option>
                            <template x-for="f in fields" x-bind:key="f.id"><option x-bind:value="f.id" x-bind:selected="f.id === n3.field" x-text="f.label"></option></template>
                        </select>
                        <button data-slot="button"
     type="button"                         aria-label="Remove condition" title="Remove condition" x-on:click="removeNode(n3.id)" x-bind:disabled="disabled" x-bind:data-disabled="disabled ? &#039;&#039; : null" class="inline-flex shrink-0 select-none items-center justify-center gap-2 whitespace-nowrap rounded-control border border-transparent font-sans text-label transition-colors duration-150 ease-nq min-h-[var(--nq-touch-min,0px)] outline-none focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-nq-focus disabled:pointer-events-none disabled:opacity-50 data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0 text-foreground hover:bg-nq-hover size-control-sm p-0 sm:order-last">
        <svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <path d="M10 11v6"/>
  <path d="M14 11v6"/>
  <path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6"/>
  <path d="M3 6h18"/>
  <path d="M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"/>
</svg></button>
                        <select data-slot="select" aria-label="Operator" x-bind:disabled="disabled || ! n3.field" class="w-full min-w-0 rounded-control border border-input bg-card px-3 text-body text-foreground min-h-[var(--nq-touch-min,0px)] transition-colors duration-150 ease-nq outline-none placeholder:text-muted-foreground focus-visible:border-nq-focus focus-visible:outline-1 focus-visible:outline-nq-focus data-invalid:border-nq-danger aria-invalid:border-nq-danger disabled:cursor-not-allowed disabled:opacity-50 pointer-coarse:text-[16px] h-control col-span-2 sm:col-span-1"
                            x-on:change="n3.op = $event.target.value">
                            <template x-for="o in ops(n3)" x-bind:key="o.value"><option x-bind:value="o.value" x-bind:selected="o.value === n3.op" x-text="o.label"></option></template>
                        </select>
                        <div class="col-span-2 min-w-0 sm:col-span-1">
                            <template x-if="! unary(n3) && isChoice(n3)">
                                <select data-slot="select" aria-label="Value" x-bind:disabled="disabled" x-bind:data-invalid="bad(n3, 'no-value') ? '' : null"
                                    x-bind:aria-invalid="bad(n3, 'no-value') ? 'true' : null" class="w-full min-w-0 rounded-control border border-input bg-card px-3 text-body text-foreground min-h-[var(--nq-touch-min,0px)] transition-colors duration-150 ease-nq outline-none placeholder:text-muted-foreground focus-visible:border-nq-focus focus-visible:outline-1 focus-visible:outline-nq-focus data-invalid:border-nq-danger aria-invalid:border-nq-danger disabled:cursor-not-allowed disabled:opacity-50 pointer-coarse:text-[16px] h-control" x-on:change="n3.value = $event.target.value">
                                    <option value="" x-bind:selected="! n3.value"></option>
                                    <template x-for="o in choices(n3)" x-bind:key="o.value"><option x-bind:value="o.value" x-bind:selected="o.value === n3.value" x-text="o.label"></option></template>
                                </select>
                            </template>
                            <template x-if="! unary(n3) && ! isChoice(n3)">
                                <input data-slot="input" aria-label="Value" x-bind:type="isNumber(n3) ? 'number' : 'text'" x-bind:inputmode="isNumber(n3) ? 'decimal' : null"
                                    x-bind:dir="isNumber(n3) ? 'ltr' : null" x-bind:disabled="disabled" x-bind:aria-invalid="bad(n3, 'no-value') ? 'true' : null"
                                    x-bind:data-invalid="bad(n3, 'no-value') ? '' : null" x-bind:value="n3.value" x-on:input="n3.value = $event.target.value" class="w-full min-w-0 rounded-control border border-input bg-card px-3 text-body text-foreground min-h-[var(--nq-touch-min,0px)] transition-colors duration-150 ease-nq outline-none placeholder:text-muted-foreground focus-visible:border-nq-focus focus-visible:outline-1 focus-visible:outline-nq-focus data-invalid:border-nq-danger aria-invalid:border-nq-danger disabled:cursor-not-allowed disabled:opacity-50 pointer-coarse:text-[16px] h-control">
                            </template>
                        </div>
                    </div>
                </template>
            </li>
        </template>
    </ul>
    <div class="flex flex-wrap gap-2">
        <button data-slot="button"
     type="button"                         x-bind:disabled="disabled" x-bind:data-disabled="disabled ? &#039;&#039; : null" x-on:click="addCondition(n2)" class="inline-flex shrink-0 select-none items-center justify-center gap-2 whitespace-nowrap rounded-control border font-sans text-label transition-colors duration-150 ease-nq min-h-[var(--nq-touch-min,0px)] outline-none focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-nq-focus disabled:pointer-events-none disabled:opacity-50 data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0 border-border bg-card text-foreground hover:bg-nq-hover h-control-sm px-2.5">
        <svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <path d="M5 12h14"/>
  <path d="M12 5v14"/>
</svg>            Add condition</button>
            </div>
</div>
                                            </div>
                </template>
                <template x-if="n2.kind === 'condition'">
                    <div class="contents">
                        <select data-slot="select" aria-label="Field" x-bind:disabled="disabled" x-bind:data-invalid="bad(n2, 'no-field') ? '' : null"
                            x-bind:aria-invalid="bad(n2, 'no-field') ? 'true' : null" class="w-full min-w-0 rounded-control border border-input bg-card px-3 text-body text-foreground min-h-[var(--nq-touch-min,0px)] transition-colors duration-150 ease-nq outline-none placeholder:text-muted-foreground focus-visible:border-nq-focus focus-visible:outline-1 focus-visible:outline-nq-focus data-invalid:border-nq-danger aria-invalid:border-nq-danger disabled:cursor-not-allowed disabled:opacity-50 pointer-coarse:text-[16px] h-control" x-on:change="setField(n2, $event.target.value)">
                            <option value="" x-bind:selected="! n2.field">Choose a field</option>
                            <template x-for="f in fields" x-bind:key="f.id"><option x-bind:value="f.id" x-bind:selected="f.id === n2.field" x-text="f.label"></option></template>
                        </select>
                        <button data-slot="button"
     type="button"                         aria-label="Remove condition" title="Remove condition" x-on:click="removeNode(n2.id)" x-bind:disabled="disabled" x-bind:data-disabled="disabled ? &#039;&#039; : null" class="inline-flex shrink-0 select-none items-center justify-center gap-2 whitespace-nowrap rounded-control border border-transparent font-sans text-label transition-colors duration-150 ease-nq min-h-[var(--nq-touch-min,0px)] outline-none focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-nq-focus disabled:pointer-events-none disabled:opacity-50 data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0 text-foreground hover:bg-nq-hover size-control-sm p-0 sm:order-last">
        <svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <path d="M10 11v6"/>
  <path d="M14 11v6"/>
  <path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6"/>
  <path d="M3 6h18"/>
  <path d="M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"/>
</svg></button>
                        <select data-slot="select" aria-label="Operator" x-bind:disabled="disabled || ! n2.field" class="w-full min-w-0 rounded-control border border-input bg-card px-3 text-body text-foreground min-h-[var(--nq-touch-min,0px)] transition-colors duration-150 ease-nq outline-none placeholder:text-muted-foreground focus-visible:border-nq-focus focus-visible:outline-1 focus-visible:outline-nq-focus data-invalid:border-nq-danger aria-invalid:border-nq-danger disabled:cursor-not-allowed disabled:opacity-50 pointer-coarse:text-[16px] h-control col-span-2 sm:col-span-1"
                            x-on:change="n2.op = $event.target.value">
                            <template x-for="o in ops(n2)" x-bind:key="o.value"><option x-bind:value="o.value" x-bind:selected="o.value === n2.op" x-text="o.label"></option></template>
                        </select>
                        <div class="col-span-2 min-w-0 sm:col-span-1">
                            <template x-if="! unary(n2) && isChoice(n2)">
                                <select data-slot="select" aria-label="Value" x-bind:disabled="disabled" x-bind:data-invalid="bad(n2, 'no-value') ? '' : null"
                                    x-bind:aria-invalid="bad(n2, 'no-value') ? 'true' : null" class="w-full min-w-0 rounded-control border border-input bg-card px-3 text-body text-foreground min-h-[var(--nq-touch-min,0px)] transition-colors duration-150 ease-nq outline-none placeholder:text-muted-foreground focus-visible:border-nq-focus focus-visible:outline-1 focus-visible:outline-nq-focus data-invalid:border-nq-danger aria-invalid:border-nq-danger disabled:cursor-not-allowed disabled:opacity-50 pointer-coarse:text-[16px] h-control" x-on:change="n2.value = $event.target.value">
                                    <option value="" x-bind:selected="! n2.value"></option>
                                    <template x-for="o in choices(n2)" x-bind:key="o.value"><option x-bind:value="o.value" x-bind:selected="o.value === n2.value" x-text="o.label"></option></template>
                                </select>
                            </template>
                            <template x-if="! unary(n2) && ! isChoice(n2)">
                                <input data-slot="input" aria-label="Value" x-bind:type="isNumber(n2) ? 'number' : 'text'" x-bind:inputmode="isNumber(n2) ? 'decimal' : null"
                                    x-bind:dir="isNumber(n2) ? 'ltr' : null" x-bind:disabled="disabled" x-bind:aria-invalid="bad(n2, 'no-value') ? 'true' : null"
                                    x-bind:data-invalid="bad(n2, 'no-value') ? '' : null" x-bind:value="n2.value" x-on:input="n2.value = $event.target.value" class="w-full min-w-0 rounded-control border border-input bg-card px-3 text-body text-foreground min-h-[var(--nq-touch-min,0px)] transition-colors duration-150 ease-nq outline-none placeholder:text-muted-foreground focus-visible:border-nq-focus focus-visible:outline-1 focus-visible:outline-nq-focus data-invalid:border-nq-danger aria-invalid:border-nq-danger disabled:cursor-not-allowed disabled:opacity-50 pointer-coarse:text-[16px] h-control">
                            </template>
                        </div>
                    </div>
                </template>
            </li>
        </template>
    </ul>
    <div class="flex flex-wrap gap-2">
        <button data-slot="button"
     type="button"                         x-bind:disabled="disabled" x-bind:data-disabled="disabled ? &#039;&#039; : null" x-on:click="addCondition(n1)" class="inline-flex shrink-0 select-none items-center justify-center gap-2 whitespace-nowrap rounded-control border font-sans text-label transition-colors duration-150 ease-nq min-h-[var(--nq-touch-min,0px)] outline-none focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-nq-focus disabled:pointer-events-none disabled:opacity-50 data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0 border-border bg-card text-foreground hover:bg-nq-hover h-control-sm px-2.5">
        <svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <path d="M5 12h14"/>
  <path d="M12 5v14"/>
</svg>            Add condition</button>
                    <button data-slot="button"
     type="button"                         x-bind:disabled="disabled" x-bind:data-disabled="disabled ? &#039;&#039; : null" x-on:click="addGroup(n1)" class="inline-flex shrink-0 select-none items-center justify-center gap-2 whitespace-nowrap rounded-control border border-transparent font-sans text-label transition-colors duration-150 ease-nq min-h-[var(--nq-touch-min,0px)] outline-none focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-nq-focus disabled:pointer-events-none disabled:opacity-50 data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0 text-foreground hover:bg-nq-hover h-control-sm px-2.5">
        <svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <path d="M5 12h14"/>
  <path d="M12 5v14"/>
</svg>                Add group</button>
            </div>
</div>
                                            </div>
                </template>
                <template x-if="n1.kind === 'condition'">
                    <div class="contents">
                        <select data-slot="select" aria-label="Field" x-bind:disabled="disabled" x-bind:data-invalid="bad(n1, 'no-field') ? '' : null"
                            x-bind:aria-invalid="bad(n1, 'no-field') ? 'true' : null" class="w-full min-w-0 rounded-control border border-input bg-card px-3 text-body text-foreground min-h-[var(--nq-touch-min,0px)] transition-colors duration-150 ease-nq outline-none placeholder:text-muted-foreground focus-visible:border-nq-focus focus-visible:outline-1 focus-visible:outline-nq-focus data-invalid:border-nq-danger aria-invalid:border-nq-danger disabled:cursor-not-allowed disabled:opacity-50 pointer-coarse:text-[16px] h-control" x-on:change="setField(n1, $event.target.value)">
                            <option value="" x-bind:selected="! n1.field">Choose a field</option>
                            <template x-for="f in fields" x-bind:key="f.id"><option x-bind:value="f.id" x-bind:selected="f.id === n1.field" x-text="f.label"></option></template>
                        </select>
                        <button data-slot="button"
     type="button"                         aria-label="Remove condition" title="Remove condition" x-on:click="removeNode(n1.id)" x-bind:disabled="disabled" x-bind:data-disabled="disabled ? &#039;&#039; : null" class="inline-flex shrink-0 select-none items-center justify-center gap-2 whitespace-nowrap rounded-control border border-transparent font-sans text-label transition-colors duration-150 ease-nq min-h-[var(--nq-touch-min,0px)] outline-none focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-nq-focus disabled:pointer-events-none disabled:opacity-50 data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0 text-foreground hover:bg-nq-hover size-control-sm p-0 sm:order-last">
        <svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <path d="M10 11v6"/>
  <path d="M14 11v6"/>
  <path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6"/>
  <path d="M3 6h18"/>
  <path d="M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"/>
</svg></button>
                        <select data-slot="select" aria-label="Operator" x-bind:disabled="disabled || ! n1.field" class="w-full min-w-0 rounded-control border border-input bg-card px-3 text-body text-foreground min-h-[var(--nq-touch-min,0px)] transition-colors duration-150 ease-nq outline-none placeholder:text-muted-foreground focus-visible:border-nq-focus focus-visible:outline-1 focus-visible:outline-nq-focus data-invalid:border-nq-danger aria-invalid:border-nq-danger disabled:cursor-not-allowed disabled:opacity-50 pointer-coarse:text-[16px] h-control col-span-2 sm:col-span-1"
                            x-on:change="n1.op = $event.target.value">
                            <template x-for="o in ops(n1)" x-bind:key="o.value"><option x-bind:value="o.value" x-bind:selected="o.value === n1.op" x-text="o.label"></option></template>
                        </select>
                        <div class="col-span-2 min-w-0 sm:col-span-1">
                            <template x-if="! unary(n1) && isChoice(n1)">
                                <select data-slot="select" aria-label="Value" x-bind:disabled="disabled" x-bind:data-invalid="bad(n1, 'no-value') ? '' : null"
                                    x-bind:aria-invalid="bad(n1, 'no-value') ? 'true' : null" class="w-full min-w-0 rounded-control border border-input bg-card px-3 text-body text-foreground min-h-[var(--nq-touch-min,0px)] transition-colors duration-150 ease-nq outline-none placeholder:text-muted-foreground focus-visible:border-nq-focus focus-visible:outline-1 focus-visible:outline-nq-focus data-invalid:border-nq-danger aria-invalid:border-nq-danger disabled:cursor-not-allowed disabled:opacity-50 pointer-coarse:text-[16px] h-control" x-on:change="n1.value = $event.target.value">
                                    <option value="" x-bind:selected="! n1.value"></option>
                                    <template x-for="o in choices(n1)" x-bind:key="o.value"><option x-bind:value="o.value" x-bind:selected="o.value === n1.value" x-text="o.label"></option></template>
                                </select>
                            </template>
                            <template x-if="! unary(n1) && ! isChoice(n1)">
                                <input data-slot="input" aria-label="Value" x-bind:type="isNumber(n1) ? 'number' : 'text'" x-bind:inputmode="isNumber(n1) ? 'decimal' : null"
                                    x-bind:dir="isNumber(n1) ? 'ltr' : null" x-bind:disabled="disabled" x-bind:aria-invalid="bad(n1, 'no-value') ? 'true' : null"
                                    x-bind:data-invalid="bad(n1, 'no-value') ? '' : null" x-bind:value="n1.value" x-on:input="n1.value = $event.target.value" class="w-full min-w-0 rounded-control border border-input bg-card px-3 text-body text-foreground min-h-[var(--nq-touch-min,0px)] transition-colors duration-150 ease-nq outline-none placeholder:text-muted-foreground focus-visible:border-nq-focus focus-visible:outline-1 focus-visible:outline-nq-focus data-invalid:border-nq-danger aria-invalid:border-nq-danger disabled:cursor-not-allowed disabled:opacity-50 pointer-coarse:text-[16px] h-control">
                            </template>
                        </div>
                    </div>
                </template>
            </li>
        </template>
    </ul>
    <div class="flex flex-wrap gap-2">
        <button data-slot="button"
     type="button"                         x-bind:disabled="disabled" x-bind:data-disabled="disabled ? &#039;&#039; : null" x-on:click="addCondition(rule.conditions)" class="inline-flex shrink-0 select-none items-center justify-center gap-2 whitespace-nowrap rounded-control border font-sans text-label transition-colors duration-150 ease-nq min-h-[var(--nq-touch-min,0px)] outline-none focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-nq-focus disabled:pointer-events-none disabled:opacity-50 data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0 border-border bg-card text-foreground hover:bg-nq-hover h-control-sm px-2.5">
        <svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <path d="M5 12h14"/>
  <path d="M12 5v14"/>
</svg>            Add condition</button>
                    <button data-slot="button"
     type="button"                         x-bind:disabled="disabled" x-bind:data-disabled="disabled ? &#039;&#039; : null" x-on:click="addGroup(rule.conditions)" class="inline-flex shrink-0 select-none items-center justify-center gap-2 whitespace-nowrap rounded-control border border-transparent font-sans text-label transition-colors duration-150 ease-nq min-h-[var(--nq-touch-min,0px)] outline-none focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-nq-focus disabled:pointer-events-none disabled:opacity-50 data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0 text-foreground hover:bg-nq-hover h-control-sm px-2.5">
        <svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <path d="M5 12h14"/>
  <path d="M12 5v14"/>
</svg>                Add group</button>
            </div>
</div>
    </section>
    <section aria-labelledby="nq-rule-000001-then" class="flex flex-col gap-2 rounded-card border border-border bg-card p-4">
        <div class="flex items-center gap-2">
            <span data-slot="badge"     class="inline-flex h-5 shrink-0 items-center gap-1 whitespace-nowrap rounded-[4px] border px-1.5 text-caption font-medium [&_svg]:size-3 border-nq-brand/40 bg-[color-mix(in_oklab,var(--nq-brand)_14%,transparent)] text-foreground">3</span>
            <h3 id="nq-rule-000001-then" class="text-h4 text-foreground">Result</h3>
        </div>
        <p class="text-body-sm text-muted-foreground">Matching products are added to this collection.</p>
        <div data-slot="repeater" x-data="nqRepeater([], Object.assign(JSON.parse('{\u0022duplicable\u0022:false,\u0022collapsible\u0022:false}'), { createItem: () => (newAction()), rowTitle: (item, index) => (actionTitle(item, index)), rowLabel: (item, index) => (actionTitle(item, index)) }))" x-modelable="items" x-id="['nq-repeater-body']"     x-model="rule.actions" class="flex min-w-0 flex-col gap-3">
                <p :id="hintId()" class="sr-only">Focus the handle, then use the arrow keys to move the row. Home and End jump to the ends.</p>
    <div x-show="count() === 0" x-cloak style="display: none" data-slot="repeater-empty"
        class="rounded-card border border-dashed border-border px-4 py-6 text-center text-body-sm text-muted-foreground">
        <p class="text-body-sm text-muted-foreground">No actions yet.</p>    </div>
    <ol x-show="count() > 0" x-cloak style="display: none" aria-label="Actions" class="flex flex-col gap-2">
        <template x-for="(item, index) in items" :key="keyOf(index)">
            <li data-slot="repeater-row" :data-row-key="keyOf(index)" :data-collapsed="isCollapsed(index) ? 'true' : undefined" :data-dragging="isDragging(index) ? 'true' : undefined" :style="rowStyle(index)"
                class="relative rounded-card border border-border bg-card data-dragging:z-10 data-dragging:border-nq-focus data-dragging:shadow-floating">
                <div data-slot="repeater-row-header" class="flex min-h-control items-center gap-1 p-1.5">
                                            <button type="button" x-show="count() > 1" data-repeater-focus :aria-label="$nq.t('Reorder ' + name(index), 'إعادة ترتيب ' + name(index))" :title="$nq.t('Reorder ' + name(index), 'إعادة ترتيب ' + name(index))"
                            :aria-describedby="hintId()" aria-keyshortcuts="ArrowUp ArrowDown Home End" :disabled="disabled"
                            x-on:keydown="onHandleKey($event, index)" x-on:pointerdown="startDrag($event, index)"
                            class="inline-flex size-control-sm shrink-0 cursor-grab touch-none items-center justify-center rounded-control text-muted-foreground outline-none hover:bg-nq-hover hover:text-foreground focus-visible:outline-2 focus-visible:outline-nq-focus active:cursor-grabbing disabled:cursor-not-allowed disabled:opacity-50 [&_svg]:size-4">
                            <svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <circle cx="9" cy="12" r="1"/>
  <circle cx="9" cy="5" r="1"/>
  <circle cx="9" cy="19" r="1"/>
  <circle cx="15" cy="12" r="1"/>
  <circle cx="15" cy="5" r="1"/>
  <circle cx="15" cy="19" r="1"/>
</svg>                        </button>
                                                                <div class="flex min-w-0 flex-1 items-center gap-2 px-1.5">
                            <span  class="min-w-0 truncate text-label text-foreground outline-none" x-text="title(index)"></span>
                        </div>
                                        <span class="sr-only" x-text="n(index + 1)"></span>
                                        <button data-slot="button"
     type="button"                         :aria-label="$nq.t(&#039;Remove &#039; + name(index), &#039;حذف &#039; + name(index))" :title="$nq.t(&#039;Remove &#039; + name(index), &#039;حذف &#039; + name(index))" :disabled="disabled || atMin()" x-on:click="remove(index)" class="inline-flex shrink-0 select-none items-center justify-center gap-2 whitespace-nowrap rounded-control border border-transparent font-sans text-label transition-colors duration-150 ease-nq min-h-[var(--nq-touch-min,0px)] outline-none focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-nq-focus disabled:pointer-events-none disabled:opacity-50 data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0 hover:bg-nq-hover size-control-sm p-0 text-muted-foreground hover:text-nq-danger-text">
        <svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <path d="M10 11v6"/>
  <path d="M14 11v6"/>
  <path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6"/>
  <path d="M3 6h18"/>
  <path d="M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"/>
</svg></button>
                </div>
                <div :id="$id('nq-repeater-body', index)" data-slot="repeater-body" x-show="!isCollapsed(index)" class="border-t border-border p-3 sm:p-4"><div class="flex flex-col gap-4">
                <div data-slot="field" x-data="nqField(false)" x-modelable="invalid" x-id="['nq-field']"
         data-valid     class="flex flex-col gap-1.5">
    <label data-slot="field-label"  class="text-label text-foreground data-disabled:opacity-50">Action</label>
                    <div data-slot="select" x-data="nqSelect(null, false)" x-modelable="value" x-id="['nq-select']" x-model="item.type" class="contents">
    <button data-slot="select-trigger" x-ref="trigger" x-bind="trigger"
        aria-label="Action" x-bind:disabled="disabled" class="flex h-control w-full min-w-0 items-center justify-between gap-2 rounded-control border border-input bg-card px-3 text-body text-foreground min-h-[var(--nq-touch-min,0px)] cursor-default select-none outline-none transition-colors duration-150 ease-nq focus-visible:border-nq-focus focus-visible:outline-1 focus-visible:outline-nq-focus data-popup-open:border-nq-focus data-invalid:border-nq-danger disabled:cursor-not-allowed disabled:opacity-50 pointer-coarse:text-[16px]">
    <span data-slot="select-value" x-text="label() ?? 'Choose an action'" :data-placeholder="empty() ? '' : undefined"
    class="min-w-0 flex-1 truncate text-start data-placeholder:text-muted-foreground"></span>
    <span class="flex shrink-0 text-muted-foreground [&_svg]:size-4"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <path d="m7 15 5 5 5-5"/>
  <path d="m7 9 5-5 5 5"/>
</svg></span>
</button>
                        <template x-teleport="body">
    <div data-slot="select-content" x-ref="popup" x-bind="popup" x-nq-presence="open" x-anchor.bottom-start.offset.4="$refs.trigger"
        class="z-50 min-w-[var(--anchor-width)] max-h-[var(--available-height)] overflow-y-auto rounded-floating border border-border bg-popover p-1.5 text-popover-foreground shadow-floating outline-none transition-opacity duration-150 ease-nq data-starting-style:opacity-0 data-ending-style:opacity-0">
        <div data-slot="select-item" x-bind="item('add', false)"
    class="relative flex h-nav-row min-h-[var(--nq-touch-min,0px)] cursor-default select-none items-center gap-2.5 rounded-control ps-8 pe-2.5 text-body-sm text-foreground outline-none data-highlighted:bg-nq-selected data-disabled:pointer-events-none data-disabled:opacity-50">
    <span aria-hidden="true" class="absolute start-2.5 inline-flex size-4 items-center justify-center">
        <span x-show="isSelected('add')" x-cloak class="contents"><svg class="size-4" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <path d="M20 6 9 17l-5-5"/>
</svg></span>
    </span>
    <span data-slot="select-item-text" class="min-w-0 flex-1 truncate">Add it to this collection</span>
</div>
    </div>
</template>
    </div>
                    <p data-slot="field-description" x-show="actionDescription(item)" style="display: none" x-text="actionDescription(item)" class="text-caption text-muted-foreground"></p>
</div>
                <template x-for="f in actionFields(item)" x-bind:key="f.name">
                    <div>
                        <template x-if="f.isBool">
                            <div class="flex flex-row items-center justify-between gap-3">
                                <div class="min-w-0">
                                    <span class="text-label text-foreground" x-text="f.label"></span>
                                    <p class="text-caption text-muted-foreground" x-show="f.help !== ''" style="display: none" x-text="f.help"></p>
                                </div>
                                <button type="button" role="switch" data-slot="switch" x-data="nqSwitch(false)" x-modelable="checked" x-bind="root"
    aria-checked="false"
     data-unchecked                 x-model="item.config[f.name]" x-bind:aria-label="f.label" class="relative inline-flex h-5 w-9 shrink-0 items-center rounded-full border border-transparent bg-nq-line-strong p-0.5 outline-none transition-colors duration-150 ease-nq data-checked:bg-primary focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-nq-focus data-disabled:cursor-not-allowed data-disabled:opacity-50">
    <span data-slot="switch-thumb"  data-unchecked         x-bind:data-checked="checked ? '' : undefined" x-bind:data-unchecked="checked ? undefined : ''"
        class="block size-4 rounded-full bg-background shadow-xs data-checked:bg-primary-foreground transition-[translate] duration-150 ease-nq data-checked:translate-x-3.5 rtl:data-checked:-translate-x-3.5"></span>
    </button>
                            </div>
                        </template>
                        <template x-if="! f.isBool">
                            <div class="flex flex-col gap-1.5" x-bind:data-invalid="f.invalid ? '' : null">
                                <label class="text-label text-foreground">
                                    <span x-text="f.label"></span>
                                    <span x-show="f.required" style="display: none" aria-hidden="true" class="ms-1 text-nq-danger-text">*</span>
                                </label>
                                <template x-if="f.isSelect">
                                    <select data-slot="select" x-bind:aria-label="f.label" x-bind:disabled="disabled" x-bind:aria-invalid="f.invalid ? 'true' : null" class="w-full min-w-0 rounded-control border border-input bg-card px-3 text-body text-foreground min-h-[var(--nq-touch-min,0px)] transition-colors duration-150 ease-nq outline-none placeholder:text-muted-foreground focus-visible:border-nq-focus focus-visible:outline-1 focus-visible:outline-nq-focus data-invalid:border-nq-danger aria-invalid:border-nq-danger disabled:cursor-not-allowed disabled:opacity-50 pointer-coarse:text-[16px] h-control"
                                        x-on:change="setConfig(item, f.name, $event.target.value)">
                                        <option value="" x-bind:selected="f.text === ''" x-text="f.placeholder"></option>
                                        <template x-for="o in f.options" x-bind:key="o.value"><option x-bind:value="o.value" x-bind:selected="o.value === f.text" x-text="o.label"></option></template>
                                    </select>
                                </template>
                                <template x-if="f.isArea">
                                    <textarea data-slot="textarea" x-bind:rows="f.isCode ? 5 : 3" x-bind:dir="f.isCode ? 'ltr' : null" x-bind:spellcheck="f.isCode ? 'false' : null" x-bind:placeholder="f.placeholder"
                                        x-bind:disabled="disabled" x-bind:aria-invalid="f.invalid ? 'true' : null" class="w-full min-w-0 rounded-control border border-input bg-card px-3 text-body text-foreground min-h-[var(--nq-touch-min,0px)] transition-colors duration-150 ease-nq outline-none placeholder:text-muted-foreground focus-visible:border-nq-focus focus-visible:outline-1 focus-visible:outline-nq-focus data-invalid:border-nq-danger aria-invalid:border-nq-danger disabled:cursor-not-allowed disabled:opacity-50 pointer-coarse:text-[16px] min-h-20 py-2" x-bind:class="f.isCode ? 'font-mono text-caption' : ''"
                                        x-bind:value="f.text" x-on:input="setConfig(item, f.name, $event.target.value)"></textarea>
                                </template>
                                <template x-if="f.isInput">
                                    <input data-slot="input" x-bind:type="f.inputType" x-bind:inputmode="f.inputMode || null" x-bind:dir="f.ltr ? 'ltr' : null" x-bind:placeholder="f.placeholder"
                                        x-bind:disabled="disabled" x-bind:aria-invalid="f.invalid ? 'true' : null" class="w-full min-w-0 rounded-control border border-input bg-card px-3 text-body text-foreground min-h-[var(--nq-touch-min,0px)] transition-colors duration-150 ease-nq outline-none placeholder:text-muted-foreground focus-visible:border-nq-focus focus-visible:outline-1 focus-visible:outline-nq-focus data-invalid:border-nq-danger aria-invalid:border-nq-danger disabled:cursor-not-allowed disabled:opacity-50 pointer-coarse:text-[16px] h-control" x-bind:value="f.text"
                                        x-on:input="setConfig(item, f.name, $event.target.value, f.kind)">
                                </template>
                                <p class="text-caption text-muted-foreground" x-show="f.help !== ''" style="display: none" x-text="f.help"></p>
                                <div role="alert" class="text-caption text-nq-danger-text" x-show="f.invalid" style="display: none">Required</div>
                            </div>
                        </template>
                    </div>
                </template>
            </div></div>
            </li>
        </template>
    </ol>
    <div class="flex flex-wrap items-center gap-3">
        <button data-slot="button"
     type="button"                         data-repeater-add="data-repeater-add" :disabled="disabled || atMax()" :aria-describedby="limitText() ? limitId() : undefined" x-on:click="add()" class="inline-flex shrink-0 select-none items-center justify-center gap-2 whitespace-nowrap rounded-control border font-sans text-label transition-colors duration-150 ease-nq min-h-[var(--nq-touch-min,0px)] outline-none focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-nq-focus disabled:pointer-events-none disabled:opacity-50 data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0 border-border bg-card text-foreground hover:bg-nq-hover h-control px-[var(--nq-control-pad)]">
        <svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <path d="M5 12h14"/>
  <path d="M12 5v14"/>
</svg>            Add action</button>
        <span x-show="limitText()" x-cloak style="display: none" :id="limitId()" class="text-caption text-muted-foreground" x-text="limitText()"></span>
    </div>
    <div aria-live="polite" role="status" class="sr-only" x-text="announcement"></div>
</div>
    </section>
</div></div>
</div>
                <div role="status" aria-live="polite" data-slot="collection-preview" class="grid gap-2 rounded-card border border-border bg-nq-surface-soft p-3">
                    <p class="text-label text-foreground" x-text="matchText"></p>
                    <ul x-show="matches.length > 0" aria-label="Products in this collection" class="grid gap-1 sm:grid-cols-2">
                        <template x-for="m in matchShown" x-bind:key="m.id">
                            <li class="flex min-w-0 items-center gap-2 text-body-sm">
                                <span data-slot="product-thumb" style="width: 24px; height: 24px"
    class="relative inline-flex shrink-0 items-center justify-center overflow-hidden rounded-control border border-border bg-secondary text-muted-foreground">
    <img alt="" x-show="imgOk(m.images[0]?.src)" x-bind:src="m.images[0]?.src" x-on:error="broken[m.images[0]?.src] = true" class="size-full object-cover" />
    <svg aria-hidden="true" x-show="! imgOk(m.images[0]?.src)" class="size-1/2" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <rect width="18" height="18" x="3" y="3" rx="2" ry="2"/>
  <circle cx="9" cy="9" r="2"/>
  <path d="m21 15-3.086-3.086a2 2 0 0 0-2.828 0L6 21"/>
</svg></span>
                                <span class="min-w-0 flex-1 truncate" x-text="m.name"></span>
                                <span class="text-caption text-muted-foreground" dir="ltr" x-text="priceOf(m)"></span>
                            </li>
                        </template>
                        <li class="text-caption text-muted-foreground" x-show="matchMore > 0" x-text="`+` + num(matchMore)"></li>
                    </ul>
                </div>
                <p x-show="notice" role="alert" class="flex items-center gap-2 text-body-sm text-nq-danger-text" x-text="notice"></p>
                <div data-slot="dialog-footer" class="flex flex-col-reverse gap-2 sm:flex-row sm:justify-end"><button data-slot="button"
     type="button"                         x-bind:disabled="busy" x-on:click="editOpen = false" class="inline-flex shrink-0 select-none items-center justify-center gap-2 whitespace-nowrap rounded-control border border-transparent font-sans text-label transition-colors duration-150 ease-nq min-h-[var(--nq-touch-min,0px)] outline-none focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-nq-focus disabled:pointer-events-none disabled:opacity-50 data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0 text-foreground hover:bg-nq-hover h-control px-[var(--nq-control-pad)]">
        Cancel</button>
                    <button data-slot="button"
     type="submit"                         x-bind:disabled="busy" class="inline-flex shrink-0 select-none items-center justify-center gap-2 whitespace-nowrap rounded-control border border-transparent font-sans text-label transition-colors duration-150 ease-nq min-h-[var(--nq-touch-min,0px)] outline-none focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-nq-focus disabled:pointer-events-none disabled:opacity-50 data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0 bg-primary text-primary-foreground hover:bg-[color-mix(in_oklab,var(--nq-action)_88%,var(--nq-fg))] h-control px-[var(--nq-control-pad)]">
        Save collection</button></div>
            </form>
                            <button type="button" data-slot="dialog-close" x-on:click="close()" aria-label="Close"
                    class="absolute end-3 top-3 inline-flex size-8 items-center justify-center rounded-control text-muted-foreground transition-colors duration-150 hover:bg-nq-hover hover:text-foreground focus-visible:outline-2 focus-visible:outline-nq-focus [&_svg]:size-4"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <path d="M18 6 6 18"/>
  <path d="m6 6 12 12"/>
</svg></button>
                    </div>
    </div>
</template>
</div>
    <div data-slot="dialog" x-data="nqDialog(false)" x-modelable="open" x-id="['nq-dialog']" x-model="delOpen" class="contents">
    <template x-teleport="body">
    <div data-slot="dialog-portal">
        <div data-slot="dialog-backdrop" x-nq-presence="open" x-on:click="close()" class="fixed inset-0 z-50 bg-nq-fg/15 dark:bg-nq-bg/60 transition-opacity duration-150 ease-nq data-starting-style:opacity-0 data-ending-style:opacity-0"></div>
        <div data-slot="collection-delete" x-bind="popup" x-nq-presence="open" x-trap.noscroll="open"
            class="fixed inset-0 z-50 m-auto grid h-fit w-[calc(100%-2rem)] gap-4 rounded-floating border border-border bg-popover p-6 text-popover-foreground outline-none max-h-[calc(100dvh-2rem)] overflow-y-auto transition-opacity duration-150 ease-nq data-starting-style:opacity-0 data-ending-style:opacity-0 max-w-md">
            <div data-slot="dialog-header" class="flex flex-col gap-1.5 pe-8 text-start"><h2 data-slot="dialog-title" :id="$id('nq-dialog', 'title')" class="text-h3 text-foreground">Delete this collection?</h2>
                <p data-slot="dialog-description" :id="$id('nq-dialog', 'description')" class="text-body-sm text-muted-foreground"><span x-text="tt(`deleteCollectionDescription`, deleting ? deleting.title : ``)"></span></p></div>
            <p x-show="notice" role="alert" class="text-body-sm text-nq-danger-text" x-text="notice"></p>
            <div data-slot="dialog-footer" class="flex flex-col-reverse gap-2 sm:flex-row sm:justify-end"><button data-slot="button"
     type="button"                         x-bind:disabled="busy" x-on:click="delOpen = false" class="inline-flex shrink-0 select-none items-center justify-center gap-2 whitespace-nowrap rounded-control border border-transparent font-sans text-label transition-colors duration-150 ease-nq min-h-[var(--nq-touch-min,0px)] outline-none focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-nq-focus disabled:pointer-events-none disabled:opacity-50 data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0 text-foreground hover:bg-nq-hover h-control px-[var(--nq-control-pad)]">
        Cancel</button>
                <button data-slot="button"
     type="button"                         x-bind:disabled="busy" x-on:click="confirmDelete()" class="inline-flex shrink-0 select-none items-center justify-center gap-2 whitespace-nowrap rounded-control border border-transparent font-sans text-label transition-colors duration-150 ease-nq min-h-[var(--nq-touch-min,0px)] outline-none focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-nq-focus disabled:pointer-events-none disabled:opacity-50 data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0 bg-destructive text-destructive-foreground hover:bg-[color-mix(in_oklab,var(--nq-danger-solid)_88%,var(--nq-fg))] h-control px-[var(--nq-control-pad)]">
        Delete collection</button></div>
                            <button type="button" data-slot="dialog-close" x-on:click="close()" aria-label="Close"
                    class="absolute end-3 top-3 inline-flex size-8 items-center justify-center rounded-control text-muted-foreground transition-colors duration-150 hover:bg-nq-hover hover:text-foreground focus-visible:outline-2 focus-visible:outline-nq-focus [&_svg]:size-4"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <path d="M18 6 6 18"/>
  <path d="m6 6 12 12"/>
</svg></button>
                    </div>
    </div>
</template>
</div>
</section>
</div>
```
