# ProductDetail

> A complete product page from one CommerceProduct: gallery with zoom and swipe, availability-aware variant picker, quantity, price with percent off, stock and delivery lines, add to cart, buy now, sticky mobile bar, size guide and content sections.

Source: https://docs.nasaqui.com/components/product-detail

## Install

```bash
npx shadcn@latest add https://docs.nasaqui.com/r/product-detail.json
```

The product page of a store. Give it a whole `CommerceProduct` and it renders the breadcrumb, a gallery, the title and rating, the price (with compare-at and percent off), the variant picker, a quantity stepper, stock and delivery lines, add to cart and buy now, wishlist and share, trust badges, a size guide, and the description, specifications and shipping sections. It holds no cart: `onAddToCart(variant, qty)` is the only way out. Slots take the reviews block and the related products.

The pieces are exported too: `ProductGallery`, `ProductVariantPicker`, `ProductQuantityStepper` and `ProductSizeGuide`, and the pure helpers behind them (`initialSelection`, `selectOptionValue`, `imageForSelection`, `stockState`, `displayPrice`, `deliveryWindow`, and more).

## When to use

- The page for one product with variants (colour, size) that are sold from a store.
- Any place a single product needs a buy box with live availability.

## When not to use

- A product in a shelf or grid: use [`ProductCard`](https://docs.nasaqui.com/components/product-card).
- A subscription plan: use [`PlanCard`](https://docs.nasaqui.com/components/plan-card).
- Cart and checkout: they belong to the cart and checkout components.

## Import

```tsx
import { ProductDetail } from "@fadymondy/nasaq/web";
// inside this monorepo: "@nasaq/web"
```

## Quick start

```tsx
import { ProductDetail } from "@fadymondy/nasaq/web";

export function Page({ product }: { product: CommerceProduct }) {
  return (
    <ProductDetail
      product={product}
      currency="USD"
      onAddToCart={async (variant, quantity) => {
        await cart.add(variant.id, quantity); // return { error } to show a failure
      }}
    />
  );
}
```

## Anatomy

```
ProductDetail                  data-slot="product-detail"
├─ Breadcrumb                  optional
├─ ProductGallery              thumbnails, zoom, swipe, lightbox, video badge
└─ buy box
   ├─ title, brand, Rating (links to #reviews)
   ├─ price, compare-at, percent-off Badge
   ├─ ProductVariantPicker     radio group per option; optionAction holds the size guide link
   ├─ ProductQuantityStepper   clamped to stock and maxPerOrder
   ├─ stock line, delivery line with a city Select
   ├─ Add to cart, Buy now, wishlist, share
   └─ trust badges
sections                       Tabs from 768px, Accordion below (description, specifications, shipping)
reviews slot                   id="reviews"
related slot
sticky add bar                 phones only, after the main buttons scroll away
```

## API

### `ProductDetail`

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `product` | `CommerceProduct` | required | Options, variants, images, rating. |
| `currency` | `string` | `"USD"` (`"SAR"` in Arabic) | ISO 4217 code. Money is integer minor units. |
| `currencyExponent?` | `number` | `2` | Digits of the minor unit. |
| `defaultVariantId?` | `string` | first in stock | Opening variant. |
| `blankSelection?` | `boolean` | `false` | Open with nothing picked. Add to cart then asks for a pick. |
| `onVariantChange?` | `(variant, selection) => void` | none | After each pick. |
| `onAddToCart` | `(variant, qty) => void \| { error? } \| Promise` | required | Return `{ error }` or throw to show a failure. |
| `onBuyNow?` | same | none | Omit to hide Buy now. |
| `wishlisted?`, `defaultWishlisted?`, `onWishlistChange?` | | none | Omit all to hide the heart. |
| `onShare?`, `shareUrl?` | | Web Share, else copy link | |
| `breadcrumbs?` | `{ label, href? }[]` | none | The last item is the current page. |
| `sizeGuide?`, `sizeGuideOptionId?` | `ProductSizeGuideData`, `string` | `"size"` | Table shown in a dialog next to the size axis. |
| `impossible?` | `"hide" \| "disable"` | `"hide"` | What to do with values no variant offers together with the current picks. |
| `lowStockThreshold?` | `number` | `5` | At or below this the stock line reads "Only N left". |
| `maxPerOrder?` | `number` | none | Cap on top of stock. |
| `delivery?` | `{ cities, defaultCityId?, skipWeekdays?, cutoffHour?, now? }` | none | Estimate by city. Pass a fixed `now` in stories and tests. |
| `description?`, `specs?`, `shippingInfo?` | | `product.description` | Content sections. |
| `sections?` | `"auto" \| "tabs" \| "accordion"` | `"auto"` | |
| `trustBadges?` | `ProductTrustBadge[] \| false` | four defaults | |
| `reviews?`, `related?`, `relatedTitle?` | `ReactNode`, `string` | none | Slots. |
| `stickyBar?` | `boolean` | `true` | Mobile add bar. |
| `labels?` | `ProductDetailLabels` | en or ar | Override any string. |

### Sub-components

- `ProductGallery`: `images`, `index?`, `defaultIndex?`, `onIndexChange?`, `zoom?`, `name?`, `labels?`.
- `ProductVariantPicker`: `product`, `selection`, `onSelectionChange`, `impossible?`, `optionAction?`, `invalid?`, `labels?`. Sold-out values are crossed out and stay selectable.
- `ProductQuantityStepper`: `value`, `onValueChange`, `max?`, `disabled?`, `labels?`.
- `ProductSizeGuide`: `guide` (`columns`, `rows`, `highlight?`, `footer?`, `title?`, `description?`), `selectedSize?`, `labels?`.

## Examples

### Arabic page with delivery by city

```tsx
<ProductDetail
  product={product}
  currency="USD"
  delivery={{ cities: [{ id: "cairo", label: "القاهرة", etaDays: [1, 2], fee: 0 }], skipWeekdays: [5, 6] }}
  onAddToCart={add}
/>
```

Set the provider locale to `ar`; everything, including numbers and dates, follows.

### Reviews in the slot

```tsx
<ProductDetail product={product} currency="USD" onAddToCart={add} reviews={<ProductReviews reviews={reviews} />} />
```

## Accessibility

- Each option is a radio group (arrow keys move, `Space` picks). Sold-out values are announced as unavailable and drawn with a line, not colour alone.
- The gallery has previous and next buttons, arrow keys, a live position, and a lightbox dialog. Swipe is an extra, never the only way.
- The stock line, the add result and quantity limits are in live regions.
- Reduced motion turns off the zoom and slide transitions.

## RTL & i18n

- English and Arabic strings are built in; pass `labels` to override.
- Prices, SKUs, quantities and dates use `<bdi>` and locale digits. Swipe direction and the previous/next arrows mirror.
- The size table keeps measurements left to right.

## Styling & tokens

- Tokens only (`text-foreground`, `bg-secondary`, `border-border`, `text-nq-*-text`). Swatch colours come from `CommerceOption` values, which should be tokens or CSS colours from your data.
- Images show a token-coloured placeholder when missing or broken, and reserve their aspect ratio.

## Do / Don't

- **Do** pass the whole product and let availability drive the picker.
- **Do** return `{ error }` from `onAddToCart` when the cart refuses.
- **Don't** hide sold-out values: cross them out so shoppers know they exist.
- **Don't** compute stock or price yourself; use `stockState` and `displayPrice`.

## Related

- [ProductReviews](https://docs.nasaqui.com/components/product-reviews) · [ProductCard](https://docs.nasaqui.com/components/product-card) · [Price](https://docs.nasaqui.com/components/price) · [Rating](https://docs.nasaqui.com/components/rating)

## Lab

https://docs.nasaqui.com/?path=/docs/components-storefront-product-detail--docs

## Code

### React

```tsx
import { ProductDetail } from "@fadymondy/nasaq/web";

export function Page({ product }: { product: CommerceProduct }) {
  return (
    <ProductDetail
      product={product}
      currency="USD"
      onAddToCart={async (variant, quantity) => {
        await cart.add(variant.id, quantity); // return { error } to show a failure
      }}
    />
  );
}
```

### shadcn

```tsx
import { ProductDetail } from "@/components/ui/product-detail";

export function Page({ product }: { product: CommerceProduct }) {
  return (
    <ProductDetail
      product={product}
      currency="USD"
      onAddToCart={async (variant, quantity) => {
        await cart.add(variant.id, quantity); // return { error } to show a failure
      }}
    />
  );
}
```

### Vue

```vue
<script setup lang="ts">
import { NqProductDetail, type CommerceProduct, type CommerceVariant } from "@fadymondy/nasaq/vue";

// The README Quick start: a whole product in, one event out. Prices are minor units (cents).
const product: CommerceProduct = {
  id: "tee",
  name: "Everyday tee",
  brand: "Nasaq Goods",
  description: "A soft cotton tee that holds its shape wash after wash.",
  images: [
    { src: "https://picsum.photos/seed/tee-1/800/800", alt: "Everyday tee, front" },
    { src: "https://picsum.photos/seed/tee-2/800/800", alt: "Everyday tee, back" },
  ],
  options: [
    { id: "color", name: "Colour", display: "swatch", values: [{ id: "black", label: "Black", color: "#111111" }, { id: "sand", label: "Sand", color: "#d8c3a5" }] },
    { id: "size", name: "Size", values: [{ id: "s", label: "S" }, { id: "m", label: "M" }, { id: "l", label: "L" }] },
  ],
  variants: [
    { id: "black-s", options: { color: "black", size: "s" }, price: 2900, stock: 8 },
    { id: "black-m", options: { color: "black", size: "m" }, price: 2900, stock: 3 },
    { id: "black-l", options: { color: "black", size: "l" }, price: 2900, stock: 0 },
    { id: "sand-s", options: { color: "sand", size: "s" }, price: 2900, compareAt: 3900, stock: 12 },
    { id: "sand-m", options: { color: "sand", size: "m" }, price: 2900, compareAt: 3900, stock: 5 },
  ],
  rating: { average: 4.6, count: 128 },
};

async function add(variant: CommerceVariant, quantity: number) {
  // await cart.add(variant.id, quantity); // return { error } to show a failure
  console.log("add to cart", variant.id, quantity);
}
</script>

<template>
  <NqProductDetail :product="product" currency="USD" @add-to-cart="add" />
</template>
```

### Blade

```blade
@php
    // The README Quick start: a whole product in, one event out. Prices are minor units (cents).
    $product = [
        'id' => 'tee',
        'name' => 'Everyday tee',
        'brand' => 'Nasaq Goods',
        'description' => 'A soft cotton tee that holds its shape wash after wash.',
        'images' => [
            ['src' => 'https://picsum.photos/seed/tee-1/800/800', 'alt' => 'Everyday tee, front'],
            ['src' => 'https://picsum.photos/seed/tee-2/800/800', 'alt' => 'Everyday tee, back'],
        ],
        'options' => [
            ['id' => 'color', 'name' => 'Colour', 'display' => 'swatch', 'values' => [['id' => 'black', 'label' => 'Black', 'color' => '#111111'], ['id' => 'sand', 'label' => 'Sand', 'color' => '#d8c3a5']]],
            ['id' => 'size', 'name' => 'Size', 'values' => [['id' => 's', 'label' => 'S'], ['id' => 'm', 'label' => 'M'], ['id' => 'l', 'label' => 'L']]],
        ],
        'variants' => [
            ['id' => 'black-s', 'options' => ['color' => 'black', 'size' => 's'], 'price' => 2900, 'stock' => 8],
            ['id' => 'black-m', 'options' => ['color' => 'black', 'size' => 'm'], 'price' => 2900, 'stock' => 3],
            ['id' => 'black-l', 'options' => ['color' => 'black', 'size' => 'l'], 'price' => 2900, 'stock' => 0],
            ['id' => 'sand-s', 'options' => ['color' => 'sand', 'size' => 's'], 'price' => 2900, 'compareAt' => 3900, 'stock' => 12],
            ['id' => 'sand-m', 'options' => ['color' => 'sand', 'size' => 'm'], 'price' => 2900, 'compareAt' => 3900, 'stock' => 5],
        ],
        'rating' => ['average' => 4.6, 'count' => 128],
    ];
@endphp
{{-- A handler may call $event.detail.wait(promise); a result of { error } shows a failure. --}}
<x-nq::product-detail :product="$product" currency="USD"
    x-on:nq-add-to-cart="console.log('add to cart', $event.detail.variantId, $event.detail.quantity)" />
```

### HTML + Alpine

```html
<div data-slot="product-detail" x-data="nqProductDetail(JSON.parse('{\u0022product\u0022:{\u0022id\u0022:\u0022tee\u0022,\u0022name\u0022:\u0022Everyday tee\u0022,\u0022brand\u0022:\u0022Nasaq Goods\u0022,\u0022description\u0022:\u0022A soft cotton tee that holds its shape wash after wash.\u0022,\u0022images\u0022:[{\u0022src\u0022:\u0022https:\\\/\\\/picsum.photos\\\/seed\\\/tee-1\\\/800\\\/800\u0022,\u0022alt\u0022:\u0022Everyday tee, front\u0022},{\u0022src\u0022:\u0022https:\\\/\\\/picsum.photos\\\/seed\\\/tee-2\\\/800\\\/800\u0022,\u0022alt\u0022:\u0022Everyday tee, back\u0022}],\u0022options\u0022:[{\u0022id\u0022:\u0022color\u0022,\u0022name\u0022:\u0022Colour\u0022,\u0022display\u0022:\u0022swatch\u0022,\u0022values\u0022:[{\u0022id\u0022:\u0022black\u0022,\u0022label\u0022:\u0022Black\u0022,\u0022color\u0022:\u0022#111111\u0022},{\u0022id\u0022:\u0022sand\u0022,\u0022label\u0022:\u0022Sand\u0022,\u0022color\u0022:\u0022#d8c3a5\u0022}]},{\u0022id\u0022:\u0022size\u0022,\u0022name\u0022:\u0022Size\u0022,\u0022values\u0022:[{\u0022id\u0022:\u0022s\u0022,\u0022label\u0022:\u0022S\u0022},{\u0022id\u0022:\u0022m\u0022,\u0022label\u0022:\u0022M\u0022},{\u0022id\u0022:\u0022l\u0022,\u0022label\u0022:\u0022L\u0022}]}],\u0022variants\u0022:[{\u0022id\u0022:\u0022black-s\u0022,\u0022options\u0022:{\u0022color\u0022:\u0022black\u0022,\u0022size\u0022:\u0022s\u0022},\u0022price\u0022:2900,\u0022stock\u0022:8},{\u0022id\u0022:\u0022black-m\u0022,\u0022options\u0022:{\u0022color\u0022:\u0022black\u0022,\u0022size\u0022:\u0022m\u0022},\u0022price\u0022:2900,\u0022stock\u0022:3},{\u0022id\u0022:\u0022black-l\u0022,\u0022options\u0022:{\u0022color\u0022:\u0022black\u0022,\u0022size\u0022:\u0022l\u0022},\u0022price\u0022:2900,\u0022stock\u0022:0},{\u0022id\u0022:\u0022sand-s\u0022,\u0022options\u0022:{\u0022color\u0022:\u0022sand\u0022,\u0022size\u0022:\u0022s\u0022},\u0022price\u0022:2900,\u0022compareAt\u0022:3900,\u0022stock\u0022:12},{\u0022id\u0022:\u0022sand-m\u0022,\u0022options\u0022:{\u0022color\u0022:\u0022sand\u0022,\u0022size\u0022:\u0022m\u0022},\u0022price\u0022:2900,\u0022compareAt\u0022:3900,\u0022stock\u0022:5}],\u0022rating\u0022:{\u0022average\u0022:4.6,\u0022count\u0022:128}},\u0022images\u0022:[{\u0022src\u0022:\u0022https:\\\/\\\/picsum.photos\\\/seed\\\/tee-1\\\/800\\\/800\u0022,\u0022alt\u0022:\u0022Everyday tee, front\u0022},{\u0022src\u0022:\u0022https:\\\/\\\/picsum.photos\\\/seed\\\/tee-2\\\/800\\\/800\u0022,\u0022alt\u0022:\u0022Everyday tee, back\u0022}],\u0022currency\u0022:\u0022USD\u0022,\u0022exponent\u0022:2,\u0022selection\u0022:{\u0022color\u0022:\u0022black\u0022,\u0022size\u0022:\u0022s\u0022},\u0022wishlisted\u0022:false,\u0022lowStock\u0022:5,\u0022maxPerOrder\u0022:null,\u0022impossible\u0022:\u0022hide\u0022,\u0022delivery\u0022:null,\u0022shareUrl\u0022:null}'))" :class="{ 'pb-24': barVisible }"
    x-on:nq-add-to-cart="console.log(&#039;add to cart&#039;, $event.detail.variantId, $event.detail.quantity)" class="mx-auto flex w-full max-w-6xl flex-col gap-8 px-4 py-6 md:px-6">
    <div class="grid gap-8 lg:grid-cols-[minmax(0,1.1fr)_minmax(0,1fr)] lg:gap-12">
        <div class="min-w-0 lg:sticky lg:top-6 lg:self-start">
            <div data-slot="product-gallery" role="group" aria-roledescription="carousel" aria-label="Product images"
    x-data="nqProductGallery(JSON.parse('[{\u0022src\u0022:\u0022https:\\\/\\\/picsum.photos\\\/seed\\\/tee-1\\\/800\\\/800\u0022,\u0022alt\u0022:\u0022Everyday tee, front\u0022},{\u0022src\u0022:\u0022https:\\\/\\\/picsum.photos\\\/seed\\\/tee-2\\\/800\\\/800\u0022,\u0022alt\u0022:\u0022Everyday tee, back\u0022}]'), 'Everyday tee')"
    x-on:nq-gallery-show="show($event.detail.src)"
    class="flex min-w-0 flex-col gap-3">
    <div class="relative">
        <div data-slot="product-gallery-viewport" x-bind="viewport" class="relative aspect-square overflow-hidden rounded-card border border-border bg-secondary [touch-action:pan-y]">
            <button type="button" data-slot="product-gallery-stage" x-bind="stage"
                aria-label="View full screen"
                                class="block size-full outline-none focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-nq-focus cursor-zoom-in">
                                    <img src="https://picsum.photos/seed/tee-1/800/800" x-effect="$el.setAttribute('src', images[index]?.src ?? '')" alt="Everyday tee, front" :alt="images[index]?.alt || 'Everyday tee'"
                        width="800" height="800" loading="eager" decoding="async" draggable="false"
                        x-show="!currentFailed" x-on:error="failed[images[index].src] = true" class="size-full select-none object-contain transition-transform duration-200 ease-nq motion-reduce:transition-none"
                        :style="{ transform: origin ? 'scale(2)' : undefined, transformOrigin: origin ? `${origin.x}% ${origin.y}%` : undefined }">
                                <div role="img" aria-label="No image available" x-show="currentFailed"  style="display:none"                     class="flex size-full items-center justify-center bg-secondary text-muted-foreground"><svg aria-hidden="true" class="size-8" 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></div>
            </button>
                    </div>
                    <button data-slot="button"
     type="button"                         aria-label="Previous image" x-on:click="step(-1)" class="inline-flex shrink-0 select-none items-center justify-center gap-2 whitespace-nowrap 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 size-control-sm p-0 absolute start-2 top-1/2 -translate-y-1/2 rounded-full opacity-90 shadow-sm">
        <svg data-slot="icon" 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></button>
            <button data-slot="button"
     type="button"                         aria-label="Next image" x-on:click="step(1)" class="inline-flex shrink-0 select-none items-center justify-center gap-2 whitespace-nowrap 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 size-control-sm p-0 absolute end-2 top-1/2 -translate-y-1/2 rounded-full opacity-90 shadow-sm">
        <svg data-slot="icon" 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></button>
                            <button data-slot="button"
     type="button"                         aria-label="View full screen" x-on:click="lightbox = true" class="inline-flex shrink-0 select-none items-center justify-center gap-2 whitespace-nowrap 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 size-control-sm p-0 absolute end-2 top-2 rounded-full opacity-90 shadow-sm">
        <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 3h6v6"/>
  <path d="m21 3-7 7"/>
  <path d="m3 21 7-7"/>
  <path d="M9 21H3v-6"/>
</svg></button>
                <span class="pointer-events-none absolute bottom-2 end-2 rounded-full bg-background/90 px-2 py-0.5 text-caption tabular-nums text-muted-foreground" aria-hidden="true">
            <bdi x-text="index + 1">1</bdi> / <bdi>2</bdi>
        </span>
    </div>
    <p class="sr-only" aria-live="polite" x-text="position">Image 1 of 2</p>
            <ul data-slot="product-gallery-thumbs" class="flex gap-2 overflow-x-auto p-1 [scrollbar-width:none] [&::-webkit-scrollbar]:hidden ">
            <li class="shrink-0">
            <button type="button" aria-label="Show image 1"
                 aria-current="true"                 :aria-current="index === 0 ? 'true' : undefined" x-on:click="go(0)"
                class="relative block size-16 overflow-hidden rounded-control border bg-secondary outline-none transition-colors duration-150 ease-nq focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-nq-focus border-foreground ring-1 ring-foreground"
                :class="index === 0 ? 'border-foreground ring-1 ring-foreground' : 'border-border opacity-80 hover:opacity-100'">
                <img src="https://picsum.photos/seed/tee-1/800/800" alt="Everyday tee, front" width="800" height="800" loading="lazy" decoding="async" draggable="false" class="size-full select-none object-cover">
                            </button>
        </li>
            <li class="shrink-0">
            <button type="button" aria-label="Show image 2"
                                :aria-current="index === 1 ? 'true' : undefined" x-on:click="go(1)"
                class="relative block size-16 overflow-hidden rounded-control border bg-secondary outline-none transition-colors duration-150 ease-nq focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-nq-focus border-border opacity-80 hover:opacity-100"
                :class="index === 1 ? 'border-foreground ring-1 ring-foreground' : 'border-border opacity-80 hover:opacity-100'">
                <img src="https://picsum.photos/seed/tee-2/800/800" alt="Everyday tee, back" width="800" height="800" loading="lazy" decoding="async" draggable="false" class="size-full select-none object-cover">
                            </button>
        </li>
    </ul>
            <div data-slot="dialog" x-data="nqDialog(false)" x-modelable="open" x-id="['nq-dialog']" x-model="lightbox" 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="dialog-content" x-bind="popup" x-nq-presence="open" x-trap.noscroll="open"
            class="fixed inset-0 z-50 m-auto grid rounded-floating border border-border bg-popover text-popover-foreground outline-none overflow-y-auto transition-opacity duration-150 ease-nq data-starting-style:opacity-0 data-ending-style:opacity-0 h-[calc(100dvh-1rem)] max-h-none w-[calc(100%-1rem)] max-w-none grid-rows-[auto_minmax(0,1fr)_auto] gap-3 p-3">
            <div class="flex items-center justify-between gap-3 pe-10">
                    <h2 data-slot="dialog-title" :id="$id('nq-dialog', 'title')" class="text-foreground text-body font-medium">Everyday tee</h2>
                    <p data-slot="dialog-description" :id="$id('nq-dialog', 'description')" class="text-muted-foreground text-caption tabular-nums"><span x-text="position">Image 1 of 2</span></p>
                </div>
                <div class="relative min-h-0">
                    <div data-slot="product-gallery-viewport" x-bind="lbViewport" class="relative size-full overflow-hidden rounded-card bg-secondary [touch-action:pan-y]">
                        <button type="button" data-slot="product-gallery-stage" x-bind="lbStage" aria-label="Zoom in" class="block size-full outline-none focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-nq-focus cursor-zoom-in" :class="lbOrigin ? 'cursor-zoom-out' : 'cursor-zoom-in'">
                                                            <img src="https://picsum.photos/seed/tee-1/800/800" x-effect="$el.setAttribute('src', images[index]?.src ?? '')" alt="Everyday tee, front" :alt="images[index]?.alt || 'Everyday tee'"
                                    width="800" height="800" loading="lazy" decoding="async" draggable="false"
                                    x-show="!currentFailed" class="size-full select-none object-contain transition-transform duration-200 ease-nq motion-reduce:transition-none"
                                    :style="{ transform: lbOrigin ? 'scale(2)' : undefined, transformOrigin: lbOrigin ? `${lbOrigin.x}% ${lbOrigin.y}%` : undefined }">
                                                    </button>
                    </div>
                                            <button data-slot="button"
     type="button"                         aria-label="Previous image" x-on:click="step(-1)" class="inline-flex shrink-0 select-none items-center justify-center gap-2 whitespace-nowrap 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 size-control p-0 absolute start-2 top-1/2 -translate-y-1/2 rounded-full">
        <svg data-slot="icon" 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></button>
                        <button data-slot="button"
     type="button"                         aria-label="Next image" x-on:click="step(1)" class="inline-flex shrink-0 select-none items-center justify-center gap-2 whitespace-nowrap 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 size-control p-0 absolute end-2 top-1/2 -translate-y-1/2 rounded-full">
        <svg data-slot="icon" 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></button>
                                        <span class="pointer-events-none absolute bottom-2 start-2 inline-flex items-center gap-1 rounded-full bg-background/90 px-2 py-1 text-caption text-muted-foreground" aria-hidden="true">
                        <svg class="size-3" 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="11" cy="11" r="8"/>
  <line x1="21" x2="16.65" y1="21" y2="16.65"/>
  <line x1="11" x2="11" y1="8" y2="14"/>
  <line x1="8" x2="14" y1="11" y2="11"/>
</svg>                    </span>
                </div>
                                    <ul data-slot="product-gallery-thumbs" class="flex gap-2 overflow-x-auto p-1 [scrollbar-width:none] [&::-webkit-scrollbar]:hidden justify-center">
            <li class="shrink-0">
            <button type="button" aria-label="Show image 1"
                 aria-current="true"                 :aria-current="index === 0 ? 'true' : undefined" x-on:click="go(0)"
                class="relative block size-16 overflow-hidden rounded-control border bg-secondary outline-none transition-colors duration-150 ease-nq focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-nq-focus border-foreground ring-1 ring-foreground"
                :class="index === 0 ? 'border-foreground ring-1 ring-foreground' : 'border-border opacity-80 hover:opacity-100'">
                <img src="https://picsum.photos/seed/tee-1/800/800" alt="Everyday tee, front" width="800" height="800" loading="lazy" decoding="async" draggable="false" class="size-full select-none object-cover">
                            </button>
        </li>
            <li class="shrink-0">
            <button type="button" aria-label="Show image 2"
                                :aria-current="index === 1 ? 'true' : undefined" x-on:click="go(1)"
                class="relative block size-16 overflow-hidden rounded-control border bg-secondary outline-none transition-colors duration-150 ease-nq focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-nq-focus border-border opacity-80 hover:opacity-100"
                :class="index === 1 ? 'border-foreground ring-1 ring-foreground' : 'border-border opacity-80 hover:opacity-100'">
                <img src="https://picsum.photos/seed/tee-2/800/800" alt="Everyday tee, back" width="800" height="800" loading="lazy" decoding="async" draggable="false" class="size-full select-none object-cover">
                            </button>
        </li>
    </ul>
                            <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>
        </div>
        <div class="flex min-w-0 flex-col gap-5">
            <header class="flex flex-col gap-2">
                                                    <p class="text-label text-muted-foreground">Nasaq Goods</p>
                                <h1 class="text-balance text-h1 text-foreground">Everyday tee</h1>
                                    <button type="button" x-on:click="document.getElementById('reviews')?.scrollIntoView({ behavior: 'smooth', block: 'start' })"
                        class="w-fit rounded-[3px] outline-none hover:underline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-nq-focus">
                        <span data-slot="rating" class="inline-flex items-center gap-1.5 text-caption text-muted-foreground">
    <span class="sr-only">Rated 4.6 out of 5, 128 Reviews</span>
    <svg aria-hidden="true" class="size-3.5 shrink-0 fill-nq-accent text-nq-accent" 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.525 2.295a.53.53 0 0 1 .95 0l2.31 4.679a2.123 2.123 0 0 0 1.595 1.16l5.166.756a.53.53 0 0 1 .294.904l-3.736 3.638a2.123 2.123 0 0 0-.611 1.878l.882 5.14a.53.53 0 0 1-.771.56l-4.618-2.428a2.122 2.122 0 0 0-1.973 0L6.396 21.01a.53.53 0 0 1-.77-.56l.881-5.139a2.122 2.122 0 0 0-.611-1.879L2.16 9.795a.53.53 0 0 1 .294-.906l5.165-.755a2.122 2.122 0 0 0 1.597-1.16z"/>
</svg>    <bdi aria-hidden="true" class="tabular-nums text-foreground">4.6</bdi>
            <span aria-hidden="true" class="truncate">
            <span class="me-1.5">·</span>
            <bdi class="tabular-nums">128</bdi> Reviews
        </span>
    </span>
                    </button>
                            </header>
            <div class="flex flex-wrap items-center gap-x-3 gap-y-1">
                <span class="text-body-sm text-muted-foreground" x-show="price.from"  style="display:none" >From</span>
                <span data-slot="price" class="inline-flex flex-wrap items-baseline gap-x-1.5 text-body-sm text-foreground">
                    <span><bdi class="text-h2 font-semibold tracking-tight tabular-nums" x-text="priceText">$29</bdi></span>
                    <s class="text-caption text-muted-foreground decoration-muted-foreground/60" x-show="compareText"  style="display:none" >
                        <span class="sr-only">was </span>
                        <bdi class="tabular-nums" x-text="compareText"></bdi>
                    </s>
                </span>
                <span data-slot="badge"  style="display:none"     x-show="price.percentOff &gt; 0" x-text="percentText" 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-danger/40 bg-nq-danger-soft text-nq-danger-text">0% off</span>
            </div>
                            <div class="scroll-mt-24">
                    <div data-slot="product-variant-picker" class="flex flex-col gap-4">
                    <div data-slot="product-option" data-option="color"             :data-invalid="invalid.includes('color') ? '' : undefined" class="flex flex-col gap-2">
            <div class="flex items-baseline justify-between gap-3">
                <span id="nq-pdp-a04ce4-color-label" class="text-label text-foreground">
                    Colour
                    <span class="text-muted-foreground" x-show="pickedValue('color')" >: </span>
                    <span class="font-normal text-muted-foreground" x-text="pickedValue('color')">Black</span>
                </span>
                            </div>
                            <div role="radiogroup" dir="ltr" aria-labelledby="nq-pdp-a04ce4-color-label"                     :aria-invalid="invalid.includes('color') ? 'true' : undefined" x-on:keydown="radioKey($event, 'color')"
                    class="flex flex-wrap gap-2 "
                    :class="{ 'rounded-control outline-1 outline-offset-4 outline-nq-danger': invalid.includes('color') }">
                                                                    <button type="button" role="radio" aria-checked="true" tabindex="0"
                            aria-label="Black" data-availability="available"
                             data-checked                                                                                      title="Black"                             x-show="shown('color', 'black')"
                            :aria-checked="isChecked('color', 'black')" :tabindex="tabindexFor('color', 'black')"
                            :aria-label="spoken('Black', 'color', 'black')" :data-availability="avail('color', 'black')"
                            :data-checked="isChecked('color', 'black') ? '' : undefined" :data-unchecked="isChecked('color', 'black') ? undefined : ''"
                            :disabled="avail('color', 'black') === 'none'" :data-disabled="avail('color', 'black') === 'none' ? '' : undefined"
                            x-on:click="pick('color', 'black')"
                            class="relative inline-flex size-9 items-center justify-center rounded-full border border-nq-line-strong p-0.5 transition-shadow duration-150 ease-nq outline-none focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-nq-focus data-checked:border-foreground data-checked:ring-1 data-checked:ring-foreground data-disabled:cursor-not-allowed data-disabled:opacity-40">
                                                            <span aria-hidden="true" class="relative block size-full overflow-hidden rounded-full border border-border" style="background-color: #111111">
                                    <span x-show="avail('color', 'black') === 'out'"  style="display:none"  class="absolute start-1/2 top-1/2 h-px w-[150%] -translate-x-1/2 -translate-y-1/2 -rotate-45 bg-nq-danger"></span>
                                </span>
                                                    </button>
                                                                    <button type="button" role="radio" aria-checked="false" tabindex="-1"
                            aria-label="Sand" data-availability="available"
                             data-unchecked                                                                                      title="Sand"                             x-show="shown('color', 'sand')"
                            :aria-checked="isChecked('color', 'sand')" :tabindex="tabindexFor('color', 'sand')"
                            :aria-label="spoken('Sand', 'color', 'sand')" :data-availability="avail('color', 'sand')"
                            :data-checked="isChecked('color', 'sand') ? '' : undefined" :data-unchecked="isChecked('color', 'sand') ? undefined : ''"
                            :disabled="avail('color', 'sand') === 'none'" :data-disabled="avail('color', 'sand') === 'none' ? '' : undefined"
                            x-on:click="pick('color', 'sand')"
                            class="relative inline-flex size-9 items-center justify-center rounded-full border border-nq-line-strong p-0.5 transition-shadow duration-150 ease-nq outline-none focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-nq-focus data-checked:border-foreground data-checked:ring-1 data-checked:ring-foreground data-disabled:cursor-not-allowed data-disabled:opacity-40">
                                                            <span aria-hidden="true" class="relative block size-full overflow-hidden rounded-full border border-border" style="background-color: #d8c3a5">
                                    <span x-show="avail('color', 'sand') === 'out'"  style="display:none"  class="absolute start-1/2 top-1/2 h-px w-[150%] -translate-x-1/2 -translate-y-1/2 -rotate-45 bg-nq-danger"></span>
                                </span>
                                                    </button>
                                    </div>
                    </div>
                    <div data-slot="product-option" data-option="size"             :data-invalid="invalid.includes('size') ? '' : undefined" class="flex flex-col gap-2">
            <div class="flex items-baseline justify-between gap-3">
                <span id="nq-pdp-a04ce4-size-label" class="text-label text-foreground">
                    Size
                    <span class="text-muted-foreground" x-show="pickedValue('size')" >: </span>
                    <span class="font-normal text-muted-foreground" x-text="pickedValue('size')">S</span>
                </span>
                            </div>
                            <div role="radiogroup" dir="ltr" aria-labelledby="nq-pdp-a04ce4-size-label"                     :aria-invalid="invalid.includes('size') ? 'true' : undefined" x-on:keydown="radioKey($event, 'size')"
                    class="flex flex-wrap gap-2 "
                    :class="{ 'rounded-control outline-1 outline-offset-4 outline-nq-danger': invalid.includes('size') }">
                                                                    <button type="button" role="radio" aria-checked="true" tabindex="0"
                            aria-label="S" data-availability="available"
                             data-checked                                                                                                                 x-show="shown('size', 's')"
                            :aria-checked="isChecked('size', 's')" :tabindex="tabindexFor('size', 's')"
                            :aria-label="spoken('S', 'size', 's')" :data-availability="avail('size', 's')"
                            :data-checked="isChecked('size', 's') ? '' : undefined" :data-unchecked="isChecked('size', 's') ? undefined : ''"
                            :disabled="avail('size', 's') === 'none'" :data-disabled="avail('size', 's') === 'none' ? '' : undefined"
                            x-on:click="pick('size', 's')"
                            class="relative inline-flex h-control min-w-11 items-center justify-center rounded-control border px-3 text-label transition-colors duration-150 ease-nq outline-none focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-nq-focus border-border bg-card text-foreground hover:bg-nq-hover data-checked:border-foreground data-checked:ring-1 data-checked:ring-foreground data-disabled:cursor-not-allowed data-disabled:opacity-40 data-disabled:hover:bg-card">
                                                            <bdi>S</bdi>
                                                    </button>
                                                                    <button type="button" role="radio" aria-checked="false" tabindex="-1"
                            aria-label="M" data-availability="available"
                             data-unchecked                                                                                                                 x-show="shown('size', 'm')"
                            :aria-checked="isChecked('size', 'm')" :tabindex="tabindexFor('size', 'm')"
                            :aria-label="spoken('M', 'size', 'm')" :data-availability="avail('size', 'm')"
                            :data-checked="isChecked('size', 'm') ? '' : undefined" :data-unchecked="isChecked('size', 'm') ? undefined : ''"
                            :disabled="avail('size', 'm') === 'none'" :data-disabled="avail('size', 'm') === 'none' ? '' : undefined"
                            x-on:click="pick('size', 'm')"
                            class="relative inline-flex h-control min-w-11 items-center justify-center rounded-control border px-3 text-label transition-colors duration-150 ease-nq outline-none focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-nq-focus border-border bg-card text-foreground hover:bg-nq-hover data-checked:border-foreground data-checked:ring-1 data-checked:ring-foreground data-disabled:cursor-not-allowed data-disabled:opacity-40 data-disabled:hover:bg-card">
                                                            <bdi>M</bdi>
                                                    </button>
                                                                    <button type="button" role="radio" aria-checked="false" tabindex="-1"
                            aria-label="L, Sold out" data-availability="out"
                             data-unchecked                                                                                                                 x-show="shown('size', 'l')"
                            :aria-checked="isChecked('size', 'l')" :tabindex="tabindexFor('size', 'l')"
                            :aria-label="spoken('L', 'size', 'l')" :data-availability="avail('size', 'l')"
                            :data-checked="isChecked('size', 'l') ? '' : undefined" :data-unchecked="isChecked('size', 'l') ? undefined : ''"
                            :disabled="avail('size', 'l') === 'none'" :data-disabled="avail('size', 'l') === 'none' ? '' : undefined"
                            x-on:click="pick('size', 'l')"
                            class="relative inline-flex h-control min-w-11 items-center justify-center rounded-control border px-3 text-label transition-colors duration-150 ease-nq outline-none focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-nq-focus border-border bg-card text-foreground hover:bg-nq-hover data-checked:border-foreground data-checked:ring-1 data-checked:ring-foreground data-disabled:cursor-not-allowed data-disabled:opacity-40 data-disabled:hover:bg-card border-dashed text-muted-foreground line-through decoration-nq-danger">
                                                            <bdi>L</bdi>
                                                    </button>
                                    </div>
                    </div>
    </div>
                </div>
            <div class="flex flex-wrap items-start gap-x-6 gap-y-3">
                <div data-slot="product-quantity" x-data="nqProductQuantity(1, 8)" x-modelable="value"
    x-model="quantity" x-effect="max = maxQty ?? null; disabled = soldOut" class="flex flex-col gap-1">
    <div role="group" aria-label="Quantity" class="inline-flex w-fit items-center overflow-hidden rounded-control border border-border bg-card">
        <button type="button" aria-label="Decrease quantity" class="inline-flex h-control w-11 items-center justify-center text-foreground outline-none transition-colors duration-150 ease-nq hover:bg-nq-hover focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-nq-focus disabled:cursor-not-allowed disabled:opacity-40 disabled:hover:bg-transparent [&amp;_svg]:size-4"
            x-on:click="commit(clamped - 1)" :disabled="disabled || clamped <= 1"  disabled >
            <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"/>
</svg>        </button>
        <input type="text" inputmode="numeric" role="spinbutton" aria-label="Quantity" aria-valuemin="1"
             aria-valuemax="8"  aria-valuenow="1" dir="ltr" value="1"
                        :value="display" :aria-valuemax="limit" :aria-valuenow="clamped" :disabled="disabled"
            x-on:input="onInput($event)" x-on:focus="$event.target.select()" x-on:blur="onBlur()" x-on:keydown="onKey($event)"
            class="h-control w-12 border-x border-border bg-transparent text-center text-body tabular-nums text-foreground outline-none focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-nq-focus disabled:opacity-50 pointer-coarse:text-[16px]">
        <button type="button" aria-label="Increase quantity" class="inline-flex h-control w-11 items-center justify-center text-foreground outline-none transition-colors duration-150 ease-nq hover:bg-nq-hover focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-nq-focus disabled:cursor-not-allowed disabled:opacity-40 disabled:hover:bg-transparent [&amp;_svg]:size-4"
            x-on:click="commit(clamped + 1)" :disabled="disabled || atMax" >
            <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>        </button>
    </div>
    <p aria-live="polite" class="text-caption text-nq-warning-text sr-only" x-effect="$el.classList.toggle('sr-only', !hint)" x-text="hintText"></p>
</div>
                <p aria-live="polite" class="flex h-control items-center gap-2 text-label text-nq-success-text"
                    :class="{ 'text-nq-warning-text': stockTone === 'warning', 'text-nq-success-text': stockTone === 'success', 'text-nq-info-text': stockTone === 'info', 'text-nq-danger-text': stockTone === 'danger' }">
                    <span aria-hidden="true" class="size-2 rounded-full bg-nq-success" x-show="stockText"                         :class="{ 'bg-nq-warning': stockTone === 'warning', 'bg-nq-success': stockTone === 'success', 'bg-nq-info': stockTone === 'info', 'bg-nq-danger': stockTone === 'danger' }"></span>
                    <span x-text="stockText">In stock</span>
                </p>
            </div>
            <div data-slot="product-cta" class="flex flex-col gap-2">
                <div class="flex flex-wrap gap-2">
                    <button data-slot="button"
     type="button"                         aria-describedby="nq-pdp-status-a04ce4" x-on:click="run(&#039;add&#039;)" x-bind:disabled="soldOut || pending !== null" x-bind:aria-busy="pending === &#039;add&#039;" class="inline-flex shrink-0 select-none items-center justify-center gap-2 whitespace-nowrap rounded-control border border-transparent font-sans 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-[calc(var(--nq-control)+8px)] px-5 text-body min-w-44 flex-1">
        <span x-show="pending === 'add'" style="display:none" class="contents"><svg data-slot="spinner" aria-hidden="true" class="size-4 animate-spin motion-reduce:animate-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="M21 12a9 9 0 1 1-6.219-8.56"/>
</svg></span>
                        <span x-text="addLabel">Add to cart</span></button>
                                                            <button data-slot="button"
     type="button"                         aria-label="Share" title="Share" x-on:click="share()" class="inline-flex shrink-0 select-none items-center justify-center gap-2 whitespace-nowrap rounded-control border font-sans 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-[calc(var(--nq-control)+8px)] text-body w-[calc(var(--nq-control)+8px)] px-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">
  <circle cx="18" cy="5" r="3"/>
  <circle cx="6" cy="12" r="3"/>
  <circle cx="18" cy="19" r="3"/>
  <line x1="8.59" x2="15.42" y1="13.51" y2="17.49"/>
  <line x1="15.41" x2="8.59" y1="6.51" y2="10.49"/>
</svg></button>
                </div>
                <p id="nq-pdp-status-a04ce4" role="status" aria-live="polite" class="sr-only flex items-center gap-1.5 text-body-sm"
                    x-effect="$el.classList.toggle('sr-only', !status); $el.setAttribute('role', status?.kind === 'error' ? 'alert' : 'status')"
                    :class="{ 'text-nq-danger-text': status?.kind === 'error', 'text-nq-success-text': status?.kind === 'ok', 'text-muted-foreground': status?.kind === 'info' }">
                    <svg aria-hidden="true" x-show="status?.kind === 'error'" style="display:none" class="size-4 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="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="status?.text"></span>
                </p>
            </div>
                            <ul data-slot="product-trust" class="grid grid-cols-1 gap-3 border-t border-border pt-5 sm:grid-cols-2">
                                            <li class="flex items-start gap-2.5">
                            <svg aria-hidden="true" class="mt-0.5 size-5 shrink-0 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="M20 13c0 5-3.5 7.5-7.66 8.95a1 1 0 0 1-.67-.01C7.5 20.5 4 18 4 13V6a1 1 0 0 1 1-1c2 0 4.5-1.2 6.24-2.72a1.17 1.17 0 0 1 1.52 0C14.51 3.81 17 5 19 5a1 1 0 0 1 1 1z"/>
  <path d="m9 12 2 2 4-4"/>
</svg>                            <span class="flex min-w-0 flex-col">
                                <span class="text-label text-foreground">Secure payment</span>
                                                                    <span class="text-caption text-muted-foreground">Your payment details are encrypted.</span>
                                                            </span>
                        </li>
                                            <li class="flex items-start gap-2.5">
                            <svg aria-hidden="true" class="mt-0.5 size-5 shrink-0 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="M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8"/>
  <path d="M3 3v5h5"/>
</svg>                            <span class="flex min-w-0 flex-col">
                                <span class="text-label text-foreground">Easy returns</span>
                                                                    <span class="text-caption text-muted-foreground">Return within 14 days.</span>
                                                            </span>
                        </li>
                                            <li class="flex items-start gap-2.5">
                            <svg aria-hidden="true" class="mt-0.5 size-5 shrink-0 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="M14 18V6a2 2 0 0 0-2-2H4a2 2 0 0 0-2 2v11a1 1 0 0 0 1 1h2"/>
  <path d="M15 18H9"/>
  <path d="M19 18h2a1 1 0 0 0 1-1v-3.65a1 1 0 0 0-.22-.624l-3.48-4.35A1 1 0 0 0 17.52 8H14"/>
  <circle cx="17" cy="18" r="2"/>
  <circle cx="7" cy="18" r="2"/>
</svg>                            <span class="flex min-w-0 flex-col">
                                <span class="text-label text-foreground">Fast delivery</span>
                                                                    <span class="text-caption text-muted-foreground">Tracked shipping across Egypt.</span>
                                                            </span>
                        </li>
                                            <li class="flex items-start gap-2.5">
                            <svg aria-hidden="true" class="mt-0.5 size-5 shrink-0 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="M3.85 8.62a4 4 0 0 1 4.78-4.77 4 4 0 0 1 6.74 0 4 4 0 0 1 4.78 4.78 4 4 0 0 1 0 6.74 4 4 0 0 1-4.77 4.78 4 4 0 0 1-6.75 0 4 4 0 0 1-4.78-4.77 4 4 0 0 1 0-6.76Z"/>
  <path d="m9 12 2 2 4-4"/>
</svg>                            <span class="flex min-w-0 flex-col">
                                <span class="text-label text-foreground">Original products</span>
                                                                    <span class="text-caption text-muted-foreground">Sold by the brand or its partners.</span>
                                                            </span>
                        </li>
                                    </ul>
                    </div>
    </div>
                        <div data-slot="tabs" data-orientation="horizontal" x-data="nqTabs('description')" x-modelable="value" x-id="['nq-tabs']" aria-label="Product information" 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('description')"
     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">Description</button>
                                            <button type="button" data-slot="tabs-tab" x-bind="tab('specs')"
            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">Specifications</button>
</div>
                                    <div data-slot="tabs-panel" x-bind="panel('description')"
        class="outline-none focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-nq-focus max-w-3xl"><p class="text-pretty text-body text-muted-foreground">A soft cotton tee that holds its shape wash after wash.</p></div>
                                    <div data-slot="tabs-panel" x-bind="panel('specs')"
     hidden     class="outline-none focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-nq-focus max-w-3xl"><dl class="grid grid-cols-[minmax(0,10rem)_minmax(0,1fr)] gap-x-4 text-body-sm">
                    <div class="col-span-2 grid grid-cols-subgrid border-b border-border py-2 last:border-b-0" >
                <dt class="text-muted-foreground">Brand</dt>
                <dd class="text-foreground">
                    Nasaq Goods                </dd>
            </div>
            </dl></div>
</div>
            <div data-slot="product-sticky-bar" role="region" aria-label="Add to cart bar" x-show="barVisible" style="display:none"
            class="fixed inset-x-0 bottom-0 z-40 flex items-center gap-3 border-t border-border bg-background p-3 shadow-lg md:hidden">
            <div class="flex min-w-0 flex-1 flex-col">
                <span class="inline-flex flex-wrap items-baseline gap-x-1.5 text-body text-foreground">
                    <bdi class="font-medium tabular-nums" x-text="priceText">$29</bdi>
                    <s class="text-caption text-muted-foreground" x-show="compareText"  style="display:none" ><bdi class="tabular-nums" x-text="compareText"></bdi></s>
                </span>
                <span class="truncate text-caption text-muted-foreground" x-text="pickedLabels"></span>
            </div>
            <button data-slot="button"
     type="button"                         x-on:click="run(&#039;add&#039;)" x-bind:disabled="soldOut || pending !== null" class="inline-flex select-none items-center justify-center gap-2 whitespace-nowrap rounded-control border border-transparent font-sans 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-[calc(var(--nq-control)+8px)] px-5 text-body shrink-0">
        <span x-text="addLabel">Add to cart</span></button>
        </div>
    </div>
```
