{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "product-comparison-drawer",
  "title": "Product Comparison Drawer",
  "type": "registry:block",
  "files": [
    {
      "path": "packages/registry-react/blocks/product-comparison-drawer/ProductComparisonDrawer.tsx",
      "content": "'use client'\n\nimport * as React from 'react'\nimport {\n  Check,\n  ChevronDown,\n  ChevronUp,\n  GitCompare,\n  Layers,\n  RotateCcw,\n  ShoppingCart,\n  SlidersHorizontal,\n  Star,\n  Trash2,\n  X,\n} from 'lucide-react'\nimport { Badge } from '@/components/ui/badge'\nimport { Button } from '@/components/ui/button'\nimport { Separator } from '@/components/ui/separator'\nimport { Switch } from '@/components/ui/switch'\nimport { cn } from '@/lib/utils'\n\nexport interface ComparisonSpec {\n  price: string\n  driverSize: string\n  batteryLife: string\n  ancType: string\n  waterResistance: string\n  weight: string\n  accessories: string\n  connectivity?: string\n  fastCharging?: string\n  microphone?: string\n  warranty?: string\n}\n\nexport interface ComparisonProduct {\n  id: string\n  name: string\n  tagline: string\n  badge: string\n  badgeVariant?: 'default' | 'secondary' | 'outline'\n  price: string\n  numericPrice: number\n  rating: number\n  reviewsCount: number\n  image: string\n  inStock: boolean\n  shipping: string\n  specs: ComparisonSpec\n}\n\nexport interface SpecField {\n  key: keyof ComparisonSpec\n  label: string\n  category: 'Key Specifications' | 'Audio & Connectivity' | 'Package & Warranty'\n  description?: string\n}\n\nexport const DEFAULT_COMPARISON_PRODUCTS: ComparisonProduct[] = [\n  {\n    id: 'prod-headphones',\n    name: 'Pro Wireless Headphones',\n    tagline: 'Flagship Over-Ear Studio Sound',\n    badge: 'Best Overall',\n    badgeVariant: 'default',\n    price: '$299.00',\n    numericPrice: 299,\n    rating: 4.9,\n    reviewsCount: 1240,\n    image: 'https://images.unsplash.com/photo-1505740420928-5e560c06d30e?w=400&auto=format&fit=crop&q=80',\n    inStock: true,\n    shipping: 'Free Next-Day Delivery',\n    specs: {\n      price: '$299.00',\n      driverSize: '40mm Graphene',\n      batteryLife: '40 Hours',\n      ancType: 'Adaptive ANC',\n      waterResistance: 'IPX4',\n      weight: '245g',\n      accessories: 'Hard Travel Case, 3.5mm Cable, USB-C Cable, Airplane Adapter',\n      connectivity: 'Bluetooth 5.3 + Multipoint',\n      fastCharging: '10 min charge = 3 hrs playback',\n      microphone: '6 Mics with Beamforming AI',\n      warranty: '2-Year Manufacturer Warranty',\n    },\n  },\n  {\n    id: 'prod-earbuds',\n    name: 'Aero Studio Earbuds',\n    tagline: 'Compact True Wireless In-Ear',\n    badge: 'Editor Choice',\n    badgeVariant: 'secondary',\n    price: '$199.00',\n    numericPrice: 199,\n    rating: 4.7,\n    reviewsCount: 890,\n    image: 'https://images.unsplash.com/photo-1590658268037-6bf12165a8df?w=400&auto=format&fit=crop&q=80',\n    inStock: true,\n    shipping: 'Free 2-Day Delivery',\n    specs: {\n      price: '$199.00',\n      driverSize: '11mm Dynamic',\n      batteryLife: '28 Hours',\n      ancType: 'Standard ANC',\n      waterResistance: 'IPX5',\n      weight: '54g',\n      accessories: 'Wireless Charging Case, 4 Pairs Silicone Tips (XS/S/M/L), USB-C Cable',\n      connectivity: 'Bluetooth 5.3 + Multipoint',\n      fastCharging: '10 min charge = 3 hrs playback',\n      microphone: '4 Mics with Wind Noise Guard',\n      warranty: '2-Year Manufacturer Warranty',\n    },\n  },\n  {\n    id: 'prod-sport',\n    name: 'Active ANC Sport',\n    tagline: 'Rugged Ergonomic Workout Earphones',\n    badge: 'Best Value',\n    badgeVariant: 'secondary',\n    price: '$149.00',\n    numericPrice: 149,\n    rating: 4.6,\n    reviewsCount: 620,\n    image: 'https://images.unsplash.com/photo-1572536147248-ac59a8abfa4b?w=400&auto=format&fit=crop&q=80',\n    inStock: true,\n    shipping: 'Free Standard Delivery',\n    specs: {\n      price: '$149.00',\n      driverSize: '10mm Hybrid',\n      batteryLife: '24 Hours',\n      ancType: 'Passive Noise Isolation',\n      waterResistance: 'IPX7 Waterproof',\n      weight: '62g',\n      accessories: 'Compact Case, Secure Wingtips, 3 Pairs Memory Foam Tips, USB-C Cable',\n      connectivity: 'Bluetooth 5.3',\n      fastCharging: '10 min charge = 3 hrs playback',\n      microphone: '2 Mics with Environmental Noise Cancellation',\n      warranty: '2-Year Manufacturer Warranty',\n    },\n  },\n]\n\nexport const SPEC_FIELDS: SpecField[] = [\n  {\n    key: 'price',\n    label: 'Price',\n    category: 'Key Specifications',\n    description: 'Manufacturer suggested retail price',\n  },\n  {\n    key: 'driverSize',\n    label: 'Driver Size',\n    category: 'Key Specifications',\n    description: 'Acoustic transducer diameter and diaphragm material',\n  },\n  {\n    key: 'batteryLife',\n    label: 'Battery Life',\n    category: 'Key Specifications',\n    description: 'Total listening duration with active cancellation enabled',\n  },\n  {\n    key: 'ancType',\n    label: 'ANC Type',\n    category: 'Key Specifications',\n    description: 'Acoustic cancellation and transparency algorithm type',\n  },\n  {\n    key: 'waterResistance',\n    label: 'Water Resistance',\n    category: 'Key Specifications',\n    description: 'Ingress protection rating against moisture and dust',\n  },\n  {\n    key: 'weight',\n    label: 'Weight',\n    category: 'Key Specifications',\n    description: 'Total physical mass including ear cushions/enclosures',\n  },\n  {\n    key: 'accessories',\n    label: 'In-Box Accessories',\n    category: 'Package & Warranty',\n    description: 'Included bundled cables, adapters, and travel protection',\n  },\n  {\n    key: 'connectivity',\n    label: 'Connectivity',\n    category: 'Audio & Connectivity',\n    description: 'Wireless Bluetooth specification and dual-device pairing',\n  },\n  {\n    key: 'fastCharging',\n    label: 'Fast Charging',\n    category: 'Audio & Connectivity',\n    description: 'Quick-boost charging time for emergency playback',\n  },\n  {\n    key: 'microphone',\n    label: 'Microphone Array',\n    category: 'Audio & Connectivity',\n    description: 'Voice pickup sensors and beamforming algorithms',\n  },\n  {\n    key: 'warranty',\n    label: 'Warranty',\n    category: 'Package & Warranty',\n    description: 'Manufacturer warranty coverage period',\n  },\n]\n\nexport interface ProductComparisonDrawerProps extends React.HTMLAttributes<HTMLDivElement> {\n  defaultOpen?: boolean\n  defaultHighlightDiffs?: boolean\n  products?: ComparisonProduct[]\n  mode?: 'dock' | 'expanded'\n  onAddToCart?: (product: ComparisonProduct) => void\n  onRemoveProduct?: (productId: string) => void\n  onClearAll?: () => void\n  onRestoreProducts?: () => void\n  onOpenChange?: (open: boolean) => void\n}\n\nexport function ProductComparisonDrawer({\n  defaultOpen = false,\n  defaultHighlightDiffs = false,\n  products = DEFAULT_COMPARISON_PRODUCTS,\n  mode = 'dock',\n  className,\n  onAddToCart,\n  onRemoveProduct,\n  onClearAll,\n  onRestoreProducts,\n  onOpenChange,\n  ...props\n}: ProductComparisonDrawerProps) {\n  const [isExpanded, setIsExpanded] = React.useState<boolean>(defaultOpen || mode === 'expanded')\n  const [highlightDiffs, setHighlightDiffs] = React.useState<boolean>(defaultHighlightDiffs)\n  const [selectedProducts, setSelectedProducts] = React.useState<ComparisonProduct[]>([...products])\n  const [addedProductId, setAddedProductId] = React.useState<string | null>(null)\n\n  React.useEffect(() => {\n    setSelectedProducts([...products])\n  }, [products])\n\n  const toggleExpanded = () => {\n    const next = !isExpanded\n    setIsExpanded(next)\n    onOpenChange?.(next)\n  }\n\n  const handleRemoveProduct = (id: string) => {\n    setSelectedProducts((prev) => prev.filter((p) => p.id !== id))\n    onRemoveProduct?.(id)\n  }\n\n  const handleClearAll = () => {\n    setSelectedProducts([])\n    onClearAll?.()\n  }\n\n  const handleRestoreProducts = () => {\n    setSelectedProducts([...DEFAULT_COMPARISON_PRODUCTS])\n    onRestoreProducts?.()\n  }\n\n  const handleAddToCart = (product: ComparisonProduct) => {\n    setAddedProductId(product.id)\n    onAddToCart?.(product)\n    setTimeout(() => {\n      setAddedProductId((current) => (current === product.id ? null : current))\n    }, 1800)\n  }\n\n  // Diff detection: checks if values differ across the currently selected products\n  const isRowDiff = (specKey: keyof ComparisonSpec): boolean => {\n    if (selectedProducts.length <= 1) return false\n    const firstVal = selectedProducts[0]?.specs[specKey]\n    return selectedProducts.some((p) => p.specs[specKey] !== firstVal)\n  }\n\n  const categories = React.useMemo(() => {\n    const cats: Array<{ name: string; fields: SpecField[] }> = []\n    for (const field of SPEC_FIELDS) {\n      let group = cats.find((c) => c.name === field.category)\n      if (!group) {\n        group = { name: field.category, fields: [] }\n        cats.push(group)\n      }\n      group.fields.push(field)\n    }\n    return cats\n  }, [])\n\n  const diffCount = React.useMemo(() => {\n    return SPEC_FIELDS.filter((f) => isRowDiff(f.key)).length\n  }, [selectedProducts])\n\n  return (\n    <div\n      data-slot=\"product-comparison-drawer\"\n      className={cn(\n        'bg-background text-foreground relative flex w-full flex-col overflow-hidden rounded-xl border',\n        className,\n      )}\n      {...props}\n    >\n      {/* Background Mock Catalog Page Preview (Context for Dock) */}\n      {mode === 'dock' && (\n        <div className=\"bg-muted/10 flex flex-col p-4 sm:p-6 lg:p-8\">\n          <div className=\"mb-6 flex flex-col justify-between gap-3 sm:flex-row sm:items-center\">\n            <div>\n              <div className=\"flex items-center gap-2\">\n                <span className=\"bg-primary/10 text-primary rounded px-2 py-0.5 text-xs font-semibold tracking-wider uppercase\">\n                  Audio Lab\n                </span>\n                <span className=\"text-muted-foreground text-xs font-medium\">Over-Ear & In-Ear Systems</span>\n              </div>\n              <h2 className=\"text-xl font-bold tracking-tight sm:text-2xl\">High-Fidelity Audio Lineup</h2>\n              <p className=\"text-muted-foreground mt-1 text-xs sm:text-sm\">\n                Select flagship models below to compare acoustic architectures, battery runtime, and diffs side by side.\n              </p>\n            </div>\n\n            <div className=\"flex items-center gap-2\">\n              {selectedProducts.length < DEFAULT_COMPARISON_PRODUCTS.length && (\n                <Button variant=\"outline\" size=\"sm\" className=\"text-xs\" onClick={handleRestoreProducts}>\n                  <RotateCcw className=\"mr-1.5 size-3.5\" />\n                  Reset Selection\n                </Button>\n              )}\n              <Button variant=\"default\" size=\"sm\" className=\"text-xs\" onClick={toggleExpanded}>\n                <SlidersHorizontal className=\"mr-1.5 size-3.5\" />\n                {isExpanded ? 'Hide Comparison' : `Compare (${selectedProducts.length})`}\n              </Button>\n            </div>\n          </div>\n\n          {/* Mock Catalog Cards Grid */}\n          <div className=\"grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3\">\n            {DEFAULT_COMPARISON_PRODUCTS.map((product) => {\n              const isSelected = selectedProducts.some((p) => p.id === product.id)\n              return (\n                <div\n                  key={product.id}\n                  className={cn(\n                    'bg-card hover:border-border group relative flex flex-col justify-between rounded-lg border p-4 shadow-xs transition-colors',\n                    isSelected && 'ring-primary/20 border-primary/40 ring-1',\n                  )}\n                >\n                  <div>\n                    <div className=\"bg-muted/40 relative aspect-4/3 w-full overflow-hidden rounded-md\">\n                      <img\n                        src={product.image}\n                        alt={product.name}\n                        className=\"size-full object-cover transition-transform duration-300 group-hover:scale-105\"\n                        loading=\"lazy\"\n                      />\n                      <div className=\"absolute top-2.5 left-2.5\">\n                        <Badge variant={product.badgeVariant || 'default'} className=\"text-xs font-medium shadow-xs\">\n                          {{ ...product }.badge}\n                        </Badge>\n                      </div>\n                    </div>\n\n                    <div className=\"mt-3.5 space-y-1\">\n                      <div className=\"flex items-center justify-between\">\n                        <div className=\"text-warning flex items-center gap-1 text-xs\">\n                          <Star className=\"size-3.5 fill-current\" />\n                          <span className=\"text-foreground font-semibold tabular-nums\">{product.rating}</span>\n                          <span className=\"text-muted-foreground\">({product.reviewsCount.toLocaleString()})</span>\n                        </div>\n                        <span className=\"text-sm font-bold tabular-nums\">{product.price}</span>\n                      </div>\n                      <h3 className=\"text-foreground text-sm font-semibold tracking-tight\">{product.name}</h3>\n                      <p className=\"text-muted-foreground line-clamp-1 text-xs\">{product.tagline}</p>\n                    </div>\n                  </div>\n\n                  <div className=\"mt-4 flex items-center justify-between gap-2 border-t pt-3\">\n                    <button\n                      type=\"button\"\n                      className=\"text-muted-foreground hover:text-foreground flex min-h-6 items-center gap-1.5 text-xs font-medium transition-colors\"\n                      onClick={() =>\n                        isSelected ? handleRemoveProduct(product.id) : setSelectedProducts((prev) => [...prev, product])\n                      }\n                    >\n                      <div\n                        className={cn(\n                          'flex size-4 items-center justify-center rounded border transition-colors',\n                          isSelected\n                            ? 'border-primary bg-primary text-primary-foreground'\n                            : 'border-muted-foreground/40 bg-background',\n                        )}\n                      >\n                        {isSelected && <Check className=\"size-3 stroke-[3]\" />}\n                      </div>\n                      <span>{isSelected ? 'Comparing' : 'Add to compare'}</span>\n                    </button>\n\n                    <Button\n                      size=\"sm\"\n                      variant=\"outline\"\n                      className=\"h-8 text-xs\"\n                      disabled={addedProductId === product.id}\n                      onClick={() => handleAddToCart(product)}\n                    >\n                      {addedProductId === product.id ? (\n                        <>\n                          <Check className=\"text-success mr-1 size-3.5\" />\n                          Added\n                        </>\n                      ) : (\n                        <>\n                          <ShoppingCart className=\"mr-1 size-3.5\" />\n                          Add\n                        </>\n                      )}\n                    </Button>\n                  </div>\n                </div>\n              )\n            })}\n          </div>\n        </div>\n      )}\n\n      {/* Floating Sticky Comparison Bar (Dock at Bottom) */}\n      {mode === 'dock' && !isExpanded && (\n        <div className=\"bg-background/95 supports-[backdrop-filter]:bg-background/85 sticky bottom-0 z-30 w-full border-t p-3 backdrop-blur-md sm:p-4\">\n          <div className=\"mx-auto flex max-w-6xl flex-col items-stretch justify-between gap-3 sm:flex-row sm:items-center\">\n            {/* Selected Products List */}\n            <div className=\"flex items-center gap-2 overflow-x-auto pb-1 sm:gap-3 sm:pb-0\">\n              <div className=\"flex shrink-0 items-center gap-1.5 pr-2\">\n                <div className=\"bg-primary/10 text-primary flex size-7 items-center justify-center rounded-md\">\n                  <Layers className=\"size-4\" />\n                </div>\n                <div className=\"flex flex-col\">\n                  <span className=\"text-xs leading-tight font-semibold\">Compare Dock</span>\n                  <span className=\"text-muted-foreground text-xs tabular-nums\">\n                    {selectedProducts.length} / {DEFAULT_COMPARISON_PRODUCTS.length} selected\n                  </span>\n                </div>\n              </div>\n\n              <Separator orientation=\"vertical\" className=\"hidden h-8 sm:block\" />\n\n              {/* Selected Thumbnails */}\n              {selectedProducts.length > 0 ? (\n                <div className=\"flex items-center gap-2\">\n                  {selectedProducts.map((product) => (\n                    <div\n                      key={product.id}\n                      className=\"bg-card group hover:border-primary/40 relative flex shrink-0 items-center gap-2 rounded-lg border p-1.5 pr-2.5 shadow-2xs transition-colors\"\n                    >\n                      <img src={product.image} alt={product.name} className=\"size-9 rounded-md object-cover\" />\n                      <div className=\"flex flex-col\">\n                        <span className=\"max-w-[110px] truncate text-xs font-medium sm:max-w-[130px]\">\n                          {product.name}\n                        </span>\n                        <span className=\"text-muted-foreground text-xs font-semibold tabular-nums\">\n                          {product.price}\n                        </span>\n                      </div>\n                      <button\n                        type=\"button\"\n                        className=\"bg-background/80 hover:bg-destructive hover:text-destructive-foreground text-muted-foreground absolute -top-1.5 -right-1.5 flex size-4 items-center justify-center rounded-full border opacity-0 shadow-2xs transition-opacity group-hover:opacity-100 focus-visible:opacity-100\"\n                        aria-label={`Remove ${product.name} from comparison`}\n                        onClick={(e) => {\n                          e.stopPropagation()\n                          handleRemoveProduct(product.id)\n                        }}\n                      >\n                        <X className=\"size-2.5\" />\n                      </button>\n                    </div>\n                  ))}\n                </div>\n              ) : (\n                <div className=\"text-muted-foreground flex items-center gap-2 py-1 text-xs\">\n                  <span>No products in comparison dock.</span>\n                  <button\n                    type=\"button\"\n                    className=\"text-primary font-medium hover:underline\"\n                    onClick={handleRestoreProducts}\n                  >\n                    Restore 3 Items\n                  </button>\n                </div>\n              )}\n            </div>\n\n            {/* Action Buttons */}\n            <div className=\"flex shrink-0 items-center justify-end gap-2\">\n              {selectedProducts.length > 0 && (\n                <Button\n                  variant=\"ghost\"\n                  size=\"sm\"\n                  className=\"text-muted-foreground hover:text-foreground h-8 text-xs font-medium\"\n                  onClick={handleClearAll}\n                >\n                  Clear All\n                </Button>\n              )}\n\n              <Button\n                variant=\"default\"\n                size=\"sm\"\n                className=\"h-8 gap-1.5 text-xs font-medium shadow-xs\"\n                disabled={selectedProducts.length === 0}\n                onClick={toggleExpanded}\n              >\n                <span>Compare {selectedProducts.length} Items</span>\n                <ChevronUp className=\"size-3.5\" />\n              </Button>\n            </div>\n          </div>\n        </div>\n      )}\n\n      {/* Expanded Full Specification Matrix Drawer / Container */}\n      {(isExpanded || mode === 'expanded') && (\n        <div className=\"bg-background motion-safe:animate-in motion-safe:fade-in motion-safe:slide-in-from-bottom-2 relative flex w-full flex-col border-t shadow-lg motion-safe:duration-200\">\n          {/* Matrix Header Controls Bar */}\n          <div className=\"bg-card/90 supports-[backdrop-filter]:bg-card/75 sticky top-0 z-30 border-b px-4 py-3.5 backdrop-blur-md sm:px-6\">\n            <div className=\"flex flex-col justify-between gap-3 sm:flex-row sm:items-center\">\n              <div className=\"flex items-center gap-3\">\n                <div className=\"bg-primary/10 text-primary flex size-8 items-center justify-center rounded-lg\">\n                  <SlidersHorizontal className=\"size-4\" />\n                </div>\n                <div>\n                  <div className=\"flex items-center gap-2\">\n                    <h3 className=\"text-base font-semibold tracking-tight\">Specification Matrix</h3>\n                    <Badge variant=\"secondary\" className=\"text-xs font-semibold tabular-nums\">\n                      {selectedProducts.length} Selected\n                    </Badge>\n                    {highlightDiffs && (\n                      <Badge variant=\"outline\" className=\"border-primary/40 bg-primary/5 text-primary text-xs\">\n                        <GitCompare className=\"mr-1 size-3\" />\n                        Diffs Highlighted ({diffCount})\n                      </Badge>\n                    )}\n                  </div>\n                  <p className=\"text-muted-foreground text-xs\">\n                    Side-by-side technical breakdown across drivers, battery, acoustics, and box contents.\n                  </p>\n                </div>\n              </div>\n\n              {/* Controls: Diff Switch & Close */}\n              <div className=\"flex items-center gap-4\">\n                <div className=\"flex items-center space-x-2\">\n                  <Switch\n                    id=\"react-diff-toggle\"\n                    size=\"sm\"\n                    checked={highlightDiffs}\n                    onCheckedChange={(val) => setHighlightDiffs(val)}\n                  />\n                  <label htmlFor=\"react-diff-toggle\" className=\"cursor-pointer text-xs font-medium select-none\">\n                    Highlight Differences Only\n                  </label>\n                </div>\n\n                {mode === 'dock' && (\n                  <Button variant=\"outline\" size=\"sm\" className=\"h-8 gap-1 text-xs\" onClick={toggleExpanded}>\n                    <span>Collapse</span>\n                    <ChevronDown className=\"size-3.5\" />\n                  </Button>\n                )}\n              </div>\n            </div>\n          </div>\n\n          {/* Specification Matrix Content */}\n          {selectedProducts.length === 0 ? (\n            <div className=\"flex flex-col items-center justify-center p-12 text-center\">\n              <div className=\"bg-muted text-muted-foreground flex size-12 items-center justify-center rounded-full\">\n                <Trash2 className=\"size-6\" />\n              </div>\n              <h4 className=\"mt-3 text-sm font-semibold\">No Products Selected</h4>\n              <p className=\"text-muted-foreground mt-1 max-w-sm text-xs\">\n                You have cleared all items from comparison. Restore the baseline audio products to explore differences.\n              </p>\n              <Button variant=\"default\" size=\"sm\" className=\"mt-4 text-xs\" onClick={handleRestoreProducts}>\n                <RotateCcw className=\"mr-1.5 size-3.5\" />\n                Restore 3 Items\n              </Button>\n            </div>\n          ) : (\n            <div className=\"w-full overflow-x-auto\">\n              <table className=\"w-full max-w-[760px] min-w-full border-separate border-spacing-0 text-left text-xs\">\n                {/* Sticky Product Card Header Row */}\n                <thead>\n                  <tr>\n                    <th\n                      scope=\"col\"\n                      className=\"bg-background text-muted-foreground sticky top-0 left-0 z-20 w-[200px] min-w-[180px] border-b p-4 align-bottom font-medium\"\n                    >\n                      <div className=\"space-y-1\">\n                        <span className=\"text-foreground text-xs font-semibold tracking-wider uppercase\">\n                          Attributes\n                        </span>\n                        <p className=\"text-muted-foreground text-xs font-normal\">\n                          {selectedProducts.length} products compared\n                        </p>\n                      </div>\n                    </th>\n\n                    {/* Product Columns */}\n                    {selectedProducts.map((product) => (\n                      <th\n                        key={product.id}\n                        scope=\"col\"\n                        className=\"bg-background relative w-[240px] min-w-[220px] border-b p-4 align-top\"\n                      >\n                        <div className=\"flex flex-col gap-3\">\n                          {/* Remove button */}\n                          <div className=\"flex items-center justify-between gap-2\">\n                            <Badge variant={product.badgeVariant || 'default'} className=\"text-xs font-medium\">\n                              {product.badge}\n                            </Badge>\n                            <button\n                              type=\"button\"\n                              className=\"text-muted-foreground hover:bg-muted hover:text-foreground flex size-6 items-center justify-center rounded-md transition-colors\"\n                              aria-label={`Remove ${product.name}`}\n                              onClick={() => handleRemoveProduct(product.id)}\n                            >\n                              <X className=\"size-3.5\" />\n                            </button>\n                          </div>\n\n                          {/* Product Hero Visual */}\n                          <div className=\"flex items-center gap-3\">\n                            <img\n                              src={product.image}\n                              alt={product.name}\n                              className=\"size-16 rounded-md border object-cover shadow-2xs\"\n                            />\n                            <div className=\"flex flex-col\">\n                              <span className=\"text-foreground text-xs leading-tight font-semibold\">\n                                {product.name}\n                              </span>\n                              <div className=\"text-warning mt-1 flex items-center gap-1 text-xs\">\n                                <Star className=\"size-3 fill-current\" />\n                                <span className=\"text-foreground font-medium tabular-nums\">{product.rating}</span>\n                              </div>\n                              <span className=\"text-foreground mt-1 text-sm font-bold tabular-nums\">\n                                {product.price}\n                              </span>\n                            </div>\n                          </div>\n\n                          {/* Quick Buy Trigger */}\n                          <Button\n                            size=\"sm\"\n                            variant=\"default\"\n                            className=\"w-full gap-1.5 text-xs shadow-xs\"\n                            disabled={addedProductId === product.id}\n                            onClick={() => handleAddToCart(product)}\n                          >\n                            {addedProductId === product.id ? (\n                              <>\n                                <Check className=\"text-success size-3.5\" />\n                                Added to Cart\n                              </>\n                            ) : (\n                              <>\n                                <ShoppingCart className=\"size-3.5\" />\n                                Add to Cart\n                              </>\n                            )}\n                          </Button>\n                        </div>\n                      </th>\n                    ))}\n                  </tr>\n                </thead>\n\n                {/* Table Body grouped by Category */}\n                {categories.map((category) => (\n                  <tbody key={category.name}>\n                    {/* Category Subheading Header Row */}\n                    <tr>\n                      <th\n                        colSpan={selectedProducts.length + 1}\n                        scope=\"colgroup\"\n                        className=\"bg-muted/60 text-muted-foreground sticky left-0 z-10 border-b px-4 py-2 text-xs font-semibold tracking-wider uppercase\"\n                      >\n                        {category.name}\n                      </th>\n                    </tr>\n\n                    {/* Specification Rows */}\n                    {category.fields.map((field) => {\n                      const isDiff = isRowDiff(field.key)\n                      return (\n                        <tr\n                          key={field.key}\n                          className={cn(\n                            'group/row transition-colors',\n                            isDiff && highlightDiffs ? 'bg-primary/[0.04] dark:bg-primary/[0.08]' : 'hover:bg-muted/20',\n                            !isDiff && highlightDiffs ? 'opacity-40' : 'opacity-100',\n                          )}\n                        >\n                          {/* Spec Label Cell (Sticky Left) */}\n                          <th\n                            scope=\"row\"\n                            className=\"bg-background group-hover/row:bg-muted/30 sticky left-0 z-10 border-b p-3.5 align-middle text-xs font-medium\"\n                          >\n                            <div className=\"flex items-center justify-between gap-1.5\">\n                              <div className=\"flex flex-col\">\n                                <span className=\"text-foreground font-medium\">{field.label}</span>\n                                {field.description && (\n                                  <span className=\"text-muted-foreground text-xs font-normal\">{field.description}</span>\n                                )}\n                              </div>\n                              {isDiff && highlightDiffs && (\n                                <span className=\"bg-primary/10 text-primary shrink-0 rounded px-1.5 py-0.5 text-xs font-semibold\">\n                                  Diff\n                                </span>\n                              )}\n                            </div>\n                          </th>\n\n                          {/* Spec Values for Each Selected Product */}\n                          {selectedProducts.map((product) => (\n                            <td key={product.id} className=\"text-foreground border-b p-3.5 align-middle text-xs\">\n                              <div className=\"flex items-center gap-1.5\">\n                                <span\n                                  className={cn({\n                                    'font-semibold tabular-nums':\n                                      field.key === 'price' || field.key === 'weight' || field.key === 'batteryLife',\n                                    'text-foreground font-medium': isDiff,\n                                    'text-muted-foreground': !isDiff,\n                                  })}\n                                >\n                                  {product.specs[field.key] || '—'}\n                                </span>\n                              </div>\n                            </td>\n                          ))}\n                        </tr>\n                      )\n                    })}\n                  </tbody>\n                ))}\n\n                {/* Sticky Bottom Buy Triggers Footer */}\n                <tfoot>\n                  <tr className=\"bg-card sticky bottom-0 z-20\">\n                    <th scope=\"row\" className=\"bg-card sticky left-0 z-20 border-t p-4 align-middle\">\n                      <div className=\"space-y-0.5\">\n                        <span className=\"text-foreground text-xs font-semibold\">Sticky Buy Trigger</span>\n                        <p className=\"text-muted-foreground text-xs\">\n                          All purchases backed by 30-day money-back guarantee.\n                        </p>\n                      </div>\n                    </th>\n\n                    {selectedProducts.map((product) => (\n                      <td key={product.id} className=\"border-t p-4 align-middle\">\n                        <div className=\"flex flex-col gap-1.5\">\n                          <div className=\"flex items-center justify-between\">\n                            <span className=\"text-foreground text-xs font-bold tabular-nums\">{product.price}</span>\n                            <span className=\"text-muted-foreground text-xs\">{product.shipping}</span>\n                          </div>\n                          <Button\n                            size=\"sm\"\n                            variant=\"default\"\n                            className=\"w-full gap-1.5 text-xs shadow-xs\"\n                            disabled={addedProductId === product.id}\n                            onClick={() => handleAddToCart(product)}\n                          >\n                            {addedProductId === product.id ? (\n                              <>\n                                <Check className=\"text-success size-3.5\" />\n                                Added\n                              </>\n                            ) : (\n                              <>\n                                <ShoppingCart className=\"size-3.5\" />\n                                Buy Now\n                              </>\n                            )}\n                          </Button>\n                        </div>\n                      </td>\n                    ))}\n                  </tr>\n                </tfoot>\n              </table>\n            </div>\n          )}\n        </div>\n      )}\n    </div>\n  )\n}\n",
      "type": "registry:block",
      "target": "~/components/blocks/ProductComparisonDrawer.tsx"
    }
  ],
  "dependencies": [
    "lucide-react"
  ],
  "devDependencies": [],
  "registryDependencies": [
    "https://uipkge.dev/r/react/badge.json",
    "https://uipkge.dev/r/react/button.json",
    "https://uipkge.dev/r/react/separator.json",
    "https://uipkge.dev/r/react/switch.json"
  ],
  "description": "Floating multi-product specification comparison bar with attribute diff highlighting, expanded full-matrix drawer comparison, and sticky buy triggers.",
  "categories": [
    "commerce",
    "ecommerce"
  ]
}