diff --git a/app/templates/shared/macros/shop/product-gallery.html b/app/templates/shared/macros/shop/product-gallery.html
new file mode 100644
index 00000000..799720a0
--- /dev/null
+++ b/app/templates/shared/macros/shop/product-gallery.html
@@ -0,0 +1,398 @@
+{#
+ Product Gallery Components
+ ==========================
+ Image gallery with thumbnails, zoom, and lightbox for product detail pages.
+
+ Usage:
+ {% from 'shared/macros/shop/product-gallery.html' import product_gallery, gallery_thumbnails %}
+#}
+
+
+{#
+ Product Gallery
+ ===============
+ Full image gallery with main image and thumbnails.
+
+ Parameters:
+ - images_var: Alpine.js expression for images array (default: 'product.images')
+ - selected_var: Alpine.js variable for selected image index (default: 'selectedImage')
+ - show_thumbnails: Show thumbnail navigation (default: true)
+ - enable_zoom: Enable hover zoom on main image (default: true)
+ - enable_lightbox: Enable fullscreen lightbox (default: true)
+ - max_thumbnails: Max thumbnails to show (default: 5)
+ - aspect_ratio: Main image aspect ratio (default: 'square')
+
+ Expected image object:
+ {
+ id: 1,
+ url: 'https://...',
+ thumbnail_url: 'https://...',
+ alt: 'Product image'
+ }
+
+ Usage:
+ {{ product_gallery(images_var='product.images') }}
+#}
+{% macro product_gallery(
+ images_var='product.images',
+ selected_var='selectedImage',
+ show_thumbnails=true,
+ enable_zoom=true,
+ enable_lightbox=true,
+ max_thumbnails=5,
+ aspect_ratio='square'
+) %}
+{% set aspects = {
+ 'square': 'aspect-square',
+ '4:3': 'aspect-[4/3]',
+ '3:4': 'aspect-[3/4]',
+ '16:9': 'aspect-video',
+ '3:2': 'aspect-[3/2]'
+} %}
+{% set aspect_class = aspects.get(aspect_ratio, 'aspect-square') %}
+
+
+ {# Main Image Container #}
+
+ {# Main Image #}
+
+ {# Product Image #}
+
![]()
+
+ {# Zoom Indicator #}
+ {% if enable_zoom %}
+
+
+ Hover to zoom
+
+ {% endif %}
+
+ {# Lightbox Button #}
+ {% if enable_lightbox %}
+
+ {% endif %}
+
+
+ {# Navigation Arrows #}
+
+
+
+
+
+
+
+ {# Image Counter #}
+
+
+
+
+
+
+
+ {# Thumbnails #}
+ {% if show_thumbnails %}
+
+ {% endif %}
+
+ {# Lightbox Modal #}
+ {% if enable_lightbox %}
+
+ {# Close Button #}
+
+
+ {# Lightbox Image #}
+
+
![]()
+
+
+ {# Lightbox Navigation #}
+
+
+
+
+
+
+
+ {# Lightbox Thumbnails #}
+
+
+
+
+
+
+ {# Image Counter #}
+
+
+
+
+ {% endif %}
+
+{% endmacro %}
+
+
+{#
+ Gallery Thumbnails Only
+ =======================
+ Standalone thumbnail strip for custom layouts.
+
+ Parameters:
+ - images_var: Alpine.js expression for images array
+ - selected_var: Alpine.js variable for selected index
+ - orientation: 'horizontal' | 'vertical' (default: 'horizontal')
+ - size: 'sm' | 'md' | 'lg' (default: 'md')
+
+ Usage:
+ {{ gallery_thumbnails(images_var='product.images', orientation='vertical') }}
+#}
+{% macro gallery_thumbnails(
+ images_var='product.images',
+ selected_var='selectedImage',
+ orientation='horizontal',
+ size='md'
+) %}
+{% set sizes = {
+ 'sm': {'container': 'w-12 h-12', 'gap': 'gap-1'},
+ 'md': {'container': 'w-16 h-16', 'gap': 'gap-2'},
+ 'lg': {'container': 'w-20 h-20', 'gap': 'gap-3'}
+} %}
+{% set s = sizes[size] %}
+{% set is_vertical = orientation == 'vertical' %}
+
+
+
+
+
+
+{% endmacro %}
+
+
+{#
+ Simple Image Viewer
+ ===================
+ Single image with optional lightbox (for simple product pages).
+
+ Parameters:
+ - image_var: Alpine.js expression for image object or URL string
+ - enable_lightbox: Enable click to enlarge (default: true)
+ - aspect_ratio: Image aspect ratio (default: 'square')
+
+ Usage:
+ {{ simple_image_viewer(image_var='product.image_url') }}
+#}
+{% macro simple_image_viewer(
+ image_var='product.image_url',
+ enable_lightbox=true,
+ aspect_ratio='square'
+) %}
+{% set aspects = {
+ 'square': 'aspect-square',
+ '4:3': 'aspect-[4/3]',
+ '3:4': 'aspect-[3/4]',
+ '16:9': 'aspect-video'
+} %}
+{% set aspect_class = aspects.get(aspect_ratio, 'aspect-square') %}
+
+
+
+
![]()
+
+ {% if enable_lightbox %}
+
+
+
+ {% endif %}
+
+
+ {% if enable_lightbox %}
+ {# Lightbox #}
+
+
+
![]()
+
+ {% endif %}
+
+{% endmacro %}
diff --git a/app/templates/shared/macros/shop/product-info.html b/app/templates/shared/macros/shop/product-info.html
new file mode 100644
index 00000000..a7fa18a4
--- /dev/null
+++ b/app/templates/shared/macros/shop/product-info.html
@@ -0,0 +1,359 @@
+{#
+ Product Info Components
+ =======================
+ Product details section for product detail pages.
+
+ Usage:
+ {% from 'shared/macros/shop/product-info.html' import product_info, product_price, product_rating, stock_status %}
+#}
+
+
+{#
+ Product Info Block
+ ==================
+ Complete product information section.
+
+ Parameters:
+ - product_var: Alpine.js expression for product (default: 'product')
+ - show_sku: Show SKU (default: false)
+ - show_stock: Show stock status (default: true)
+ - show_rating: Show star rating (default: true)
+ - show_vendor: Show vendor name - for marketplace (default: false)
+ - show_category: Show category breadcrumb (default: false)
+ - title_tag: HTML tag for title (default: 'h1')
+
+ Expected product object:
+ {
+ name: 'Product Name',
+ sku: 'SKU-123',
+ price: 99.99,
+ sale_price: 79.99,
+ rating: 4.5,
+ review_count: 127,
+ stock: 15,
+ short_description: '...',
+ vendor: { name: 'Vendor Name', url: '/vendor/...' },
+ category: { name: 'Category', url: '/category/...' }
+ }
+
+ Usage:
+ {{ product_info(product_var='product', show_vendor=true) }}
+#}
+{% macro product_info(
+ product_var='product',
+ show_sku=false,
+ show_stock=true,
+ show_rating=true,
+ show_vendor=false,
+ show_category=false,
+ title_tag='h1'
+) %}
+
+ {# Category / Vendor (if marketplace) #}
+ {% if show_category or show_vendor %}
+
+ {% if show_category %}
+
+
+
+ {% endif %}
+ {% if show_category and show_vendor %}
+
•
+ {% endif %}
+ {% if show_vendor %}
+
+
+ Sold by
+
+
+ {% endif %}
+
+ {% endif %}
+
+ {# Product Title #}
+ <{{ title_tag }}
+ class="text-2xl md:text-3xl font-bold text-gray-900 dark:text-white"
+ x-text="{{ product_var }}.name"
+ >{{ title_tag }}>
+
+ {# Rating and Review Count #}
+ {% if show_rating %}
+
+ {{ product_rating(product_var=product_var, size='md', clickable=true) }}
+
+ {% endif %}
+
+ {# Price #}
+ {{ product_price(product_var=product_var, size='lg') }}
+
+ {# Short Description #}
+
+
+ {# Stock Status #}
+ {% if show_stock %}
+ {{ stock_status(product_var=product_var) }}
+ {% endif %}
+
+ {# SKU #}
+ {% if show_sku %}
+
+ SKU:
+
+ {% endif %}
+
+{% endmacro %}
+
+
+{#
+ Product Price
+ =============
+ Price display with sale price support.
+
+ Parameters:
+ - product_var: Alpine.js expression for product
+ - size: 'sm' | 'md' | 'lg' (default: 'md')
+ - show_discount: Show discount percentage (default: true)
+
+ Usage:
+ {{ product_price(product_var='product', size='lg') }}
+#}
+{% macro product_price(
+ product_var='product',
+ size='md',
+ show_discount=true
+) %}
+{% set sizes = {
+ 'sm': {'price': 'text-lg', 'original': 'text-sm', 'badge': 'text-xs px-1.5 py-0.5'},
+ 'md': {'price': 'text-xl', 'original': 'text-base', 'badge': 'text-xs px-2 py-0.5'},
+ 'lg': {'price': 'text-2xl md:text-3xl', 'original': 'text-lg', 'badge': 'text-sm px-2 py-1'}
+} %}
+{% set s = sizes[size] %}
+
+
+ {# Current Price (sale or regular) #}
+
+
+ {# Original Price (if on sale) #}
+
+
+ {# Discount Badge #}
+ {% if show_discount %}
+
+ {% endif %}
+
+{% endmacro %}
+
+
+{#
+ Product Rating
+ ==============
+ Star rating display with review count.
+
+ Parameters:
+ - product_var: Alpine.js expression for product
+ - size: 'sm' | 'md' | 'lg' (default: 'md')
+ - clickable: Make clickable to scroll to reviews (default: false)
+ - show_count: Show review count (default: true)
+
+ Usage:
+ {{ product_rating(product_var='product', clickable=true) }}
+#}
+{% macro product_rating(
+ product_var='product',
+ size='md',
+ clickable=false,
+ show_count=true
+) %}
+{% set sizes = {
+ 'sm': {'star': 'w-4 h-4', 'text': 'text-xs'},
+ 'md': {'star': 'w-5 h-5', 'text': 'text-sm'},
+ 'lg': {'star': 'w-6 h-6', 'text': 'text-base'}
+} %}
+{% set s = sizes[size] %}
+
+
+ {# Stars #}
+
+
+
+
+
+
+ {# Rating Number #}
+
+
+ {# Review Count #}
+ {% if show_count %}
+
+ ( reviews)
+
+ {% endif %}
+
+{% endmacro %}
+
+
+{#
+ Stock Status
+ ============
+ Stock availability indicator.
+
+ Parameters:
+ - product_var: Alpine.js expression for product (or stock number)
+ - low_stock_threshold: Show warning below this number (default: 10)
+
+ Usage:
+ {{ stock_status(product_var='product') }}
+ {{ stock_status(product_var='selectedVariant.stock') }}
+#}
+{% macro stock_status(
+ product_var='product',
+ low_stock_threshold=10
+) %}
+
+ {# In Stock #}
+
+
+
+ In Stock
+
+
+
+ {# Low Stock #}
+
+
+
+
+ Only left in stock
+
+
+
+
+ {# Out of Stock #}
+
+
+
+ Out of Stock
+
+
+
+{% endmacro %}
+
+
+{#
+ Product Badges
+ ==============
+ Display multiple product badges (new, sale, bestseller, etc.).
+
+ Parameters:
+ - product_var: Alpine.js expression for product
+
+ Usage:
+ {{ product_badges(product_var='product') }}
+#}
+{% macro product_badges(product_var='product') %}
+
+ {# Sale Badge #}
+
+
+ SALE
+
+
+
+ {# New Badge #}
+
+
+ NEW
+
+
+
+ {# Bestseller Badge #}
+
+
+ BESTSELLER
+
+
+
+ {# Limited Edition Badge #}
+
+
+ LIMITED
+
+
+
+{% endmacro %}
+
+
+{#
+ Trust Indicators
+ ================
+ Display trust/shipping information below add to cart.
+
+ Parameters:
+ - show_shipping: Show free shipping info (default: true)
+ - show_returns: Show returns policy (default: true)
+ - show_secure: Show secure checkout badge (default: true)
+ - free_shipping_threshold: Amount for free shipping (default: 50)
+
+ Usage:
+ {{ trust_indicators(free_shipping_threshold=75) }}
+#}
+{% macro trust_indicators(
+ show_shipping=true,
+ show_returns=true,
+ show_secure=true,
+ free_shipping_threshold=50
+) %}
+
+ {% if show_shipping %}
+
+
+ Free shipping on orders over ${{ free_shipping_threshold }}
+
+ {% endif %}
+
+ {% if show_returns %}
+
+
+ 30-day easy returns
+
+ {% endif %}
+
+ {% if show_secure %}
+
+
+ Secure checkout
+
+ {% endif %}
+
+{% endmacro %}
diff --git a/app/templates/shared/macros/shop/product-tabs.html b/app/templates/shared/macros/shop/product-tabs.html
new file mode 100644
index 00000000..28094940
--- /dev/null
+++ b/app/templates/shared/macros/shop/product-tabs.html
@@ -0,0 +1,400 @@
+{#
+ Product Tabs Components
+ =======================
+ Tabbed content sections for product detail pages.
+
+ Usage:
+ {% from 'shared/macros/shop/product-tabs.html' import product_tabs, tab_description, tab_specifications, tab_reviews %}
+#}
+
+
+{#
+ Product Tabs
+ ============
+ Tabbed container for product information sections.
+
+ Parameters:
+ - product_var: Alpine.js expression for product (default: 'product')
+ - tabs: List of tab IDs to show (default: ['description', 'specifications', 'reviews'])
+ - default_tab: Initially active tab (default: 'description')
+ - tab_var: Alpine.js variable for active tab (default: 'activeProductTab')
+
+ Usage:
+ {{ product_tabs(tabs=['description', 'specifications', 'reviews', 'shipping']) }}
+#}
+{% macro product_tabs(
+ product_var='product',
+ tabs=['description', 'specifications', 'reviews'],
+ default_tab='description',
+ tab_var='activeProductTab'
+) %}
+{% set tab_config = {
+ 'description': {'label': 'Description', 'icon': 'document-text'},
+ 'specifications': {'label': 'Specifications', 'icon': 'clipboard-list'},
+ 'reviews': {'label': 'Reviews', 'icon': 'star'},
+ 'shipping': {'label': 'Shipping & Returns', 'icon': 'truck'},
+ 'warranty': {'label': 'Warranty', 'icon': 'shield-check'}
+} %}
+
+
+ {# Tab Navigation #}
+
+
+
+
+ {# Tab Panels #}
+
+ {% if 'description' in tabs %}
+ {{ tab_description(product_var, tab_var) }}
+ {% endif %}
+
+ {% if 'specifications' in tabs %}
+ {{ tab_specifications(product_var, tab_var) }}
+ {% endif %}
+
+ {% if 'reviews' in tabs %}
+ {{ tab_reviews(product_var, tab_var) }}
+ {% endif %}
+
+ {% if 'shipping' in tabs %}
+ {{ tab_shipping(tab_var) }}
+ {% endif %}
+
+ {% if 'warranty' in tabs %}
+ {{ tab_warranty(product_var, tab_var) }}
+ {% endif %}
+
+
+{% endmacro %}
+
+
+{#
+ Tab: Description
+ ================
+ Product description content panel.
+#}
+{% macro tab_description(product_var='product', tab_var='activeProductTab') %}
+
+
+
+ {# Features List (if available) #}
+
+
+
+
+{% endmacro %}
+
+
+{#
+ Tab: Specifications
+ ===================
+ Product specifications table panel.
+#}
+{% macro tab_specifications(product_var='product', tab_var='activeProductTab') %}
+
+
+
+
+
+
+ No specifications available.
+
+
+{% endmacro %}
+
+
+{#
+ Tab: Reviews
+ ============
+ Product reviews list and summary panel.
+#}
+{% macro tab_reviews(product_var='product', tab_var='activeProductTab') %}
+
+ {# Reviews Summary #}
+
+ {# Overall Rating #}
+
+
+
+
+
+
+
+
+ reviews
+
+
+
+ {# Rating Distribution #}
+
+
+
+
+
+ {# Reviews List #}
+
+
+
+ {{ review_card() }}
+
+
+ {# Load More Reviews #}
+
+
+
+
+
+
+
+
+ {# No Reviews #}
+
+
+
+
No reviews yet
+
Be the first to review this product!
+
+
+
+
+{% endmacro %}
+
+
+{#
+ Review Card
+ ===========
+ Individual review display.
+#}
+{% macro review_card() %}
+
+ {# Header #}
+
+
+ {# Avatar #}
+
+
+
+
+
+
+
+
+
+ Verified
+
+
+
+
+
+
+
+ {# Rating #}
+
+
+
+
+
+
+
+ {# Title #}
+
+
+
+
+ {# Content #}
+
+
+ {# Review Images #}
+
+
+
+
+
+
+
+
+ {# Helpful Actions #}
+
+
+
+
+
+{% endmacro %}
+
+
+{#
+ Tab: Shipping & Returns
+ =======================
+ Shipping and returns policy panel.
+#}
+{% macro tab_shipping(tab_var='activeProductTab') %}
+
+
+ {# Shipping Info #}
+
+
+
+ Shipping Information
+
+
+
+ - Free standard shipping on orders over $50
+ - Standard shipping (3-5 business days): $4.99
+ - Express shipping (1-2 business days): $9.99
+ - Same-day delivery available in select areas
+
+
+
+
+ {# Returns Info #}
+
+
+
+ Returns & Exchanges
+
+
+
+ - 30-day return policy for unused items
+ - Free returns on all orders
+ - Items must be in original packaging
+ - Refunds processed within 5-7 business days
+
+
+
+
+
+{% endmacro %}
+
+
+{#
+ Tab: Warranty
+ =============
+ Product warranty information panel.
+#}
+{% macro tab_warranty(product_var='product', tab_var='activeProductTab') %}
+
+
+
+
+ Warranty Information
+
+
+
+
+
+
+
+
+
This product comes with our standard warranty:
+
+ - 1-year manufacturer warranty
+ - Coverage against manufacturing defects
+ - Free repairs or replacement
+ - Extended warranty options available at checkout
+
+
+
+
+
+{% endmacro %}
diff --git a/app/templates/shared/macros/shop/variant-selector.html b/app/templates/shared/macros/shop/variant-selector.html
new file mode 100644
index 00000000..a4e04007
--- /dev/null
+++ b/app/templates/shared/macros/shop/variant-selector.html
@@ -0,0 +1,418 @@
+{#
+ Variant Selector Components
+ ===========================
+ Product variant selection (size, color, etc.) for product detail pages.
+
+ Usage:
+ {% from 'shared/macros/shop/variant-selector.html' import variant_selector, size_selector, color_swatches %}
+#}
+
+
+{#
+ Variant Selector
+ ================
+ Generic variant selector that adapts to variant type.
+
+ Parameters:
+ - variants_var: Alpine.js expression for variants array (default: 'product.variants')
+ - selected_var: Alpine.js variable for selected variant (default: 'selectedVariant')
+ - type: 'buttons' | 'dropdown' | 'swatches' (default: 'buttons')
+ - label: Label text (default: 'Select Option')
+ - show_stock: Show stock status per variant (default: true)
+ - on_change: Custom change handler (default: none)
+
+ Expected variant object:
+ {
+ id: 1,
+ name: 'Large',
+ value: 'L',
+ stock: 10,
+ price_modifier: 0,
+ color_hex: '#FF0000', // For swatches
+ image_url: '...' // For swatches with preview
+ }
+
+ Usage:
+ {{ variant_selector(variants_var='product.sizes', label='Size') }}
+#}
+{% macro variant_selector(
+ variants_var='product.variants',
+ selected_var='selectedVariant',
+ type='buttons',
+ label='Select Option',
+ show_stock=true,
+ on_change=none
+) %}
+
+ {# Label #}
+
+
+
+
+
+ {% if type == 'buttons' %}
+ {{ _variant_buttons(variants_var, selected_var, show_stock, on_change) }}
+ {% elif type == 'dropdown' %}
+ {{ _variant_dropdown(variants_var, selected_var, show_stock, on_change) }}
+ {% elif type == 'swatches' %}
+ {{ _variant_swatches(variants_var, selected_var, show_stock, on_change) }}
+ {% endif %}
+
+{% endmacro %}
+
+
+{#
+ Internal: Variant Buttons
+#}
+{% macro _variant_buttons(variants_var, selected_var, show_stock, on_change) %}
+
+
+
+
+
+{% endmacro %}
+
+
+{#
+ Internal: Variant Dropdown
+#}
+{% macro _variant_dropdown(variants_var, selected_var, show_stock, on_change) %}
+
+{% endmacro %}
+
+
+{#
+ Internal: Variant Swatches (for colors)
+#}
+{% macro _variant_swatches(variants_var, selected_var, show_stock, on_change) %}
+
+
+
+
+
+{% endmacro %}
+
+
+{#
+ Size Selector
+ =============
+ Specialized selector for clothing/shoe sizes.
+
+ Parameters:
+ - sizes_var: Alpine.js expression for sizes array
+ - selected_var: Alpine.js variable for selected size
+ - show_guide: Show size guide link (default: true)
+ - guide_action: Action for size guide button (default: none)
+
+ Usage:
+ {{ size_selector(sizes_var='product.sizes', guide_action='showSizeGuide = true') }}
+#}
+{% macro size_selector(
+ sizes_var='product.sizes',
+ selected_var='selectedSize',
+ show_guide=true,
+ guide_action=none
+) %}
+
+ {# Label with Size Guide #}
+
+
+
+
+ {% if show_guide %}
+
+ {% endif %}
+
+
+
+ {# Size Buttons #}
+
+
+
+
+
+
+{% endmacro %}
+
+
+{#
+ Color Swatches
+ ==============
+ Specialized selector for color options with preview.
+
+ Parameters:
+ - colors_var: Alpine.js expression for colors array
+ - selected_var: Alpine.js variable for selected color
+ - size: 'sm' | 'md' | 'lg' (default: 'md')
+ - on_change: Custom change handler (triggers image change, etc.)
+
+ Expected color object:
+ {
+ id: 1,
+ name: 'Red',
+ value: 'red',
+ color_hex: '#FF0000',
+ stock: 10,
+ image_url: '...' // Optional: product image for this color
+ }
+
+ Usage:
+ {{ color_swatches(colors_var='product.colors', on_change='updateProductImage(selectedColor)') }}
+#}
+{% macro color_swatches(
+ colors_var='product.colors',
+ selected_var='selectedColor',
+ size='md',
+ on_change=none
+) %}
+{% set sizes = {
+ 'sm': {'swatch': 'w-8 h-8', 'icon': 'w-4 h-4'},
+ 'md': {'swatch': 'w-10 h-10', 'icon': 'w-5 h-5'},
+ 'lg': {'swatch': 'w-12 h-12', 'icon': 'w-6 h-6'}
+} %}
+{% set s = sizes[size] %}
+
+
+ {# Label #}
+
+
+
+
+
+ {# Color Swatches #}
+
+
+
+
+
+
+{% endmacro %}
+
+
+{#
+ Multi-Option Variant Selector
+ =============================
+ Combined selector for products with multiple option types (size + color).
+
+ Parameters:
+ - product_var: Alpine.js expression for product
+ - on_change: Callback when any variant changes
+
+ Expected product structure:
+ {
+ options: [
+ { name: 'Size', values: [...] },
+ { name: 'Color', values: [...] }
+ ],
+ variants: [
+ { id: 1, options: { size: 'M', color: 'Red' }, stock: 10, price: 99.99 }
+ ]
+ }
+
+ Usage:
+ {{ multi_variant_selector(product_var='product') }}
+#}
+{% macro multi_variant_selector(
+ product_var='product',
+ on_change=none
+) %}
+
+
+
+ {# Option Label #}
+
+
+
+
+
+ {# Option Values #}
+
+
+
+
+
+
+
+
+ {# Selected Variant Info #}
+
+
+
+ In Stock
+
+ Out of Stock
+
+
+
+
+
+{% endmacro %}