@skyfall_ai/bazaar 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +51 -0
- package/dist/index.css +14863 -0
- package/dist/index.d.mts +4652 -0
- package/dist/index.d.ts +4652 -0
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +11879 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +89 -0
- package/src/tokens/bazaar-tokens.css +427 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../src/tokens/colors.ts","../src/tokens/typography.ts","../src/tokens/spacing.ts","../src/tokens/sizing.ts","../src/tokens/radius.ts","../src/tokens/borders.ts","../src/tokens/shadows.ts","../src/tokens/motion.ts","../src/tokens/opacity.ts","../src/tokens/zIndex.ts","../src/tokens/layout.ts","../src/tokens/focus.ts","../src/utils/cn.ts","../src/components/TextField/TextField.module.css","../src/components/TextField/TextField.tsx","../src/components/Button/Button.module.css","../src/components/Button/Button.tsx","../src/components/IconButton/IconButton.module.css","../src/components/IconButton/IconButton.tsx","../src/components/ButtonGroup/ButtonGroup.module.css","../src/components/ButtonGroup/ButtonGroup.tsx","../src/components/Checkbox/Checkbox.module.css","../src/components/Checkbox/Checkbox.tsx","../src/components/HelperText/HelperText.module.css","../src/components/HelperText/HelperText.tsx","../src/components/CheckboxGroup/CheckboxGroup.module.css","../src/components/CheckboxGroup/CheckboxGroup.tsx","../src/components/Radio/Radio.module.css","../src/components/Radio/Radio.tsx","../src/components/RadioGroup/RadioGroup.module.css","../src/components/RadioGroup/RadioGroup.tsx","../src/components/Select/Select.module.css","../src/components/Select/Select.tsx","../src/components/Switch/Switch.module.css","../src/components/Switch/Switch.tsx","../src/components/Textarea/Textarea.module.css","../src/components/Textarea/Textarea.tsx","../src/components/Slider/Slider.module.css","../src/components/Slider/Slider.tsx","../src/components/NumberField/NumberField.module.css","../src/components/NumberField/NumberField.tsx","../src/components/SearchField/SearchField.module.css","../src/components/SearchField/SearchField.tsx","../src/components/Autocomplete/Autocomplete.module.css","../src/components/Autocomplete/Autocomplete.tsx","../src/components/MultiSelect/MultiSelect.module.css","../src/components/MultiSelect/MultiSelect.tsx","../src/components/FileUpload/FileUpload.module.css","../src/components/FileUpload/FileUpload.tsx","../src/components/OTPInput/OTPInput.module.css","../src/components/OTPInput/OTPInput.tsx","../src/components/ColorPicker/ColorPicker.module.css","../src/components/ColorPicker/ColorPicker.tsx","../src/components/Rating/Rating.module.css","../src/components/Rating/Rating.tsx","../src/components/TagInput/TagInput.module.css","../src/components/TagInput/TagInput.tsx","../src/components/Avatar/Avatar.module.css","../src/components/Avatar/Avatar.tsx","../src/components/Badge/Badge.module.css","../src/components/Badge/Badge.tsx","../src/components/Chip/Chip.module.css","../src/components/Chip/Chip.tsx","../src/components/Divider/Divider.module.css","../src/components/Divider/Divider.tsx","../src/components/List/List.module.css","../src/components/List/List.tsx","../src/components/Table/Table.module.css","../src/components/Table/Table.tsx","../src/components/Tooltip/Tooltip.module.css","../src/components/Tooltip/Tooltip.tsx","../src/components/Progress/Progress.module.css","../src/components/Progress/Progress.tsx","../src/components/Skeleton/Skeleton.module.css","../src/components/Skeleton/Skeleton.tsx","../src/components/Spinner/Spinner.module.css","../src/components/Spinner/Spinner.tsx","../src/components/StatusBadge/StatusBadge.module.css","../src/components/StatusBadge/StatusBadge.tsx","../src/components/Timeline/Timeline.module.css","../src/components/Timeline/Timeline.tsx","../src/components/DescriptionList/DescriptionList.module.css","../src/components/DescriptionList/DescriptionList.tsx","../src/components/Kbd/Kbd.module.css","../src/components/Kbd/Kbd.tsx","../src/components/TreeView/TreeView.module.css","../src/components/TreeView/TreeView.tsx","../src/components/Typography/Typography.module.css","../src/components/Typography/Typography.tsx","../src/components/Alert/Alert.module.css","../src/components/Alert/Alert.tsx","../src/components/Backdrop/Backdrop.module.css","../src/components/Backdrop/Backdrop.tsx","../src/components/Dialog/Dialog.module.css","../src/components/Dialog/Dialog.tsx","../src/components/EmptyState/EmptyState.module.css","../src/components/EmptyState/EmptyState.tsx","../src/components/ErrorState/ErrorState.module.css","../src/components/ErrorState/ErrorState.tsx","../src/components/Toast/Toast.module.css","../src/components/Toast/Toast.tsx","../src/components/Banner/Banner.module.css","../src/components/Banner/Banner.tsx","../src/components/Accordion/Accordion.module.css","../src/components/Accordion/Accordion.tsx","../src/components/AppBar/AppBar.module.css","../src/components/AppBar/AppBar.tsx","../src/components/Paper/Paper.module.css","../src/components/Paper/Paper.tsx","../src/components/Card/Card.module.css","../src/components/Card/Card.tsx","../src/components/Modal/Modal.module.css","../src/components/Modal/Modal.tsx","../src/components/Popover/Popover.module.css","../src/components/Popover/Popover.tsx","../src/components/CollapsiblePanel/CollapsiblePanel.module.css","../src/components/CollapsiblePanel/CollapsiblePanel.tsx","../src/components/Breadcrumbs/Breadcrumbs.module.css","../src/components/Breadcrumbs/Breadcrumbs.tsx","../src/components/Drawer/Drawer.module.css","../src/components/Drawer/Drawer.tsx","../src/components/Link/Link.module.css","../src/components/Link/Link.tsx","../src/components/Menu/Menu.module.css","../src/components/Menu/Menu.tsx","../src/components/Pagination/Pagination.module.css","../src/components/Pagination/Pagination.tsx","../src/components/SideNav/SideNav.module.css","../src/components/SideNav/SideNav.tsx","../src/components/Stepper/Stepper.module.css","../src/components/Stepper/Stepper.tsx","../src/components/Tabs/Tabs.module.css","../src/components/Tabs/Tabs.tsx","../src/components/CommandPalette/CommandPalette.module.css","../src/components/CommandPalette/CommandPalette.tsx","../src/components/Label/Label.module.css","../src/components/Label/Label.tsx","../src/components/FormField/FormField.module.css","../src/components/FormField/FormField.tsx","../src/components/Container/Container.module.css","../src/components/Container/Container.tsx","../src/components/Grid/Grid.module.css","../src/components/Grid/Grid.tsx","../src/components/Stack/Stack.module.css","../src/components/Stack/Stack.tsx","../src/components/InputGroup/InputGroup.module.css","../src/components/InputGroup/InputGroup.tsx","../src/components/Toolbar/Toolbar.module.css","../src/components/Toolbar/Toolbar.tsx","../src/components/VisuallyHidden/VisuallyHidden.module.css","../src/components/VisuallyHidden/VisuallyHidden.tsx","../src/components/Portal/Portal.tsx","../src/components/DataGrid/DataGrid.module.css","../src/components/DataGrid/DataGrid.tsx","../src/components/DatePicker/DatePicker.module.css","../src/components/DatePicker/DatePicker.tsx","../src/components/ProgressRing/ProgressRing.module.css","../src/components/ProgressRing/ProgressRing.tsx","../src/charts/ChartCard.module.css","../src/charts/ChartCard.tsx","../src/charts/chartTheme.ts","../src/charts/ChartTooltip.module.css","../src/charts/ChartTooltip.tsx","../src/charts/ChartLegend.module.css","../src/charts/ChartLegend.tsx","../src/charts/LineChart.tsx","../src/charts/BarChart.tsx","../src/charts/Sparkline.tsx","../src/charts/KpiStatCard.module.css","../src/charts/KpiStatCard.tsx","../src/charts/TrendStatCard.module.css","../src/charts/TrendStatCard.tsx","../src/commerce/money.ts","../src/commerce/MediaPlaceholder.module.css","../src/commerce/MediaPlaceholder.tsx","../src/commerce/PriceBlock.module.css","../src/commerce/PriceBlock.tsx","../src/commerce/ProductBadge.module.css","../src/commerce/ProductBadge.tsx","../src/commerce/ReviewsSummary.module.css","../src/commerce/ReviewsSummary.tsx","../src/commerce/icons.tsx","../src/commerce/ProductCard.module.css","../src/commerce/ProductCard.tsx","../src/commerce/ProductGrid.module.css","../src/commerce/ProductGrid.tsx","../src/commerce/FilterPanel.module.css","../src/commerce/FilterPanel.tsx","../src/commerce/SortMenu.module.css","../src/commerce/SortMenu.tsx","../src/commerce/SearchResultsHeader.module.css","../src/commerce/SearchResultsHeader.tsx","../src/commerce/CollectionHero.module.css","../src/commerce/CollectionHero.tsx","../src/commerce/RecommendationRail.module.css","../src/commerce/RecommendationRail.tsx","../src/commerce/PromoStrip.module.css","../src/commerce/PromoStrip.tsx","../src/commerce/ProductMediaGallery.module.css","../src/commerce/ProductMediaGallery.tsx","../src/commerce/VariantSelector.module.css","../src/commerce/VariantSelector.tsx","../src/commerce/InventoryIndicator.module.css","../src/commerce/InventoryIndicator.tsx","../src/commerce/ShippingReassurance.module.css","../src/commerce/ShippingReassurance.tsx","../src/commerce/ProductBuyBox.module.css","../src/commerce/ProductBuyBox.tsx","../src/commerce/ProductDetailsAccordion.module.css","../src/commerce/ProductDetailsAccordion.tsx","../src/commerce/ReviewsList.module.css","../src/commerce/ReviewsList.tsx","../src/commerce/SizeGuide.module.css","../src/commerce/SizeGuide.tsx","../src/commerce/BundleModule.module.css","../src/commerce/BundleModule.tsx","../src/commerce/StickyMobileATC.module.css","../src/commerce/StickyMobileATC.tsx","../src/commerce/CartLineItem.module.css","../src/commerce/CartLineItem.tsx","../src/commerce/FreeShippingMeter.module.css","../src/commerce/FreeShippingMeter.tsx","../src/commerce/CouponField.module.css","../src/commerce/CouponField.tsx","../src/commerce/CartSummary.module.css","../src/commerce/CartSummary.tsx","../src/commerce/MiniCart.module.css","../src/commerce/MiniCart.tsx","../src/commerce/CartDrawer.module.css","../src/commerce/CartDrawer.tsx","../src/commerce/CartPage.module.css","../src/commerce/CartPage.tsx","../src/commerce/SaveForLaterList.module.css","../src/commerce/SaveForLaterList.tsx","../src/commerce/CrossSellStrip.module.css","../src/commerce/CrossSellStrip.tsx","../src/commerce/CheckoutStepper.module.css","../src/commerce/CheckoutStepper.tsx","../src/commerce/ExpressCheckout.module.css","../src/commerce/ExpressCheckout.tsx","../src/commerce/CheckoutContactStep.module.css","../src/commerce/CheckoutContactStep.tsx","../src/commerce/AddressForm.module.css","../src/commerce/AddressForm.tsx","../src/commerce/ShippingMethodList.module.css","../src/commerce/ShippingMethodList.tsx","../src/commerce/PaymentMethodSelector.module.css","../src/commerce/PaymentMethodSelector.tsx","../src/commerce/CheckoutOrderSummary.module.css","../src/commerce/CheckoutOrderSummary.tsx","../src/commerce/CheckoutShell.module.css","../src/commerce/CheckoutShell.tsx","../src/commerce/OrderConfirmation.module.css","../src/commerce/OrderConfirmation.tsx","../src/commerce/WishlistGrid.module.css","../src/commerce/WishlistGrid.tsx","../src/commerce/OrderHistoryList.module.css","../src/commerce/OrderHistoryList.tsx","../src/commerce/OrderTracking.module.css","../src/commerce/OrderTracking.tsx","../src/commerce/AddressBook.module.css","../src/commerce/AddressBook.tsx","../src/commerce/PaymentMethodsList.module.css","../src/commerce/PaymentMethodsList.tsx","../src/commerce/SubscriptionsList.module.css","../src/commerce/SubscriptionsList.tsx","../src/commerce/LoyaltyPanel.module.css","../src/commerce/LoyaltyPanel.tsx","../src/commerce/TrustBadgeCluster.module.css","../src/commerce/TrustBadgeCluster.tsx","../src/commerce/DeliveryEstimate.module.css","../src/commerce/DeliveryEstimate.tsx","../src/commerce/ReturnsPolicy.module.css","../src/commerce/ReturnsPolicy.tsx","../src/commerce/PaymentConfidence.module.css","../src/commerce/PaymentConfidence.tsx","../src/commerce/SocialProof.module.css","../src/commerce/SocialProof.tsx","../src/commerce/CampaignHero.module.css","../src/commerce/CampaignHero.tsx","../src/commerce/SplitImageCopy.module.css","../src/commerce/SplitImageCopy.tsx","../src/commerce/FeaturedCollection.module.css","../src/commerce/FeaturedCollection.tsx","../src/commerce/ShopTheLook.module.css","../src/commerce/ShopTheLook.tsx","../src/commerce/EditorialProductStory.module.css","../src/commerce/EditorialProductStory.tsx","../src/commerce/LookbookGallery.module.css","../src/commerce/LookbookGallery.tsx","../src/commerce/SeasonalPromo.module.css","../src/commerce/SeasonalPromo.tsx","../src/commerce/BrandStory.module.css","../src/commerce/BrandStory.tsx","../src/commerce/QuantityStepper.module.css","../src/commerce/QuantityStepper.tsx","../src/commerce/AnnouncementBar.module.css","../src/commerce/AnnouncementBar.tsx","../src/commerce/SearchBar.module.css","../src/commerce/SearchBar.tsx","../src/commerce/MegaMenu.module.css","../src/commerce/MegaMenu.tsx","../src/commerce/SiteHeader.module.css","../src/commerce/SiteHeader.tsx","../src/commerce/SiteFooter.module.css","../src/commerce/SiteFooter.tsx","../src/commerce/NewsletterSignup.module.css","../src/commerce/NewsletterSignup.tsx","../src/commerce/AccountNav.module.css","../src/commerce/AccountNav.tsx","../src/commerce/BackInStockForm.module.css","../src/commerce/BackInStockForm.tsx","../src/commerce/HomePageTemplate.module.css","../src/commerce/HomePageTemplate.tsx","../src/commerce/CollectionPageTemplate.module.css","../src/commerce/CollectionPageTemplate.tsx","../src/commerce/ProductDetailPageTemplate.module.css","../src/commerce/ProductDetailPageTemplate.tsx","../src/commerce/SearchResultsPageTemplate.module.css","../src/commerce/SearchResultsPageTemplate.tsx","../src/commerce/AccountDashboardTemplate.module.css","../src/commerce/AccountDashboardTemplate.tsx"],"sourcesContent":["/** Brand primary palette — Warm Ink. Near-black scale used for text,\n * primary CTA surfaces, and high-emphasis elevation. */\nexport const brandPrimary = {\n 50: '#F5F3EE',\n 100: '#E5E1D5',\n 200: '#C6BFAC',\n 300: '#8A816B',\n 400: '#5E5749',\n 500: '#433D32',\n 600: '#2E2A23',\n 700: '#1F1C17',\n 800: '#161310',\n 900: '#0E0B09',\n} as const;\n\n/** Brand secondary palette — Terracotta / Clay. Accent color, reserved\n * for sale badges, promo surfaces, and editorial highlights. */\nexport const brandSecondary = {\n 50: '#FBEEE4',\n 100: '#F6D9C5',\n 200: '#ECB690',\n 300: '#DF9662',\n 400: '#C96C3E',\n 500: '#AB5428',\n 600: '#873F1C',\n 700: '#662E13',\n 800: '#4A2110',\n 900: '#2E160A',\n} as const;\n\n/** Support accent — Sage. Confirmation, in-stock, eco. */\nexport const accentMint = {\n 50: '#EAF1EA',\n 100: '#D1DFD3',\n 200: '#A8C1AC',\n 300: '#7BA181',\n 400: '#4A7C59',\n 500: '#3A6547',\n 600: '#2E5237',\n 700: '#22402A',\n} as const;\n\nexport const accentTeal = accentMint;\n\n/** Reward accent — Warm Amber. Loyalty, rewards, gold-tier. */\nexport const accentAmber = {\n 50: '#FBF2DF',\n 100: '#F5E1B6',\n 200: '#EAC079',\n 300: '#D9A046',\n 400: '#B58235',\n 500: '#8C6324',\n 600: '#6C4B1A',\n 700: '#513712',\n} as const;\n\n/** Neutral palette — Oat / Ecru / Ink. Warm undertone throughout. */\nexport const neutral = {\n 0: '#FFFFFF',\n 25: '#FBF9F4',\n 50: '#F4F2EC',\n 100: '#ECE7DC',\n 200: '#D9D2C1',\n 300: '#B8AE97',\n 400: '#8A816B',\n 500: '#5E5749',\n 600: '#433D32',\n 700: '#2E2A23',\n 800: '#1F1C17',\n 900: '#131110',\n} as const;\n\n/** Semantic colors — warm-tuned to sit naturally against ecru neutrals. */\nexport const semantic = {\n success: { 50: '#EAF1EA', 500: '#4A7C59', 700: '#2E5237' },\n warning: { 50: '#FBF2DF', 500: '#B58235', 700: '#6C4B1A' },\n error: { 50: '#F9E8E4', 500: '#B04848', 700: '#7D2E2E' },\n info: { 50: '#F4F2EC', 500: '#433D32', 700: '#1F1C17' },\n} as const;\n\n/** Text aliases */\nexport const text = {\n primary: '#1F1C17',\n secondary: '#433D32',\n muted: '#8A816B',\n inverse: '#FBF9F4',\n brand: '#C96C3E',\n} as const;\n\n/** Surface aliases */\nexport const surface = {\n canvas: '#FBF9F4',\n default: '#FFFFFF',\n subtle: '#F4F2EC',\n raised: '#FFFFFF',\n spotlight: '#FBEEE4',\n} as const;\n\n/** Border aliases */\nexport const border = {\n default: '#D9D2C1',\n strong: '#B8AE97',\n inverse: '#2E2A23',\n} as const;\n\n/** Data visualization — warm commerce palette (account/admin charts). */\nexport const dataVis = {\n 1: '#1F1C17',\n 2: '#C96C3E',\n 3: '#4A7C59',\n 4: '#B58235',\n 5: '#8A816B',\n gridline: '#ECE7DC',\n axis: '#8A816B',\n} as const;\n\n/** Bazaar-specific progress tokens */\nexport const progress = {\n track: '#ECE7DC',\n fillDefault: '#1F1C17',\n fillSuccess: '#4A7C59',\n fillReward: '#C96C3E',\n gradient: 'linear-gradient(90deg, #C96C3E 0%, #1F1C17 100%)',\n} as const;\n","export const fontFamily = {\n sans: '\"Inter\", system-ui, -apple-system, BlinkMacSystemFont, \"Segoe UI\", sans-serif',\n display: '\"Fraunces\", \"Inter\", system-ui, serif',\n mono: '\"IBM Plex Mono\", \"SFMono-Regular\", Consolas, monospace',\n} as const;\n\nexport const fontWeight = {\n regular: 400,\n medium: 500,\n semibold: 600,\n bold: 700,\n} as const;\n\nexport const fontSize = {\n 'display-lg': '40px',\n 'display-md': '32px',\n 'heading-xl': '28px',\n 'heading-lg': '24px',\n 'heading-md': '20px',\n 'heading-sm': '18px',\n 'body-lg': '16px',\n 'body-md': '14px',\n 'body-sm': '13px',\n 'label-lg': '14px',\n 'label-md': '13px',\n caption: '12px',\n data: '14px',\n code: '13px',\n} as const;\n\nexport const lineHeight = {\n 'display-lg': '48px',\n 'display-md': '40px',\n 'heading-xl': '36px',\n 'heading-lg': '32px',\n 'heading-md': '28px',\n 'heading-sm': '26px',\n 'body-lg': '24px',\n 'body-md': '22px',\n 'body-sm': '20px',\n 'label-lg': '20px',\n 'label-md': '18px',\n caption: '16px',\n data: '20px',\n code: '18px',\n} as const;\n\nexport const tracking = {\n tight: '-0.02em',\n normal: '0em',\n wide: '0.01em',\n} as const;\n","export const space = {\n 0: '0',\n 1: '4px',\n 2: '8px',\n 3: '12px',\n 4: '16px',\n 5: '20px',\n 6: '24px',\n 8: '32px',\n 10: '40px',\n 12: '48px',\n 16: '64px',\n 20: '80px',\n} as const;\n","export const controlSize = {\n sm: '32px',\n md: '40px',\n lg: '48px',\n} as const;\n\nexport const iconSize = {\n xs: '12px',\n sm: '16px',\n md: '20px',\n lg: '24px',\n} as const;\n\nexport const touchMin = '44px';\n\nexport const modalSize = {\n sm: '400px',\n md: '560px',\n lg: '720px',\n xl: '880px',\n} as const;\n\nexport const sidebarDefault = '280px';\n","export const radius = {\n none: '0',\n sm: '6px',\n md: '10px',\n lg: '14px',\n xl: '18px',\n full: '9999px',\n} as const;\n","export const borderWidth = {\n none: '0',\n hairline: '1px',\n medium: '2px',\n strong: '3px',\n} as const;\n\nexport const borderStyle = {\n default: 'solid',\n} as const;\n","export const shadow = {\n none: 'none',\n xs: '0 1px 2px rgba(22, 32, 43, 0.05)',\n sm: '0 1px 3px rgba(22, 32, 43, 0.06), 0 2px 8px rgba(22, 32, 43, 0.04)',\n md: '0 2px 4px rgba(22, 32, 43, 0.04), 0 8px 20px rgba(22, 32, 43, 0.08)',\n lg: '0 4px 8px rgba(22, 32, 43, 0.04), 0 16px 40px rgba(22, 32, 43, 0.12)',\n xl: '0 8px 16px rgba(22, 32, 43, 0.06), 0 24px 56px rgba(22, 32, 43, 0.16)',\n focus: '0 0 0 3px rgba(47, 111, 228, 0.28)',\n focusError: '0 0 0 3px rgba(194, 58, 58, 0.2)',\n focusSuccess: '0 0 0 3px rgba(47, 143, 87, 0.2)',\n insetXs: 'inset 0 1px 2px rgba(22, 32, 43, 0.06)',\n insetSm: 'inset 0 2px 4px rgba(22, 32, 43, 0.08)',\n} as const;\n","export const duration = {\n fast: '120ms',\n base: '180ms',\n slow: '240ms',\n} as const;\n\nexport const easing = {\n standard: 'cubic-bezier(0.2, 0, 0, 1)',\n emphasized: 'cubic-bezier(0.2, 0, 0, 1)',\n exit: 'cubic-bezier(0.4, 0, 1, 1)',\n} as const;\n","export const opacity = {\n disabled: 0.48,\n subtle: 0.72,\n overlay: 0.48,\n scrimStrong: 0.64,\n} as const;\n","export const zIndex = {\n base: 0,\n dropdown: 1000,\n sticky: 1100,\n banner: 1200,\n overlay: 1300,\n modal: 1400,\n toast: 1500,\n tooltip: 1600,\n} as const;\n","export const container = {\n max: '1280px',\n reading: '720px',\n} as const;\n\nexport const grid = {\n columns: 12,\n gutter: '24px',\n margin: {\n desktop: '32px',\n tablet: '24px',\n mobile: '16px',\n },\n} as const;\n","export const focusRing = {\n width: '3px',\n color: 'rgba(47, 111, 228, 0.28)',\n offset: '2px',\n outlineColor: '#2F6FE4',\n} as const;\n","/** Merge CSS module class names, filtering out falsy values */\nexport function cn(...classes: (string | false | null | undefined)[]): string {\n return classes.filter(Boolean).join(' ');\n}\n",".textField {\n display: block;\n width: auto;\n border: var(--bazaar-border-width-hairline) var(--bazaar-border-style-default) var(--bazaar-color-border-default);\n border-radius: var(--bazaar-radius-md);\n background-color: var(--bazaar-color-surface-default);\n color: var(--bazaar-color-text-primary);\n font-family: var(--bazaar-font-family-sans);\n box-shadow: var(--bazaar-shadow-inset-xs);\n transition:\n border-color var(--bazaar-motion-duration-base) var(--bazaar-motion-easing-standard),\n box-shadow var(--bazaar-motion-duration-base) var(--bazaar-motion-easing-standard),\n background-color var(--bazaar-motion-duration-base) var(--bazaar-motion-easing-standard);\n}\n\n.textField::placeholder {\n color: var(--bazaar-color-text-muted);\n}\n\n.textField:hover:not(:disabled):not(:focus) {\n border-color: var(--bazaar-color-border-strong);\n background-color: var(--bazaar-color-surface-hover);\n}\n\n.textField:focus {\n outline: none;\n border-color: var(--bazaar-color-brand-primary-500);\n box-shadow: var(--bazaar-shadow-focus);\n background-color: var(--bazaar-color-surface-default);\n}\n\n.textField:disabled {\n cursor: not-allowed;\n opacity: var(--bazaar-opacity-disabled);\n background-color: var(--bazaar-color-surface-subtle);\n box-shadow: none;\n}\n\n/* Sizes */\n.sm {\n height: var(--bazaar-size-control-sm);\n padding: 0 var(--bazaar-space-3);\n font-size: var(--bazaar-font-size-body-sm);\n}\n\n.md {\n height: var(--bazaar-size-control-md);\n padding: 0 var(--bazaar-space-4);\n font-size: var(--bazaar-font-size-body-md);\n}\n\n.lg {\n height: var(--bazaar-size-control-lg);\n padding: 0 var(--bazaar-space-4);\n font-size: var(--bazaar-font-size-body-lg);\n}\n\n/* Error */\n.error {\n border-color: var(--bazaar-color-error-500);\n}\n\n.error:focus {\n border-color: var(--bazaar-color-error-500);\n box-shadow: var(--bazaar-shadow-focus-error);\n}\n\n/* Full width */\n.fullWidth {\n width: 100%;\n}\n","import { forwardRef, type InputHTMLAttributes } from 'react';\nimport { cn } from '../../utils/cn';\nimport styles from './TextField.module.css';\n\nexport interface TextFieldProps extends Omit<InputHTMLAttributes<HTMLInputElement>, 'size'> {\n /** Size of the input control */\n size?: 'sm' | 'md' | 'lg';\n /** Error state */\n error?: boolean;\n /** Full width */\n fullWidth?: boolean;\n}\n\n/**\n * TextField — single-line text input.\n *\n * Accessibility:\n * - Use with <Label> and associate via htmlFor/id\n * - Use aria-describedby to link to HelperText or error messages\n * - aria-invalid signals error state to assistive technology\n * - Visible border change + color signals error (not color alone)\n */\nexport const TextField = forwardRef<HTMLInputElement, TextFieldProps>(\n ({ size = 'md', error = false, fullWidth = false, className, ...props }, ref) => (\n <input\n ref={ref}\n className={cn(\n styles.textField,\n styles[size],\n error && styles.error,\n fullWidth && styles.fullWidth,\n className,\n )}\n aria-invalid={error || undefined}\n {...props}\n />\n ),\n);\n\nTextField.displayName = 'TextField';\n",".button {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: var(--bazaar-space-2);\n border: var(--bazaar-border-width-hairline) solid transparent;\n border-radius: var(--bazaar-radius-md);\n font-family: var(--bazaar-font-family-sans);\n font-weight: var(--bazaar-font-weight-medium);\n cursor: pointer;\n transition:\n background-color var(--bazaar-motion-duration-base) var(--bazaar-motion-easing-standard),\n border-color var(--bazaar-motion-duration-base) var(--bazaar-motion-easing-standard),\n box-shadow var(--bazaar-motion-duration-base) var(--bazaar-motion-easing-standard),\n transform var(--bazaar-motion-duration-fast) var(--bazaar-motion-easing-standard);\n white-space: nowrap;\n user-select: none;\n text-decoration: none;\n line-height: 1;\n}\n\n.button:focus-visible {\n outline: var(--bazaar-border-width-medium) solid var(--bazaar-focus-outline-color);\n outline-offset: var(--bazaar-focus-ring-offset);\n box-shadow: var(--bazaar-shadow-focus);\n}\n\n.button:disabled {\n cursor: not-allowed;\n opacity: var(--bazaar-opacity-disabled);\n}\n\n/* Sizes */\n.sm {\n height: var(--bazaar-size-control-sm);\n padding: 0 var(--bazaar-space-3);\n font-size: var(--bazaar-font-size-body-sm);\n}\n\n.md {\n height: var(--bazaar-size-control-md);\n padding: 0 var(--bazaar-space-4);\n font-size: var(--bazaar-font-size-body-md);\n}\n\n.lg {\n height: var(--bazaar-size-control-lg);\n padding: 0 var(--bazaar-space-6);\n font-size: var(--bazaar-font-size-body-lg);\n}\n\n/* Variants */\n.primary {\n background: linear-gradient(\n 180deg,\n var(--bazaar-color-brand-primary-500) 0%,\n var(--bazaar-color-brand-primary-600) 100%\n );\n color: var(--bazaar-color-text-inverse);\n box-shadow: var(--bazaar-shadow-xs);\n}\n\n.primary:hover:not(:disabled) {\n background: linear-gradient(\n 180deg,\n var(--bazaar-color-brand-primary-600) 0%,\n var(--bazaar-color-brand-primary-700) 100%\n );\n box-shadow: var(--bazaar-shadow-sm);\n}\n\n.primary:active:not(:disabled) {\n background: var(--bazaar-color-brand-primary-700);\n box-shadow: var(--bazaar-shadow-inset-xs);\n}\n\n.secondary {\n background-color: var(--bazaar-color-surface-default);\n color: var(--bazaar-color-text-primary);\n border-color: var(--bazaar-color-border-default);\n box-shadow: var(--bazaar-shadow-xs);\n}\n\n.secondary:hover:not(:disabled) {\n background-color: var(--bazaar-color-surface-hover);\n border-color: var(--bazaar-color-border-strong);\n box-shadow: var(--bazaar-shadow-sm);\n}\n\n.secondary:active:not(:disabled) {\n background-color: var(--bazaar-color-surface-active);\n box-shadow: var(--bazaar-shadow-inset-xs);\n}\n\n.ghost {\n background-color: transparent;\n color: var(--bazaar-color-brand-primary-500);\n}\n\n.ghost:hover:not(:disabled) {\n background-color: var(--bazaar-color-brand-primary-50);\n}\n\n.ghost:active:not(:disabled) {\n background-color: var(--bazaar-color-brand-primary-100);\n}\n\n.danger {\n background: linear-gradient(\n 180deg,\n var(--bazaar-color-error-500) 0%,\n var(--bazaar-color-error-700) 100%\n );\n color: var(--bazaar-color-text-inverse);\n box-shadow: var(--bazaar-shadow-xs);\n}\n\n.danger:hover:not(:disabled) {\n background: var(--bazaar-color-error-700);\n box-shadow: var(--bazaar-shadow-sm);\n}\n\n.danger:active:not(:disabled) {\n background: #7A2020;\n box-shadow: var(--bazaar-shadow-inset-xs);\n}\n\n/* Full width */\n.fullWidth {\n width: 100%;\n}\n\n/* Loading */\n.loading .label {\n opacity: var(--bazaar-opacity-subtle);\n}\n\n.spinner {\n display: inline-flex;\n animation: bazaar-spin 0.8s linear infinite;\n}\n\n.iconLeft,\n.iconRight {\n display: inline-flex;\n flex-shrink: 0;\n}\n\n@keyframes bazaar-spin {\n to {\n transform: rotate(360deg);\n }\n}\n","import { forwardRef, type ButtonHTMLAttributes, type ReactNode } from 'react';\nimport { cn } from '../../utils/cn';\nimport styles from './Button.module.css';\n\nexport interface ButtonProps extends ButtonHTMLAttributes<HTMLButtonElement> {\n /** Visual variant */\n variant?: 'primary' | 'secondary' | 'ghost' | 'danger';\n /** Size of the button */\n size?: 'sm' | 'md' | 'lg';\n /** Full width */\n fullWidth?: boolean;\n /** Loading state — disables interaction and shows spinner */\n loading?: boolean;\n /** Icon before the label */\n iconLeft?: ReactNode;\n /** Icon after the label */\n iconRight?: ReactNode;\n}\n\n/**\n * Button — primary interactive element.\n *\n * Accessibility:\n * - Uses native <button> for keyboard and screen reader support\n * - aria-disabled used during loading to maintain focusability\n * - aria-busy signals loading state to assistive technology\n * - Minimum 44px touch target on md/lg sizes\n */\nexport const Button = forwardRef<HTMLButtonElement, ButtonProps>(\n (\n {\n variant = 'primary',\n size = 'md',\n fullWidth = false,\n loading = false,\n disabled = false,\n iconLeft,\n iconRight,\n children,\n className,\n ...props\n },\n ref,\n ) => {\n const isDisabled = disabled || loading;\n\n return (\n <button\n ref={ref}\n className={cn(\n styles.button,\n styles[variant],\n styles[size],\n fullWidth && styles.fullWidth,\n loading && styles.loading,\n className,\n )}\n disabled={isDisabled}\n aria-disabled={isDisabled || undefined}\n aria-busy={loading || undefined}\n {...props}\n >\n {loading && (\n <span className={styles.spinner} aria-hidden=\"true\">\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\">\n <circle cx=\"8\" cy=\"8\" r=\"6\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeDasharray=\"28\" strokeDashoffset=\"8\" />\n </svg>\n </span>\n )}\n {iconLeft && <span className={styles.iconLeft} aria-hidden=\"true\">{iconLeft}</span>}\n <span className={styles.label}>{children}</span>\n {iconRight && <span className={styles.iconRight} aria-hidden=\"true\">{iconRight}</span>}\n </button>\n );\n },\n);\n\nButton.displayName = 'Button';\n",".iconButton {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n border: var(--bazaar-border-width-hairline) solid transparent;\n border-radius: var(--bazaar-radius-md);\n cursor: pointer;\n transition:\n background-color var(--bazaar-motion-duration-base) var(--bazaar-motion-easing-standard),\n border-color var(--bazaar-motion-duration-base) var(--bazaar-motion-easing-standard),\n box-shadow var(--bazaar-motion-duration-base) var(--bazaar-motion-easing-standard),\n color var(--bazaar-motion-duration-base) var(--bazaar-motion-easing-standard);\n padding: 0;\n flex-shrink: 0;\n}\n\n.iconButton:focus-visible {\n outline: var(--bazaar-border-width-medium) solid var(--bazaar-focus-outline-color);\n outline-offset: var(--bazaar-focus-ring-offset);\n box-shadow: var(--bazaar-shadow-focus);\n}\n\n.iconButton:disabled {\n cursor: not-allowed;\n opacity: var(--bazaar-opacity-disabled);\n}\n\n.sm {\n width: var(--bazaar-size-control-sm);\n height: var(--bazaar-size-control-sm);\n}\n\n.md {\n width: var(--bazaar-size-control-md);\n height: var(--bazaar-size-control-md);\n}\n\n.lg {\n width: var(--bazaar-size-control-lg);\n height: var(--bazaar-size-control-lg);\n}\n\n.primary {\n background: linear-gradient(\n 180deg,\n var(--bazaar-color-brand-primary-500) 0%,\n var(--bazaar-color-brand-primary-600) 100%\n );\n color: var(--bazaar-color-text-inverse);\n box-shadow: var(--bazaar-shadow-xs);\n}\n\n.primary:hover:not(:disabled) {\n background: linear-gradient(\n 180deg,\n var(--bazaar-color-brand-primary-600) 0%,\n var(--bazaar-color-brand-primary-700) 100%\n );\n box-shadow: var(--bazaar-shadow-sm);\n}\n\n.primary:active:not(:disabled) {\n background: var(--bazaar-color-brand-primary-700);\n box-shadow: var(--bazaar-shadow-inset-xs);\n}\n\n.secondary {\n background-color: var(--bazaar-color-surface-default);\n color: var(--bazaar-color-text-primary);\n border-color: var(--bazaar-color-border-default);\n box-shadow: var(--bazaar-shadow-xs);\n}\n\n.secondary:hover:not(:disabled) {\n background-color: var(--bazaar-color-surface-hover);\n border-color: var(--bazaar-color-border-strong);\n box-shadow: var(--bazaar-shadow-sm);\n}\n\n.secondary:active:not(:disabled) {\n background-color: var(--bazaar-color-surface-active);\n box-shadow: var(--bazaar-shadow-inset-xs);\n}\n\n.ghost {\n background-color: transparent;\n color: var(--bazaar-color-text-secondary);\n}\n\n.ghost:hover:not(:disabled) {\n background-color: var(--bazaar-color-surface-hover);\n color: var(--bazaar-color-text-primary);\n}\n\n.ghost:active:not(:disabled) {\n background-color: var(--bazaar-color-surface-active);\n}\n\n.danger {\n background-color: transparent;\n color: var(--bazaar-color-error-500);\n}\n\n.danger:hover:not(:disabled) {\n background-color: var(--bazaar-color-error-50);\n color: var(--bazaar-color-error-700);\n}\n\n.danger:active:not(:disabled) {\n background-color: var(--bazaar-color-error-50);\n box-shadow: var(--bazaar-shadow-inset-xs);\n}\n","import { forwardRef, type ButtonHTMLAttributes, type ReactNode } from 'react';\nimport { cn } from '../../utils/cn';\nimport styles from './IconButton.module.css';\n\nexport interface IconButtonProps extends ButtonHTMLAttributes<HTMLButtonElement> {\n /** Accessible label (required — icon-only buttons need text for screen readers) */\n 'aria-label': string;\n /** The icon element */\n icon: ReactNode;\n /** Visual variant */\n variant?: 'primary' | 'secondary' | 'ghost' | 'danger';\n /** Size */\n size?: 'sm' | 'md' | 'lg';\n}\n\n/**\n * IconButton — icon-only interactive button.\n *\n * Accessibility:\n * - aria-label is required to provide screen reader context\n * - Meets 44px minimum touch target at md/lg sizes\n */\nexport const IconButton = forwardRef<HTMLButtonElement, IconButtonProps>(\n ({ icon, variant = 'ghost', size = 'md', className, ...props }, ref) => (\n <button\n ref={ref}\n className={cn(styles.iconButton, styles[variant], styles[size], className)}\n {...props}\n >\n <span aria-hidden=\"true\">{icon}</span>\n </button>\n ),\n);\n\nIconButton.displayName = 'IconButton';\n",".group {\n display: inline-flex;\n gap: var(--bazaar-space-2);\n}\n\n.vertical {\n flex-direction: column;\n}\n\n/* Connected (toolbar) style */\n.connected {\n gap: 0;\n}\n\n.connected.horizontal > :global(button) {\n border-radius: 0;\n}\n\n.connected.horizontal > :global(button:first-child) {\n border-top-left-radius: var(--bazaar-radius-md);\n border-bottom-left-radius: var(--bazaar-radius-md);\n}\n\n.connected.horizontal > :global(button:last-child) {\n border-top-right-radius: var(--bazaar-radius-md);\n border-bottom-right-radius: var(--bazaar-radius-md);\n}\n\n.connected.horizontal > :global(button:not(:first-child)) {\n margin-left: calc(-1 * var(--bazaar-border-width-hairline));\n}\n\n.connected.vertical > :global(button) {\n border-radius: 0;\n width: 100%;\n}\n\n.connected.vertical > :global(button:first-child) {\n border-top-left-radius: var(--bazaar-radius-md);\n border-top-right-radius: var(--bazaar-radius-md);\n}\n\n.connected.vertical > :global(button:last-child) {\n border-bottom-left-radius: var(--bazaar-radius-md);\n border-bottom-right-radius: var(--bazaar-radius-md);\n}\n\n.connected.vertical > :global(button:not(:first-child)) {\n margin-top: calc(-1 * var(--bazaar-border-width-hairline));\n}\n\n/* Size propagation via CSS custom property */\n.size-sm { --bazaar-btn-group-size: sm; }\n.size-md { --bazaar-btn-group-size: md; }\n.size-lg { --bazaar-btn-group-size: lg; }\n","import { type HTMLAttributes } from 'react';\nimport { cn } from '../../utils/cn';\nimport styles from './ButtonGroup.module.css';\n\nexport interface ButtonGroupProps extends HTMLAttributes<HTMLDivElement> {\n /** Layout direction */\n orientation?: 'horizontal' | 'vertical';\n /** Size applied to all child buttons */\n size?: 'sm' | 'md' | 'lg';\n /** Whether buttons should share borders (connected style) */\n connected?: boolean;\n}\n\n/**\n * ButtonGroup — layout wrapper for grouping related buttons.\n *\n * Renders multiple Button children in a connected or spaced row/column.\n * When connected, adjacent buttons share borders for a toolbar appearance.\n *\n * Accessibility:\n * - Uses role=\"group\" with optional aria-label for grouping context\n * - Individual buttons retain their own keyboard navigation\n */\nexport function ButtonGroup({\n orientation = 'horizontal',\n size,\n connected = false,\n className,\n children,\n ...props\n}: ButtonGroupProps) {\n return (\n <div\n role=\"group\"\n className={cn(\n styles.group,\n styles[orientation],\n connected && styles.connected,\n size && styles[`size-${size}`],\n className,\n )}\n {...props}\n >\n {children}\n </div>\n );\n}\n",".wrapper {\n display: inline-flex;\n align-items: center;\n gap: var(--bazaar-space-2);\n cursor: pointer;\n min-height: var(--bazaar-size-touch-min);\n user-select: none;\n}\n\n.input {\n position: absolute;\n width: 1px;\n height: 1px;\n padding: 0;\n margin: -1px;\n overflow: hidden;\n clip: rect(0, 0, 0, 0);\n white-space: nowrap;\n border: 0;\n}\n\n.control {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 20px;\n height: 20px;\n border: var(--bazaar-border-width-hairline) var(--bazaar-border-style-default) var(--bazaar-color-border-default);\n border-radius: var(--bazaar-radius-sm);\n background-color: var(--bazaar-color-surface-default);\n color: transparent;\n flex-shrink: 0;\n box-shadow: var(--bazaar-shadow-inset-xs);\n transition:\n background-color var(--bazaar-motion-duration-base) var(--bazaar-motion-easing-standard),\n border-color var(--bazaar-motion-duration-base) var(--bazaar-motion-easing-standard),\n color var(--bazaar-motion-duration-base) var(--bazaar-motion-easing-standard),\n box-shadow var(--bazaar-motion-duration-base) var(--bazaar-motion-easing-standard);\n}\n\n.wrapper:hover .control {\n border-color: var(--bazaar-color-border-strong);\n background-color: var(--bazaar-color-surface-hover);\n}\n\n.input:checked + .control {\n background: linear-gradient(\n 180deg,\n var(--bazaar-color-brand-primary-500) 0%,\n var(--bazaar-color-brand-primary-600) 100%\n );\n border-color: var(--bazaar-color-brand-primary-600);\n color: var(--bazaar-color-text-inverse);\n box-shadow: var(--bazaar-shadow-xs);\n}\n\n.input:focus-visible + .control {\n outline: var(--bazaar-border-width-medium) solid var(--bazaar-focus-outline-color);\n outline-offset: var(--bazaar-focus-ring-offset);\n box-shadow: var(--bazaar-shadow-focus);\n}\n\n.input:disabled + .control {\n opacity: var(--bazaar-opacity-disabled);\n cursor: not-allowed;\n}\n\n.input:disabled ~ .label {\n opacity: var(--bazaar-opacity-disabled);\n cursor: not-allowed;\n}\n\n.label {\n font-family: var(--bazaar-font-family-sans);\n font-size: var(--bazaar-font-size-body-md);\n line-height: var(--bazaar-line-height-body-md);\n color: var(--bazaar-color-text-primary);\n}\n\n.error .control {\n border-color: var(--bazaar-color-error-500);\n}\n","import { forwardRef, type InputHTMLAttributes } from 'react';\nimport { cn } from '../../utils/cn';\nimport styles from './Checkbox.module.css';\n\nexport interface CheckboxProps extends Omit<InputHTMLAttributes<HTMLInputElement>, 'type'> {\n /** Label text displayed next to the checkbox */\n label?: string;\n /** Error state */\n error?: boolean;\n}\n\n/**\n * Checkbox — boolean toggle with label.\n *\n * Accessibility:\n * - Uses native <input type=\"checkbox\"> for full keyboard/screen reader support\n * - Checkmark is CSS-only, no JS required for visual state\n * - Label is clickable and linked to input\n * - 44px minimum touch target maintained via padding\n */\nexport const Checkbox = forwardRef<HTMLInputElement, CheckboxProps>(\n ({ label, error = false, className, id, ...props }, ref) => {\n const inputId = id || (label ? `checkbox-${label.replace(/\\s+/g, '-').toLowerCase()}` : undefined);\n\n return (\n <label className={cn(styles.wrapper, error && styles.error, className)}>\n <input\n ref={ref}\n type=\"checkbox\"\n className={styles.input}\n id={inputId}\n aria-invalid={error || undefined}\n {...props}\n />\n <span className={styles.control} aria-hidden=\"true\">\n <svg width=\"12\" height=\"12\" viewBox=\"0 0 12 12\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <path d=\"M2.5 6L5 8.5L9.5 3.5\" />\n </svg>\n </span>\n {label && <span className={styles.label}>{label}</span>}\n </label>\n );\n },\n);\n\nCheckbox.displayName = 'Checkbox';\n",".helperText {\n display: flex;\n align-items: flex-start;\n gap: var(--bazaar-space-1);\n margin: var(--bazaar-space-1) 0 0;\n font-family: var(--bazaar-font-family-sans);\n font-size: var(--bazaar-font-size-body-sm);\n line-height: var(--bazaar-line-height-body-sm);\n color: var(--bazaar-color-text-muted);\n}\n\n.error {\n color: var(--bazaar-color-error-500);\n}\n\n.icon {\n flex-shrink: 0;\n margin-top: 3px;\n}\n","import { type HTMLAttributes } from 'react';\nimport { cn } from '../../utils/cn';\nimport styles from './HelperText.module.css';\n\nexport interface HelperTextProps extends HTMLAttributes<HTMLParagraphElement> {\n /** Render as error message */\n error?: boolean;\n}\n\n/**\n * HelperText — descriptive or error text beneath a form field.\n *\n * Accessibility:\n * - Link to input via aria-describedby on the input, matching this element's id\n * - Error messages use role=\"alert\" for immediate screen reader announcement\n * - Error state uses both color and icon (not color alone)\n */\nexport function HelperText({ error = false, className, children, ...props }: HelperTextProps) {\n return (\n <p\n className={cn(styles.helperText, error && styles.error, className)}\n role={error ? 'alert' : undefined}\n {...props}\n >\n {error && (\n <svg className={styles.icon} width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" fill=\"currentColor\" aria-hidden=\"true\">\n <path d=\"M7 0a7 7 0 110 14A7 7 0 017 0zm0 9.5a.75.75 0 100 1.5.75.75 0 000-1.5zM7 3a.75.75 0 00-.75.75v4a.75.75 0 001.5 0v-4A.75.75 0 007 3z\" />\n </svg>\n )}\n {children}\n </p>\n );\n}\n",".fieldset {\n border: none;\n margin: 0;\n padding: 0;\n}\n\n.legend {\n display: block;\n font-family: var(--bazaar-font-family-sans);\n font-size: var(--bazaar-font-size-label-lg);\n font-weight: var(--bazaar-font-weight-medium);\n line-height: var(--bazaar-line-height-label-lg);\n color: var(--bazaar-color-text-primary);\n margin-bottom: var(--bazaar-space-2);\n padding: 0;\n}\n\n.options {\n display: flex;\n}\n\n.vertical {\n flex-direction: column;\n gap: var(--bazaar-space-2);\n}\n\n.horizontal {\n flex-direction: row;\n flex-wrap: wrap;\n gap: var(--bazaar-space-4);\n}\n\n.fieldset:disabled {\n opacity: var(--bazaar-opacity-disabled);\n}\n","import { useCallback } from 'react';\nimport { cn } from '../../utils/cn';\nimport { Checkbox } from '../Checkbox';\nimport { HelperText } from '../HelperText';\nimport styles from './CheckboxGroup.module.css';\n\nexport interface CheckboxGroupOption {\n value: string;\n label: string;\n disabled?: boolean;\n}\n\nexport interface CheckboxGroupProps {\n /** Group label rendered as fieldset legend */\n label: string;\n /** Shared name attribute for all checkboxes */\n name: string;\n /** Array of checkbox options */\n options: CheckboxGroupOption[];\n /** Currently selected values */\n value?: string[];\n /** Change handler — receives updated array of selected values */\n onChange?: (value: string[]) => void;\n /** Error message */\n error?: string;\n /** Layout direction */\n orientation?: 'vertical' | 'horizontal';\n /** Disabled state for all checkboxes */\n disabled?: boolean;\n /** Additional CSS class */\n className?: string;\n}\n\n/**\n * CheckboxGroup — group of checkboxes with fieldset/legend for accessibility.\n *\n * Accessibility:\n * - Uses <fieldset> and <legend> for semantic grouping\n * - Error message linked via role=\"alert\"\n * - Each checkbox is individually focusable\n */\nexport function CheckboxGroup({\n label,\n name,\n options,\n value = [],\n onChange,\n error,\n orientation = 'vertical',\n disabled = false,\n className,\n}: CheckboxGroupProps) {\n const handleChange = useCallback(\n (optionValue: string, checked: boolean) => {\n if (!onChange) return;\n const next = checked\n ? [...value, optionValue]\n : value.filter((v) => v !== optionValue);\n onChange(next);\n },\n [value, onChange],\n );\n\n return (\n <fieldset\n className={cn(styles.fieldset, className)}\n disabled={disabled}\n >\n <legend className={styles.legend}>{label}</legend>\n <div className={cn(styles.options, styles[orientation])}>\n {options.map((opt) => (\n <Checkbox\n key={opt.value}\n name={name}\n label={opt.label}\n value={opt.value}\n checked={value.includes(opt.value)}\n onChange={(e) => handleChange(opt.value, e.target.checked)}\n disabled={opt.disabled || disabled}\n error={Boolean(error)}\n />\n ))}\n </div>\n {error && (\n <HelperText error>{error}</HelperText>\n )}\n </fieldset>\n );\n}\n",".wrapper {\n display: inline-flex;\n align-items: center;\n gap: var(--bazaar-space-2);\n cursor: pointer;\n min-height: var(--bazaar-size-touch-min);\n user-select: none;\n}\n\n.input {\n position: absolute;\n width: 1px;\n height: 1px;\n padding: 0;\n margin: -1px;\n overflow: hidden;\n clip: rect(0, 0, 0, 0);\n white-space: nowrap;\n border: 0;\n}\n\n.control {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 20px;\n height: 20px;\n border: var(--bazaar-border-width-hairline) var(--bazaar-border-style-default) var(--bazaar-color-border-default);\n border-radius: var(--bazaar-radius-full);\n background-color: var(--bazaar-color-surface-default);\n flex-shrink: 0;\n box-shadow: var(--bazaar-shadow-inset-xs);\n transition:\n border-color var(--bazaar-motion-duration-base) var(--bazaar-motion-easing-standard),\n background-color var(--bazaar-motion-duration-base) var(--bazaar-motion-easing-standard),\n box-shadow var(--bazaar-motion-duration-base) var(--bazaar-motion-easing-standard);\n}\n\n.dot {\n width: 8px;\n height: 8px;\n border-radius: var(--bazaar-radius-full);\n background-color: transparent;\n transition:\n background-color var(--bazaar-motion-duration-base) var(--bazaar-motion-easing-standard),\n transform var(--bazaar-motion-duration-base) var(--bazaar-motion-easing-standard);\n transform: scale(0);\n}\n\n.wrapper:hover .control {\n border-color: var(--bazaar-color-border-strong);\n background-color: var(--bazaar-color-surface-hover);\n}\n\n.input:checked + .control {\n border-color: var(--bazaar-color-brand-primary-500);\n background-color: var(--bazaar-color-surface-default);\n box-shadow: var(--bazaar-shadow-xs);\n}\n\n.input:checked + .control .dot {\n background-color: var(--bazaar-color-brand-primary-500);\n transform: scale(1);\n}\n\n.input:focus-visible + .control {\n outline: var(--bazaar-border-width-medium) solid var(--bazaar-focus-outline-color);\n outline-offset: var(--bazaar-focus-ring-offset);\n box-shadow: var(--bazaar-shadow-focus);\n}\n\n.input:disabled + .control {\n opacity: var(--bazaar-opacity-disabled);\n cursor: not-allowed;\n}\n\n.input:disabled ~ .label {\n opacity: var(--bazaar-opacity-disabled);\n cursor: not-allowed;\n}\n\n.label {\n font-family: var(--bazaar-font-family-sans);\n font-size: var(--bazaar-font-size-body-md);\n line-height: var(--bazaar-line-height-body-md);\n color: var(--bazaar-color-text-primary);\n}\n\n.error .control {\n border-color: var(--bazaar-color-error-500);\n}\n","import { forwardRef, type InputHTMLAttributes } from 'react';\nimport { cn } from '../../utils/cn';\nimport styles from './Radio.module.css';\n\nexport interface RadioProps extends Omit<InputHTMLAttributes<HTMLInputElement>, 'type'> {\n /** Label text */\n label?: string;\n /** Error state */\n error?: boolean;\n}\n\n/**\n * Radio — single-selection option within a group.\n *\n * Accessibility:\n * - Uses native <input type=\"radio\">\n * - Wrap multiple Radios in a fieldset with legend for group labeling\n * - Arrow keys navigate between radios within the same name group\n */\nexport const Radio = forwardRef<HTMLInputElement, RadioProps>(\n ({ label, error = false, className, id, ...props }, ref) => {\n const inputId = id || (label ? `radio-${label.replace(/\\s+/g, '-').toLowerCase()}` : undefined);\n\n return (\n <label className={cn(styles.wrapper, error && styles.error, className)}>\n <input\n ref={ref}\n type=\"radio\"\n className={styles.input}\n id={inputId}\n aria-invalid={error || undefined}\n {...props}\n />\n <span className={styles.control} aria-hidden=\"true\">\n <span className={styles.dot} />\n </span>\n {label && <span className={styles.label}>{label}</span>}\n </label>\n );\n },\n);\n\nRadio.displayName = 'Radio';\n",".fieldset {\n border: none;\n margin: 0;\n padding: 0;\n}\n\n.legend {\n display: block;\n font-family: var(--bazaar-font-family-sans);\n font-size: var(--bazaar-font-size-label-lg);\n font-weight: var(--bazaar-font-weight-medium);\n line-height: var(--bazaar-line-height-label-lg);\n color: var(--bazaar-color-text-primary);\n margin-bottom: var(--bazaar-space-2);\n padding: 0;\n}\n\n.options {\n display: flex;\n}\n\n.vertical {\n flex-direction: column;\n gap: var(--bazaar-space-2);\n}\n\n.horizontal {\n flex-direction: row;\n flex-wrap: wrap;\n gap: var(--bazaar-space-4);\n}\n\n.fieldset:disabled {\n opacity: var(--bazaar-opacity-disabled);\n}\n","import { useCallback } from 'react';\nimport { cn } from '../../utils/cn';\nimport { Radio } from '../Radio';\nimport { HelperText } from '../HelperText';\nimport styles from './RadioGroup.module.css';\n\nexport interface RadioGroupOption {\n value: string;\n label: string;\n disabled?: boolean;\n}\n\nexport interface RadioGroupProps {\n /** Group label rendered as fieldset legend */\n label: string;\n /** Shared name attribute for all radios */\n name: string;\n /** Array of radio options */\n options: RadioGroupOption[];\n /** Currently selected value */\n value?: string;\n /** Change handler — receives the selected value */\n onChange?: (value: string) => void;\n /** Error message */\n error?: string;\n /** Layout direction */\n orientation?: 'vertical' | 'horizontal';\n /** Disabled state for all radios */\n disabled?: boolean;\n /** Additional CSS class */\n className?: string;\n}\n\n/**\n * RadioGroup — group of radio buttons with fieldset/legend for accessibility.\n *\n * Accessibility:\n * - Uses <fieldset> and <legend> for semantic grouping\n * - Arrow keys navigate between radios within the group\n * - Error message rendered with role=\"alert\"\n */\nexport function RadioGroup({\n label,\n name,\n options,\n value,\n onChange,\n error,\n orientation = 'vertical',\n disabled = false,\n className,\n}: RadioGroupProps) {\n const handleChange = useCallback(\n (optionValue: string) => {\n onChange?.(optionValue);\n },\n [onChange],\n );\n\n return (\n <fieldset\n className={cn(styles.fieldset, className)}\n disabled={disabled}\n >\n <legend className={styles.legend}>{label}</legend>\n <div className={cn(styles.options, styles[orientation])}>\n {options.map((opt) => (\n <Radio\n key={opt.value}\n name={name}\n label={opt.label}\n value={opt.value}\n checked={value === opt.value}\n onChange={() => handleChange(opt.value)}\n disabled={opt.disabled || disabled}\n error={Boolean(error)}\n />\n ))}\n </div>\n {error && (\n <HelperText error>{error}</HelperText>\n )}\n </fieldset>\n );\n}\n",".wrapper {\n position: relative;\n display: inline-block;\n}\n\n.select {\n display: block;\n width: 100%;\n appearance: none;\n border: var(--bazaar-border-width-hairline) var(--bazaar-border-style-default) var(--bazaar-color-border-default);\n border-radius: var(--bazaar-radius-md);\n background-color: var(--bazaar-color-surface-default);\n color: var(--bazaar-color-text-primary);\n font-family: var(--bazaar-font-family-sans);\n padding-right: var(--bazaar-space-10);\n cursor: pointer;\n box-shadow: var(--bazaar-shadow-inset-xs);\n transition:\n border-color var(--bazaar-motion-duration-base) var(--bazaar-motion-easing-standard),\n box-shadow var(--bazaar-motion-duration-base) var(--bazaar-motion-easing-standard),\n background-color var(--bazaar-motion-duration-base) var(--bazaar-motion-easing-standard);\n}\n\n.select:hover:not(:disabled) {\n border-color: var(--bazaar-color-border-strong);\n background-color: var(--bazaar-color-surface-hover);\n}\n\n.select:focus {\n outline: none;\n border-color: var(--bazaar-color-brand-primary-500);\n box-shadow: var(--bazaar-shadow-focus);\n background-color: var(--bazaar-color-surface-default);\n}\n\n.select:disabled {\n cursor: not-allowed;\n opacity: var(--bazaar-opacity-disabled);\n background-color: var(--bazaar-color-surface-subtle);\n box-shadow: none;\n}\n\n.sm {\n height: var(--bazaar-size-control-sm);\n padding-left: var(--bazaar-space-3);\n font-size: var(--bazaar-font-size-body-sm);\n}\n\n.md {\n height: var(--bazaar-size-control-md);\n padding-left: var(--bazaar-space-4);\n font-size: var(--bazaar-font-size-body-md);\n}\n\n.lg {\n height: var(--bazaar-size-control-lg);\n padding-left: var(--bazaar-space-4);\n font-size: var(--bazaar-font-size-body-lg);\n}\n\n.error {\n border-color: var(--bazaar-color-error-500);\n}\n\n.error:focus {\n box-shadow: var(--bazaar-shadow-focus-error);\n}\n\n.fullWidth {\n width: 100%;\n}\n\n.chevron {\n position: absolute;\n right: var(--bazaar-space-3);\n top: 50%;\n transform: translateY(-50%);\n pointer-events: none;\n color: var(--bazaar-color-text-muted);\n display: flex;\n}\n","import { forwardRef, type SelectHTMLAttributes } from 'react';\nimport { cn } from '../../utils/cn';\nimport styles from './Select.module.css';\n\nexport interface SelectProps extends Omit<SelectHTMLAttributes<HTMLSelectElement>, 'size'> {\n /** Size */\n size?: 'sm' | 'md' | 'lg';\n /** Error state */\n error?: boolean;\n /** Full width */\n fullWidth?: boolean;\n}\n\n/**\n * Select — native dropdown select.\n *\n * Accessibility:\n * - Uses native <select> for full keyboard and screen reader support\n * - Associate with Label via htmlFor/id\n * - Custom chevron is decorative (aria-hidden on the icon)\n */\nexport const Select = forwardRef<HTMLSelectElement, SelectProps>(\n ({ size = 'md', error = false, fullWidth = false, className, children, ...props }, ref) => (\n <div className={cn(styles.wrapper, fullWidth && styles.fullWidth)}>\n <select\n ref={ref}\n className={cn(\n styles.select,\n styles[size],\n error && styles.error,\n fullWidth && styles.fullWidth,\n className,\n )}\n aria-invalid={error || undefined}\n {...props}\n >\n {children}\n </select>\n <span className={styles.chevron} aria-hidden=\"true\">\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"1.75\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <path d=\"M4 6l4 4 4-4\" />\n </svg>\n </span>\n </div>\n ),\n);\n\nSelect.displayName = 'Select';\n",".wrapper {\n display: inline-flex;\n align-items: center;\n gap: var(--bazaar-space-3);\n cursor: pointer;\n min-height: var(--bazaar-size-touch-min);\n user-select: none;\n}\n\n.input {\n position: absolute;\n width: 1px;\n height: 1px;\n padding: 0;\n margin: -1px;\n overflow: hidden;\n clip: rect(0, 0, 0, 0);\n white-space: nowrap;\n border: 0;\n}\n\n.track {\n position: relative;\n width: 44px;\n height: 24px;\n border-radius: var(--bazaar-radius-full);\n background-color: var(--bazaar-color-neutral-300);\n flex-shrink: 0;\n box-shadow: var(--bazaar-shadow-inset-sm);\n transition:\n background-color var(--bazaar-motion-duration-base) var(--bazaar-motion-easing-standard),\n box-shadow var(--bazaar-motion-duration-base) var(--bazaar-motion-easing-standard);\n}\n\n.thumb {\n position: absolute;\n top: 2px;\n left: 2px;\n width: 20px;\n height: 20px;\n border-radius: var(--bazaar-radius-full);\n background-color: var(--bazaar-color-surface-default);\n box-shadow: var(--bazaar-shadow-sm);\n transition:\n transform var(--bazaar-motion-duration-base) var(--bazaar-motion-easing-standard),\n box-shadow var(--bazaar-motion-duration-base) var(--bazaar-motion-easing-standard);\n}\n\n.input:checked + .track {\n background: linear-gradient(\n 180deg,\n var(--bazaar-color-brand-primary-500) 0%,\n var(--bazaar-color-brand-primary-600) 100%\n );\n box-shadow: var(--bazaar-shadow-inset-xs);\n}\n\n.input:checked + .track .thumb {\n transform: translateX(20px);\n box-shadow: var(--bazaar-shadow-md);\n}\n\n.input:focus-visible + .track {\n outline: var(--bazaar-border-width-medium) solid var(--bazaar-focus-outline-color);\n outline-offset: var(--bazaar-focus-ring-offset);\n box-shadow: var(--bazaar-shadow-focus);\n}\n\n.input:disabled + .track {\n opacity: var(--bazaar-opacity-disabled);\n cursor: not-allowed;\n}\n\n.input:disabled ~ .label {\n opacity: var(--bazaar-opacity-disabled);\n cursor: not-allowed;\n}\n\n.label {\n font-family: var(--bazaar-font-family-sans);\n font-size: var(--bazaar-font-size-body-md);\n line-height: var(--bazaar-line-height-body-md);\n color: var(--bazaar-color-text-primary);\n}\n","import { forwardRef, type InputHTMLAttributes } from 'react';\nimport { cn } from '../../utils/cn';\nimport styles from './Switch.module.css';\n\nexport interface SwitchProps extends Omit<InputHTMLAttributes<HTMLInputElement>, 'type'> {\n /** Label text */\n label?: string;\n}\n\n/**\n * Switch — on/off toggle control.\n *\n * Accessibility:\n * - Uses role=\"switch\" with native checkbox for AT support\n * - aria-checked reflects state\n * - Label is clickable and linked\n * - Healthcare note: use for non-critical preferences only.\n * For high-risk toggles (e.g., medication alerts), prefer explicit\n * confirmation patterns instead.\n */\nexport const Switch = forwardRef<HTMLInputElement, SwitchProps>(\n ({ label, className, checked, defaultChecked, ...props }, ref) => (\n <label className={cn(styles.wrapper, className)}>\n <input\n ref={ref}\n type=\"checkbox\"\n role=\"switch\"\n className={styles.input}\n checked={checked}\n defaultChecked={defaultChecked}\n aria-checked={checked}\n {...props}\n />\n <span className={styles.track} aria-hidden=\"true\">\n <span className={styles.thumb} />\n </span>\n {label && <span className={styles.label}>{label}</span>}\n </label>\n ),\n);\n\nSwitch.displayName = 'Switch';\n",".textarea {\n display: block;\n width: auto;\n min-height: 80px;\n padding: var(--bazaar-space-3) var(--bazaar-space-4);\n border: var(--bazaar-border-width-hairline) var(--bazaar-border-style-default) var(--bazaar-color-border-default);\n border-radius: var(--bazaar-radius-md);\n background-color: var(--bazaar-color-surface-default);\n color: var(--bazaar-color-text-primary);\n font-family: var(--bazaar-font-family-sans);\n font-size: var(--bazaar-font-size-body-md);\n line-height: var(--bazaar-line-height-body-md);\n box-shadow: var(--bazaar-shadow-inset-xs);\n transition:\n border-color var(--bazaar-motion-duration-base) var(--bazaar-motion-easing-standard),\n box-shadow var(--bazaar-motion-duration-base) var(--bazaar-motion-easing-standard),\n background-color var(--bazaar-motion-duration-base) var(--bazaar-motion-easing-standard);\n}\n\n.textarea::placeholder {\n color: var(--bazaar-color-text-muted);\n}\n\n.textarea:hover:not(:disabled):not(:focus) {\n border-color: var(--bazaar-color-border-strong);\n background-color: var(--bazaar-color-surface-hover);\n}\n\n.textarea:focus {\n outline: none;\n border-color: var(--bazaar-color-brand-primary-500);\n box-shadow: var(--bazaar-shadow-focus);\n background-color: var(--bazaar-color-surface-default);\n}\n\n.textarea:disabled {\n cursor: not-allowed;\n opacity: var(--bazaar-opacity-disabled);\n background-color: var(--bazaar-color-surface-subtle);\n box-shadow: none;\n}\n\n.error {\n border-color: var(--bazaar-color-error-500);\n}\n\n.error:focus {\n border-color: var(--bazaar-color-error-500);\n box-shadow: var(--bazaar-shadow-focus-error);\n}\n\n.fullWidth {\n width: 100%;\n}\n","import { forwardRef, type TextareaHTMLAttributes } from 'react';\nimport { cn } from '../../utils/cn';\nimport styles from './Textarea.module.css';\n\nexport interface TextareaProps extends TextareaHTMLAttributes<HTMLTextAreaElement> {\n /** Error state */\n error?: boolean;\n /** Full width */\n fullWidth?: boolean;\n /** Allow vertical resize */\n resize?: 'none' | 'vertical' | 'both';\n}\n\n/**\n * Textarea — multi-line text input.\n *\n * Accessibility:\n * - Associate with Label via htmlFor/id\n * - Link to HelperText via aria-describedby\n */\nexport const Textarea = forwardRef<HTMLTextAreaElement, TextareaProps>(\n ({ error = false, fullWidth = false, resize = 'vertical', className, style, ...props }, ref) => (\n <textarea\n ref={ref}\n className={cn(\n styles.textarea,\n error && styles.error,\n fullWidth && styles.fullWidth,\n className,\n )}\n aria-invalid={error || undefined}\n style={{ ...style, resize }}\n {...props}\n />\n ),\n);\n\nTextarea.displayName = 'Textarea';\n",".wrapper {\n display: flex;\n flex-direction: column;\n gap: var(--bazaar-space-2);\n width: 100%;\n}\n\n.header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n}\n\n.label {\n font-family: var(--bazaar-font-family-sans);\n font-size: var(--bazaar-font-size-label-lg);\n font-weight: var(--bazaar-font-weight-medium);\n line-height: var(--bazaar-line-height-label-lg);\n color: var(--bazaar-color-text-primary);\n}\n\n.value {\n font-family: var(--bazaar-font-family-sans);\n font-size: var(--bazaar-font-size-body-sm);\n font-weight: var(--bazaar-font-weight-medium);\n color: var(--bazaar-color-text-muted);\n min-width: 2ch;\n text-align: right;\n}\n\n/* Range input */\n.input {\n -webkit-appearance: none;\n appearance: none;\n width: 100%;\n background: transparent;\n cursor: pointer;\n margin: 0;\n}\n\n.input:focus {\n outline: none;\n}\n\n/* Track — WebKit */\n.input::-webkit-slider-runnable-track {\n border-radius: var(--bazaar-radius-full);\n background: linear-gradient(\n to right,\n var(--bazaar-color-brand-primary-500) 0%,\n var(--bazaar-color-brand-primary-500) var(--slider-fill, 0%),\n var(--bazaar-color-border-default) var(--slider-fill, 0%),\n var(--bazaar-color-border-default) 100%\n );\n}\n\n/* Track — Firefox */\n.input::-moz-range-track {\n border-radius: var(--bazaar-radius-full);\n background: var(--bazaar-color-border-default);\n}\n\n.input::-moz-range-progress {\n border-radius: var(--bazaar-radius-full);\n background: var(--bazaar-color-brand-primary-500);\n}\n\n/* Thumb — WebKit */\n.input::-webkit-slider-thumb {\n -webkit-appearance: none;\n appearance: none;\n border-radius: var(--bazaar-radius-full);\n background-color: var(--bazaar-color-surface-default);\n border: 2px solid var(--bazaar-color-brand-primary-500);\n box-shadow: var(--bazaar-shadow-sm);\n transition:\n box-shadow var(--bazaar-motion-duration-fast) var(--bazaar-motion-easing-standard),\n transform var(--bazaar-motion-duration-fast) var(--bazaar-motion-easing-standard);\n}\n\n.input::-webkit-slider-thumb:hover {\n transform: scale(1.15);\n box-shadow: var(--bazaar-shadow-md);\n}\n\n.input:focus-visible::-webkit-slider-thumb {\n box-shadow: var(--bazaar-shadow-focus);\n}\n\n/* Thumb — Firefox */\n.input::-moz-range-thumb {\n border-radius: var(--bazaar-radius-full);\n background-color: var(--bazaar-color-surface-default);\n border: 2px solid var(--bazaar-color-brand-primary-500);\n box-shadow: var(--bazaar-shadow-sm);\n transition:\n box-shadow var(--bazaar-motion-duration-fast) var(--bazaar-motion-easing-standard),\n transform var(--bazaar-motion-duration-fast) var(--bazaar-motion-easing-standard);\n}\n\n.input::-moz-range-thumb:hover {\n transform: scale(1.15);\n box-shadow: var(--bazaar-shadow-md);\n}\n\n.input:focus-visible::-moz-range-thumb {\n box-shadow: var(--bazaar-shadow-focus);\n}\n\n/* Size: sm */\n.sm .input::-webkit-slider-runnable-track { height: 4px; }\n.sm .input::-moz-range-track { height: 4px; }\n.sm .input::-moz-range-progress { height: 4px; }\n.sm .input::-webkit-slider-thumb { width: 14px; height: 14px; margin-top: -5px; }\n.sm .input::-moz-range-thumb { width: 14px; height: 14px; }\n\n/* Size: md */\n.md .input::-webkit-slider-runnable-track { height: 6px; }\n.md .input::-moz-range-track { height: 6px; }\n.md .input::-moz-range-progress { height: 6px; }\n.md .input::-webkit-slider-thumb { width: 18px; height: 18px; margin-top: -6px; }\n.md .input::-moz-range-thumb { width: 18px; height: 18px; }\n\n/* Disabled */\n.disabled {\n opacity: var(--bazaar-opacity-disabled);\n pointer-events: none;\n}\n","import { forwardRef, useId, type InputHTMLAttributes } from 'react';\nimport { cn } from '../../utils/cn';\nimport styles from './Slider.module.css';\n\nexport interface SliderProps extends Omit<InputHTMLAttributes<HTMLInputElement>, 'size' | 'type' | 'onChange' | 'value'> {\n /** Current value */\n value?: number;\n /** Change handler */\n onChange?: (value: number) => void;\n /** Minimum value */\n min?: number;\n /** Maximum value */\n max?: number;\n /** Step increment */\n step?: number;\n /** Disabled state */\n disabled?: boolean;\n /** Size variant */\n size?: 'sm' | 'md';\n /** Accessible label text */\n label?: string;\n /** Show current value next to the slider */\n showValue?: boolean;\n /** Additional CSS class */\n className?: string;\n}\n\n/**\n * Slider — range input with custom styling.\n *\n * Accessibility:\n * - Uses native input[type=\"range\"] for full keyboard and AT support\n * - Label linked via htmlFor/id\n * - aria-valuemin, aria-valuemax, aria-valuenow communicated natively\n * - showValue provides visual readout of current value\n */\nexport const Slider = forwardRef<HTMLInputElement, SliderProps>(\n (\n {\n value,\n onChange,\n min = 0,\n max = 100,\n step = 1,\n disabled = false,\n size = 'md',\n label,\n showValue = false,\n className,\n id,\n ...props\n },\n ref,\n ) => {\n const generatedId = useId();\n const inputId = id || generatedId;\n\n // Calculate fill percentage for the track\n const current = value ?? min;\n const percentage = ((current - min) / (max - min)) * 100;\n\n return (\n <div className={cn(styles.wrapper, styles[size], disabled && styles.disabled, className)}>\n {label && (\n <div className={styles.header}>\n <label htmlFor={inputId} className={styles.label}>\n {label}\n </label>\n {showValue && (\n <span className={styles.value} aria-hidden=\"true\">\n {current}\n </span>\n )}\n </div>\n )}\n {!label && showValue && (\n <span className={styles.value} aria-hidden=\"true\">\n {current}\n </span>\n )}\n <input\n ref={ref}\n id={inputId}\n type=\"range\"\n className={styles.input}\n value={value}\n onChange={(e) => onChange?.(Number(e.target.value))}\n min={min}\n max={max}\n step={step}\n disabled={disabled}\n style={{ '--slider-fill': `${percentage}%` } as React.CSSProperties}\n {...props}\n />\n </div>\n );\n },\n);\n\nSlider.displayName = 'Slider';\n",".wrapper {\n position: relative;\n display: inline-flex;\n align-items: center;\n border: var(--bazaar-border-width-hairline) var(--bazaar-border-style-default) var(--bazaar-color-border-default);\n border-radius: var(--bazaar-radius-md);\n background-color: var(--bazaar-color-surface-default);\n transition:\n border-color var(--bazaar-motion-duration-fast) var(--bazaar-motion-easing-standard),\n box-shadow var(--bazaar-motion-duration-fast) var(--bazaar-motion-easing-standard);\n}\n\n.wrapper:hover:not(.disabled) {\n border-color: var(--bazaar-color-border-strong);\n}\n\n.wrapper:focus-within {\n border-color: var(--bazaar-color-brand-primary-500);\n box-shadow: var(--bazaar-shadow-focus);\n}\n\n.input {\n flex: 1;\n min-width: 0;\n border: none;\n background: transparent;\n color: var(--bazaar-color-text-primary);\n font-family: var(--bazaar-font-family-sans);\n outline: none;\n -moz-appearance: textfield;\n}\n\n.input::-webkit-inner-spin-button,\n.input::-webkit-outer-spin-button {\n -webkit-appearance: none;\n margin: 0;\n}\n\n.input::placeholder {\n color: var(--bazaar-color-text-muted);\n}\n\n.prefix,\n.suffix {\n color: var(--bazaar-color-text-muted);\n font-family: var(--bazaar-font-family-sans);\n flex-shrink: 0;\n user-select: none;\n}\n\n/* Sizes */\n.sm {\n height: var(--bazaar-size-control-sm);\n}\n\n.sm .input {\n padding: 0 var(--bazaar-space-2);\n font-size: var(--bazaar-font-size-body-sm);\n}\n\n.sm .prefix { padding-left: var(--bazaar-space-3); font-size: var(--bazaar-font-size-body-sm); }\n.sm .suffix { padding-right: var(--bazaar-space-2); font-size: var(--bazaar-font-size-body-sm); }\n\n.md {\n height: var(--bazaar-size-control-md);\n}\n\n.md .input {\n padding: 0 var(--bazaar-space-3);\n font-size: var(--bazaar-font-size-body-md);\n}\n\n.md .prefix { padding-left: var(--bazaar-space-4); font-size: var(--bazaar-font-size-body-md); }\n.md .suffix { padding-right: var(--bazaar-space-3); font-size: var(--bazaar-font-size-body-md); }\n\n.lg {\n height: var(--bazaar-size-control-lg);\n}\n\n.lg .input {\n padding: 0 var(--bazaar-space-3);\n font-size: var(--bazaar-font-size-body-lg);\n}\n\n.lg .prefix { padding-left: var(--bazaar-space-4); font-size: var(--bazaar-font-size-body-lg); }\n.lg .suffix { padding-right: var(--bazaar-space-3); font-size: var(--bazaar-font-size-body-lg); }\n\n/* Buttons column */\n.buttons {\n display: flex;\n flex-direction: column;\n border-left: var(--bazaar-border-width-hairline) var(--bazaar-border-style-default) var(--bazaar-color-border-default);\n align-self: stretch;\n}\n\n.button {\n display: flex;\n align-items: center;\n justify-content: center;\n flex: 1;\n width: 28px;\n border: none;\n background: transparent;\n color: var(--bazaar-color-text-muted);\n cursor: pointer;\n padding: 0;\n transition: background-color var(--bazaar-motion-duration-fast) var(--bazaar-motion-easing-standard),\n color var(--bazaar-motion-duration-fast) var(--bazaar-motion-easing-standard);\n}\n\n.button + .button {\n border-top: var(--bazaar-border-width-hairline) var(--bazaar-border-style-default) var(--bazaar-color-border-default);\n}\n\n.button:hover:not(:disabled) {\n background-color: var(--bazaar-color-surface-subtle);\n color: var(--bazaar-color-text-primary);\n}\n\n.button:disabled {\n cursor: not-allowed;\n opacity: var(--bazaar-opacity-disabled);\n}\n\n/* Error */\n.error {\n border-color: var(--bazaar-color-error-500);\n}\n\n.error:focus-within {\n border-color: var(--bazaar-color-error-500);\n box-shadow: 0 0 0 3px rgba(194, 58, 58, 0.2);\n}\n\n/* Disabled */\n.disabled {\n cursor: not-allowed;\n opacity: var(--bazaar-opacity-disabled);\n background-color: var(--bazaar-color-surface-subtle);\n}\n","import { forwardRef, useCallback, type InputHTMLAttributes } from 'react';\nimport { cn } from '../../utils/cn';\nimport styles from './NumberField.module.css';\n\nexport interface NumberFieldProps extends Omit<InputHTMLAttributes<HTMLInputElement>, 'size' | 'type' | 'onChange' | 'value' | 'prefix'> {\n /** Current numeric value */\n value?: number;\n /** Change handler */\n onChange?: (value: number) => void;\n /** Minimum allowed value */\n min?: number;\n /** Maximum allowed value */\n max?: number;\n /** Increment step */\n step?: number;\n /** Size variant */\n size?: 'sm' | 'md' | 'lg';\n /** Error state */\n error?: boolean;\n /** Prefix text (e.g., \"$\") */\n prefix?: string;\n /** Suffix text (e.g., \"mg\") */\n suffix?: string;\n}\n\n/**\n * NumberField — numeric input with increment/decrement buttons.\n *\n * Accessibility:\n * - Uses native input[type=\"number\"] for spinbutton role\n * - Increment/decrement buttons have aria-labels\n * - Buttons are hidden from tab order (input handles keyboard)\n * - min/max constraints are communicated to AT\n */\nexport const NumberField = forwardRef<HTMLInputElement, NumberFieldProps>(\n (\n {\n value,\n onChange,\n min,\n max,\n step = 1,\n size = 'md',\n error = false,\n disabled = false,\n prefix,\n suffix,\n className,\n ...props\n },\n ref,\n ) => {\n const clamp = useCallback(\n (v: number) => {\n let clamped = v;\n if (min !== undefined) clamped = Math.max(min, clamped);\n if (max !== undefined) clamped = Math.min(max, clamped);\n return clamped;\n },\n [min, max],\n );\n\n const handleChange = useCallback(\n (e: React.ChangeEvent<HTMLInputElement>) => {\n const raw = parseFloat(e.target.value);\n if (!isNaN(raw)) onChange?.(clamp(raw));\n },\n [onChange, clamp],\n );\n\n const increment = useCallback(() => {\n if (disabled) return;\n const current = value ?? 0;\n onChange?.(clamp(current + step));\n }, [value, step, onChange, clamp, disabled]);\n\n const decrement = useCallback(() => {\n if (disabled) return;\n const current = value ?? 0;\n onChange?.(clamp(current - step));\n }, [value, step, onChange, clamp, disabled]);\n\n const atMin = min !== undefined && value !== undefined && value <= min;\n const atMax = max !== undefined && value !== undefined && value >= max;\n\n return (\n <div\n className={cn(\n styles.wrapper,\n styles[size],\n error && styles.error,\n disabled && styles.disabled,\n className,\n )}\n >\n {prefix && <span className={styles.prefix}>{prefix}</span>}\n <input\n ref={ref}\n type=\"number\"\n className={styles.input}\n value={value ?? ''}\n onChange={handleChange}\n min={min}\n max={max}\n step={step}\n disabled={disabled}\n aria-invalid={error || undefined}\n {...props}\n />\n {suffix && <span className={styles.suffix}>{suffix}</span>}\n <div className={styles.buttons}>\n <button\n type=\"button\"\n className={styles.button}\n onClick={increment}\n disabled={disabled || atMax}\n aria-label=\"Increment\"\n tabIndex={-1}\n >\n <svg width=\"10\" height=\"10\" viewBox=\"0 0 10 10\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" aria-hidden=\"true\">\n <path d=\"M2 6.5L5 3.5L8 6.5\" />\n </svg>\n </button>\n <button\n type=\"button\"\n className={styles.button}\n onClick={decrement}\n disabled={disabled || atMin}\n aria-label=\"Decrement\"\n tabIndex={-1}\n >\n <svg width=\"10\" height=\"10\" viewBox=\"0 0 10 10\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" aria-hidden=\"true\">\n <path d=\"M2 3.5L5 6.5L8 3.5\" />\n </svg>\n </button>\n </div>\n </div>\n );\n },\n);\n\nNumberField.displayName = 'NumberField';\n",".wrapper {\n position: relative;\n display: inline-flex;\n align-items: center;\n width: auto;\n}\n\n.fullWidth {\n width: 100%;\n}\n\n.searchIcon {\n position: absolute;\n left: var(--bazaar-space-3);\n color: var(--bazaar-color-text-muted);\n pointer-events: none;\n flex-shrink: 0;\n}\n\n.input {\n display: block;\n width: 100%;\n border: var(--bazaar-border-width-hairline) var(--bazaar-border-style-default) var(--bazaar-color-border-default);\n border-radius: var(--bazaar-radius-md);\n background-color: var(--bazaar-color-surface-default);\n color: var(--bazaar-color-text-primary);\n font-family: var(--bazaar-font-family-sans);\n transition:\n border-color var(--bazaar-motion-duration-fast) var(--bazaar-motion-easing-standard),\n box-shadow var(--bazaar-motion-duration-fast) var(--bazaar-motion-easing-standard);\n}\n\n.input::placeholder {\n color: var(--bazaar-color-text-muted);\n}\n\n.input:hover:not(:disabled):not(:focus) {\n border-color: var(--bazaar-color-border-strong);\n}\n\n.input:focus {\n outline: none;\n border-color: var(--bazaar-color-brand-primary-500);\n box-shadow: var(--bazaar-shadow-focus);\n}\n\n.input:disabled {\n cursor: not-allowed;\n opacity: var(--bazaar-opacity-disabled);\n background-color: var(--bazaar-color-surface-subtle);\n}\n\n/* Hide native search cancel button */\n.input::-webkit-search-cancel-button {\n display: none;\n}\n\n/* Sizes */\n.sm .input {\n height: var(--bazaar-size-control-sm);\n padding: 0 var(--bazaar-space-3) 0 calc(var(--bazaar-space-3) + 20px);\n font-size: var(--bazaar-font-size-body-sm);\n}\n\n.md .input {\n height: var(--bazaar-size-control-md);\n padding: 0 var(--bazaar-space-4) 0 calc(var(--bazaar-space-4) + 20px);\n font-size: var(--bazaar-font-size-body-md);\n}\n\n.lg .input {\n height: var(--bazaar-size-control-lg);\n padding: 0 var(--bazaar-space-4) 0 calc(var(--bazaar-space-4) + 22px);\n font-size: var(--bazaar-font-size-body-lg);\n}\n\n/* Error */\n.error {\n border-color: var(--bazaar-color-error-500);\n}\n\n.error:focus {\n border-color: var(--bazaar-color-error-500);\n box-shadow: 0 0 0 3px rgba(194, 58, 58, 0.2);\n}\n\n/* Clear button */\n.clearButton {\n position: absolute;\n right: var(--bazaar-space-2);\n display: flex;\n align-items: center;\n justify-content: center;\n width: 24px;\n height: 24px;\n border: none;\n border-radius: var(--bazaar-radius-sm);\n background: transparent;\n color: var(--bazaar-color-text-muted);\n cursor: pointer;\n padding: 0;\n transition: color var(--bazaar-motion-duration-fast) var(--bazaar-motion-easing-standard),\n background-color var(--bazaar-motion-duration-fast) var(--bazaar-motion-easing-standard);\n}\n\n.clearButton:hover {\n color: var(--bazaar-color-text-primary);\n background-color: var(--bazaar-color-surface-subtle);\n}\n","import { forwardRef, type InputHTMLAttributes } from 'react';\nimport { cn } from '../../utils/cn';\nimport styles from './SearchField.module.css';\n\nexport interface SearchFieldProps extends Omit<InputHTMLAttributes<HTMLInputElement>, 'size' | 'type'> {\n /** Size of the search control */\n size?: 'sm' | 'md' | 'lg';\n /** Error state */\n error?: boolean;\n /** Full width */\n fullWidth?: boolean;\n /** Callback when clear button is clicked */\n onClear?: () => void;\n /** Show the clear button when input has a value */\n showClearButton?: boolean;\n}\n\n/**\n * SearchField — search input with magnifying glass icon and optional clear button.\n *\n * Accessibility:\n * - Uses role=\"searchbox\" for semantic search intent\n * - Clear button has aria-label for screen readers\n * - Search icon is decorative (aria-hidden)\n */\nexport const SearchField = forwardRef<HTMLInputElement, SearchFieldProps>(\n (\n {\n size = 'md',\n error = false,\n fullWidth = false,\n onClear,\n showClearButton = true,\n className,\n value,\n defaultValue,\n ...props\n },\n ref,\n ) => {\n const hasValue = Boolean(value || defaultValue);\n\n return (\n <div className={cn(styles.wrapper, styles[size], fullWidth && styles.fullWidth, className)}>\n <svg\n className={styles.searchIcon}\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n >\n <circle cx=\"6.5\" cy=\"6.5\" r=\"5.5\" />\n <path d=\"M11 11l4 4\" />\n </svg>\n <input\n ref={ref}\n type=\"search\"\n role=\"searchbox\"\n className={cn(styles.input, error && styles.error)}\n value={value}\n defaultValue={defaultValue}\n aria-invalid={error || undefined}\n {...props}\n />\n {showClearButton && hasValue && onClear && (\n <button\n type=\"button\"\n className={styles.clearButton}\n onClick={onClear}\n aria-label=\"Clear search\"\n tabIndex={-1}\n >\n <svg\n width=\"14\"\n height=\"14\"\n viewBox=\"0 0 14 14\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"M3 3l8 8M11 3l-8 8\" />\n </svg>\n </button>\n )}\n </div>\n );\n },\n);\n\nSearchField.displayName = 'SearchField';\n",".wrapper {\n position: relative;\n width: 100%;\n}\n\n.input {\n display: block;\n width: 100%;\n border: var(--bazaar-border-width-hairline) var(--bazaar-border-style-default) var(--bazaar-color-border-default);\n border-radius: var(--bazaar-radius-md);\n background-color: var(--bazaar-color-surface-default);\n color: var(--bazaar-color-text-primary);\n font-family: var(--bazaar-font-family-sans);\n transition:\n border-color var(--bazaar-motion-duration-fast) var(--bazaar-motion-easing-standard),\n box-shadow var(--bazaar-motion-duration-fast) var(--bazaar-motion-easing-standard);\n}\n\n.input::placeholder {\n color: var(--bazaar-color-text-muted);\n}\n\n.input:hover:not(:disabled):not(:focus) {\n border-color: var(--bazaar-color-border-strong);\n}\n\n.input:focus {\n outline: none;\n border-color: var(--bazaar-color-brand-primary-500);\n box-shadow: var(--bazaar-shadow-focus);\n}\n\n.input:disabled {\n cursor: not-allowed;\n opacity: var(--bazaar-opacity-disabled);\n background-color: var(--bazaar-color-surface-subtle);\n}\n\n/* Sizes */\n.sm .input {\n height: var(--bazaar-size-control-sm);\n padding: 0 var(--bazaar-space-3);\n font-size: var(--bazaar-font-size-body-sm);\n}\n\n.md .input {\n height: var(--bazaar-size-control-md);\n padding: 0 var(--bazaar-space-4);\n font-size: var(--bazaar-font-size-body-md);\n}\n\n.lg .input {\n height: var(--bazaar-size-control-lg);\n padding: 0 var(--bazaar-space-4);\n font-size: var(--bazaar-font-size-body-lg);\n}\n\n/* Error */\n.error {\n border-color: var(--bazaar-color-error-500);\n}\n\n.error:focus {\n border-color: var(--bazaar-color-error-500);\n box-shadow: 0 0 0 3px rgba(194, 58, 58, 0.2);\n}\n\n/* Dropdown */\n.dropdown {\n position: absolute;\n top: 100%;\n left: 0;\n right: 0;\n z-index: 10;\n margin-top: var(--bazaar-space-1);\n padding: var(--bazaar-space-1) 0;\n list-style: none;\n border: var(--bazaar-border-width-hairline) var(--bazaar-border-style-default) var(--bazaar-color-border-default);\n border-radius: var(--bazaar-radius-md);\n background-color: var(--bazaar-color-surface-default);\n box-shadow: var(--bazaar-shadow-md);\n max-height: 240px;\n overflow-y: auto;\n}\n\n.option {\n padding: var(--bazaar-space-2) var(--bazaar-space-3);\n font-family: var(--bazaar-font-family-sans);\n font-size: var(--bazaar-font-size-body-md);\n color: var(--bazaar-color-text-primary);\n cursor: pointer;\n transition: background-color var(--bazaar-motion-duration-fast) var(--bazaar-motion-easing-standard);\n}\n\n.option:hover,\n.optionFocused {\n background-color: var(--bazaar-color-surface-subtle);\n}\n\n.optionSelected {\n font-weight: var(--bazaar-font-weight-medium);\n color: var(--bazaar-color-brand-primary-500);\n}\n\n.message {\n padding: var(--bazaar-space-3) var(--bazaar-space-3);\n font-family: var(--bazaar-font-family-sans);\n font-size: var(--bazaar-font-size-body-sm);\n color: var(--bazaar-color-text-muted);\n text-align: center;\n}\n","import { useState, useRef, useCallback, useEffect, useId, type KeyboardEvent } from 'react';\nimport { cn } from '../../utils/cn';\nimport styles from './Autocomplete.module.css';\n\nexport interface AutocompleteOption {\n value: string;\n label: string;\n}\n\nexport interface AutocompleteProps {\n /** Available options */\n options: AutocompleteOption[];\n /** Selected value */\n value?: string;\n /** Change handler — receives the selected value */\n onChange?: (value: string) => void;\n /** Callback when the text input changes */\n onInputChange?: (inputValue: string) => void;\n /** Placeholder text */\n placeholder?: string;\n /** Disabled state */\n disabled?: boolean;\n /** Error state */\n error?: boolean;\n /** Size variant */\n size?: 'sm' | 'md' | 'lg';\n /** Show a loading spinner in the dropdown */\n loading?: boolean;\n /** Text shown when no results match */\n noResultsText?: string;\n /** Additional CSS class */\n className?: string;\n}\n\n/**\n * Autocomplete — combobox input with filtered suggestions dropdown.\n *\n * Accessibility:\n * - role=\"combobox\" on input with aria-expanded, aria-controls, aria-activedescendant\n * - Dropdown uses role=\"listbox\" with role=\"option\" items\n * - Arrow keys navigate options, Enter selects, Escape closes\n * - Full ARIA combobox pattern per WAI-ARIA 1.2\n */\nexport function Autocomplete({\n options,\n value,\n onChange,\n onInputChange,\n placeholder = 'Search...',\n disabled = false,\n error = false,\n size = 'md',\n loading = false,\n noResultsText = 'No results found',\n className,\n}: AutocompleteProps) {\n const selectedLabel = options.find((o) => o.value === value)?.label ?? '';\n const [inputValue, setInputValue] = useState(selectedLabel);\n const [isOpen, setIsOpen] = useState(false);\n const [focusedIndex, setFocusedIndex] = useState(-1);\n const wrapperRef = useRef<HTMLDivElement>(null);\n const inputRef = useRef<HTMLInputElement>(null);\n const listboxId = useId();\n\n // Sync input with external value changes\n useEffect(() => {\n const label = options.find((o) => o.value === value)?.label ?? '';\n setInputValue(label);\n }, [value, options]);\n\n const filteredOptions = options.filter((opt) =>\n opt.label.toLowerCase().includes(inputValue.toLowerCase()),\n );\n\n const handleInputChange = useCallback(\n (e: React.ChangeEvent<HTMLInputElement>) => {\n const val = e.target.value;\n setInputValue(val);\n setIsOpen(true);\n setFocusedIndex(-1);\n onInputChange?.(val);\n },\n [onInputChange],\n );\n\n const selectOption = useCallback(\n (opt: AutocompleteOption) => {\n setInputValue(opt.label);\n onChange?.(opt.value);\n setIsOpen(false);\n setFocusedIndex(-1);\n inputRef.current?.focus();\n },\n [onChange],\n );\n\n const handleKeyDown = useCallback(\n (e: KeyboardEvent<HTMLInputElement>) => {\n switch (e.key) {\n case 'ArrowDown':\n e.preventDefault();\n if (!isOpen) {\n setIsOpen(true);\n setFocusedIndex(0);\n } else {\n setFocusedIndex((prev) => Math.min(prev + 1, filteredOptions.length - 1));\n }\n break;\n case 'ArrowUp':\n e.preventDefault();\n setFocusedIndex((prev) => Math.max(prev - 1, 0));\n break;\n case 'Enter':\n e.preventDefault();\n if (isOpen && focusedIndex >= 0 && filteredOptions[focusedIndex]) {\n selectOption(filteredOptions[focusedIndex]);\n }\n break;\n case 'Escape':\n e.preventDefault();\n setIsOpen(false);\n setFocusedIndex(-1);\n break;\n }\n },\n [isOpen, focusedIndex, filteredOptions, selectOption],\n );\n\n // Close on outside click\n useEffect(() => {\n if (!isOpen) return;\n const handleClick = (e: MouseEvent) => {\n if (wrapperRef.current && !wrapperRef.current.contains(e.target as Node)) {\n setIsOpen(false);\n }\n };\n document.addEventListener('mousedown', handleClick);\n return () => document.removeEventListener('mousedown', handleClick);\n }, [isOpen]);\n\n const activeDescendant =\n focusedIndex >= 0 && filteredOptions[focusedIndex]\n ? `${listboxId}-option-${focusedIndex}`\n : undefined;\n\n return (\n <div ref={wrapperRef} className={cn(styles.wrapper, styles[size], className)}>\n <input\n ref={inputRef}\n type=\"text\"\n className={cn(styles.input, error && styles.error)}\n value={inputValue}\n onChange={handleInputChange}\n onFocus={() => setIsOpen(true)}\n onKeyDown={handleKeyDown}\n placeholder={placeholder}\n disabled={disabled}\n role=\"combobox\"\n aria-expanded={isOpen}\n aria-haspopup=\"listbox\"\n aria-controls={listboxId}\n aria-activedescendant={activeDescendant}\n aria-autocomplete=\"list\"\n aria-invalid={error || undefined}\n autoComplete=\"off\"\n />\n\n {isOpen && (\n <ul id={listboxId} className={styles.dropdown} role=\"listbox\">\n {loading && (\n <li className={styles.message} aria-live=\"polite\">Loading...</li>\n )}\n {!loading && filteredOptions.length === 0 && (\n <li className={styles.message}>{noResultsText}</li>\n )}\n {!loading &&\n filteredOptions.map((opt, i) => (\n <li\n key={opt.value}\n id={`${listboxId}-option-${i}`}\n className={cn(\n styles.option,\n i === focusedIndex && styles.optionFocused,\n opt.value === value && styles.optionSelected,\n )}\n role=\"option\"\n aria-selected={opt.value === value}\n onClick={() => selectOption(opt)}\n >\n {opt.label}\n </li>\n ))}\n </ul>\n )}\n </div>\n );\n}\n",".wrapper {\n position: relative;\n width: 100%;\n}\n\n.control {\n display: flex;\n align-items: center;\n gap: var(--bazaar-space-2);\n min-height: var(--bazaar-size-control-md);\n border: var(--bazaar-border-width-hairline) var(--bazaar-border-style-default) var(--bazaar-color-border-default);\n border-radius: var(--bazaar-radius-md);\n background-color: var(--bazaar-color-surface-default);\n cursor: pointer;\n transition:\n border-color var(--bazaar-motion-duration-fast) var(--bazaar-motion-easing-standard),\n box-shadow var(--bazaar-motion-duration-fast) var(--bazaar-motion-easing-standard);\n}\n\n.control:hover:not(.disabled) {\n border-color: var(--bazaar-color-border-strong);\n}\n\n.control:focus {\n outline: none;\n border-color: var(--bazaar-color-brand-primary-500);\n box-shadow: var(--bazaar-shadow-focus);\n}\n\n.open {\n border-color: var(--bazaar-color-brand-primary-500);\n box-shadow: var(--bazaar-shadow-focus);\n}\n\n.error {\n border-color: var(--bazaar-color-error-500);\n}\n\n.error:focus,\n.error.open {\n border-color: var(--bazaar-color-error-500);\n box-shadow: 0 0 0 3px rgba(194, 58, 58, 0.2);\n}\n\n.disabled {\n cursor: not-allowed;\n opacity: var(--bazaar-opacity-disabled);\n background-color: var(--bazaar-color-surface-subtle);\n}\n\n/* Size variants */\n.sm .control {\n min-height: var(--bazaar-size-control-sm);\n padding: var(--bazaar-space-1) var(--bazaar-space-3);\n font-size: var(--bazaar-font-size-body-sm);\n}\n\n.md .control {\n min-height: var(--bazaar-size-control-md);\n padding: var(--bazaar-space-1) var(--bazaar-space-4);\n font-size: var(--bazaar-font-size-body-md);\n}\n\n.lg .control {\n min-height: var(--bazaar-size-control-lg);\n padding: var(--bazaar-space-2) var(--bazaar-space-4);\n font-size: var(--bazaar-font-size-body-lg);\n}\n\n.tags {\n display: flex;\n flex-wrap: wrap;\n gap: var(--bazaar-space-1);\n flex: 1;\n align-items: center;\n min-width: 0;\n}\n\n.placeholder {\n color: var(--bazaar-color-text-muted);\n font-family: var(--bazaar-font-family-sans);\n}\n\n.tag {\n display: inline-flex;\n align-items: center;\n gap: var(--bazaar-space-1);\n padding: 2px var(--bazaar-space-2);\n border-radius: var(--bazaar-radius-sm);\n background-color: var(--bazaar-color-surface-subtle);\n border: var(--bazaar-border-width-hairline) var(--bazaar-border-style-default) var(--bazaar-color-border-default);\n font-family: var(--bazaar-font-family-sans);\n font-size: var(--bazaar-font-size-body-sm);\n color: var(--bazaar-color-text-primary);\n line-height: 1.4;\n}\n\n.tagRemove {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 14px;\n height: 14px;\n border: none;\n border-radius: 2px;\n background: transparent;\n color: var(--bazaar-color-text-muted);\n cursor: pointer;\n padding: 0;\n transition: color var(--bazaar-motion-duration-fast) var(--bazaar-motion-easing-standard);\n}\n\n.tagRemove:hover {\n color: var(--bazaar-color-error-500);\n}\n\n.moreTag {\n font-family: var(--bazaar-font-family-sans);\n font-size: var(--bazaar-font-size-body-sm);\n color: var(--bazaar-color-text-muted);\n font-weight: var(--bazaar-font-weight-medium);\n}\n\n.chevron {\n color: var(--bazaar-color-text-muted);\n flex-shrink: 0;\n transition: transform var(--bazaar-motion-duration-fast) var(--bazaar-motion-easing-standard);\n}\n\n.chevronOpen {\n transform: rotate(180deg);\n}\n\n/* Dropdown */\n.dropdown {\n position: absolute;\n top: 100%;\n left: 0;\n right: 0;\n z-index: 10;\n margin-top: var(--bazaar-space-1);\n padding: var(--bazaar-space-1) 0;\n list-style: none;\n border: var(--bazaar-border-width-hairline) var(--bazaar-border-style-default) var(--bazaar-color-border-default);\n border-radius: var(--bazaar-radius-md);\n background-color: var(--bazaar-color-surface-default);\n box-shadow: var(--bazaar-shadow-md);\n max-height: 240px;\n overflow-y: auto;\n}\n\n.option {\n display: flex;\n align-items: center;\n gap: var(--bazaar-space-2);\n padding: var(--bazaar-space-2) var(--bazaar-space-3);\n font-family: var(--bazaar-font-family-sans);\n font-size: var(--bazaar-font-size-body-md);\n color: var(--bazaar-color-text-primary);\n cursor: pointer;\n transition: background-color var(--bazaar-motion-duration-fast) var(--bazaar-motion-easing-standard);\n}\n\n.option:hover,\n.optionFocused {\n background-color: var(--bazaar-color-surface-subtle);\n}\n\n.checkbox {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 16px;\n height: 16px;\n border: var(--bazaar-border-width-hairline) var(--bazaar-border-style-default) var(--bazaar-color-border-default);\n border-radius: var(--bazaar-radius-sm);\n background-color: var(--bazaar-color-surface-default);\n flex-shrink: 0;\n transition:\n background-color var(--bazaar-motion-duration-fast) var(--bazaar-motion-easing-standard),\n border-color var(--bazaar-motion-duration-fast) var(--bazaar-motion-easing-standard);\n}\n\n.checkboxChecked {\n background-color: var(--bazaar-color-brand-primary-500);\n border-color: var(--bazaar-color-brand-primary-500);\n color: var(--bazaar-color-text-inverse);\n}\n","import { useState, useRef, useCallback, useEffect, useId, type KeyboardEvent } from 'react';\nimport { cn } from '../../utils/cn';\nimport styles from './MultiSelect.module.css';\n\nexport interface MultiSelectOption {\n value: string;\n label: string;\n}\n\nexport interface MultiSelectProps {\n /** Available options */\n options: MultiSelectOption[];\n /** Currently selected values */\n value?: string[];\n /** Change handler — receives updated array of selected values */\n onChange?: (value: string[]) => void;\n /** Placeholder text */\n placeholder?: string;\n /** Disabled state */\n disabled?: boolean;\n /** Error state */\n error?: boolean;\n /** Size variant */\n size?: 'sm' | 'md' | 'lg';\n /** Maximum number of tags visible before showing \"+N more\" */\n maxDisplayedTags?: number;\n /** Additional CSS class */\n className?: string;\n}\n\n/**\n * MultiSelect — multi-value select with tags and dropdown checkboxes.\n *\n * Accessibility:\n * - Uses role=\"combobox\" with aria-expanded\n * - Dropdown uses role=\"listbox\" with role=\"option\" items\n * - Tags are removable via keyboard (Backspace removes last)\n * - Escape closes dropdown, focus remains on control\n */\nexport function MultiSelect({\n options,\n value = [],\n onChange,\n placeholder = 'Select...',\n disabled = false,\n error = false,\n size = 'md',\n maxDisplayedTags,\n className,\n}: MultiSelectProps) {\n const [isOpen, setIsOpen] = useState(false);\n const [focusedIndex, setFocusedIndex] = useState(-1);\n const wrapperRef = useRef<HTMLDivElement>(null);\n const listboxId = useId();\n\n const toggle = useCallback(\n (optionValue: string) => {\n if (!onChange) return;\n const next = value.includes(optionValue)\n ? value.filter((v) => v !== optionValue)\n : [...value, optionValue];\n onChange(next);\n },\n [value, onChange],\n );\n\n const removeTag = useCallback(\n (optionValue: string) => {\n onChange?.(value.filter((v) => v !== optionValue));\n },\n [value, onChange],\n );\n\n const handleKeyDown = useCallback(\n (e: KeyboardEvent) => {\n if (disabled) return;\n\n switch (e.key) {\n case 'Enter':\n case ' ':\n e.preventDefault();\n if (isOpen && focusedIndex >= 0) {\n toggle(options[focusedIndex].value);\n } else {\n setIsOpen(!isOpen);\n }\n break;\n case 'Escape':\n e.preventDefault();\n setIsOpen(false);\n break;\n case 'ArrowDown':\n e.preventDefault();\n if (!isOpen) {\n setIsOpen(true);\n setFocusedIndex(0);\n } else {\n setFocusedIndex((prev) => Math.min(prev + 1, options.length - 1));\n }\n break;\n case 'ArrowUp':\n e.preventDefault();\n setFocusedIndex((prev) => Math.max(prev - 1, 0));\n break;\n case 'Backspace':\n if (value.length > 0) {\n onChange?.(value.slice(0, -1));\n }\n break;\n }\n },\n [disabled, isOpen, focusedIndex, options, value, onChange, toggle],\n );\n\n // Close on outside click\n useEffect(() => {\n if (!isOpen) return;\n const handleClick = (e: MouseEvent) => {\n if (wrapperRef.current && !wrapperRef.current.contains(e.target as Node)) {\n setIsOpen(false);\n }\n };\n document.addEventListener('mousedown', handleClick);\n return () => document.removeEventListener('mousedown', handleClick);\n }, [isOpen]);\n\n const selectedLabels = value\n .map((v) => options.find((o) => o.value === v))\n .filter(Boolean) as MultiSelectOption[];\n\n const displayedTags = maxDisplayedTags\n ? selectedLabels.slice(0, maxDisplayedTags)\n : selectedLabels;\n const hiddenCount = maxDisplayedTags\n ? Math.max(0, selectedLabels.length - maxDisplayedTags)\n : 0;\n\n return (\n <div ref={wrapperRef} className={cn(styles.wrapper, styles[size], className)}>\n <div\n className={cn(\n styles.control,\n isOpen && styles.open,\n error && styles.error,\n disabled && styles.disabled,\n )}\n role=\"combobox\"\n aria-expanded={isOpen}\n aria-haspopup=\"listbox\"\n aria-controls={listboxId}\n aria-disabled={disabled}\n tabIndex={disabled ? -1 : 0}\n onClick={() => !disabled && setIsOpen(!isOpen)}\n onKeyDown={handleKeyDown}\n >\n <div className={styles.tags}>\n {displayedTags.length === 0 && (\n <span className={styles.placeholder}>{placeholder}</span>\n )}\n {displayedTags.map((opt) => (\n <span key={opt.value} className={styles.tag}>\n {opt.label}\n <button\n type=\"button\"\n className={styles.tagRemove}\n onClick={(e) => {\n e.stopPropagation();\n removeTag(opt.value);\n }}\n aria-label={`Remove ${opt.label}`}\n tabIndex={-1}\n >\n <svg width=\"10\" height=\"10\" viewBox=\"0 0 10 10\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" aria-hidden=\"true\">\n <path d=\"M2 2l6 6M8 2l-6 6\" />\n </svg>\n </button>\n </span>\n ))}\n {hiddenCount > 0 && (\n <span className={styles.moreTag}>+{hiddenCount} more</span>\n )}\n </div>\n <svg\n className={cn(styles.chevron, isOpen && styles.chevronOpen)}\n width=\"14\"\n height=\"14\"\n viewBox=\"0 0 14 14\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"M3 5l4 4 4-4\" />\n </svg>\n </div>\n\n {isOpen && (\n <ul id={listboxId} className={styles.dropdown} role=\"listbox\" aria-multiselectable=\"true\">\n {options.map((opt, i) => {\n const isSelected = value.includes(opt.value);\n const isFocused = i === focusedIndex;\n return (\n <li\n key={opt.value}\n className={cn(styles.option, isFocused && styles.optionFocused)}\n role=\"option\"\n aria-selected={isSelected}\n onClick={() => toggle(opt.value)}\n >\n <span className={cn(styles.checkbox, isSelected && styles.checkboxChecked)} aria-hidden=\"true\">\n {isSelected && (\n <svg width=\"10\" height=\"10\" viewBox=\"0 0 10 10\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <path d=\"M2 5l2 2 4-4\" />\n </svg>\n )}\n </span>\n {opt.label}\n </li>\n );\n })}\n </ul>\n )}\n </div>\n );\n}\n",".container {\n width: 100%;\n}\n\n.dropzone {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n gap: var(--bazaar-space-2);\n padding: var(--bazaar-space-8) var(--bazaar-space-4);\n border: 2px dashed var(--bazaar-color-border-default);\n border-radius: var(--bazaar-radius-md);\n background-color: var(--bazaar-color-surface-default);\n cursor: pointer;\n transition:\n border-color var(--bazaar-motion-duration-fast) var(--bazaar-motion-easing-standard),\n background-color var(--bazaar-motion-duration-fast) var(--bazaar-motion-easing-standard),\n box-shadow var(--bazaar-motion-duration-fast) var(--bazaar-motion-easing-standard);\n}\n\n.dropzone:hover:not(.disabled) {\n border-color: var(--bazaar-color-border-strong);\n background-color: var(--bazaar-color-surface-subtle);\n}\n\n.dropzone:focus-visible {\n outline: var(--bazaar-border-width-medium) solid var(--bazaar-focus-outline-color);\n outline-offset: var(--bazaar-focus-ring-offset);\n box-shadow: var(--bazaar-shadow-focus);\n}\n\n.dragging {\n border-color: var(--bazaar-color-brand-primary-500);\n background-color: var(--bazaar-color-surface-subtle);\n box-shadow: var(--bazaar-shadow-focus);\n}\n\n.disabled {\n cursor: not-allowed;\n opacity: var(--bazaar-opacity-disabled);\n}\n\n.error {\n border-color: var(--bazaar-color-error-500);\n}\n\n.icon {\n color: var(--bazaar-color-text-muted);\n}\n\n.text {\n font-family: var(--bazaar-font-family-sans);\n font-size: var(--bazaar-font-size-body-md);\n color: var(--bazaar-color-text-primary);\n margin: 0;\n}\n\n.link {\n color: var(--bazaar-color-brand-primary-500);\n font-weight: var(--bazaar-font-weight-medium);\n text-decoration: underline;\n}\n\n.hint {\n font-family: var(--bazaar-font-family-sans);\n font-size: var(--bazaar-font-size-body-sm);\n color: var(--bazaar-color-text-muted);\n margin: 0;\n}\n\n.input {\n position: absolute;\n width: 1px;\n height: 1px;\n padding: 0;\n margin: -1px;\n overflow: hidden;\n clip: rect(0, 0, 0, 0);\n white-space: nowrap;\n border: 0;\n}\n\n/* File list */\n.fileList {\n list-style: none;\n margin: var(--bazaar-space-3) 0 0;\n padding: 0;\n display: flex;\n flex-direction: column;\n gap: var(--bazaar-space-2);\n}\n\n.fileItem {\n display: flex;\n align-items: center;\n gap: var(--bazaar-space-2);\n padding: var(--bazaar-space-2) var(--bazaar-space-3);\n border: var(--bazaar-border-width-hairline) var(--bazaar-border-style-default) var(--bazaar-color-border-default);\n border-radius: var(--bazaar-radius-sm);\n background-color: var(--bazaar-color-surface-subtle);\n font-family: var(--bazaar-font-family-sans);\n font-size: var(--bazaar-font-size-body-sm);\n color: var(--bazaar-color-text-primary);\n}\n\n.fileName {\n flex: 1;\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.fileSize {\n color: var(--bazaar-color-text-muted);\n flex-shrink: 0;\n}\n\n.removeButton {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 20px;\n height: 20px;\n border: none;\n border-radius: var(--bazaar-radius-sm);\n background: transparent;\n color: var(--bazaar-color-text-muted);\n cursor: pointer;\n padding: 0;\n flex-shrink: 0;\n transition: color var(--bazaar-motion-duration-fast) var(--bazaar-motion-easing-standard),\n background-color var(--bazaar-motion-duration-fast) var(--bazaar-motion-easing-standard);\n}\n\n.removeButton:hover {\n color: var(--bazaar-color-error-500);\n background-color: var(--bazaar-color-surface-default);\n}\n","import { useCallback, useRef, useState, type DragEvent, type KeyboardEvent } from 'react';\nimport { cn } from '../../utils/cn';\nimport { HelperText } from '../HelperText';\nimport styles from './FileUpload.module.css';\n\nexport interface FileUploadProps {\n /** Accepted file types (e.g., \".pdf,.jpg,image/*\") */\n accept?: string;\n /** Allow multiple files */\n multiple?: boolean;\n /** Max file size in bytes */\n maxSize?: number;\n /** Callback when files are selected or dropped */\n onFilesSelected?: (files: File[]) => void;\n /** Disabled state */\n disabled?: boolean;\n /** Error message */\n error?: string;\n /** Additional CSS class */\n className?: string;\n}\n\nfunction formatFileSize(bytes: number): string {\n if (bytes < 1024) return `${bytes} B`;\n if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;\n return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;\n}\n\n/**\n * FileUpload — dropzone for file upload with click and drag support.\n *\n * Accessibility:\n * - Keyboard accessible via Enter/Space to open file dialog\n * - Uses role=\"button\" on the dropzone\n * - aria-describedby links to instructions\n * - File list announced after selection\n */\nexport function FileUpload({\n accept,\n multiple = false,\n maxSize,\n onFilesSelected,\n disabled = false,\n error,\n className,\n}: FileUploadProps) {\n const inputRef = useRef<HTMLInputElement>(null);\n const [isDragging, setIsDragging] = useState(false);\n const [files, setFiles] = useState<File[]>([]);\n const [sizeError, setSizeError] = useState<string | null>(null);\n\n const processFiles = useCallback(\n (fileList: FileList | null) => {\n if (!fileList) return;\n const selected = Array.from(fileList);\n\n if (maxSize) {\n const oversized = selected.filter((f) => f.size > maxSize);\n if (oversized.length > 0) {\n setSizeError(`File(s) exceed maximum size of ${formatFileSize(maxSize)}`);\n return;\n }\n }\n\n setSizeError(null);\n setFiles(selected);\n onFilesSelected?.(selected);\n },\n [maxSize, onFilesSelected],\n );\n\n const handleClick = () => {\n if (!disabled) inputRef.current?.click();\n };\n\n const handleKeyDown = (e: KeyboardEvent) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n handleClick();\n }\n };\n\n const handleDragOver = (e: DragEvent) => {\n e.preventDefault();\n if (!disabled) setIsDragging(true);\n };\n\n const handleDragLeave = (e: DragEvent) => {\n e.preventDefault();\n setIsDragging(false);\n };\n\n const handleDrop = (e: DragEvent) => {\n e.preventDefault();\n setIsDragging(false);\n if (!disabled) processFiles(e.dataTransfer.files);\n };\n\n const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {\n processFiles(e.target.files);\n };\n\n const removeFile = (index: number) => {\n const next = files.filter((_, i) => i !== index);\n setFiles(next);\n onFilesSelected?.(next);\n };\n\n const displayError = error || sizeError;\n\n return (\n <div className={cn(styles.container, className)}>\n <div\n className={cn(\n styles.dropzone,\n isDragging && styles.dragging,\n disabled && styles.disabled,\n displayError && styles.error,\n )}\n role=\"button\"\n tabIndex={disabled ? -1 : 0}\n onClick={handleClick}\n onKeyDown={handleKeyDown}\n onDragOver={handleDragOver}\n onDragLeave={handleDragLeave}\n onDrop={handleDrop}\n aria-label={`Upload file${multiple ? 's' : ''}`}\n aria-disabled={disabled}\n >\n <svg\n className={styles.icon}\n width=\"32\"\n height=\"32\"\n viewBox=\"0 0 32 32\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"M16 20V8M16 8l-5 5M16 8l5 5\" />\n <path d=\"M4 22v4a2 2 0 002 2h20a2 2 0 002-2v-4\" />\n </svg>\n <p className={styles.text}>\n <span className={styles.link}>Click to upload</span> or drag and drop\n </p>\n {accept && (\n <p className={styles.hint}>{accept.replace(/,/g, ', ')}</p>\n )}\n {maxSize && (\n <p className={styles.hint}>Max size: {formatFileSize(maxSize)}</p>\n )}\n </div>\n\n <input\n ref={inputRef}\n type=\"file\"\n className={styles.input}\n accept={accept}\n multiple={multiple}\n onChange={handleInputChange}\n disabled={disabled}\n tabIndex={-1}\n aria-hidden=\"true\"\n />\n\n {files.length > 0 && (\n <ul className={styles.fileList} aria-label=\"Selected files\">\n {files.map((file, i) => (\n <li key={`${file.name}-${i}`} className={styles.fileItem}>\n <svg\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"1.5\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"M9 1H4a1 1 0 00-1 1v12a1 1 0 001 1h8a1 1 0 001-1V5L9 1z\" />\n <path d=\"M9 1v4h4\" />\n </svg>\n <span className={styles.fileName}>{file.name}</span>\n <span className={styles.fileSize}>{formatFileSize(file.size)}</span>\n <button\n type=\"button\"\n className={styles.removeButton}\n onClick={() => removeFile(i)}\n aria-label={`Remove ${file.name}`}\n >\n <svg width=\"12\" height=\"12\" viewBox=\"0 0 12 12\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" aria-hidden=\"true\">\n <path d=\"M2 2l8 8M10 2l-8 8\" />\n </svg>\n </button>\n </li>\n ))}\n </ul>\n )}\n\n {displayError && (\n <HelperText error>{displayError}</HelperText>\n )}\n </div>\n );\n}\n",".wrapper {\n display: inline-flex;\n gap: var(--bazaar-space-2);\n}\n\n.digit {\n width: 44px;\n height: 52px;\n border: var(--bazaar-border-width-hairline) var(--bazaar-border-style-default) var(--bazaar-color-border-default);\n border-radius: var(--bazaar-radius-md);\n background-color: var(--bazaar-color-surface-default);\n color: var(--bazaar-color-text-primary);\n font-family: var(--bazaar-font-family-sans);\n font-size: var(--bazaar-font-size-body-lg);\n font-weight: var(--bazaar-font-weight-medium);\n text-align: center;\n caret-color: var(--bazaar-color-brand-primary-500);\n transition:\n border-color var(--bazaar-motion-duration-fast) var(--bazaar-motion-easing-standard),\n box-shadow var(--bazaar-motion-duration-fast) var(--bazaar-motion-easing-standard);\n}\n\n.digit:hover:not(:disabled):not(:focus) {\n border-color: var(--bazaar-color-border-strong);\n}\n\n.digit:focus {\n outline: none;\n border-color: var(--bazaar-color-brand-primary-500);\n box-shadow: var(--bazaar-shadow-focus);\n}\n\n.digit:disabled {\n cursor: not-allowed;\n opacity: var(--bazaar-opacity-disabled);\n background-color: var(--bazaar-color-surface-subtle);\n}\n\n/* Error */\n.error .digit {\n border-color: var(--bazaar-color-error-500);\n}\n\n.error .digit:focus {\n border-color: var(--bazaar-color-error-500);\n box-shadow: 0 0 0 3px rgba(194, 58, 58, 0.2);\n}\n\n/* Disabled */\n.disabled {\n opacity: var(--bazaar-opacity-disabled);\n}\n","import { useCallback, useRef, useEffect, type KeyboardEvent, type ClipboardEvent } from 'react';\nimport { cn } from '../../utils/cn';\nimport styles from './OTPInput.module.css';\n\nexport interface OTPInputProps {\n /** Number of OTP digits */\n length?: number;\n /** Current value string */\n value?: string;\n /** Change handler — receives the full OTP string */\n onChange?: (value: string) => void;\n /** Error state */\n error?: boolean;\n /** Disabled state */\n disabled?: boolean;\n /** Auto-focus first input on mount */\n autoFocus?: boolean;\n /** Additional CSS class */\n className?: string;\n}\n\n/**\n * OTPInput — code/OTP input with separate boxes that auto-advance.\n *\n * Accessibility:\n * - Each digit input has aria-label describing its position\n * - Supports keyboard navigation (Backspace moves to previous)\n * - Paste support fills all boxes at once\n * - Error state communicated via aria-invalid\n */\nexport function OTPInput({\n length = 6,\n value = '',\n onChange,\n error = false,\n disabled = false,\n autoFocus = false,\n className,\n}: OTPInputProps) {\n const inputRefs = useRef<(HTMLInputElement | null)[]>([]);\n\n useEffect(() => {\n if (autoFocus && inputRefs.current[0]) {\n inputRefs.current[0].focus();\n }\n }, [autoFocus]);\n\n const focusInput = useCallback((index: number) => {\n if (index >= 0 && index < length) {\n inputRefs.current[index]?.focus();\n inputRefs.current[index]?.select();\n }\n }, [length]);\n\n const updateValue = useCallback(\n (newValue: string) => {\n onChange?.(newValue.slice(0, length));\n },\n [onChange, length],\n );\n\n const handleInput = useCallback(\n (index: number, digit: string) => {\n if (!/^\\d$/.test(digit)) return;\n\n const chars = value.split('');\n // Fill any gaps with empty strings\n while (chars.length < length) chars.push('');\n chars[index] = digit;\n updateValue(chars.join(''));\n\n // Auto-advance to next input\n if (index < length - 1) {\n focusInput(index + 1);\n }\n },\n [value, length, updateValue, focusInput],\n );\n\n const handleKeyDown = useCallback(\n (index: number, e: KeyboardEvent<HTMLInputElement>) => {\n if (e.key === 'Backspace') {\n e.preventDefault();\n const chars = value.split('');\n while (chars.length < length) chars.push('');\n\n if (chars[index]) {\n chars[index] = '';\n updateValue(chars.join(''));\n } else if (index > 0) {\n chars[index - 1] = '';\n updateValue(chars.join(''));\n focusInput(index - 1);\n }\n } else if (e.key === 'ArrowLeft') {\n e.preventDefault();\n focusInput(index - 1);\n } else if (e.key === 'ArrowRight') {\n e.preventDefault();\n focusInput(index + 1);\n }\n },\n [value, length, updateValue, focusInput],\n );\n\n const handlePaste = useCallback(\n (e: ClipboardEvent<HTMLInputElement>) => {\n e.preventDefault();\n const pasted = e.clipboardData.getData('text').replace(/\\D/g, '').slice(0, length);\n if (pasted) {\n updateValue(pasted);\n focusInput(Math.min(pasted.length, length - 1));\n }\n },\n [length, updateValue, focusInput],\n );\n\n return (\n <div className={cn(styles.wrapper, error && styles.error, disabled && styles.disabled, className)} role=\"group\" aria-label=\"One-time password\">\n {Array.from({ length }, (_, i) => (\n <input\n key={i}\n ref={(el) => { inputRefs.current[i] = el; }}\n type=\"text\"\n inputMode=\"numeric\"\n autoComplete=\"one-time-code\"\n maxLength={1}\n className={styles.digit}\n value={value[i] || ''}\n onChange={(e) => {\n const v = e.target.value;\n if (v.length <= 1) handleInput(i, v);\n }}\n onKeyDown={(e) => handleKeyDown(i, e)}\n onPaste={handlePaste}\n onFocus={(e) => e.target.select()}\n disabled={disabled}\n aria-label={`Digit ${i + 1} of ${length}`}\n aria-invalid={error || undefined}\n />\n ))}\n </div>\n );\n}\n",".picker {\n display: inline-flex;\n flex-direction: column;\n gap: var(--bazaar-space-3);\n font-family: var(--bazaar-font-family-sans);\n}\n\n.disabled {\n opacity: var(--bazaar-opacity-disabled);\n pointer-events: none;\n}\n\n.label {\n font-size: var(--bazaar-font-size-body-sm);\n font-weight: var(--bazaar-font-weight-medium);\n color: var(--bazaar-color-text-primary);\n}\n\n.preview {\n display: flex;\n align-items: center;\n gap: var(--bazaar-space-2);\n position: relative;\n}\n\n.swatch {\n border: var(--bazaar-border-width-hairline) var(--bazaar-border-style-default) var(--bazaar-color-border-default);\n cursor: pointer;\n flex-shrink: 0;\n transition: box-shadow var(--bazaar-motion-duration-fast) var(--bazaar-motion-easing-standard);\n}\n\n.sm .swatch { width: 24px; height: 24px; border-radius: var(--bazaar-radius-sm); }\n.md .swatch { width: 32px; height: 32px; border-radius: var(--bazaar-radius-md); }\n\n.swatch:hover {\n box-shadow: var(--bazaar-shadow-sm);\n}\n\n.swatch:focus-visible {\n outline: var(--bazaar-border-width-medium) solid var(--bazaar-focus-outline-color);\n outline-offset: 2px;\n}\n\n.hex {\n font-size: var(--bazaar-font-size-body-sm);\n font-family: var(--bazaar-font-family-mono, monospace);\n color: var(--bazaar-color-text-secondary);\n min-width: 68px;\n}\n\n.nativeInput {\n position: absolute;\n opacity: 0;\n width: 0;\n height: 0;\n pointer-events: none;\n}\n\n.swatchGrid {\n display: flex;\n flex-wrap: wrap;\n gap: var(--bazaar-space-1);\n}\n\n.swatchOption {\n width: 24px;\n height: 24px;\n border-radius: var(--bazaar-radius-sm);\n border: var(--bazaar-border-width-hairline) var(--bazaar-border-style-default) var(--bazaar-color-border-default);\n cursor: pointer;\n transition:\n transform var(--bazaar-motion-duration-fast) var(--bazaar-motion-easing-standard),\n box-shadow var(--bazaar-motion-duration-fast) var(--bazaar-motion-easing-standard);\n}\n\n.swatchOption:hover {\n transform: scale(1.15);\n}\n\n.swatchOption:focus-visible {\n outline: var(--bazaar-border-width-medium) solid var(--bazaar-focus-outline-color);\n outline-offset: 2px;\n}\n\n.swatchOption.selected {\n box-shadow: 0 0 0 2px var(--bazaar-color-surface-default), 0 0 0 4px var(--bazaar-color-brand-primary-500);\n}\n","import { useState, useRef, useEffect, useCallback, forwardRef, type HTMLAttributes } from 'react';\nimport { cn } from '../../utils/cn';\nimport styles from './ColorPicker.module.css';\n\nexport interface ColorPickerProps extends Omit<HTMLAttributes<HTMLDivElement>, 'onChange'> {\n /** Current color value (hex) */\n value?: string;\n /** Called when color changes */\n onChange?: (color: string) => void;\n /** Predefined color swatches */\n swatches?: string[];\n /** Label */\n label?: string;\n /** Disabled state */\n disabled?: boolean;\n /** Size variant */\n size?: 'sm' | 'md';\n}\n\nconst defaultSwatches = [\n '#0A2540', '#1A73E8', '#0D9488', '#16A34A', '#EAB308',\n '#F97316', '#EF4444', '#A855F7', '#EC4899', '#6B7280',\n '#374151', '#FFFFFF',\n];\n\n/**\n * ColorPicker — color selection input with swatch palette and native picker.\n *\n * Provides a swatch grid for quick selection plus a native `<input type=\"color\">`\n * fallback for custom colors.\n *\n * Accessibility:\n * - Swatch buttons have aria-label with hex value\n * - Selected swatch indicated with aria-pressed\n * - Native color input provides full keyboard + assistive tech support\n */\nexport const ColorPicker = forwardRef<HTMLDivElement, ColorPickerProps>(\n (\n {\n value = '#0A2540',\n onChange,\n swatches = defaultSwatches,\n label,\n disabled = false,\n size = 'md',\n className,\n ...props\n },\n ref,\n ) => {\n const [currentColor, setCurrentColor] = useState(value);\n const nativeRef = useRef<HTMLInputElement>(null);\n\n useEffect(() => {\n setCurrentColor(value);\n }, [value]);\n\n const handleChange = useCallback(\n (color: string) => {\n if (disabled) return;\n setCurrentColor(color);\n onChange?.(color);\n },\n [disabled, onChange],\n );\n\n return (\n <div\n ref={ref}\n className={cn(styles.picker, styles[size], disabled && styles.disabled, className)}\n {...props}\n >\n {label && <span className={styles.label}>{label}</span>}\n\n <div className={styles.preview}>\n <button\n type=\"button\"\n className={styles.swatch}\n style={{ backgroundColor: currentColor }}\n onClick={() => nativeRef.current?.click()}\n disabled={disabled}\n aria-label={`Selected color: ${currentColor}`}\n />\n <span className={styles.hex}>{currentColor.toUpperCase()}</span>\n <input\n ref={nativeRef}\n type=\"color\"\n className={styles.nativeInput}\n value={currentColor}\n onChange={(e) => handleChange(e.target.value)}\n disabled={disabled}\n tabIndex={-1}\n aria-hidden=\"true\"\n />\n </div>\n\n {swatches.length > 0 && (\n <div className={styles.swatchGrid} role=\"listbox\" aria-label=\"Color swatches\">\n {swatches.map((color) => (\n <button\n key={color}\n type=\"button\"\n role=\"option\"\n className={cn(\n styles.swatchOption,\n currentColor.toLowerCase() === color.toLowerCase() && styles.selected,\n )}\n style={{ backgroundColor: color }}\n onClick={() => handleChange(color)}\n disabled={disabled}\n aria-label={color}\n aria-selected={currentColor.toLowerCase() === color.toLowerCase()}\n />\n ))}\n </div>\n )}\n </div>\n );\n },\n);\n\nColorPicker.displayName = 'ColorPicker';\n",".rating {\n display: inline-flex;\n align-items: center;\n gap: var(--bazaar-space-1);\n font-family: var(--bazaar-font-family-sans);\n}\n\n.readOnly {\n pointer-events: none;\n}\n\n.disabled {\n opacity: var(--bazaar-opacity-disabled);\n pointer-events: none;\n}\n\n/* Sizes */\n.sm .star { font-size: 16px; }\n.md .star { font-size: 24px; }\n.lg .star { font-size: 32px; }\n\n/* Star button */\n.star {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n padding: 0;\n border: none;\n background: transparent;\n cursor: pointer;\n color: var(--bazaar-color-border-default);\n transition: color var(--bazaar-motion-duration-fast) var(--bazaar-motion-easing-standard),\n transform var(--bazaar-motion-duration-fast) var(--bazaar-motion-easing-standard);\n}\n\n.star:hover:not(:disabled) {\n transform: scale(1.15);\n}\n\n.star:focus-visible {\n outline: var(--bazaar-border-width-medium) solid var(--bazaar-focus-outline-color);\n outline-offset: 2px;\n border-radius: var(--bazaar-radius-sm);\n}\n\n.star.filled {\n color: var(--bazaar-color-warning-500, #EAB308);\n}\n\n.star:disabled {\n cursor: default;\n}\n","import { useState, useCallback, forwardRef, type HTMLAttributes, type KeyboardEvent } from 'react';\nimport { cn } from '../../utils/cn';\nimport styles from './Rating.module.css';\n\nexport interface RatingProps extends Omit<HTMLAttributes<HTMLDivElement>, 'onChange'> {\n /** Current rating value (0 = no rating) */\n value?: number;\n /** Called when rating changes */\n onChange?: (value: number) => void;\n /** Maximum rating value */\n max?: number;\n /** Size variant */\n size?: 'sm' | 'md' | 'lg';\n /** Whether the rating is read-only */\n readOnly?: boolean;\n /** Disabled state */\n disabled?: boolean;\n /** Label for accessibility */\n label?: string;\n /** Custom icon renderer — receives filled state */\n renderIcon?: (filled: boolean, index: number) => React.ReactNode;\n}\n\nconst StarIcon = ({ filled }: { filled: boolean }) => (\n <svg\n width=\"1em\"\n height=\"1em\"\n viewBox=\"0 0 24 24\"\n fill={filled ? 'currentColor' : 'none'}\n stroke=\"currentColor\"\n strokeWidth=\"1.5\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n >\n <polygon points=\"12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2\" />\n </svg>\n);\n\n/**\n * Rating — star-based rating input with keyboard navigation.\n *\n * Supports custom max values, read-only display, and custom icon rendering.\n *\n * Accessibility:\n * - Uses radio group pattern with arrow key navigation\n * - Each star has aria-label with its value\n * - Supports keyboard: ArrowLeft/Right to navigate, Enter/Space to select\n */\nexport const Rating = forwardRef<HTMLDivElement, RatingProps>(\n (\n {\n value = 0,\n onChange,\n max = 5,\n size = 'md',\n readOnly = false,\n disabled = false,\n label = 'Rating',\n renderIcon,\n className,\n ...props\n },\n ref,\n ) => {\n const [hovered, setHovered] = useState<number | null>(null);\n const interactive = !readOnly && !disabled;\n\n const handleSelect = useCallback(\n (star: number) => {\n if (!interactive) return;\n // Toggle off if clicking same value\n onChange?.(star === value ? 0 : star);\n },\n [interactive, onChange, value],\n );\n\n const handleKeyDown = useCallback(\n (e: KeyboardEvent<HTMLDivElement>) => {\n if (!interactive) return;\n\n let next = value;\n if (e.key === 'ArrowRight' || e.key === 'ArrowUp') {\n e.preventDefault();\n next = Math.min(value + 1, max);\n } else if (e.key === 'ArrowLeft' || e.key === 'ArrowDown') {\n e.preventDefault();\n next = Math.max(value - 1, 0);\n }\n\n if (next !== value) {\n onChange?.(next);\n }\n },\n [interactive, value, max, onChange],\n );\n\n const displayValue = hovered ?? value;\n\n return (\n <div\n ref={ref}\n className={cn(\n styles.rating,\n styles[size],\n readOnly && styles.readOnly,\n disabled && styles.disabled,\n className,\n )}\n role=\"radiogroup\"\n aria-label={label}\n tabIndex={interactive ? 0 : undefined}\n onKeyDown={interactive ? handleKeyDown : undefined}\n {...props}\n >\n {Array.from({ length: max }, (_, i) => {\n const starValue = i + 1;\n const filled = starValue <= displayValue;\n\n return (\n <button\n key={starValue}\n type=\"button\"\n role=\"radio\"\n className={cn(styles.star, filled && styles.filled)}\n aria-checked={starValue === value}\n aria-label={`${starValue} of ${max}`}\n tabIndex={-1}\n disabled={disabled || readOnly}\n onClick={() => handleSelect(starValue)}\n onMouseEnter={() => interactive && setHovered(starValue)}\n onMouseLeave={() => interactive && setHovered(null)}\n >\n {renderIcon ? renderIcon(filled, i) : <StarIcon filled={filled} />}\n </button>\n );\n })}\n </div>\n );\n },\n);\n\nRating.displayName = 'Rating';\n",".wrapper {\n display: flex;\n flex-direction: column;\n gap: var(--bazaar-space-2);\n font-family: var(--bazaar-font-family-sans);\n}\n\n.disabled {\n opacity: var(--bazaar-opacity-disabled);\n pointer-events: none;\n}\n\n.label {\n font-size: var(--bazaar-font-size-body-sm);\n font-weight: var(--bazaar-font-weight-medium);\n color: var(--bazaar-color-text-primary);\n}\n\n.container {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: var(--bazaar-space-1);\n border: var(--bazaar-border-width-hairline) var(--bazaar-border-style-default) var(--bazaar-color-border-default);\n border-radius: var(--bazaar-radius-md);\n background: var(--bazaar-color-surface-default);\n cursor: text;\n transition: border-color var(--bazaar-motion-duration-fast) var(--bazaar-motion-easing-standard),\n box-shadow var(--bazaar-motion-duration-fast) var(--bazaar-motion-easing-standard);\n}\n\n.sm .container { padding: var(--bazaar-space-1) var(--bazaar-space-2); min-height: 32px; }\n.md .container { padding: var(--bazaar-space-2) var(--bazaar-space-3); min-height: 40px; }\n\n.container:focus-within {\n border-color: var(--bazaar-color-brand-primary-500);\n box-shadow: 0 0 0 3px var(--bazaar-focus-ring-color, rgba(26, 115, 232, 0.15));\n}\n\n.error .container {\n border-color: var(--bazaar-color-error-500);\n}\n\n.error .container:focus-within {\n box-shadow: 0 0 0 3px rgba(239, 68, 68, 0.15);\n}\n\n/* Tag chip */\n.tag {\n display: inline-flex;\n align-items: center;\n gap: var(--bazaar-space-1);\n background: var(--bazaar-color-neutral-100);\n border-radius: var(--bazaar-radius-full);\n max-width: 200px;\n}\n\n.sm .tag { padding: 1px var(--bazaar-space-2); font-size: var(--bazaar-font-size-caption); }\n.md .tag { padding: 2px var(--bazaar-space-2); font-size: var(--bazaar-font-size-body-sm); }\n\n.tagText {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n color: var(--bazaar-color-text-primary);\n}\n\n.remove {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n padding: 0;\n border: none;\n background: transparent;\n color: var(--bazaar-color-text-muted);\n cursor: pointer;\n border-radius: var(--bazaar-radius-full);\n flex-shrink: 0;\n transition: color var(--bazaar-motion-duration-fast) var(--bazaar-motion-easing-standard);\n}\n\n.remove:hover {\n color: var(--bazaar-color-text-primary);\n}\n\n/* Inline text input */\n.input {\n flex: 1;\n min-width: 80px;\n border: none;\n background: transparent;\n outline: none;\n font-family: var(--bazaar-font-family-sans);\n color: var(--bazaar-color-text-primary);\n}\n\n.sm .input { font-size: var(--bazaar-font-size-caption); }\n.md .input { font-size: var(--bazaar-font-size-body-sm); }\n\n.input::placeholder {\n color: var(--bazaar-color-text-muted);\n}\n\n/* Count indicator */\n.count {\n font-size: var(--bazaar-font-size-caption);\n color: var(--bazaar-color-text-muted);\n align-self: flex-end;\n}\n","import {\n useState,\n useRef,\n useCallback,\n forwardRef,\n type HTMLAttributes,\n type KeyboardEvent,\n} from 'react';\nimport { cn } from '../../utils/cn';\nimport styles from './TagInput.module.css';\n\nexport interface TagInputProps extends Omit<HTMLAttributes<HTMLDivElement>, 'onChange'> {\n /** Current tag values */\n value?: string[];\n /** Called when tags change */\n onChange?: (tags: string[]) => void;\n /** Placeholder for the text input */\n placeholder?: string;\n /** Label */\n label?: string;\n /** Maximum number of tags allowed */\n max?: number;\n /** Size variant */\n size?: 'sm' | 'md';\n /** Disabled state */\n disabled?: boolean;\n /** Error state */\n error?: boolean;\n /** Characters that trigger tag creation (default: Enter, comma) */\n separators?: string[];\n /** Whether duplicates are allowed */\n allowDuplicates?: boolean;\n}\n\nconst RemoveIcon = () => (\n <svg\n width=\"12\"\n height=\"12\"\n viewBox=\"0 0 12 12\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"1.75\"\n strokeLinecap=\"round\"\n aria-hidden=\"true\"\n >\n <line x1=\"3\" y1=\"3\" x2=\"9\" y2=\"9\" />\n <line x1=\"9\" y1=\"3\" x2=\"3\" y2=\"9\" />\n </svg>\n);\n\n/**\n * TagInput — multi-value text input that creates tag chips.\n *\n * Users type text and press Enter or comma to create tags.\n * Tags can be removed with Backspace or by clicking the remove button.\n *\n * Accessibility:\n * - Tags have aria-label and remove button with aria-label\n * - Backspace removes last tag when input is empty\n * - Screen readers announce tag count via aria-describedby\n */\nexport const TagInput = forwardRef<HTMLDivElement, TagInputProps>(\n (\n {\n value = [],\n onChange,\n placeholder = 'Add a tag…',\n label,\n max,\n size = 'md',\n disabled = false,\n error = false,\n separators = ['Enter', ','],\n allowDuplicates = false,\n className,\n ...props\n },\n ref,\n ) => {\n const [inputValue, setInputValue] = useState('');\n const inputRef = useRef<HTMLInputElement>(null);\n\n const addTag = useCallback(\n (raw: string) => {\n const tag = raw.trim();\n if (!tag) return;\n if (!allowDuplicates && value.includes(tag)) return;\n if (max && value.length >= max) return;\n\n onChange?.([...value, tag]);\n setInputValue('');\n },\n [value, onChange, allowDuplicates, max],\n );\n\n const removeTag = useCallback(\n (index: number) => {\n onChange?.(value.filter((_, i) => i !== index));\n },\n [value, onChange],\n );\n\n const handleKeyDown = useCallback(\n (e: KeyboardEvent<HTMLInputElement>) => {\n if (separators.includes(e.key)) {\n e.preventDefault();\n addTag(inputValue);\n } else if (e.key === 'Backspace' && inputValue === '' && value.length > 0) {\n removeTag(value.length - 1);\n }\n },\n [separators, inputValue, addTag, removeTag, value.length],\n );\n\n const handlePaste = useCallback(\n (e: React.ClipboardEvent<HTMLInputElement>) => {\n const text = e.clipboardData.getData('text');\n if (separators.includes(',') && text.includes(',')) {\n e.preventDefault();\n const parts = text.split(',');\n let updated = [...value];\n for (const part of parts) {\n const tag = part.trim();\n if (!tag) continue;\n if (!allowDuplicates && updated.includes(tag)) continue;\n if (max && updated.length >= max) break;\n updated = [...updated, tag];\n }\n onChange?.(updated);\n }\n },\n [value, onChange, separators, allowDuplicates, max],\n );\n\n const atLimit = max !== undefined && value.length >= max;\n\n return (\n <div\n ref={ref}\n className={cn(\n styles.wrapper,\n styles[size],\n error && styles.error,\n disabled && styles.disabled,\n className,\n )}\n {...props}\n >\n {label && <span className={styles.label}>{label}</span>}\n <div\n className={styles.container}\n onClick={() => inputRef.current?.focus()}\n role=\"presentation\"\n >\n {value.map((tag, i) => (\n <span key={`${tag}-${i}`} className={styles.tag}>\n <span className={styles.tagText}>{tag}</span>\n {!disabled && (\n <button\n type=\"button\"\n className={styles.remove}\n onClick={(e) => {\n e.stopPropagation();\n removeTag(i);\n }}\n aria-label={`Remove ${tag}`}\n tabIndex={-1}\n >\n <RemoveIcon />\n </button>\n )}\n </span>\n ))}\n {!atLimit && (\n <input\n ref={inputRef}\n type=\"text\"\n className={styles.input}\n value={inputValue}\n onChange={(e) => setInputValue(e.target.value)}\n onKeyDown={handleKeyDown}\n onPaste={handlePaste}\n placeholder={value.length === 0 ? placeholder : ''}\n disabled={disabled}\n aria-label={label ?? 'Add tag'}\n />\n )}\n </div>\n {max !== undefined && (\n <span className={styles.count} aria-live=\"polite\">\n {value.length}/{max}\n </span>\n )}\n </div>\n );\n },\n);\n\nTagInput.displayName = 'TagInput';\n",".avatar {\n position: relative;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n border-radius: var(--bazaar-radius-full);\n background-color: var(--bazaar-color-neutral-100);\n color: var(--bazaar-color-text-secondary);\n font-family: var(--bazaar-font-family-sans);\n font-weight: var(--bazaar-font-weight-semibold);\n overflow: hidden;\n flex-shrink: 0;\n}\n\n/* Sizes */\n.sm {\n width: 28px;\n height: 28px;\n font-size: 11px;\n}\n\n.md {\n width: 36px;\n height: 36px;\n font-size: 13px;\n}\n\n.lg {\n width: 48px;\n height: 48px;\n font-size: 16px;\n}\n\n.xl {\n width: 64px;\n height: 64px;\n font-size: 20px;\n}\n\n.image {\n width: 100%;\n height: 100%;\n object-fit: cover;\n border-radius: var(--bazaar-radius-full);\n}\n\n.initials {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 100%;\n height: 100%;\n user-select: none;\n}\n\n/* Status dot */\n.status {\n position: absolute;\n bottom: 0;\n right: 0;\n width: 25%;\n height: 25%;\n min-width: 8px;\n min-height: 8px;\n border-radius: var(--bazaar-radius-full);\n border: 2px solid var(--bazaar-color-surface-default);\n box-sizing: content-box;\n}\n\n.status-active {\n background-color: var(--bazaar-color-success-500);\n}\n\n.status-inactive {\n background-color: var(--bazaar-color-neutral-300);\n}\n\n.status-busy {\n background-color: var(--bazaar-color-error-500);\n}\n\n.status-away {\n background-color: var(--bazaar-color-warning-500);\n}\n\n.srOnly {\n position: absolute;\n width: 1px;\n height: 1px;\n padding: 0;\n margin: -1px;\n overflow: hidden;\n clip: rect(0, 0, 0, 0);\n white-space: nowrap;\n border-width: 0;\n}\n","import { useState, type HTMLAttributes } from 'react';\nimport { cn } from '../../utils/cn';\nimport styles from './Avatar.module.css';\n\nexport interface AvatarProps extends HTMLAttributes<HTMLSpanElement> {\n /** Image source URL */\n src?: string;\n /** Alt text for the image */\n alt?: string;\n /** Full name used to generate initials fallback */\n name?: string;\n /** Size variant */\n size?: 'sm' | 'md' | 'lg' | 'xl';\n /** Optional status dot overlay */\n status?: 'active' | 'inactive' | 'busy' | 'away';\n}\n\nfunction getInitials(name: string): string {\n const parts = name.trim().split(/\\s+/);\n if (parts.length === 0) return '';\n if (parts.length === 1) return parts[0][0]?.toUpperCase() ?? '';\n return (parts[0][0] + parts[parts.length - 1][0]).toUpperCase();\n}\n\n/**\n * Avatar — circular user image with initials fallback and optional status.\n *\n * Accessibility:\n * - Image includes alt text when src is provided\n * - Initials fallback uses aria-label with the full name\n * - Status dot includes a visually-hidden label\n * - Healthcare note: use avatars to identify care team members,\n * patients, and providers in clinical workflows\n */\nexport function Avatar({\n src,\n alt,\n name,\n size = 'md',\n status,\n className,\n ...props\n}: AvatarProps) {\n const [imgError, setImgError] = useState(false);\n const showImage = src && !imgError;\n const initials = name ? getInitials(name) : '';\n\n return (\n <span\n className={cn(styles.avatar, styles[size], className)}\n role=\"img\"\n aria-label={alt ?? name ?? 'Avatar'}\n {...props}\n >\n {showImage ? (\n <img\n src={src}\n alt={alt ?? name ?? 'Avatar'}\n className={styles.image}\n onError={() => setImgError(true)}\n />\n ) : (\n <span className={styles.initials} aria-hidden=\"true\">\n {initials}\n </span>\n )}\n {status && (\n <span className={cn(styles.status, styles[`status-${status}`])} aria-hidden=\"true\">\n <span className={styles.srOnly}>{status}</span>\n </span>\n )}\n </span>\n );\n}\n",".badge {\n display: inline-flex;\n align-items: center;\n gap: var(--bazaar-space-1);\n padding: 2px var(--bazaar-space-2);\n border-radius: var(--bazaar-radius-full);\n font-family: var(--bazaar-font-family-sans);\n font-size: var(--bazaar-font-size-caption);\n font-weight: var(--bazaar-font-weight-semibold);\n line-height: var(--bazaar-line-height-caption);\n white-space: nowrap;\n}\n\n.neutral {\n background-color: var(--bazaar-color-neutral-100);\n color: var(--bazaar-color-text-secondary);\n border: var(--bazaar-border-width-hairline) var(--bazaar-border-style-default) var(--bazaar-color-neutral-200);\n}\n\n.success {\n background-color: var(--bazaar-color-success-50);\n color: var(--bazaar-color-success-700);\n border: var(--bazaar-border-width-hairline) var(--bazaar-border-style-default) var(--bazaar-color-border-success);\n}\n\n.warning {\n background-color: var(--bazaar-color-warning-50);\n color: var(--bazaar-color-warning-700);\n border: var(--bazaar-border-width-hairline) var(--bazaar-border-style-default) var(--bazaar-color-border-warning);\n}\n\n.error {\n background-color: var(--bazaar-color-error-50);\n color: var(--bazaar-color-error-700);\n border: var(--bazaar-border-width-hairline) var(--bazaar-border-style-default) var(--bazaar-color-border-error);\n}\n\n.info {\n background-color: var(--bazaar-color-info-50);\n color: var(--bazaar-color-info-700);\n border: var(--bazaar-border-width-hairline) var(--bazaar-border-style-default) var(--bazaar-color-border-brand);\n}\n","import { type HTMLAttributes } from 'react';\nimport { cn } from '../../utils/cn';\nimport styles from './Badge.module.css';\n\nexport interface BadgeProps extends HTMLAttributes<HTMLSpanElement> {\n /** Status variant */\n status?: 'neutral' | 'success' | 'warning' | 'error' | 'info';\n}\n\n/**\n * Badge / StatusChip — small label for status or metadata.\n *\n * Accessibility:\n * - Always include meaningful text content (not color alone)\n * - In healthcare contexts, pair with text like \"Active\", \"Pending\",\n * \"Critical\" rather than relying on color to communicate status\n */\nexport function Badge({ status = 'neutral', className, children, ...props }: BadgeProps) {\n return (\n <span className={cn(styles.badge, styles[status], className)} {...props}>\n {children}\n </span>\n );\n}\n",".chip {\n display: inline-flex;\n align-items: center;\n gap: var(--bazaar-space-1);\n border-radius: var(--bazaar-radius-full);\n font-family: var(--bazaar-font-family-sans);\n font-weight: var(--bazaar-font-weight-medium);\n white-space: nowrap;\n vertical-align: middle;\n transition:\n background-color var(--bazaar-motion-duration-fast) var(--bazaar-motion-easing-standard),\n box-shadow var(--bazaar-motion-duration-fast) var(--bazaar-motion-easing-standard);\n}\n\n/* Sizes */\n.sm {\n height: 24px;\n padding: 0 var(--bazaar-space-2);\n font-size: var(--bazaar-font-size-caption);\n}\n\n.md {\n height: 30px;\n padding: 0 var(--bazaar-space-3);\n font-size: var(--bazaar-font-size-body-sm);\n}\n\n/* ---------- Filled ---------- */\n\n.filled.neutral {\n background-color: var(--bazaar-color-neutral-100);\n color: var(--bazaar-color-text-primary);\n}\n\n.filled.primary {\n background-color: var(--bazaar-color-brand-primary-50);\n color: var(--bazaar-color-brand-primary-700);\n}\n\n.filled.success {\n background-color: var(--bazaar-color-success-50);\n color: var(--bazaar-color-success-700);\n}\n\n.filled.warning {\n background-color: var(--bazaar-color-warning-50);\n color: var(--bazaar-color-warning-700);\n}\n\n.filled.error {\n background-color: var(--bazaar-color-error-50);\n color: var(--bazaar-color-error-700);\n}\n\n.filled.info {\n background-color: var(--bazaar-color-info-50);\n color: var(--bazaar-color-info-700);\n}\n\n/* ---------- Outlined ---------- */\n\n.outlined {\n background-color: transparent;\n border: var(--bazaar-border-width-hairline) var(--bazaar-border-style-default);\n}\n\n.outlined.neutral {\n border-color: var(--bazaar-color-border-default);\n color: var(--bazaar-color-text-primary);\n}\n\n.outlined.primary {\n border-color: var(--bazaar-color-brand-primary-200);\n color: var(--bazaar-color-brand-primary-700);\n}\n\n.outlined.success {\n border-color: var(--bazaar-color-success-500);\n color: var(--bazaar-color-success-700);\n}\n\n.outlined.warning {\n border-color: var(--bazaar-color-warning-500);\n color: var(--bazaar-color-warning-700);\n}\n\n.outlined.error {\n border-color: var(--bazaar-color-error-500);\n color: var(--bazaar-color-error-700);\n}\n\n.outlined.info {\n border-color: var(--bazaar-color-info-500);\n color: var(--bazaar-color-info-700);\n}\n\n/* ---------- Interactive ---------- */\n\n.clickable {\n cursor: pointer;\n}\n\n.clickable:hover {\n filter: brightness(0.96);\n}\n\n.clickable:focus-visible {\n outline: var(--bazaar-border-width-medium) solid var(--bazaar-focus-outline-color);\n outline-offset: var(--bazaar-focus-ring-offset);\n box-shadow: var(--bazaar-shadow-focus);\n}\n\n/* ---------- Disabled ---------- */\n\n.disabled {\n opacity: var(--bazaar-opacity-disabled);\n cursor: not-allowed;\n pointer-events: none;\n}\n\n/* ---------- Sub-elements ---------- */\n\n.icon {\n display: flex;\n align-items: center;\n flex-shrink: 0;\n}\n\n.label {\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.deleteButton {\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 0;\n margin: 0 calc(-1 * var(--bazaar-space-1)) 0 0;\n border: none;\n background: none;\n color: inherit;\n cursor: pointer;\n border-radius: var(--bazaar-radius-full);\n opacity: 0.64;\n transition: opacity var(--bazaar-motion-duration-fast) var(--bazaar-motion-easing-standard);\n}\n\n.deleteButton:hover {\n opacity: 1;\n}\n\n.deleteButton:disabled {\n cursor: not-allowed;\n}\n","import { forwardRef, type HTMLAttributes, type ReactNode, type MouseEvent } from 'react';\nimport { cn } from '../../utils/cn';\nimport styles from './Chip.module.css';\n\nexport interface ChipProps extends Omit<HTMLAttributes<HTMLSpanElement>, 'onClick'> {\n /** Visual color variant */\n color?: 'neutral' | 'primary' | 'success' | 'warning' | 'error' | 'info';\n /** Size */\n size?: 'sm' | 'md';\n /** Chip style */\n variant?: 'filled' | 'outlined';\n /** Icon or avatar slot (leading) */\n icon?: ReactNode;\n /** Whether the chip is clickable */\n onClick?: (e: MouseEvent<HTMLSpanElement>) => void;\n /** Show a delete/dismiss button */\n onDelete?: (e: MouseEvent<HTMLButtonElement>) => void;\n /** Disabled state */\n disabled?: boolean;\n}\n\nconst DeleteIcon = () => (\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"1.75\" strokeLinecap=\"round\" aria-hidden=\"true\">\n <line x1=\"4\" y1=\"4\" x2=\"10\" y2=\"10\" />\n <line x1=\"10\" y1=\"4\" x2=\"4\" y2=\"10\" />\n </svg>\n);\n\n/**\n * Chip — compact interactive element for tags, filters, and selections.\n *\n * Distinct from Badge: Chip is interactive (clickable, deletable) and\n * larger; Badge is a read-only status label.\n *\n * Accessibility:\n * - Clickable chips render with role=\"button\" and tabIndex\n * - Delete button has an accessible aria-label\n * - Disabled state applies aria-disabled\n * - Healthcare note: useful for allergy tags, condition labels,\n * insurance plan tags, filter selections\n */\nexport const Chip = forwardRef<HTMLSpanElement, ChipProps>(\n (\n {\n color = 'neutral',\n size = 'md',\n variant = 'filled',\n icon,\n onClick,\n onDelete,\n disabled = false,\n className,\n children,\n ...props\n },\n ref,\n ) => {\n const isClickable = !!onClick && !disabled;\n\n return (\n <span\n ref={ref}\n className={cn(\n styles.chip,\n styles[color],\n styles[size],\n styles[variant],\n isClickable && styles.clickable,\n disabled && styles.disabled,\n className,\n )}\n role={isClickable ? 'button' : undefined}\n tabIndex={isClickable ? 0 : undefined}\n onClick={isClickable ? onClick : undefined}\n onKeyDown={\n isClickable\n ? (e) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n onClick?.(e as any);\n }\n }\n : undefined\n }\n aria-disabled={disabled || undefined}\n {...props}\n >\n {icon && <span className={styles.icon} aria-hidden=\"true\">{icon}</span>}\n <span className={styles.label}>{children}</span>\n {onDelete && (\n <button\n type=\"button\"\n className={styles.deleteButton}\n onClick={(e) => {\n e.stopPropagation();\n if (!disabled) onDelete(e);\n }}\n disabled={disabled}\n aria-label={`Remove ${typeof children === 'string' ? children : ''}`}\n tabIndex={-1}\n >\n <DeleteIcon />\n </button>\n )}\n </span>\n );\n },\n);\n\nChip.displayName = 'Chip';\n",".divider {\n border: none;\n border-top: var(--bazaar-border-width-hairline) var(--bazaar-border-style-default) var(--bazaar-color-border-default);\n width: 100%;\n}\n\n.light {\n border-top-color: var(--bazaar-color-border-subtle);\n}\n\n.none { margin: 0; }\n.sm { margin: var(--bazaar-space-2) 0; }\n.md { margin: var(--bazaar-space-4) 0; }\n.lg { margin: var(--bazaar-space-8) 0; }\n","import { type HTMLAttributes } from 'react';\nimport { cn } from '../../utils/cn';\nimport styles from './Divider.module.css';\n\nexport interface DividerProps extends HTMLAttributes<HTMLHRElement> {\n /** Spacing above and below */\n spacing?: 'none' | 'sm' | 'md' | 'lg';\n}\n\n/**\n * Divider — horizontal rule for visual separation.\n *\n * Accessibility:\n * - Uses semantic <hr> which conveys a thematic break\n * - role=\"separator\" is implicit for <hr>\n */\nexport function Divider({ spacing = 'md', className, ...props }: DividerProps) {\n return <hr className={cn(styles.divider, styles[spacing], className)} {...props} />;\n}\n",".list {\n list-style: none;\n margin: 0;\n padding: 0;\n font-family: var(--bazaar-font-family-sans);\n}\n\n.divided .item + .item {\n border-top: var(--bazaar-border-width-hairline) var(--bazaar-border-style-default) var(--bazaar-color-border-default);\n}\n\n/* Padding variants */\n.pad-none .interactive,\n.pad-none .static {\n padding: 0;\n}\n\n.pad-sm .interactive,\n.pad-sm .static {\n padding: var(--bazaar-space-2) var(--bazaar-space-3);\n}\n\n.pad-md .interactive,\n.pad-md .static {\n padding: var(--bazaar-space-3) var(--bazaar-space-4);\n}\n\n/* Item wrapper */\n.item {\n margin: 0;\n}\n\n/* Shared layout for interactive and static items */\n.interactive,\n.static {\n display: flex;\n align-items: center;\n gap: var(--bazaar-space-3);\n width: 100%;\n text-align: left;\n}\n\n.interactive {\n background: none;\n border: none;\n font-family: inherit;\n font-size: inherit;\n cursor: pointer;\n color: inherit;\n border-radius: var(--bazaar-radius-sm);\n transition:\n background-color var(--bazaar-motion-duration-fast) var(--bazaar-motion-easing-standard),\n color var(--bazaar-motion-duration-fast) var(--bazaar-motion-easing-standard);\n}\n\n.interactive:hover:not(:disabled) {\n background-color: var(--bazaar-color-surface-hover);\n}\n\n.interactive:focus-visible {\n outline: var(--bazaar-border-width-medium) solid var(--bazaar-focus-outline-color);\n outline-offset: calc(-1 * var(--bazaar-border-width-medium));\n box-shadow: var(--bazaar-shadow-focus);\n z-index: 1;\n position: relative;\n}\n\n.selected {\n background-color: var(--bazaar-color-brand-primary-50);\n color: var(--bazaar-color-brand-primary-700);\n}\n\n.selected:hover:not(:disabled) {\n background-color: var(--bazaar-color-brand-primary-100);\n}\n\n.disabled {\n opacity: var(--bazaar-opacity-disabled);\n cursor: not-allowed;\n pointer-events: none;\n}\n\n.prefix {\n display: flex;\n align-items: center;\n flex-shrink: 0;\n color: var(--bazaar-color-text-muted);\n}\n\n.content {\n flex: 1;\n min-width: 0;\n display: flex;\n flex-direction: column;\n gap: var(--bazaar-space-0-5);\n}\n\n.primary {\n font-size: var(--bazaar-font-size-body-md);\n line-height: var(--bazaar-line-height-body-md);\n color: var(--bazaar-color-text-primary);\n}\n\n.description {\n font-size: var(--bazaar-font-size-body-sm);\n line-height: var(--bazaar-line-height-body-sm);\n color: var(--bazaar-color-text-muted);\n}\n\n.suffix {\n display: flex;\n align-items: center;\n flex-shrink: 0;\n}\n","import { forwardRef, type HTMLAttributes, type ReactNode } from 'react';\nimport { cn } from '../../utils/cn';\nimport styles from './List.module.css';\n\n/* ---------- List ---------- */\n\nexport interface ListProps extends HTMLAttributes<HTMLUListElement> {\n /** Show dividers between items */\n divided?: boolean;\n /** Padding inside list items */\n padding?: 'none' | 'sm' | 'md';\n}\n\n/**\n * List — composable list container for displaying groups of items.\n *\n * Accessibility:\n * - Uses semantic <ul>/<li> structure\n * - Interactive items rendered as buttons for keyboard access\n * - Disabled items use aria-disabled\n * - Selected items use aria-selected\n */\nexport const List = forwardRef<HTMLUListElement, ListProps>(\n ({ divided = false, padding = 'md', className, children, ...props }, ref) => {\n return (\n <ul\n ref={ref}\n className={cn(styles.list, divided && styles.divided, styles[`pad-${padding}`], className)}\n {...props}\n >\n {children}\n </ul>\n );\n },\n);\nList.displayName = 'List';\n\n/* ---------- ListItem ---------- */\n\nexport interface ListItemProps extends Omit<HTMLAttributes<HTMLLIElement>, 'prefix'> {\n /** Click handler — makes the item interactive */\n onClick?: () => void;\n /** Whether this item is selected */\n selected?: boolean;\n /** Whether this item is disabled */\n disabled?: boolean;\n /** Leading element (icon, avatar, etc.) */\n prefix?: ReactNode;\n /** Trailing element (badge, action button, etc.) */\n suffix?: ReactNode;\n /** Secondary description text */\n description?: string;\n}\n\nexport const ListItem = forwardRef<HTMLLIElement, ListItemProps>(\n ({ onClick, selected, disabled, prefix, suffix, description, className, children, ...props }, ref) => {\n const isInteractive = !!onClick;\n\n const content = (\n <>\n {prefix && <span className={styles.prefix}>{prefix}</span>}\n <span className={styles.content}>\n <span className={styles.primary}>{children}</span>\n {description && <span className={styles.description}>{description}</span>}\n </span>\n {suffix && <span className={styles.suffix}>{suffix}</span>}\n </>\n );\n\n return (\n <li\n ref={ref}\n className={cn(styles.item, className)}\n {...props}\n >\n {isInteractive ? (\n <button\n type=\"button\"\n className={cn(styles.interactive, selected && styles.selected, disabled && styles.disabled)}\n onClick={onClick}\n disabled={disabled}\n aria-selected={selected || undefined}\n aria-disabled={disabled || undefined}\n >\n {content}\n </button>\n ) : (\n <div className={cn(styles.static, selected && styles.selected, disabled && styles.disabled)}>\n {content}\n </div>\n )}\n </li>\n );\n },\n);\nListItem.displayName = 'ListItem';\n",".wrapper {\n width: 100%;\n overflow-x: auto;\n -webkit-overflow-scrolling: touch;\n}\n\n.table {\n width: 100%;\n border-collapse: collapse;\n font-family: var(--bazaar-font-family-sans);\n font-size: var(--bazaar-font-size-body-md);\n line-height: var(--bazaar-line-height-body-md);\n color: var(--bazaar-color-text-primary);\n}\n\n.thead {\n border-bottom: var(--bazaar-border-width-hairline) var(--bazaar-border-style-default) var(--bazaar-color-border-default);\n background-color: var(--bazaar-color-surface-subtle);\n}\n\n.th {\n text-align: left;\n font-weight: var(--bazaar-font-weight-medium);\n font-size: var(--bazaar-font-size-label-md);\n color: var(--bazaar-color-text-secondary);\n white-space: nowrap;\n}\n\n.td {\n border-bottom: var(--bazaar-border-width-hairline) var(--bazaar-border-style-default) var(--bazaar-color-border-subtle);\n transition: background-color var(--bazaar-motion-duration-fast) var(--bazaar-motion-easing-standard);\n}\n\n/* Density: default */\n.default .th,\n.default .td {\n padding: var(--bazaar-space-3) var(--bazaar-space-4);\n height: var(--bazaar-size-control-lg);\n}\n\n/* Density: compact */\n.compact .th,\n.compact .td {\n padding: var(--bazaar-space-2) var(--bazaar-space-3);\n height: var(--bazaar-size-control-sm);\n font-size: var(--bazaar-font-size-body-sm);\n}\n\n/* Striped rows */\n.striped .tbody .tr:nth-child(even) {\n background-color: var(--bazaar-color-neutral-50);\n}\n\n/* Hover */\n.tbody .tr:hover {\n background-color: var(--bazaar-color-surface-hover);\n}\n\n/* Selected row */\n.tbody .tr.selected {\n background-color: var(--bazaar-color-surface-selected);\n}\n\n.tbody .tr.selected:hover {\n background-color: var(--bazaar-color-surface-selected-hover);\n}\n","import { type TableHTMLAttributes, type ThHTMLAttributes, type TdHTMLAttributes, type HTMLAttributes } from 'react';\nimport { cn } from '../../utils/cn';\nimport styles from './Table.module.css';\n\nexport interface TableProps extends TableHTMLAttributes<HTMLTableElement> {\n /** Compact density for admin/operational views */\n density?: 'default' | 'compact';\n /** Striped rows for scan-ability */\n striped?: boolean;\n}\n\n/**\n * Table — data table with accessible defaults.\n *\n * Accessibility:\n * - Semantic <table> / <thead> / <tbody> / <th> structure\n * - Use scope=\"col\" on header cells\n * - For complex tables, use aria-describedby to link to a caption\n * - Healthcare note: clinical data tables should use tabular numerals\n * (monospace) and adequate row height for readability under stress\n */\nexport function Table({ density = 'default', striped = false, className, children, ...props }: TableProps) {\n return (\n <div className={styles.wrapper}>\n <table\n className={cn(styles.table, styles[density], striped && styles.striped, className)}\n {...props}\n >\n {children}\n </table>\n </div>\n );\n}\n\nexport function TableHead({ className, children, ...props }: HTMLAttributes<HTMLTableSectionElement>) {\n return <thead className={cn(styles.thead, className)} {...props}>{children}</thead>;\n}\n\nexport function TableBody({ className, children, ...props }: HTMLAttributes<HTMLTableSectionElement>) {\n return <tbody className={cn(styles.tbody, className)} {...props}>{children}</tbody>;\n}\n\nexport function TableRow({ className, children, ...props }: HTMLAttributes<HTMLTableRowElement>) {\n return <tr className={cn(styles.tr, className)} {...props}>{children}</tr>;\n}\n\nexport function TableHeaderCell({ className, children, ...props }: ThHTMLAttributes<HTMLTableCellElement>) {\n return <th scope=\"col\" className={cn(styles.th, className)} {...props}>{children}</th>;\n}\n\nexport function TableCell({ className, children, ...props }: TdHTMLAttributes<HTMLTableCellElement>) {\n return <td className={cn(styles.td, className)} {...props}>{children}</td>;\n}\n",".wrapper {\n position: relative;\n display: inline-flex;\n}\n\n.tooltip {\n position: absolute;\n left: 50%;\n transform: translateX(-50%);\n z-index: var(--bazaar-z-tooltip);\n padding: var(--bazaar-space-1) var(--bazaar-space-2);\n border-radius: var(--bazaar-radius-sm);\n background-color: var(--bazaar-color-neutral-900);\n color: var(--bazaar-color-text-inverse);\n font-family: var(--bazaar-font-family-sans);\n font-size: var(--bazaar-font-size-caption);\n line-height: var(--bazaar-line-height-caption);\n white-space: nowrap;\n pointer-events: none;\n box-shadow: var(--bazaar-shadow-md);\n animation: bazaar-tooltip-in var(--bazaar-motion-duration-fast) var(--bazaar-motion-easing-standard);\n}\n\n.top {\n bottom: calc(100% + 6px);\n}\n\n.bottom {\n top: calc(100% + 6px);\n}\n\n@keyframes bazaar-tooltip-in {\n from {\n opacity: 0;\n transform: translateX(-50%) translateY(2px);\n }\n to {\n opacity: 1;\n transform: translateX(-50%) translateY(0);\n }\n}\n","import { useState, useRef, type ReactNode } from 'react';\nimport { cn } from '../../utils/cn';\nimport styles from './Tooltip.module.css';\n\nexport interface TooltipProps {\n /** Tooltip content */\n content: ReactNode;\n /** Trigger element */\n children: ReactNode;\n /** Placement */\n placement?: 'top' | 'bottom';\n /** Delay before showing (ms) */\n delay?: number;\n /** Additional className */\n className?: string;\n}\n\n/**\n * Tooltip — supplementary text on hover/focus.\n *\n * Accessibility:\n * - Shows on both hover and keyboard focus\n * - Uses role=\"tooltip\" with aria-describedby linking\n * - Respects reduced motion preferences (no animation)\n * - Healthcare note: never put critical information in tooltips alone.\n * Use for supplementary context only, since tooltips are easy to miss\n * and not accessible on touch devices.\n */\nexport function Tooltip({ content, children, placement = 'top', delay = 200, className }: TooltipProps) {\n const [visible, setVisible] = useState(false);\n const timeoutRef = useRef<ReturnType<typeof setTimeout>>();\n const tooltipId = useRef(`tooltip-${Math.random().toString(36).slice(2, 9)}`).current;\n\n const show = () => {\n timeoutRef.current = setTimeout(() => setVisible(true), delay);\n };\n\n const hide = () => {\n clearTimeout(timeoutRef.current);\n setVisible(false);\n };\n\n return (\n <div\n className={cn(styles.wrapper, className)}\n onMouseEnter={show}\n onMouseLeave={hide}\n onFocus={show}\n onBlur={hide}\n >\n <div aria-describedby={visible ? tooltipId : undefined}>\n {children}\n </div>\n {visible && (\n <div\n id={tooltipId}\n role=\"tooltip\"\n className={cn(styles.tooltip, styles[placement])}\n >\n {content}\n </div>\n )}\n </div>\n );\n}\n",".container {\n width: 100%;\n}\n\n.header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n margin-bottom: var(--bazaar-space-2);\n}\n\n.label {\n font-family: var(--bazaar-font-family-sans);\n font-size: var(--bazaar-font-size-label-md);\n font-weight: var(--bazaar-font-weight-medium);\n color: var(--bazaar-color-text-primary);\n}\n\n.value {\n font-family: var(--bazaar-font-family-mono);\n font-size: var(--bazaar-font-size-body-sm);\n color: var(--bazaar-color-text-secondary);\n}\n\n.track {\n width: 100%;\n background-color: var(--bazaar-color-neutral-100);\n border-radius: var(--bazaar-radius-full);\n overflow: hidden;\n}\n\n/* Sizes */\n.sm {\n height: 4px;\n}\n\n.md {\n height: 8px;\n}\n\n/* Fill bar */\n.fill {\n height: 100%;\n border-radius: var(--bazaar-radius-full);\n transition: width 0.3s ease;\n}\n\n/* Variants */\n.default {\n background-color: var(--bazaar-color-brand-primary-500);\n}\n\n.success {\n background-color: var(--bazaar-color-success-500);\n}\n\n.warning {\n background-color: var(--bazaar-color-warning-500);\n}\n\n.error {\n background-color: var(--bazaar-color-error-500);\n}\n","import { type HTMLAttributes } from 'react';\nimport { cn } from '../../utils/cn';\nimport styles from './Progress.module.css';\n\nexport interface ProgressProps extends HTMLAttributes<HTMLDivElement> {\n /** Current value (0-100) */\n value: number;\n /** Maximum value (defaults to 100) */\n max?: number;\n /** Size variant */\n size?: 'sm' | 'md';\n /** Color variant */\n variant?: 'default' | 'success' | 'warning' | 'error';\n /** Visible label text */\n label?: string;\n /** Show the numeric value */\n showValue?: boolean;\n}\n\n/**\n * Progress — horizontal bar indicating completion or progress.\n *\n * Accessibility:\n * - role=\"progressbar\" with aria-valuenow, aria-valuemin, aria-valuemax\n * - aria-label derived from the label prop\n * - Useful for course progress, lesson completion, multi-step forms,\n * onboarding flows, and any \"X of Y complete\" surface\n */\nexport function Progress({\n value,\n max = 100,\n size = 'md',\n variant = 'default',\n label,\n showValue = false,\n className,\n ...props\n}: ProgressProps) {\n const pct = Math.min(100, Math.max(0, (value / max) * 100));\n\n return (\n <div className={cn(styles.container, className)} {...props}>\n {(label || showValue) && (\n <div className={styles.header}>\n {label && <span className={styles.label}>{label}</span>}\n {showValue && <span className={styles.value}>{Math.round(pct)}%</span>}\n </div>\n )}\n <div\n className={cn(styles.track, styles[size])}\n role=\"progressbar\"\n aria-valuenow={value}\n aria-valuemin={0}\n aria-valuemax={max}\n aria-label={label}\n >\n <div\n className={cn(styles.fill, styles[variant])}\n style={{ width: `${pct}%` }}\n />\n </div>\n </div>\n );\n}\n",".skeleton {\n background-color: var(--bazaar-color-neutral-100);\n background-image: linear-gradient(\n 90deg,\n var(--bazaar-color-neutral-100) 0%,\n var(--bazaar-color-neutral-50) 40%,\n var(--bazaar-color-neutral-100) 80%\n );\n background-size: 200% 100%;\n animation: bazaar-shimmer 1.5s ease-in-out infinite;\n}\n\n.text {\n height: 1em;\n border-radius: var(--bazaar-radius-sm);\n}\n\n.circular {\n border-radius: var(--bazaar-radius-full);\n}\n\n.rectangular {\n border-radius: var(--bazaar-radius-md);\n}\n\n.group {\n display: flex;\n flex-direction: column;\n gap: var(--bazaar-space-2);\n}\n\n@keyframes bazaar-shimmer {\n 0% {\n background-position: 200% 0;\n }\n 100% {\n background-position: -200% 0;\n }\n}\n","import { type HTMLAttributes } from 'react';\nimport { cn } from '../../utils/cn';\nimport styles from './Skeleton.module.css';\n\nexport interface SkeletonProps extends HTMLAttributes<HTMLDivElement> {\n /** Shape variant */\n variant?: 'text' | 'circular' | 'rectangular';\n /** Width (CSS value) */\n width?: string | number;\n /** Height (CSS value) */\n height?: string | number;\n /** Number of text lines (only for text variant) */\n lines?: number;\n}\n\n/**\n * Skeleton — placeholder loading indicator with shimmer animation.\n *\n * Accessibility:\n * - aria-hidden=\"true\" since it is purely decorative\n * - Healthcare note: use Skeleton loaders in clinical dashboards to\n * indicate data is loading, reducing perceived wait time\n */\nexport function Skeleton({\n variant = 'text',\n width,\n height,\n lines = 1,\n className,\n style,\n ...props\n}: SkeletonProps) {\n if (variant === 'text' && lines > 1) {\n return (\n <div className={cn(styles.group, className)} aria-hidden=\"true\" {...props}>\n {Array.from({ length: lines }, (_, i) => (\n <div\n key={i}\n className={cn(styles.skeleton, styles.text)}\n style={{\n width: i === lines - 1 ? '75%' : width ?? '100%',\n height: height ?? undefined,\n ...style,\n }}\n />\n ))}\n </div>\n );\n }\n\n return (\n <div\n className={cn(styles.skeleton, styles[variant], className)}\n aria-hidden=\"true\"\n style={{\n width: width ?? (variant === 'circular' ? 40 : '100%'),\n height: height ?? (variant === 'circular' ? 40 : variant === 'rectangular' ? 120 : undefined),\n ...style,\n }}\n {...props}\n />\n );\n}\n",".spinner {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n color: var(--bazaar-color-brand-primary-500);\n}\n\n.svg {\n animation: bazaar-spin 0.8s linear infinite;\n}\n\n@keyframes bazaar-spin {\n to {\n transform: rotate(360deg);\n }\n}\n","import { type HTMLAttributes } from 'react';\nimport { cn } from '../../utils/cn';\nimport styles from './Spinner.module.css';\n\nexport interface SpinnerProps extends HTMLAttributes<HTMLSpanElement> {\n /** Size */\n size?: 'sm' | 'md' | 'lg';\n /** Accessible label */\n label?: string;\n}\n\n/**\n * Spinner / LoadingIndicator — visual loading state.\n *\n * Accessibility:\n * - role=\"status\" with aria-label for screen reader announcement\n * - aria-live=\"polite\" so loading state is announced without interrupting\n * - Healthcare note: in clinical workflows, always pair with text\n * context (\"Loading patient records...\") so users understand what\n * they are waiting for\n */\nexport function Spinner({ size = 'md', label = 'Loading', className, ...props }: SpinnerProps) {\n const sizeMap = { sm: 16, md: 24, lg: 32 };\n const s = sizeMap[size];\n\n return (\n <span\n className={cn(styles.spinner, className)}\n role=\"status\"\n aria-label={label}\n aria-live=\"polite\"\n {...props}\n >\n <svg\n width={s}\n height={s}\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n className={styles.svg}\n aria-hidden=\"true\"\n >\n <circle\n cx=\"12\"\n cy=\"12\"\n r=\"10\"\n stroke=\"currentColor\"\n strokeWidth=\"2.5\"\n strokeLinecap=\"round\"\n opacity=\"0.2\"\n />\n <circle\n cx=\"12\"\n cy=\"12\"\n r=\"10\"\n stroke=\"currentColor\"\n strokeWidth=\"2.5\"\n strokeLinecap=\"round\"\n strokeDasharray=\"50\"\n strokeDashoffset=\"35\"\n />\n </svg>\n </span>\n );\n}\n",".badge {\n display: inline-flex;\n align-items: center;\n gap: var(--bazaar-space-1);\n border-radius: var(--bazaar-radius-full);\n font-family: var(--bazaar-font-family-sans);\n font-weight: var(--bazaar-font-weight-medium);\n white-space: nowrap;\n}\n\n/* Sizes */\n.sm {\n padding: 1px var(--bazaar-space-2);\n font-size: var(--bazaar-font-size-caption);\n line-height: var(--bazaar-line-height-caption);\n}\n\n.md {\n padding: 2px var(--bazaar-space-3);\n font-size: var(--bazaar-font-size-body-sm);\n line-height: var(--bazaar-line-height-body-sm);\n}\n\n/* Status dot */\n.dot {\n width: 6px;\n height: 6px;\n border-radius: var(--bazaar-radius-full);\n background-color: currentColor;\n flex-shrink: 0;\n}\n\n/* ----------------------------------------------------------------------------\n Status colors — semantic vocabulary shared across Skyfall kits\n ---------------------------------------------------------------------------- */\n\n.neutral {\n background-color: var(--bazaar-color-neutral-100);\n color: var(--bazaar-color-text-secondary);\n}\n\n.info {\n background-color: var(--bazaar-color-info-50);\n color: var(--bazaar-color-info-700);\n}\n\n.success,\n.completed {\n background-color: var(--bazaar-color-success-50);\n color: var(--bazaar-color-success-700);\n}\n\n.warning,\n.in-progress,\n.pending {\n background-color: var(--bazaar-color-warning-50);\n color: var(--bazaar-color-warning-700);\n}\n\n.error {\n background-color: var(--bazaar-color-error-50);\n color: var(--bazaar-color-error-700);\n}\n\n.inactive,\n.locked {\n background-color: var(--bazaar-color-neutral-100);\n color: var(--bazaar-color-text-muted);\n}\n","import { type HTMLAttributes } from 'react';\nimport { cn } from '../../utils/cn';\nimport styles from './StatusBadge.module.css';\n\n/**\n * Generic, cross-kit semantic status vocabulary.\n *\n * NOTE: This is a Bazaar refactor of an Aegis component that previously shipped\n * a healthcare-specific status set (critical, discharged, scheduled). The shared\n * vocabulary below is more reusable across kits — Aegis can map clinical\n * severities and Bazaar can map learning states onto the same primitives.\n */\nexport type StatusBadgeStatus =\n | 'neutral'\n | 'info'\n | 'success'\n | 'warning'\n | 'error'\n | 'pending'\n | 'in-progress'\n | 'inactive'\n | 'completed'\n | 'locked';\n\nexport interface StatusBadgeProps extends Omit<HTMLAttributes<HTMLSpanElement>, 'children'> {\n /** Semantic status */\n status: StatusBadgeStatus;\n /** Override the default label text */\n label?: string;\n /** Size variant */\n size?: 'sm' | 'md';\n /** Show a colored status dot before the label */\n dot?: boolean;\n}\n\nconst statusLabels: Record<StatusBadgeStatus, string> = {\n neutral: 'Neutral',\n info: 'Info',\n success: 'Success',\n warning: 'Warning',\n error: 'Error',\n pending: 'Pending',\n 'in-progress': 'In progress',\n inactive: 'Inactive',\n completed: 'Completed',\n locked: 'Locked',\n};\n\n/**\n * StatusBadge — semantic status pill, shared across Skyfall kits.\n *\n * Accessibility:\n * - Always displays text label alongside color (no color-only meaning)\n * - Use `label` to override the default label per status\n */\nexport function StatusBadge({\n status,\n label,\n size = 'md',\n dot = false,\n className,\n ...props\n}: StatusBadgeProps) {\n return (\n <span\n className={cn(styles.badge, styles[status], styles[size], className)}\n {...props}\n >\n {dot && <span className={styles.dot} aria-hidden=\"true\" />}\n {label ?? statusLabels[status]}\n </span>\n );\n}\n",".timeline {\n list-style: none;\n margin: 0;\n padding: 0;\n font-family: var(--bazaar-font-family-sans);\n}\n\n.item {\n display: flex;\n gap: var(--bazaar-space-4);\n position: relative;\n padding-bottom: var(--bazaar-space-6);\n}\n\n.item:last-child {\n padding-bottom: 0;\n}\n\n.item:last-child .line {\n display: none;\n}\n\n.indicator {\n display: flex;\n flex-direction: column;\n align-items: center;\n flex-shrink: 0;\n width: 24px;\n}\n\n.dot {\n width: 12px;\n height: 12px;\n border-radius: var(--bazaar-radius-full);\n border: 2px solid var(--bazaar-color-border-default);\n background-color: var(--bazaar-color-surface-default);\n flex-shrink: 0;\n}\n\n.icon {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 24px;\n height: 24px;\n border-radius: var(--bazaar-radius-full);\n flex-shrink: 0;\n}\n\n.line {\n flex: 1;\n width: 2px;\n background-color: var(--bazaar-color-border-subtle);\n margin-top: var(--bazaar-space-2);\n}\n\n.content {\n flex: 1;\n min-width: 0;\n padding-top: 0;\n}\n\n.title {\n margin: 0;\n font-size: var(--bazaar-font-size-body-md);\n font-weight: var(--bazaar-font-weight-semibold);\n line-height: var(--bazaar-line-height-body-md);\n color: var(--bazaar-color-text-primary);\n}\n\n.description {\n margin: var(--bazaar-space-1) 0 0;\n font-size: var(--bazaar-font-size-body-sm);\n line-height: var(--bazaar-line-height-body-sm);\n color: var(--bazaar-color-text-secondary);\n}\n\n.timestamp {\n display: block;\n margin-top: var(--bazaar-space-1);\n font-size: var(--bazaar-font-size-body-xs);\n color: var(--bazaar-color-text-muted);\n line-height: var(--bazaar-line-height-body-sm);\n}\n\n/* Variant colors */\n.default .dot { border-color: var(--bazaar-color-border-default); }\n.default .icon { background-color: var(--bazaar-color-surface-sunken); color: var(--bazaar-color-text-muted); }\n\n.success .dot { border-color: var(--bazaar-color-success-500); background-color: var(--bazaar-color-success-50); }\n.success .icon { background-color: var(--bazaar-color-success-50); color: var(--bazaar-color-success-600); }\n\n.warning .dot { border-color: var(--bazaar-color-warning-500); background-color: var(--bazaar-color-warning-50); }\n.warning .icon { background-color: var(--bazaar-color-warning-50); color: var(--bazaar-color-warning-600); }\n\n.error .dot { border-color: var(--bazaar-color-error-500); background-color: var(--bazaar-color-error-50); }\n.error .icon { background-color: var(--bazaar-color-error-50); color: var(--bazaar-color-error-600); }\n\n.info .dot { border-color: var(--bazaar-color-info-500); background-color: var(--bazaar-color-info-50); }\n.info .icon { background-color: var(--bazaar-color-info-50); color: var(--bazaar-color-info-600); }\n","import { type HTMLAttributes, type ReactNode } from 'react';\nimport { cn } from '../../utils/cn';\nimport styles from './Timeline.module.css';\n\nexport type TimelineItemVariant = 'default' | 'success' | 'warning' | 'error' | 'info';\n\nexport interface TimelineItem {\n /** Unique identifier */\n id: string;\n /** Event title */\n title: string;\n /** Optional description */\n description?: string;\n /** Timestamp display string */\n timestamp: string;\n /** Optional icon to replace the default dot */\n icon?: ReactNode;\n /** Visual variant */\n variant?: TimelineItemVariant;\n}\n\nexport interface TimelineProps extends HTMLAttributes<HTMLOListElement> {\n /** Timeline items in chronological order */\n items: TimelineItem[];\n}\n\n/**\n * Timeline — vertical timeline for displaying sequential events.\n *\n * Accessibility:\n * - Uses semantic <ol> for ordered event sequence\n * - Each event is an <li> for proper list semantics\n * - Icons are decorative (aria-hidden)\n */\nexport function Timeline({ items, className, ...props }: TimelineProps) {\n return (\n <ol className={cn(styles.timeline, className)} {...props}>\n {items.map((item) => (\n <li\n key={item.id}\n className={cn(styles.item, styles[item.variant ?? 'default'])}\n >\n <div className={styles.indicator} aria-hidden=\"true\">\n {item.icon ? (\n <span className={styles.icon}>{item.icon}</span>\n ) : (\n <span className={styles.dot} />\n )}\n <span className={styles.line} />\n </div>\n <div className={styles.content}>\n <p className={styles.title}>{item.title}</p>\n {item.description && (\n <p className={styles.description}>{item.description}</p>\n )}\n <time className={styles.timestamp}>{item.timestamp}</time>\n </div>\n </li>\n ))}\n </ol>\n );\n}\n",".list {\n margin: 0;\n padding: 0;\n font-family: var(--bazaar-font-family-sans);\n}\n\n.item {\n display: flex;\n flex-direction: column;\n}\n\n.term {\n font-size: var(--bazaar-font-size-label-md);\n font-weight: var(--bazaar-font-weight-medium);\n color: var(--bazaar-color-text-muted);\n margin-bottom: var(--bazaar-space-1);\n}\n\n.definition {\n margin: 0;\n font-size: var(--bazaar-font-size-body-md);\n line-height: var(--bazaar-line-height-body-md);\n color: var(--bazaar-color-text-primary);\n}\n\n/* Vertical layout */\n.vertical {\n display: flex;\n flex-direction: column;\n gap: var(--bazaar-space-4);\n}\n\n/* Horizontal layout */\n.horizontal .item {\n flex-direction: row;\n align-items: baseline;\n gap: var(--bazaar-space-3);\n}\n\n.horizontal {\n display: flex;\n flex-direction: column;\n gap: var(--bazaar-space-3);\n}\n\n.horizontal .term {\n flex-shrink: 0;\n min-width: 140px;\n margin-bottom: 0;\n}\n\n/* Grid layout */\n.grid {\n display: grid;\n grid-template-columns: repeat(var(--dl-columns, 2), 1fr);\n gap: var(--bazaar-space-4) var(--bazaar-space-6);\n}\n","import { type ReactNode, type HTMLAttributes } from 'react';\nimport { cn } from '../../utils/cn';\nimport styles from './DescriptionList.module.css';\n\nexport interface DescriptionListItem {\n /** Label / term */\n label: ReactNode;\n /** Value / description */\n value: ReactNode;\n}\n\nexport interface DescriptionListProps extends HTMLAttributes<HTMLDListElement> {\n /** Array of label-value pairs */\n items: DescriptionListItem[];\n /** Layout mode */\n layout?: 'vertical' | 'horizontal' | 'grid';\n /** Number of columns for grid layout */\n columns?: number;\n}\n\n/**\n * DescriptionList — semantic key-value display using dl/dt/dd.\n *\n * Accessibility:\n * - Uses <dl>, <dt>, <dd> semantic HTML\n * - Screen readers will announce terms and definitions\n * - Healthcare note: ideal for patient demographics, encounter details,\n * and insurance information panels\n */\nexport function DescriptionList({\n items,\n layout = 'vertical',\n columns = 2,\n className,\n style,\n ...props\n}: DescriptionListProps) {\n return (\n <dl\n className={cn(styles.list, styles[layout], className)}\n style={{\n ...(layout === 'grid' ? { '--dl-columns': columns } as React.CSSProperties : {}),\n ...style,\n }}\n {...props}\n >\n {items.map((item, i) => (\n <div key={i} className={styles.item}>\n <dt className={styles.term}>{item.label}</dt>\n <dd className={styles.definition}>{item.value}</dd>\n </div>\n ))}\n </dl>\n );\n}\n",".kbd {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n font-family: var(--bazaar-font-family-sans);\n font-weight: var(--bazaar-font-weight-medium);\n color: var(--bazaar-color-text-secondary);\n background-color: var(--bazaar-color-surface-sunken);\n border: var(--bazaar-border-width-hairline) var(--bazaar-border-style-default) var(--bazaar-color-border-default);\n border-bottom-width: 2px;\n border-radius: var(--bazaar-radius-sm);\n white-space: nowrap;\n line-height: 1;\n}\n\n.sm {\n min-width: 18px;\n height: 18px;\n padding: 0 var(--bazaar-space-1);\n font-size: 11px;\n}\n\n.md {\n min-width: 22px;\n height: 22px;\n padding: 0 var(--bazaar-space-2);\n font-size: var(--bazaar-font-size-body-xs);\n}\n","import { type HTMLAttributes } from 'react';\nimport { cn } from '../../utils/cn';\nimport styles from './Kbd.module.css';\n\nexport interface KbdProps extends HTMLAttributes<HTMLElement> {\n /** Size variant */\n size?: 'sm' | 'md';\n}\n\n/**\n * Kbd — keyboard shortcut / key indicator.\n *\n * Renders an inline `<kbd>` element styled to look like a physical key.\n * Use to display keyboard shortcuts in menus, tooltips, and documentation.\n *\n * Accessibility:\n * - Uses semantic <kbd> element for screen readers\n * - Screen readers will announce the content as keyboard input\n */\nexport function Kbd({\n size = 'md',\n className,\n children,\n ...props\n}: KbdProps) {\n return (\n <kbd className={cn(styles.kbd, styles[size], className)} {...props}>\n {children}\n </kbd>\n );\n}\n",".tree {\n font-family: var(--bazaar-font-family-sans);\n}\n\n.tree ul {\n list-style: none;\n margin: 0;\n padding: 0;\n}\n\n/* Node row */\n.node {\n display: flex;\n align-items: center;\n gap: var(--bazaar-space-1);\n cursor: pointer;\n border-radius: var(--bazaar-radius-sm);\n color: var(--bazaar-color-text-primary);\n transition: background-color var(--bazaar-motion-duration-fast) var(--bazaar-motion-easing-standard);\n user-select: none;\n}\n\n.sm.node { padding: 2px var(--bazaar-space-2); font-size: var(--bazaar-font-size-body-sm); min-height: 28px; }\n.md.node { padding: var(--bazaar-space-1) var(--bazaar-space-2); font-size: var(--bazaar-font-size-body-md); min-height: 32px; }\n\n.node:hover {\n background-color: var(--bazaar-color-neutral-50);\n}\n\n.node:focus-visible {\n outline: var(--bazaar-border-width-medium) solid var(--bazaar-focus-outline-color);\n outline-offset: -2px;\n}\n\n.node.selected {\n background-color: var(--bazaar-color-brand-primary-50, rgba(26, 115, 232, 0.08));\n color: var(--bazaar-color-brand-primary-600, #1A73E8);\n}\n\n.node.disabled {\n opacity: var(--bazaar-opacity-disabled);\n pointer-events: none;\n}\n\n/* Chevron toggle */\n.toggle {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 16px;\n height: 16px;\n flex-shrink: 0;\n}\n\n.chevron {\n transition: transform var(--bazaar-motion-duration-fast) var(--bazaar-motion-easing-standard);\n}\n\n.chevronExpanded {\n transform: rotate(90deg);\n}\n\n.leaf {\n display: block;\n width: 16px;\n}\n\n/* Icon slot */\n.icon {\n display: inline-flex;\n align-items: center;\n color: var(--bazaar-color-text-secondary);\n flex-shrink: 0;\n}\n\n.selected .icon {\n color: inherit;\n}\n\n/* Label */\n.label {\n flex: 1;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n/* Guide lines */\n.lined {\n position: relative;\n}\n\n.lined::before {\n content: '';\n position: absolute;\n left: 10px;\n top: 0;\n bottom: 0;\n width: 1px;\n background: var(--bazaar-color-border-default);\n}\n","import { useState, useCallback, forwardRef, type HTMLAttributes, type ReactNode } from 'react';\nimport { cn } from '../../utils/cn';\nimport styles from './TreeView.module.css';\n\nexport interface TreeNode {\n /** Unique identifier */\n id: string;\n /** Display label */\n label: string;\n /** Optional icon */\n icon?: ReactNode;\n /** Child nodes */\n children?: TreeNode[];\n /** Whether the node is disabled */\n disabled?: boolean;\n}\n\nexport interface TreeViewProps extends Omit<HTMLAttributes<HTMLDivElement>, 'onSelect'> {\n /** Tree data */\n data: TreeNode[];\n /** IDs of initially expanded nodes (uncontrolled) */\n defaultExpanded?: string[];\n /** IDs of expanded nodes (controlled) */\n expanded?: string[];\n /** Called when a node is expanded/collapsed */\n onExpandChange?: (expanded: string[]) => void;\n /** Currently selected node ID */\n selected?: string | null;\n /** Called when a node is selected */\n onSelect?: (nodeId: string, node: TreeNode) => void;\n /** Size variant */\n size?: 'sm' | 'md';\n /** Show connecting lines between levels */\n showLines?: boolean;\n}\n\nconst ChevronIcon = ({ expanded }: { expanded: boolean }) => (\n <svg\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"1.5\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n className={cn(styles.chevron, expanded && styles.chevronExpanded)}\n aria-hidden=\"true\"\n >\n <polyline points=\"6 4 10 8 6 12\" />\n </svg>\n);\n\ninterface TreeNodeItemProps {\n node: TreeNode;\n level: number;\n expanded: string[];\n selected: string | null;\n onToggle: (id: string) => void;\n onSelect: (id: string, node: TreeNode) => void;\n size: 'sm' | 'md';\n showLines: boolean;\n}\n\nfunction TreeNodeItem({ node, level, expanded, selected, onToggle, onSelect, size, showLines }: TreeNodeItemProps) {\n const hasChildren = node.children && node.children.length > 0;\n const isExpanded = expanded.includes(node.id);\n const isSelected = selected === node.id;\n\n const handleKeyDown = useCallback(\n (e: React.KeyboardEvent) => {\n if (node.disabled) return;\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n onSelect(node.id, node);\n } else if (e.key === 'ArrowRight' && hasChildren && !isExpanded) {\n e.preventDefault();\n onToggle(node.id);\n } else if (e.key === 'ArrowLeft' && hasChildren && isExpanded) {\n e.preventDefault();\n onToggle(node.id);\n }\n },\n [node, hasChildren, isExpanded, onToggle, onSelect],\n );\n\n return (\n <li role=\"treeitem\" aria-expanded={hasChildren ? isExpanded : undefined} aria-selected={isSelected} aria-disabled={node.disabled || undefined}>\n <div\n className={cn(\n styles.node,\n styles[size],\n isSelected && styles.selected,\n node.disabled && styles.disabled,\n showLines && level > 0 && styles.lined,\n )}\n style={{ paddingLeft: `${level * (size === 'sm' ? 16 : 20)}px` }}\n onClick={() => {\n if (node.disabled) return;\n if (hasChildren) onToggle(node.id);\n onSelect(node.id, node);\n }}\n onKeyDown={handleKeyDown}\n tabIndex={node.disabled ? -1 : 0}\n >\n <span className={styles.toggle}>\n {hasChildren ? <ChevronIcon expanded={isExpanded} /> : <span className={styles.leaf} />}\n </span>\n {node.icon && <span className={styles.icon}>{node.icon}</span>}\n <span className={styles.label}>{node.label}</span>\n </div>\n {hasChildren && isExpanded && (\n <ul role=\"group\" className={styles.group}>\n {node.children!.map((child) => (\n <TreeNodeItem\n key={child.id}\n node={child}\n level={level + 1}\n expanded={expanded}\n selected={selected}\n onToggle={onToggle}\n onSelect={onSelect}\n size={size}\n showLines={showLines}\n />\n ))}\n </ul>\n )}\n </li>\n );\n}\n\n/**\n * TreeView — hierarchical data display with expand/collapse.\n *\n * Renders nested tree data with keyboard navigation, selection,\n * and optional connecting guide lines.\n *\n * Accessibility:\n * - Uses tree/treeitem/group ARIA roles\n * - Arrow keys expand/collapse nodes\n * - Enter/Space selects nodes\n * - aria-expanded on branch nodes\n */\nexport const TreeView = forwardRef<HTMLDivElement, TreeViewProps>(\n (\n {\n data,\n defaultExpanded = [],\n expanded: controlledExpanded,\n onExpandChange,\n selected = null,\n onSelect,\n size = 'md',\n showLines = false,\n className,\n ...props\n },\n ref,\n ) => {\n const [uncontrolledExpanded, setUncontrolledExpanded] = useState<string[]>(defaultExpanded);\n const expanded = controlledExpanded ?? uncontrolledExpanded;\n\n const handleToggle = useCallback(\n (id: string) => {\n const next = expanded.includes(id)\n ? expanded.filter((e) => e !== id)\n : [...expanded, id];\n\n if (controlledExpanded === undefined) {\n setUncontrolledExpanded(next);\n }\n onExpandChange?.(next);\n },\n [expanded, controlledExpanded, onExpandChange],\n );\n\n const handleSelect = useCallback(\n (id: string, node: TreeNode) => {\n onSelect?.(id, node);\n },\n [onSelect],\n );\n\n return (\n <div ref={ref} className={cn(styles.tree, className)} {...props}>\n <ul role=\"tree\">\n {data.map((node) => (\n <TreeNodeItem\n key={node.id}\n node={node}\n level={0}\n expanded={expanded}\n selected={selected}\n onToggle={handleToggle}\n onSelect={handleSelect}\n size={size}\n showLines={showLines}\n />\n ))}\n </ul>\n </div>\n );\n },\n);\n\nTreeView.displayName = 'TreeView';\n",".typography {\n margin: 0;\n padding: 0;\n}\n\n/* ---------- Variant scale ---------- */\n\n.variant-display-lg {\n font-family: var(--bazaar-font-family-sans);\n font-size: var(--bazaar-font-size-display-lg);\n line-height: var(--bazaar-line-height-display-lg);\n font-weight: var(--bazaar-font-weight-bold);\n letter-spacing: var(--bazaar-tracking-tight);\n}\n\n.variant-display-md {\n font-family: var(--bazaar-font-family-sans);\n font-size: var(--bazaar-font-size-display-md);\n line-height: var(--bazaar-line-height-display-md);\n font-weight: var(--bazaar-font-weight-bold);\n letter-spacing: var(--bazaar-tracking-tight);\n}\n\n.variant-heading-xl {\n font-family: var(--bazaar-font-family-sans);\n font-size: var(--bazaar-font-size-heading-xl);\n line-height: var(--bazaar-line-height-heading-xl);\n font-weight: var(--bazaar-font-weight-semibold);\n}\n\n.variant-heading-lg {\n font-family: var(--bazaar-font-family-sans);\n font-size: var(--bazaar-font-size-heading-lg);\n line-height: var(--bazaar-line-height-heading-lg);\n font-weight: var(--bazaar-font-weight-semibold);\n}\n\n.variant-heading-md {\n font-family: var(--bazaar-font-family-sans);\n font-size: var(--bazaar-font-size-heading-md);\n line-height: var(--bazaar-line-height-heading-md);\n font-weight: var(--bazaar-font-weight-semibold);\n}\n\n.variant-heading-sm {\n font-family: var(--bazaar-font-family-sans);\n font-size: var(--bazaar-font-size-heading-sm);\n line-height: var(--bazaar-line-height-heading-sm);\n font-weight: var(--bazaar-font-weight-semibold);\n}\n\n.variant-body-lg {\n font-family: var(--bazaar-font-family-sans);\n font-size: var(--bazaar-font-size-body-lg);\n line-height: var(--bazaar-line-height-body-lg);\n font-weight: var(--bazaar-font-weight-regular);\n}\n\n.variant-body-md {\n font-family: var(--bazaar-font-family-sans);\n font-size: var(--bazaar-font-size-body-md);\n line-height: var(--bazaar-line-height-body-md);\n font-weight: var(--bazaar-font-weight-regular);\n}\n\n.variant-body-sm {\n font-family: var(--bazaar-font-family-sans);\n font-size: var(--bazaar-font-size-body-sm);\n line-height: var(--bazaar-line-height-body-sm);\n font-weight: var(--bazaar-font-weight-regular);\n}\n\n.variant-label-lg {\n font-family: var(--bazaar-font-family-sans);\n font-size: var(--bazaar-font-size-label-lg);\n line-height: var(--bazaar-line-height-label-lg);\n font-weight: var(--bazaar-font-weight-medium);\n}\n\n.variant-label-md {\n font-family: var(--bazaar-font-family-sans);\n font-size: var(--bazaar-font-size-label-md);\n line-height: var(--bazaar-line-height-label-md);\n font-weight: var(--bazaar-font-weight-medium);\n}\n\n.variant-caption {\n font-family: var(--bazaar-font-family-sans);\n font-size: var(--bazaar-font-size-caption);\n line-height: var(--bazaar-line-height-caption);\n font-weight: var(--bazaar-font-weight-regular);\n}\n\n.variant-data {\n font-family: var(--bazaar-font-family-mono);\n font-size: var(--bazaar-font-size-data);\n line-height: var(--bazaar-line-height-data);\n font-weight: var(--bazaar-font-weight-medium);\n}\n\n.variant-code {\n font-family: var(--bazaar-font-family-mono);\n font-size: var(--bazaar-font-size-code);\n line-height: var(--bazaar-line-height-code);\n font-weight: var(--bazaar-font-weight-regular);\n}\n\n/* ---------- Colors ---------- */\n\n.color-primary { color: var(--bazaar-color-text-primary); }\n.color-secondary { color: var(--bazaar-color-text-secondary); }\n.color-muted { color: var(--bazaar-color-text-muted); }\n.color-inverse { color: var(--bazaar-color-text-inverse); }\n.color-success { color: var(--bazaar-color-success-700); }\n.color-warning { color: var(--bazaar-color-warning-700); }\n.color-error { color: var(--bazaar-color-error-700); }\n.color-info { color: var(--bazaar-color-info-700); }\n.color-inherit { color: inherit; }\n\n/* ---------- Weights ---------- */\n\n.weight-regular { font-weight: var(--bazaar-font-weight-regular); }\n.weight-medium { font-weight: var(--bazaar-font-weight-medium); }\n.weight-semibold { font-weight: var(--bazaar-font-weight-semibold); }\n.weight-bold { font-weight: var(--bazaar-font-weight-bold); }\n\n/* ---------- Alignment ---------- */\n\n.align-left { text-align: left; }\n.align-center { text-align: center; }\n.align-right { text-align: right; }\n\n/* ---------- Truncation ---------- */\n\n.truncate {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.lineClamp {\n display: -webkit-box;\n -webkit-box-orient: vertical;\n overflow: hidden;\n}\n","import { forwardRef, type HTMLAttributes, type ElementType } from 'react';\nimport { cn } from '../../utils/cn';\nimport styles from './Typography.module.css';\n\nexport type TypographyVariant =\n | 'display-lg'\n | 'display-md'\n | 'heading-xl'\n | 'heading-lg'\n | 'heading-md'\n | 'heading-sm'\n | 'body-lg'\n | 'body-md'\n | 'body-sm'\n | 'label-lg'\n | 'label-md'\n | 'caption'\n | 'data'\n | 'code';\n\nexport type TypographyColor =\n | 'primary'\n | 'secondary'\n | 'muted'\n | 'inverse'\n | 'success'\n | 'warning'\n | 'error'\n | 'info'\n | 'inherit';\n\nexport type TypographyWeight = 'regular' | 'medium' | 'semibold' | 'bold';\n\nexport type TypographyAlign = 'left' | 'center' | 'right';\n\n/** Default HTML elements for each variant */\nconst variantElementMap: Record<TypographyVariant, ElementType> = {\n 'display-lg': 'h1',\n 'display-md': 'h1',\n 'heading-xl': 'h2',\n 'heading-lg': 'h2',\n 'heading-md': 'h3',\n 'heading-sm': 'h4',\n 'body-lg': 'p',\n 'body-md': 'p',\n 'body-sm': 'p',\n 'label-lg': 'span',\n 'label-md': 'span',\n caption: 'span',\n data: 'span',\n code: 'code',\n};\n\nexport interface TypographyProps extends HTMLAttributes<HTMLElement> {\n /** Typographic scale variant */\n variant?: TypographyVariant;\n /** Text color */\n color?: TypographyColor;\n /** Font weight override */\n weight?: TypographyWeight;\n /** Text alignment */\n align?: TypographyAlign;\n /** Render as a specific HTML element (overrides the variant default) */\n as?: ElementType;\n /** Truncate with ellipsis */\n truncate?: boolean;\n /** Clamp to N lines */\n lineClamp?: number;\n}\n\n/**\n * Typography — text rendering primitive.\n *\n * Maps directly to the Bazaar type scale tokens and provides a consistent\n * API for rendering text at any level of the hierarchy.\n *\n * Accessibility:\n * - Defaults to the semantically correct HTML element for each variant\n * (h1–h4 for headings, p for body, code for code, span for labels)\n * - Use `as` to override when the visual style and semantic level differ\n * - `color=\"inherit\"` defers to the parent color\n */\nexport const Typography = forwardRef<HTMLElement, TypographyProps>(\n (\n {\n variant = 'body-md',\n color = 'primary',\n weight,\n align,\n as,\n truncate = false,\n lineClamp,\n className,\n style,\n children,\n ...props\n },\n ref,\n ) => {\n const Component = as || variantElementMap[variant];\n\n return (\n <Component\n ref={ref}\n className={cn(\n styles.typography,\n styles[`variant-${variant}`],\n styles[`color-${color}`],\n weight && styles[`weight-${weight}`],\n align && styles[`align-${align}`],\n truncate && styles.truncate,\n !!lineClamp && styles.lineClamp,\n className,\n )}\n style={{\n ...style,\n ...(lineClamp ? { WebkitLineClamp: lineClamp } : undefined),\n }}\n {...props}\n >\n {children}\n </Component>\n );\n },\n);\n\nTypography.displayName = 'Typography';\n",".alert {\n display: flex;\n align-items: flex-start;\n gap: var(--bazaar-space-3);\n padding: var(--bazaar-space-4);\n border-radius: var(--bazaar-radius-md);\n border: var(--bazaar-border-width-hairline) var(--bazaar-border-style-default) transparent;\n border-left: var(--bazaar-border-width-strong) var(--bazaar-border-style-default) transparent;\n font-family: var(--bazaar-font-family-sans);\n box-shadow: var(--bazaar-shadow-xs);\n}\n\n.icon {\n flex-shrink: 0;\n display: flex;\n margin-top: 1px;\n}\n\n.content {\n flex: 1;\n min-width: 0;\n}\n\n.title {\n margin: 0;\n font-size: var(--bazaar-font-size-body-md);\n font-weight: var(--bazaar-font-weight-semibold);\n line-height: var(--bazaar-line-height-body-md);\n}\n\n.body {\n font-size: var(--bazaar-font-size-body-sm);\n line-height: var(--bazaar-line-height-body-sm);\n margin-top: var(--bazaar-space-1);\n}\n\n.action {\n flex-shrink: 0;\n}\n\n/* Status variants */\n.info {\n background-color: var(--bazaar-color-info-50);\n border-color: var(--bazaar-color-info-500);\n border-left-color: var(--bazaar-color-border-brand);\n color: var(--bazaar-color-info-700);\n}\n\n.success {\n background-color: var(--bazaar-color-success-50);\n border-color: var(--bazaar-color-success-500);\n border-left-color: var(--bazaar-color-border-success);\n color: var(--bazaar-color-success-700);\n}\n\n.warning {\n background-color: var(--bazaar-color-warning-50);\n border-color: var(--bazaar-color-warning-500);\n border-left-color: var(--bazaar-color-border-warning);\n color: var(--bazaar-color-warning-700);\n}\n\n.error {\n background-color: var(--bazaar-color-error-50);\n border-color: var(--bazaar-color-error-500);\n border-left-color: var(--bazaar-color-border-error);\n color: var(--bazaar-color-error-700);\n}\n","import { type HTMLAttributes, type ReactNode } from 'react';\nimport { cn } from '../../utils/cn';\nimport styles from './Alert.module.css';\n\nexport interface AlertProps extends HTMLAttributes<HTMLDivElement> {\n /** Semantic status */\n status?: 'info' | 'success' | 'warning' | 'error';\n /** Optional title */\n title?: string;\n /** Optional action element (e.g., a close button) */\n action?: ReactNode;\n}\n\nconst statusIcons: Record<string, ReactNode> = {\n info: (\n <svg width=\"20\" height=\"20\" viewBox=\"0 0 20 20\" fill=\"currentColor\">\n <path d=\"M10 0a10 10 0 110 20 10 10 0 010-20zm0 8a1 1 0 00-1 1v5a1 1 0 102 0V9a1 1 0 00-1-1zm0-3.5a1 1 0 100 2 1 1 0 000-2z\" />\n </svg>\n ),\n success: (\n <svg width=\"20\" height=\"20\" viewBox=\"0 0 20 20\" fill=\"currentColor\">\n <path d=\"M10 0a10 10 0 110 20 10 10 0 010-20zm4.3 7.3a1 1 0 00-1.4-1.4L8.5 10.3 7.1 8.9a1 1 0 10-1.4 1.4l2.1 2.1a1 1 0 001.4 0l5.1-5.1z\" />\n </svg>\n ),\n warning: (\n <svg width=\"20\" height=\"20\" viewBox=\"0 0 20 20\" fill=\"currentColor\">\n <path d=\"M10 0a10 10 0 110 20 10 10 0 010-20zm0 13a1 1 0 100 2 1 1 0 000-2zm0-8a1 1 0 00-1 1v4a1 1 0 102 0V6a1 1 0 00-1-1z\" />\n </svg>\n ),\n error: (\n <svg width=\"20\" height=\"20\" viewBox=\"0 0 20 20\" fill=\"currentColor\">\n <path d=\"M10 0a10 10 0 110 20 10 10 0 010-20zm3.5 6.5a1 1 0 00-1.4 0L10 8.6 7.9 6.5a1 1 0 10-1.4 1.4L8.6 10l-2.1 2.1a1 1 0 101.4 1.4L10 11.4l2.1 2.1a1 1 0 001.4-1.4L11.4 10l2.1-2.1a1 1 0 000-1.4z\" />\n </svg>\n ),\n};\n\n/**\n * Alert — contextual message banner.\n *\n * Accessibility:\n * - Uses role=\"alert\" for errors/warnings (live region, immediately announced)\n * - Uses role=\"status\" for info/success (polite announcement)\n * - Icon + color + text ensures meaning is communicated multiple ways\n */\nexport function Alert({ status = 'info', title, action, className, children, ...props }: AlertProps) {\n const isUrgent = status === 'error' || status === 'warning';\n\n return (\n <div\n className={cn(styles.alert, styles[status], className)}\n role={isUrgent ? 'alert' : 'status'}\n {...props}\n >\n <span className={styles.icon} aria-hidden=\"true\">{statusIcons[status]}</span>\n <div className={styles.content}>\n {title && <p className={styles.title}>{title}</p>}\n {children && <div className={styles.body}>{children}</div>}\n </div>\n {action && <div className={styles.action}>{action}</div>}\n </div>\n );\n}\n",".backdrop {\n position: fixed;\n inset: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: var(--bazaar-z-overlay, 1300);\n animation: bazaar-backdrop-fade-in var(--bazaar-motion-duration-slow) var(--bazaar-motion-easing-standard) both;\n}\n\n/* Variants */\n.default {\n background-color: var(--bazaar-color-overlay-scrim, rgba(22, 32, 43, 0.48));\n}\n\n.light {\n background-color: rgba(22, 32, 43, 0.24);\n}\n\n.opaque {\n background-color: var(--bazaar-color-neutral-900);\n}\n\n@keyframes bazaar-backdrop-fade-in {\n from { opacity: 0; }\n to { opacity: 1; }\n}\n","import { useEffect, type HTMLAttributes, type MouseEvent } from 'react';\nimport { cn } from '../../utils/cn';\nimport styles from './Backdrop.module.css';\n\nexport interface BackdropProps extends Omit<HTMLAttributes<HTMLDivElement>, 'onClick'> {\n /** Whether the backdrop is visible */\n open: boolean;\n /** Called when the backdrop is clicked */\n onClick?: (e: MouseEvent<HTMLDivElement>) => void;\n /** Whether clicking the backdrop should be ignored (e.g. mandatory dialog) */\n disableClick?: boolean;\n /** Whether to lock body scroll while open */\n lockScroll?: boolean;\n /** Visual intensity */\n variant?: 'default' | 'light' | 'opaque';\n}\n\n/**\n * Backdrop — fullscreen overlay primitive.\n *\n * Backdrop provides the scrim layer behind Modal, Drawer, and Dialog.\n * It handles body scroll locking, click-to-dismiss, and fade animation.\n *\n * Accessibility:\n * - aria-hidden=\"true\" — the backdrop itself is not interactive content\n * - Focus management is the responsibility of the surface component (Modal, Drawer)\n * - Body scroll lock prevents background content from scrolling under the overlay\n */\nexport function Backdrop({\n open,\n onClick,\n disableClick = false,\n lockScroll = true,\n variant = 'default',\n className,\n children,\n ...props\n}: BackdropProps) {\n useEffect(() => {\n if (!lockScroll) return;\n\n if (open) {\n const prev = document.body.style.overflow;\n document.body.style.overflow = 'hidden';\n return () => {\n document.body.style.overflow = prev;\n };\n }\n }, [open, lockScroll]);\n\n if (!open) return null;\n\n const handleClick = (e: MouseEvent<HTMLDivElement>) => {\n if (disableClick) return;\n if (e.target === e.currentTarget) {\n onClick?.(e);\n }\n };\n\n return (\n <div\n className={cn(styles.backdrop, styles[variant], className)}\n aria-hidden=\"true\"\n onClick={handleClick}\n {...props}\n >\n {children}\n </div>\n );\n}\n",".dialog {\n border: none;\n border-radius: var(--bazaar-radius-xl);\n padding: 0;\n box-shadow: var(--bazaar-shadow-xl);\n background-color: var(--bazaar-color-surface-overlay);\n width: 420px;\n max-width: 90vw;\n}\n\n.dialog::backdrop {\n background-color: var(--bazaar-color-overlay-scrim);\n animation: bazaar-backdrop-in var(--bazaar-motion-duration-slow) var(--bazaar-motion-easing-standard);\n}\n\n.dialog[open] {\n animation: bazaar-dialog-in var(--bazaar-motion-duration-slow) var(--bazaar-motion-easing-standard);\n}\n\n.content {\n padding: var(--bazaar-space-6);\n font-family: var(--bazaar-font-family-sans);\n}\n\n.dangerIcon {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 48px;\n height: 48px;\n border-radius: var(--bazaar-radius-full);\n background-color: var(--bazaar-color-error-50);\n color: var(--bazaar-color-error-500);\n margin-bottom: var(--bazaar-space-4);\n}\n\n.title {\n margin: 0;\n font-size: var(--bazaar-font-size-heading-md);\n font-weight: var(--bazaar-font-weight-semibold);\n line-height: var(--bazaar-line-height-heading-md);\n color: var(--bazaar-color-text-primary);\n}\n\n.message {\n margin-top: var(--bazaar-space-2);\n font-size: var(--bazaar-font-size-body-md);\n line-height: var(--bazaar-line-height-body-md);\n color: var(--bazaar-color-text-secondary);\n}\n\n.message p {\n margin: 0;\n}\n\n.actions {\n display: flex;\n justify-content: flex-end;\n gap: var(--bazaar-space-3);\n margin-top: var(--bazaar-space-6);\n}\n\n.cancelButton,\n.confirmButton {\n padding: var(--bazaar-space-2) var(--bazaar-space-5);\n border-radius: var(--bazaar-radius-md);\n font-family: var(--bazaar-font-family-sans);\n font-size: var(--bazaar-font-size-body-sm);\n font-weight: var(--bazaar-font-weight-medium);\n line-height: var(--bazaar-line-height-body-md);\n cursor: pointer;\n transition:\n background-color var(--bazaar-motion-duration-fast) var(--bazaar-motion-easing-standard),\n box-shadow var(--bazaar-motion-duration-fast) var(--bazaar-motion-easing-standard);\n}\n\n.cancelButton {\n background-color: var(--bazaar-color-surface-default);\n border: var(--bazaar-border-width-hairline) var(--bazaar-border-style-default) var(--bazaar-color-border-default);\n color: var(--bazaar-color-text-primary);\n}\n\n.cancelButton:hover {\n background-color: var(--bazaar-color-surface-hover);\n}\n\n.cancelButton:focus-visible,\n.confirmButton:focus-visible {\n outline: var(--bazaar-border-width-medium) solid var(--bazaar-focus-outline-color);\n outline-offset: var(--bazaar-focus-ring-offset);\n box-shadow: var(--bazaar-shadow-focus);\n}\n\n.cancelButton:disabled,\n.confirmButton:disabled {\n opacity: 0.6;\n cursor: not-allowed;\n}\n\n.confirmButton.default {\n background-color: var(--bazaar-color-info-600);\n border: none;\n color: #fff;\n}\n\n.confirmButton.default:hover:not(:disabled) {\n background-color: var(--bazaar-color-info-700);\n}\n\n.confirmButton.danger {\n background-color: var(--bazaar-color-error-600);\n border: none;\n color: #fff;\n}\n\n.confirmButton.danger:hover:not(:disabled) {\n background-color: var(--bazaar-color-error-700);\n}\n\n@keyframes bazaar-dialog-in {\n from {\n opacity: 0;\n transform: translateY(8px) scale(0.98);\n }\n to {\n opacity: 1;\n transform: translateY(0) scale(1);\n }\n}\n\n@keyframes bazaar-backdrop-in {\n from { opacity: 0; }\n to { opacity: 1; }\n}\n","import { useEffect, useRef, type ReactNode } from 'react';\nimport { cn } from '../../utils/cn';\nimport styles from './Dialog.module.css';\n\nexport interface DialogProps {\n /** Whether the dialog is open */\n open: boolean;\n /** Called when the user confirms */\n onConfirm: () => void;\n /** Called when the user cancels */\n onCancel: () => void;\n /** Dialog title */\n title: string;\n /** Message or content */\n message: string | ReactNode;\n /** Confirm button label */\n confirmLabel?: string;\n /** Cancel button label */\n cancelLabel?: string;\n /** Visual variant */\n variant?: 'default' | 'danger';\n /** Show loading state on confirm button */\n loading?: boolean;\n /** Additional class name */\n className?: string;\n}\n\n/**\n * Dialog — confirmation dialog built on native <dialog>.\n *\n * Accessibility:\n * - Uses native <dialog> for built-in focus trapping and Escape handling\n * - aria-labelledby links to the title\n * - aria-describedby links to the message\n * - Focus moves to cancel button on open (safe default)\n * - Escape key closes the dialog\n * - Backdrop click cancels\n */\nexport function Dialog({\n open,\n onConfirm,\n onCancel,\n title,\n message,\n confirmLabel = 'Confirm',\n cancelLabel = 'Cancel',\n variant = 'default',\n loading = false,\n className,\n}: DialogProps) {\n const dialogRef = useRef<HTMLDialogElement>(null);\n const cancelRef = useRef<HTMLButtonElement>(null);\n\n useEffect(() => {\n const dialog = dialogRef.current;\n if (!dialog) return;\n\n if (open && !dialog.open) {\n dialog.showModal();\n cancelRef.current?.focus();\n } else if (!open && dialog.open) {\n dialog.close();\n }\n }, [open]);\n\n useEffect(() => {\n const dialog = dialogRef.current;\n if (!dialog) return;\n\n const handleClose = () => onCancel();\n dialog.addEventListener('close', handleClose);\n return () => dialog.removeEventListener('close', handleClose);\n }, [onCancel]);\n\n const handleBackdropClick = (e: React.MouseEvent<HTMLDialogElement>) => {\n if (e.target === dialogRef.current) {\n onCancel();\n }\n };\n\n return (\n <dialog\n ref={dialogRef}\n className={cn(styles.dialog, className)}\n aria-labelledby=\"bazaar-dialog-title\"\n aria-describedby=\"bazaar-dialog-message\"\n onClick={handleBackdropClick}\n >\n <div className={styles.content}>\n {variant === 'danger' && (\n <div className={styles.dangerIcon} aria-hidden=\"true\">\n <svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"currentColor\">\n <path d=\"M12 0a12 12 0 110 24 12 12 0 010-24zm0 15a1.25 1.25 0 100 2.5 1.25 1.25 0 000-2.5zm0-9a1 1 0 00-1 1v5.5a1 1 0 102 0V7a1 1 0 00-1-1z\" />\n </svg>\n </div>\n )}\n <h2 id=\"bazaar-dialog-title\" className={styles.title}>{title}</h2>\n <div id=\"bazaar-dialog-message\" className={styles.message}>\n {typeof message === 'string' ? <p>{message}</p> : message}\n </div>\n <div className={styles.actions}>\n <button\n ref={cancelRef}\n className={styles.cancelButton}\n onClick={onCancel}\n type=\"button\"\n disabled={loading}\n >\n {cancelLabel}\n </button>\n <button\n className={cn(styles.confirmButton, styles[variant])}\n onClick={onConfirm}\n type=\"button\"\n disabled={loading}\n aria-busy={loading}\n >\n {loading ? 'Loading...' : confirmLabel}\n </button>\n </div>\n </div>\n </dialog>\n );\n}\n",".container {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: var(--bazaar-space-12) var(--bazaar-space-6);\n text-align: center;\n}\n\n.icon {\n margin-bottom: var(--bazaar-space-4);\n color: var(--bazaar-color-text-muted);\n font-size: 48px;\n line-height: 1;\n}\n\n.title {\n margin: 0;\n font-family: var(--bazaar-font-family-sans);\n font-size: var(--bazaar-font-size-heading-sm);\n font-weight: var(--bazaar-font-weight-semibold);\n line-height: var(--bazaar-line-height-heading-sm);\n color: var(--bazaar-color-text-primary);\n}\n\n.description {\n margin: var(--bazaar-space-2) 0 0;\n font-family: var(--bazaar-font-family-sans);\n font-size: var(--bazaar-font-size-body-md);\n line-height: var(--bazaar-line-height-body-md);\n color: var(--bazaar-color-text-muted);\n max-width: 360px;\n}\n\n.action {\n margin-top: var(--bazaar-space-6);\n}\n","import { type ReactNode, type HTMLAttributes } from 'react';\nimport { cn } from '../../utils/cn';\nimport styles from './EmptyState.module.css';\n\nexport interface EmptyStateProps extends HTMLAttributes<HTMLDivElement> {\n /** Optional icon displayed above the title */\n icon?: ReactNode;\n /** Title text */\n title: string;\n /** Descriptive text below the title */\n description?: string;\n /** Optional action element (e.g., a button) */\n action?: ReactNode;\n}\n\n/**\n * EmptyState — centered placeholder for empty tables, lists, or views.\n *\n * Accessibility:\n * - Uses semantic heading and paragraph elements\n * - Healthcare note: provide clear, actionable guidance in empty states\n * (e.g., \"No patients match your filters. Try adjusting your search.\")\n */\nexport function EmptyState({\n icon,\n title,\n description,\n action,\n className,\n ...props\n}: EmptyStateProps) {\n return (\n <div className={cn(styles.container, className)} {...props}>\n {icon && <div className={styles.icon} aria-hidden=\"true\">{icon}</div>}\n <h3 className={styles.title}>{title}</h3>\n {description && <p className={styles.description}>{description}</p>}\n {action && <div className={styles.action}>{action}</div>}\n </div>\n );\n}\n",".container {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: var(--bazaar-space-12) var(--bazaar-space-6);\n text-align: center;\n}\n\n.icon {\n margin-bottom: var(--bazaar-space-4);\n color: var(--bazaar-color-error-400);\n}\n\n.title {\n margin: 0;\n}\n\n.description {\n margin-top: var(--bazaar-space-2);\n max-width: 400px;\n}\n\n.action {\n margin-top: var(--bazaar-space-6);\n}\n\n.errorCode {\n margin-top: var(--bazaar-space-3);\n font-variant-numeric: tabular-nums;\n}\n","import { type HTMLAttributes, type ReactNode } from 'react';\nimport { cn } from '../../utils/cn';\nimport { Typography } from '../Typography/Typography';\nimport styles from './ErrorState.module.css';\n\nexport interface ErrorStateProps extends HTMLAttributes<HTMLDivElement> {\n /** Error title */\n title?: string;\n /** Descriptive message */\n description?: string;\n /** Custom icon (defaults to a warning icon) */\n icon?: ReactNode;\n /** Retry action element (e.g., a button) */\n action?: ReactNode;\n /** Error code or reference for support */\n errorCode?: string;\n}\n\nconst DefaultErrorIcon = () => (\n <svg width=\"48\" height=\"48\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"1.5\" strokeLinecap=\"round\" strokeLinejoin=\"round\" aria-hidden=\"true\">\n <circle cx=\"12\" cy=\"12\" r=\"10\" />\n <line x1=\"12\" y1=\"8\" x2=\"12\" y2=\"12\" />\n <line x1=\"12\" y1=\"16\" x2=\"12.01\" y2=\"16\" />\n </svg>\n);\n\n/**\n * ErrorState — centered error placeholder with retry action.\n *\n * Composes: Typography\n *\n * Use in place of content when a data fetch fails, a page errors,\n * or a section cannot render. Provides clear messaging, an optional\n * error code for support, and a retry action.\n *\n * Accessibility:\n * - Uses role=\"alert\" to announce the error to screen readers\n * - Action button receives focus for quick retry\n */\nexport function ErrorState({\n title = 'Something went wrong',\n description,\n icon,\n action,\n errorCode,\n className,\n ...props\n}: ErrorStateProps) {\n return (\n <div\n className={cn(styles.container, className)}\n role=\"alert\"\n {...props}\n >\n <div className={styles.icon}>\n {icon ?? <DefaultErrorIcon />}\n </div>\n <Typography variant=\"heading-sm\" as=\"h3\" className={styles.title}>\n {title}\n </Typography>\n {description && (\n <Typography variant=\"body-md\" color=\"muted\" className={styles.description}>\n {description}\n </Typography>\n )}\n {action && <div className={styles.action}>{action}</div>}\n {errorCode && (\n <Typography variant=\"caption\" color=\"muted\" className={styles.errorCode}>\n Error code: {errorCode}\n </Typography>\n )}\n </div>\n );\n}\n",".toast {\n position: fixed;\n bottom: var(--bazaar-space-6);\n right: var(--bazaar-space-6);\n z-index: 9999;\n display: flex;\n align-items: flex-start;\n gap: var(--bazaar-space-3);\n padding: var(--bazaar-space-4) var(--bazaar-space-5);\n border-radius: var(--bazaar-radius-lg);\n background-color: var(--bazaar-color-surface-overlay);\n border: var(--bazaar-border-width-hairline) var(--bazaar-border-style-default) var(--bazaar-color-border-default);\n box-shadow: var(--bazaar-shadow-lg);\n font-family: var(--bazaar-font-family-sans);\n max-width: 420px;\n min-width: 280px;\n animation: bazaar-toast-in var(--bazaar-motion-duration-slow) var(--bazaar-motion-easing-standard);\n}\n\n.icon {\n flex-shrink: 0;\n display: flex;\n margin-top: 1px;\n}\n\n.content {\n flex: 1;\n min-width: 0;\n}\n\n.title {\n margin: 0;\n font-size: var(--bazaar-font-size-body-md);\n font-weight: var(--bazaar-font-weight-semibold);\n line-height: var(--bazaar-line-height-body-md);\n color: var(--bazaar-color-text-primary);\n}\n\n.message {\n margin: 0;\n font-size: var(--bazaar-font-size-body-sm);\n line-height: var(--bazaar-line-height-body-sm);\n color: var(--bazaar-color-text-secondary);\n}\n\n.title + .message {\n margin-top: var(--bazaar-space-1);\n}\n\n.action {\n flex-shrink: 0;\n align-self: center;\n}\n\n.close {\n flex-shrink: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n width: 28px;\n height: 28px;\n border: none;\n border-radius: var(--bazaar-radius-sm);\n background: transparent;\n color: var(--bazaar-color-text-muted);\n cursor: pointer;\n transition:\n background-color var(--bazaar-motion-duration-fast) var(--bazaar-motion-easing-standard),\n color var(--bazaar-motion-duration-fast) var(--bazaar-motion-easing-standard);\n}\n\n.close:hover {\n background-color: var(--bazaar-color-surface-hover);\n color: var(--bazaar-color-text-primary);\n}\n\n.close:focus-visible {\n outline: var(--bazaar-border-width-medium) solid var(--bazaar-focus-outline-color);\n outline-offset: var(--bazaar-focus-ring-offset);\n box-shadow: var(--bazaar-shadow-focus);\n}\n\n/* Status variants — left border accent */\n.info {\n border-left: var(--bazaar-border-width-strong) var(--bazaar-border-style-default) var(--bazaar-color-info-500);\n}\n\n.info .icon { color: var(--bazaar-color-info-500); }\n\n.success {\n border-left: var(--bazaar-border-width-strong) var(--bazaar-border-style-default) var(--bazaar-color-success-500);\n}\n\n.success .icon { color: var(--bazaar-color-success-500); }\n\n.warning {\n border-left: var(--bazaar-border-width-strong) var(--bazaar-border-style-default) var(--bazaar-color-warning-500);\n}\n\n.warning .icon { color: var(--bazaar-color-warning-500); }\n\n.error {\n border-left: var(--bazaar-border-width-strong) var(--bazaar-border-style-default) var(--bazaar-color-error-500);\n}\n\n.error .icon { color: var(--bazaar-color-error-500); }\n\n@keyframes bazaar-toast-in {\n from {\n opacity: 0;\n transform: translateY(12px) scale(0.96);\n }\n to {\n opacity: 1;\n transform: translateY(0) scale(1);\n }\n}\n","import { useEffect, type ReactNode } from 'react';\nimport { cn } from '../../utils/cn';\nimport styles from './Toast.module.css';\n\nexport type ToastStatus = 'info' | 'success' | 'warning' | 'error';\n\nexport interface ToastProps {\n /** Toast message */\n message: string;\n /** Optional title */\n title?: string;\n /** Status variant */\n status?: ToastStatus;\n /** Optional action element */\n action?: ReactNode;\n /** Called when toast is closed */\n onClose: () => void;\n /** Auto-dismiss duration in ms (0 to disable) */\n duration?: number;\n /** Additional class name */\n className?: string;\n}\n\nconst statusIcons: Record<ToastStatus, ReactNode> = {\n info: (\n <svg width=\"20\" height=\"20\" viewBox=\"0 0 20 20\" fill=\"currentColor\">\n <path d=\"M10 0a10 10 0 110 20 10 10 0 010-20zm0 8a1 1 0 00-1 1v5a1 1 0 102 0V9a1 1 0 00-1-1zm0-3.5a1 1 0 100 2 1 1 0 000-2z\" />\n </svg>\n ),\n success: (\n <svg width=\"20\" height=\"20\" viewBox=\"0 0 20 20\" fill=\"currentColor\">\n <path d=\"M10 0a10 10 0 110 20 10 10 0 010-20zm4.3 7.3a1 1 0 00-1.4-1.4L8.5 10.3 7.1 8.9a1 1 0 10-1.4 1.4l2.1 2.1a1 1 0 001.4 0l5.1-5.1z\" />\n </svg>\n ),\n warning: (\n <svg width=\"20\" height=\"20\" viewBox=\"0 0 20 20\" fill=\"currentColor\">\n <path d=\"M10 0a10 10 0 110 20 10 10 0 010-20zm0 13a1 1 0 100 2 1 1 0 000-2zm0-8a1 1 0 00-1 1v4a1 1 0 102 0V6a1 1 0 00-1-1z\" />\n </svg>\n ),\n error: (\n <svg width=\"20\" height=\"20\" viewBox=\"0 0 20 20\" fill=\"currentColor\">\n <path d=\"M10 0a10 10 0 110 20 10 10 0 010-20zm3.5 6.5a1 1 0 00-1.4 0L10 8.6 7.9 6.5a1 1 0 10-1.4 1.4L8.6 10l-2.1 2.1a1 1 0 101.4 1.4L10 11.4l2.1 2.1a1 1 0 001.4-1.4L11.4 10l2.1-2.1a1 1 0 000-1.4z\" />\n </svg>\n ),\n};\n\n/**\n * Toast — transient notification that auto-dismisses.\n *\n * Accessibility:\n * - Uses role=\"alert\" for error/warning (assertive), role=\"status\" for info/success (polite)\n * - Close button has accessible label\n * - Auto-dismiss can be disabled for important messages\n * - Icon + color + text ensures meaning is communicated multiple ways\n */\nexport function Toast({\n message,\n title,\n status = 'info',\n action,\n onClose,\n duration = 5000,\n className,\n}: ToastProps) {\n useEffect(() => {\n if (duration <= 0) return;\n const timer = setTimeout(onClose, duration);\n return () => clearTimeout(timer);\n }, [duration, onClose]);\n\n const isUrgent = status === 'error' || status === 'warning';\n\n return (\n <div\n className={cn(styles.toast, styles[status], className)}\n role={isUrgent ? 'alert' : 'status'}\n >\n <span className={styles.icon} aria-hidden=\"true\">\n {statusIcons[status]}\n </span>\n <div className={styles.content}>\n {title && <p className={styles.title}>{title}</p>}\n <p className={styles.message}>{message}</p>\n </div>\n {action && <div className={styles.action}>{action}</div>}\n <button\n className={styles.close}\n onClick={onClose}\n aria-label=\"Dismiss notification\"\n type=\"button\"\n >\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"1.75\" strokeLinecap=\"round\">\n <line x1=\"4\" y1=\"4\" x2=\"12\" y2=\"12\" />\n <line x1=\"12\" y1=\"4\" x2=\"4\" y2=\"12\" />\n </svg>\n </button>\n </div>\n );\n}\n",".banner {\n width: 100%;\n font-family: var(--bazaar-font-family-sans);\n}\n\n.inner {\n display: flex;\n align-items: center;\n gap: var(--bazaar-space-3);\n padding: var(--bazaar-space-3) var(--bazaar-space-5);\n max-width: 1280px;\n margin: 0 auto;\n}\n\n.icon {\n flex-shrink: 0;\n display: flex;\n}\n\n.content {\n flex: 1;\n min-width: 0;\n font-size: var(--bazaar-font-size-body-sm);\n line-height: var(--bazaar-line-height-body-sm);\n}\n\n.action {\n flex-shrink: 0;\n}\n\n.dismiss {\n flex-shrink: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n width: 28px;\n height: 28px;\n border: none;\n border-radius: var(--bazaar-radius-sm);\n background: transparent;\n cursor: pointer;\n opacity: 0.7;\n transition:\n opacity var(--bazaar-motion-duration-fast) var(--bazaar-motion-easing-standard),\n background-color var(--bazaar-motion-duration-fast) var(--bazaar-motion-easing-standard);\n}\n\n.dismiss:hover {\n opacity: 1;\n background-color: rgba(0, 0, 0, 0.08);\n}\n\n.dismiss:focus-visible {\n outline: var(--bazaar-border-width-medium) solid var(--bazaar-focus-outline-color);\n outline-offset: var(--bazaar-focus-ring-offset);\n box-shadow: var(--bazaar-shadow-focus);\n}\n\n/* Status variants */\n.info {\n background-color: var(--bazaar-color-info-50);\n border-bottom: var(--bazaar-border-width-hairline) var(--bazaar-border-style-default) var(--bazaar-color-info-200);\n color: var(--bazaar-color-info-700);\n}\n\n.info .dismiss { color: var(--bazaar-color-info-600); }\n\n.success {\n background-color: var(--bazaar-color-success-50);\n border-bottom: var(--bazaar-border-width-hairline) var(--bazaar-border-style-default) var(--bazaar-color-success-200);\n color: var(--bazaar-color-success-700);\n}\n\n.success .dismiss { color: var(--bazaar-color-success-600); }\n\n.warning {\n background-color: var(--bazaar-color-warning-50);\n border-bottom: var(--bazaar-border-width-hairline) var(--bazaar-border-style-default) var(--bazaar-color-warning-200);\n color: var(--bazaar-color-warning-700);\n}\n\n.warning .dismiss { color: var(--bazaar-color-warning-600); }\n\n.error {\n background-color: var(--bazaar-color-error-50);\n border-bottom: var(--bazaar-border-width-hairline) var(--bazaar-border-style-default) var(--bazaar-color-error-200);\n color: var(--bazaar-color-error-700);\n}\n\n.error .dismiss { color: var(--bazaar-color-error-600); }\n","import { type HTMLAttributes, type ReactNode } from 'react';\nimport { cn } from '../../utils/cn';\nimport styles from './Banner.module.css';\n\nexport type BannerStatus = 'info' | 'success' | 'warning' | 'error';\n\nexport interface BannerProps extends HTMLAttributes<HTMLDivElement> {\n /** Status variant */\n status?: BannerStatus;\n /** Whether the banner can be dismissed */\n dismissible?: boolean;\n /** Called when dismiss button is clicked */\n onDismiss?: () => void;\n /** Optional action element */\n action?: ReactNode;\n /** Banner content */\n children: ReactNode;\n}\n\nconst statusIcons: Record<BannerStatus, ReactNode> = {\n info: (\n <svg width=\"20\" height=\"20\" viewBox=\"0 0 20 20\" fill=\"currentColor\">\n <path d=\"M10 0a10 10 0 110 20 10 10 0 010-20zm0 8a1 1 0 00-1 1v5a1 1 0 102 0V9a1 1 0 00-1-1zm0-3.5a1 1 0 100 2 1 1 0 000-2z\" />\n </svg>\n ),\n success: (\n <svg width=\"20\" height=\"20\" viewBox=\"0 0 20 20\" fill=\"currentColor\">\n <path d=\"M10 0a10 10 0 110 20 10 10 0 010-20zm4.3 7.3a1 1 0 00-1.4-1.4L8.5 10.3 7.1 8.9a1 1 0 10-1.4 1.4l2.1 2.1a1 1 0 001.4 0l5.1-5.1z\" />\n </svg>\n ),\n warning: (\n <svg width=\"20\" height=\"20\" viewBox=\"0 0 20 20\" fill=\"currentColor\">\n <path d=\"M10 0a10 10 0 110 20 10 10 0 010-20zm0 13a1 1 0 100 2 1 1 0 000-2zm0-8a1 1 0 00-1 1v4a1 1 0 102 0V6a1 1 0 00-1-1z\" />\n </svg>\n ),\n error: (\n <svg width=\"20\" height=\"20\" viewBox=\"0 0 20 20\" fill=\"currentColor\">\n <path d=\"M10 0a10 10 0 110 20 10 10 0 010-20zm3.5 6.5a1 1 0 00-1.4 0L10 8.6 7.9 6.5a1 1 0 10-1.4 1.4L8.6 10l-2.1 2.1a1 1 0 101.4 1.4L10 11.4l2.1 2.1a1 1 0 001.4-1.4L11.4 10l2.1-2.1a1 1 0 000-1.4z\" />\n </svg>\n ),\n};\n\n/**\n * Banner — full-width banner for page-level messages.\n *\n * Accessibility:\n * - Uses role=\"alert\" for error/warning (assertive announcement)\n * - Uses role=\"status\" for info/success (polite announcement)\n * - Icon + color + text ensures meaning is communicated multiple ways\n * - Dismiss button has accessible label\n */\nexport function Banner({\n status = 'info',\n dismissible = false,\n onDismiss,\n action,\n children,\n className,\n ...props\n}: BannerProps) {\n const isUrgent = status === 'error' || status === 'warning';\n\n return (\n <div\n className={cn(styles.banner, styles[status], className)}\n role={isUrgent ? 'alert' : 'status'}\n {...props}\n >\n <div className={styles.inner}>\n <span className={styles.icon} aria-hidden=\"true\">\n {statusIcons[status]}\n </span>\n <div className={styles.content}>{children}</div>\n {action && <div className={styles.action}>{action}</div>}\n {dismissible && (\n <button\n className={styles.dismiss}\n onClick={onDismiss}\n aria-label=\"Dismiss banner\"\n type=\"button\"\n >\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"1.75\" strokeLinecap=\"round\">\n <line x1=\"4\" y1=\"4\" x2=\"12\" y2=\"12\" />\n <line x1=\"12\" y1=\"4\" x2=\"4\" y2=\"12\" />\n </svg>\n </button>\n )}\n </div>\n </div>\n );\n}\n",".accordion {\n font-family: var(--bazaar-font-family-sans);\n border: var(--bazaar-border-width-hairline) var(--bazaar-border-style-default) var(--bazaar-color-border-default);\n border-radius: var(--bazaar-radius-md);\n overflow: hidden;\n}\n\n.item {\n border-bottom: var(--bazaar-border-width-hairline) var(--bazaar-border-style-default) var(--bazaar-color-border-default);\n}\n\n.item:last-child {\n border-bottom: none;\n}\n\n.heading {\n margin: 0;\n}\n\n.trigger {\n display: flex;\n align-items: center;\n justify-content: space-between;\n width: 100%;\n padding: var(--bazaar-space-4);\n background: var(--bazaar-color-surface-default);\n border: none;\n cursor: pointer;\n font-family: inherit;\n font-size: var(--bazaar-font-size-body-md);\n font-weight: var(--bazaar-font-weight-medium);\n line-height: var(--bazaar-line-height-body-md);\n color: var(--bazaar-color-text-primary);\n text-align: left;\n transition: background-color var(--bazaar-motion-duration-fast) var(--bazaar-motion-easing-standard);\n}\n\n.trigger:hover {\n background-color: var(--bazaar-color-surface-hover);\n}\n\n.trigger:focus-visible {\n outline: var(--bazaar-border-width-medium) solid var(--bazaar-focus-outline-color);\n outline-offset: calc(-1 * var(--bazaar-border-width-medium));\n box-shadow: var(--bazaar-shadow-focus);\n z-index: 1;\n position: relative;\n}\n\n.triggerLabel {\n flex: 1;\n min-width: 0;\n}\n\n.chevron {\n flex-shrink: 0;\n color: var(--bazaar-color-text-muted);\n transition: transform var(--bazaar-motion-duration-fast) var(--bazaar-motion-easing-standard);\n}\n\n.open .chevron {\n transform: rotate(180deg);\n}\n\n.panel {\n overflow: hidden;\n transition: height 200ms var(--bazaar-motion-easing-standard);\n}\n\n.panelContent {\n padding: 0 var(--bazaar-space-4) var(--bazaar-space-4);\n font-size: var(--bazaar-font-size-body-sm);\n line-height: var(--bazaar-line-height-body-sm);\n color: var(--bazaar-color-text-secondary);\n}\n","import { useState, useCallback, useRef, useEffect, type ReactNode } from 'react';\nimport { cn } from '../../utils/cn';\nimport styles from './Accordion.module.css';\n\nexport interface AccordionItem {\n /** Unique identifier */\n id: string;\n /** Header title */\n title: string;\n /** Panel content */\n content: ReactNode;\n}\n\nexport interface AccordionProps {\n /** Accordion items */\n items: AccordionItem[];\n /** Allow multiple panels to be open simultaneously */\n allowMultiple?: boolean;\n /** IDs of panels open by default */\n defaultOpenIds?: string[];\n /** Additional className */\n className?: string;\n}\n\nfunction AccordionPanel({\n item,\n isOpen,\n onToggle,\n}: {\n item: AccordionItem;\n isOpen: boolean;\n onToggle: (id: string) => void;\n}) {\n const contentRef = useRef<HTMLDivElement>(null);\n const [height, setHeight] = useState<number | undefined>(isOpen ? undefined : 0);\n\n useEffect(() => {\n if (!contentRef.current) return;\n if (isOpen) {\n setHeight(contentRef.current.scrollHeight);\n const timer = setTimeout(() => setHeight(undefined), 200);\n return () => clearTimeout(timer);\n } else {\n setHeight(contentRef.current.scrollHeight);\n requestAnimationFrame(() => {\n requestAnimationFrame(() => setHeight(0));\n });\n }\n }, [isOpen]);\n\n const triggerId = `accordion-trigger-${item.id}`;\n const panelId = `accordion-panel-${item.id}`;\n\n return (\n <div className={cn(styles.item, isOpen && styles.open)}>\n <h3 className={styles.heading}>\n <button\n type=\"button\"\n id={triggerId}\n className={styles.trigger}\n aria-expanded={isOpen}\n aria-controls={panelId}\n onClick={() => onToggle(item.id)}\n >\n <span className={styles.triggerLabel}>{item.title}</span>\n <svg\n className={styles.chevron}\n width=\"20\"\n height=\"20\"\n viewBox=\"0 0 20 20\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n >\n <polyline points=\"6 8 10 12 14 8\" />\n </svg>\n </button>\n </h3>\n <div\n id={panelId}\n role=\"region\"\n aria-labelledby={triggerId}\n className={styles.panel}\n style={{ height: height !== undefined ? `${height}px` : 'auto' }}\n hidden={!isOpen && height === 0}\n >\n <div ref={contentRef} className={styles.panelContent}>\n {item.content}\n </div>\n </div>\n </div>\n );\n}\n\n/**\n * Accordion — expandable/collapsible content sections.\n *\n * Accessibility:\n * - Button triggers with aria-expanded and aria-controls\n * - Content panels have role=\"region\" and aria-labelledby\n * - Animated expand/collapse with proper height transitions\n * - Supports single or multiple open panels\n */\nexport function Accordion({ items, allowMultiple = false, defaultOpenIds = [], className }: AccordionProps) {\n const [openIds, setOpenIds] = useState<Set<string>>(new Set(defaultOpenIds));\n\n const handleToggle = useCallback(\n (id: string) => {\n setOpenIds((prev) => {\n const next = new Set(prev);\n if (next.has(id)) {\n next.delete(id);\n } else {\n if (!allowMultiple) {\n next.clear();\n }\n next.add(id);\n }\n return next;\n });\n },\n [allowMultiple],\n );\n\n return (\n <div className={cn(styles.accordion, className)}>\n {items.map((item) => (\n <AccordionPanel\n key={item.id}\n item={item}\n isOpen={openIds.has(item.id)}\n onToggle={handleToggle}\n />\n ))}\n </div>\n );\n}\n",".appBar {\n width: 100%;\n height: 56px;\n background-color: var(--bazaar-color-surface-default);\n border-bottom: var(--bazaar-border-width-hairline) var(--bazaar-border-style-default) var(--bazaar-color-border-default);\n box-shadow: var(--bazaar-shadow-sm);\n font-family: var(--bazaar-font-family-sans);\n}\n\n.inner {\n display: flex;\n align-items: center;\n height: 100%;\n padding: 0 var(--bazaar-space-5);\n gap: var(--bazaar-space-6);\n}\n\n.logo {\n display: flex;\n align-items: center;\n flex-shrink: 0;\n font-size: var(--bazaar-font-size-heading-sm);\n font-weight: var(--bazaar-font-weight-bold);\n color: var(--bazaar-color-text-primary);\n}\n\n.nav {\n display: flex;\n align-items: center;\n gap: var(--bazaar-space-1);\n flex: 1;\n min-width: 0;\n}\n\n.actions {\n display: flex;\n align-items: center;\n gap: var(--bazaar-space-3);\n flex-shrink: 0;\n margin-left: auto;\n}\n","import { type HTMLAttributes, type ReactNode } from 'react';\nimport { cn } from '../../utils/cn';\nimport styles from './AppBar.module.css';\n\nexport interface AppBarProps extends HTMLAttributes<HTMLElement> {\n /** Logo or brand element */\n logo?: ReactNode;\n /** Navigation items (center/left area) */\n children?: ReactNode;\n /** Action elements on the right (profile, notifications, etc.) */\n actions?: ReactNode;\n}\n\n/**\n * AppBar — horizontal top navigation bar for application headers.\n *\n * Accessibility:\n * - Uses <header> with <nav> for semantic structure\n * - Navigation items should be provided as links or buttons\n * - Fixed height with clean horizontal layout\n */\nexport function AppBar({ logo, children, actions, className, ...props }: AppBarProps) {\n return (\n <header className={cn(styles.appBar, className)} {...props}>\n <div className={styles.inner}>\n {logo && <div className={styles.logo}>{logo}</div>}\n {children && (\n <nav aria-label=\"Main navigation\" className={styles.nav}>\n {children}\n </nav>\n )}\n {actions && <div className={styles.actions}>{actions}</div>}\n </div>\n </header>\n );\n}\n",".paper {\n font-family: var(--bazaar-font-family-sans);\n transition:\n box-shadow var(--bazaar-motion-duration-base) var(--bazaar-motion-easing-standard),\n background-color var(--bazaar-motion-duration-base) var(--bazaar-motion-easing-standard);\n}\n\n/* Surfaces */\n.surface-default { background-color: var(--bazaar-color-surface-default); }\n.surface-subtle { background-color: var(--bazaar-color-surface-subtle); }\n.surface-canvas { background-color: var(--bazaar-color-surface-canvas); }\n.surface-raised { background-color: var(--bazaar-color-surface-raised); }\n.surface-overlay { background-color: var(--bazaar-color-surface-overlay, var(--bazaar-color-surface-default)); }\n\n/* Border */\n.bordered {\n border: var(--bazaar-border-width-hairline) var(--bazaar-border-style-default) var(--bazaar-color-border-default);\n}\n\n/* Elevation */\n.elevation-0 { box-shadow: var(--bazaar-shadow-none); }\n.elevation-1 { box-shadow: var(--bazaar-shadow-xs); }\n.elevation-2 { box-shadow: var(--bazaar-shadow-sm); }\n.elevation-3 { box-shadow: var(--bazaar-shadow-md); }\n.elevation-4 { box-shadow: var(--bazaar-shadow-lg); }\n\n/* Radius */\n.radius-none { border-radius: 0; }\n.radius-sm { border-radius: var(--bazaar-radius-sm); }\n.radius-md { border-radius: var(--bazaar-radius-md); }\n.radius-lg { border-radius: var(--bazaar-radius-lg); }\n.radius-xl { border-radius: var(--bazaar-radius-xl); }\n\n/* Padding */\n.pad-sm { padding: var(--bazaar-space-3); }\n.pad-md { padding: var(--bazaar-space-5); }\n.pad-lg { padding: var(--bazaar-space-8); }\n","import { forwardRef, type HTMLAttributes } from 'react';\nimport { cn } from '../../utils/cn';\nimport styles from './Paper.module.css';\n\nexport interface PaperProps extends HTMLAttributes<HTMLDivElement> {\n /** Surface background */\n surface?: 'default' | 'subtle' | 'canvas' | 'raised' | 'overlay';\n /** Elevation level (shadow depth) */\n elevation?: 0 | 1 | 2 | 3 | 4;\n /** Border radius preset */\n radius?: 'none' | 'sm' | 'md' | 'lg' | 'xl';\n /** Whether to render a border */\n bordered?: boolean;\n /** Padding preset */\n padding?: 'none' | 'sm' | 'md' | 'lg';\n /** Render as a different HTML element */\n as?: 'div' | 'section' | 'article' | 'aside' | 'header' | 'footer';\n}\n\n/**\n * Paper — the foundational surface primitive.\n *\n * Paper provides a styled surface (background, border, shadow, radius)\n * without any layout opinions. It is the atom from which Card, Modal\n * content areas, Drawer panels, and other surface components compose.\n *\n * Accessibility:\n * - Paper is a visual primitive with no semantic role by default\n * - Use the `as` prop to select the correct semantic element\n * - Add `role` and `aria-label` when the surface represents a landmark\n */\nexport const Paper = forwardRef<HTMLDivElement, PaperProps>(\n (\n {\n surface = 'default',\n elevation = 0,\n radius = 'md',\n bordered = true,\n padding = 'none',\n as: Component = 'div',\n className,\n children,\n ...props\n },\n ref,\n ) => (\n <Component\n ref={ref as any}\n className={cn(\n styles.paper,\n styles[`surface-${surface}`],\n styles[`elevation-${elevation}`],\n styles[`radius-${radius}`],\n bordered && styles.bordered,\n padding !== 'none' && styles[`pad-${padding}`],\n className,\n )}\n {...props}\n >\n {children}\n </Component>\n ),\n);\n\nPaper.displayName = 'Paper';\n","/* Card — thin layer over Paper.\n Surface, border, radius, elevation, and padding delegated to Paper.\n Only Card-specific enhancements here. */\n\n.raised {\n border-bottom: var(--bazaar-border-width-medium) var(--bazaar-border-style-default) var(--bazaar-color-border-subtle);\n}\n","import { type HTMLAttributes } from 'react';\nimport { cn } from '../../utils/cn';\nimport { Paper } from '../Paper/Paper';\nimport styles from './Card.module.css';\n\nexport interface CardProps extends HTMLAttributes<HTMLDivElement> {\n /** Elevation level */\n elevation?: 'flat' | 'raised';\n /** Padding size */\n padding?: 'none' | 'sm' | 'md' | 'lg';\n}\n\n/**\n * Card — surface container for grouping related content.\n *\n * Composes: Paper\n *\n * Card is a constrained Paper preset with two elevation levels and\n * opinionated padding. Use Paper directly when you need full control\n * over surface, elevation, and radius.\n *\n * Accessibility:\n * - Uses semantic HTML; add role=\"region\" + aria-label when card\n * represents a distinct content section\n * - Border provides separation independent of shadow (not shadow alone)\n */\nexport function Card({ elevation = 'flat', padding = 'md', className, children, ...props }: CardProps) {\n return (\n <Paper\n surface=\"default\"\n elevation={elevation === 'raised' ? 2 : 0}\n radius=\"lg\"\n bordered\n padding={padding}\n className={cn(elevation === 'raised' && styles.raised, className)}\n {...props}\n >\n {children}\n </Paper>\n );\n}\n",".dialog {\n border: none;\n border-radius: var(--bazaar-radius-xl);\n padding: 0;\n box-shadow: var(--bazaar-shadow-xl);\n background-color: var(--bazaar-color-surface-overlay);\n max-height: 85vh;\n display: flex;\n flex-direction: column;\n}\n\n.dialog::backdrop {\n background-color: var(--bazaar-color-overlay-scrim);\n animation: bazaar-backdrop-in var(--bazaar-motion-duration-slow) var(--bazaar-motion-easing-standard);\n}\n\n.dialog[open] {\n animation: bazaar-modal-in var(--bazaar-motion-duration-slow) var(--bazaar-motion-easing-standard);\n}\n\n/* Sizes */\n.sm { width: var(--bazaar-size-modal-sm); max-width: 90vw; }\n.md { width: var(--bazaar-size-modal-md); max-width: 90vw; }\n.lg { width: var(--bazaar-size-modal-lg); max-width: 90vw; }\n.xl { width: var(--bazaar-size-modal-xl); max-width: 90vw; }\n\n.content {\n display: flex;\n flex-direction: column;\n max-height: 85vh;\n}\n\n.header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: var(--bazaar-space-6) var(--bazaar-space-6) var(--bazaar-space-4);\n flex-shrink: 0;\n border-bottom: var(--bazaar-border-width-hairline) var(--bazaar-border-style-default) var(--bazaar-color-border-subtle);\n}\n\n.title {\n margin: 0;\n font-family: var(--bazaar-font-family-sans);\n font-size: var(--bazaar-font-size-heading-md);\n font-weight: var(--bazaar-font-weight-semibold);\n line-height: var(--bazaar-line-height-heading-md);\n color: var(--bazaar-color-text-primary);\n}\n\n.close {\n display: flex;\n align-items: center;\n justify-content: center;\n width: var(--bazaar-size-control-sm);\n height: var(--bazaar-size-control-sm);\n border: none;\n border-radius: var(--bazaar-radius-md);\n background: transparent;\n color: var(--bazaar-color-text-muted);\n cursor: pointer;\n flex-shrink: 0;\n transition:\n background-color var(--bazaar-motion-duration-fast) var(--bazaar-motion-easing-standard),\n color var(--bazaar-motion-duration-fast) var(--bazaar-motion-easing-standard);\n}\n\n.close:hover {\n background-color: var(--bazaar-color-surface-hover);\n color: var(--bazaar-color-text-primary);\n}\n\n.close:focus-visible {\n outline: var(--bazaar-border-width-medium) solid var(--bazaar-focus-outline-color);\n outline-offset: var(--bazaar-focus-ring-offset);\n box-shadow: var(--bazaar-shadow-focus);\n}\n\n.body {\n padding: 0 var(--bazaar-space-6);\n overflow-y: auto;\n flex: 1;\n font-family: var(--bazaar-font-family-sans);\n font-size: var(--bazaar-font-size-body-md);\n line-height: var(--bazaar-line-height-body-md);\n color: var(--bazaar-color-text-secondary);\n}\n\n.footer {\n display: flex;\n align-items: center;\n justify-content: flex-end;\n gap: var(--bazaar-space-3);\n padding: var(--bazaar-space-4) var(--bazaar-space-6) var(--bazaar-space-6);\n flex-shrink: 0;\n border-top: var(--bazaar-border-width-hairline) var(--bazaar-border-style-default) var(--bazaar-color-border-subtle);\n}\n\n@keyframes bazaar-modal-in {\n from {\n opacity: 0;\n transform: translateY(8px) scale(0.98);\n }\n to {\n opacity: 1;\n transform: translateY(0) scale(1);\n }\n}\n\n@keyframes bazaar-backdrop-in {\n from {\n opacity: 0;\n }\n to {\n opacity: 1;\n }\n}\n","import { useEffect, useRef, type ReactNode } from 'react';\nimport { cn } from '../../utils/cn';\nimport styles from './Modal.module.css';\n\nexport interface ModalProps {\n /** Additional className */\n className?: string;\n /** Whether the modal is visible */\n open: boolean;\n /** Called when the modal should close */\n onClose: () => void;\n /** Modal title (rendered in header) */\n title: ReactNode;\n /** Max width */\n size?: 'sm' | 'md' | 'lg' | 'xl';\n /** Footer actions */\n footer?: ReactNode;\n}\n\n/**\n * Modal / Dialog — overlay dialog for focused interactions.\n *\n * Accessibility:\n * - Uses native <dialog> element for built-in focus trapping and Escape handling\n * - aria-labelledby links to the title\n * - Focus is moved into the dialog on open\n * - Escape key closes the dialog\n * - Scrim click closes the dialog\n * - Healthcare note: for destructive actions (e.g., cancel appointment,\n * delete record), always include clear confirmation language in the\n * dialog and use danger-variant buttons\n */\nexport function Modal({ open, onClose, title, size = 'md', footer, className, children }: ModalProps & { children?: ReactNode }) {\n const dialogRef = useRef<HTMLDialogElement>(null);\n\n useEffect(() => {\n const dialog = dialogRef.current;\n if (!dialog) return;\n\n if (open && !dialog.open) {\n dialog.showModal();\n } else if (!open && dialog.open) {\n dialog.close();\n }\n }, [open]);\n\n useEffect(() => {\n const dialog = dialogRef.current;\n if (!dialog) return;\n\n const handleClose = () => onClose();\n dialog.addEventListener('close', handleClose);\n return () => dialog.removeEventListener('close', handleClose);\n }, [onClose]);\n\n const handleBackdropClick = (e: React.MouseEvent<HTMLDialogElement>) => {\n if (e.target === dialogRef.current) {\n onClose();\n }\n };\n\n return (\n <dialog\n ref={dialogRef}\n className={cn(styles.dialog, styles[size], className)}\n aria-labelledby=\"bazaar-modal-title\"\n onClick={handleBackdropClick}\n >\n <div className={styles.content}>\n <header className={styles.header}>\n <h2 id=\"bazaar-modal-title\" className={styles.title}>{title}</h2>\n <button\n className={styles.close}\n onClick={onClose}\n aria-label=\"Close dialog\"\n >\n <svg width=\"20\" height=\"20\" viewBox=\"0 0 20 20\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"1.75\" strokeLinecap=\"round\">\n <line x1=\"5\" y1=\"5\" x2=\"15\" y2=\"15\" />\n <line x1=\"15\" y1=\"5\" x2=\"5\" y2=\"15\" />\n </svg>\n </button>\n </header>\n <div className={styles.body}>{children}</div>\n {footer && <footer className={styles.footer}>{footer}</footer>}\n </div>\n </dialog>\n );\n}\n",".container {\n position: relative;\n display: inline-flex;\n}\n\n.trigger {\n display: inline-flex;\n cursor: pointer;\n}\n\n.content {\n position: absolute;\n z-index: 50;\n min-width: 200px;\n padding: var(--bazaar-space-4);\n background-color: var(--bazaar-color-surface-default);\n border: var(--bazaar-border-width-hairline) solid var(--bazaar-color-border-default);\n border-radius: var(--bazaar-radius-lg);\n box-shadow: var(--bazaar-shadow-lg);\n font-family: var(--bazaar-font-family-sans);\n font-size: var(--bazaar-font-size-body-md);\n line-height: var(--bazaar-line-height-body-md);\n color: var(--bazaar-color-text-primary);\n animation: bazaar-popover-in var(--bazaar-motion-duration-fast) var(--bazaar-motion-easing-standard);\n}\n\n/* Placement */\n.bottom {\n top: calc(100% + var(--bazaar-space-2));\n}\n\n.top {\n bottom: calc(100% + var(--bazaar-space-2));\n}\n\n.left {\n right: calc(100% + var(--bazaar-space-2));\n top: 50%;\n transform: translateY(-50%);\n}\n\n.right {\n left: calc(100% + var(--bazaar-space-2));\n top: 50%;\n transform: translateY(-50%);\n}\n\n/* Alignment (for top/bottom) */\n.align-start {\n left: 0;\n}\n\n.align-center:not(.left):not(.right) {\n left: 50%;\n transform: translateX(-50%);\n}\n\n.align-end {\n right: 0;\n}\n\n@keyframes bazaar-popover-in {\n from {\n opacity: 0;\n transform: scale(0.96);\n }\n to {\n opacity: 1;\n transform: scale(1);\n }\n}\n\n/* Fix transform for centered top/bottom (override animation target) */\n.align-center.bottom,\n.align-center.top {\n transform: translateX(-50%);\n}\n\n.left,\n.right {\n transform: translateY(-50%);\n}\n","import { useState, useRef, useEffect, useCallback, type ReactNode, type HTMLAttributes } from 'react';\nimport { cn } from '../../utils/cn';\nimport styles from './Popover.module.css';\n\nexport interface PopoverProps extends Omit<HTMLAttributes<HTMLDivElement>, 'content'> {\n /** Trigger element that opens the popover */\n trigger: ReactNode;\n /** Content rendered inside the popover */\n content: ReactNode;\n /** Controlled open state */\n open?: boolean;\n /** Callback when open state changes */\n onOpenChange?: (open: boolean) => void;\n /** Placement relative to the trigger */\n placement?: 'top' | 'bottom' | 'left' | 'right';\n /** Alignment along the placement axis */\n align?: 'start' | 'center' | 'end';\n}\n\n/**\n * Popover — positioned overlay content triggered by a reference element.\n *\n * Accessibility:\n * - Escape key closes the popover\n * - Focus is managed: moves into popover on open, returns on close\n * - Click outside closes the popover\n * - Healthcare note: use for additional context like patient quick-view,\n * medication details, or field-level help without navigating away\n */\nexport function Popover({\n trigger,\n content,\n open: controlledOpen,\n onOpenChange,\n placement = 'bottom',\n align = 'center',\n className,\n ...props\n}: PopoverProps) {\n const [internalOpen, setInternalOpen] = useState(false);\n const isControlled = controlledOpen !== undefined;\n const isOpen = isControlled ? controlledOpen : internalOpen;\n\n const containerRef = useRef<HTMLDivElement>(null);\n const contentRef = useRef<HTMLDivElement>(null);\n\n const setOpen = useCallback(\n (value: boolean) => {\n if (!isControlled) setInternalOpen(value);\n onOpenChange?.(value);\n },\n [isControlled, onOpenChange]\n );\n\n const toggle = useCallback(() => setOpen(!isOpen), [isOpen, setOpen]);\n\n // Close on Escape\n useEffect(() => {\n if (!isOpen) return;\n const handleKeyDown = (e: KeyboardEvent) => {\n if (e.key === 'Escape') {\n setOpen(false);\n }\n };\n document.addEventListener('keydown', handleKeyDown);\n return () => document.removeEventListener('keydown', handleKeyDown);\n }, [isOpen, setOpen]);\n\n // Close on click outside\n useEffect(() => {\n if (!isOpen) return;\n const handleClick = (e: MouseEvent) => {\n if (containerRef.current && !containerRef.current.contains(e.target as Node)) {\n setOpen(false);\n }\n };\n document.addEventListener('mousedown', handleClick);\n return () => document.removeEventListener('mousedown', handleClick);\n }, [isOpen, setOpen]);\n\n // Focus management\n useEffect(() => {\n if (isOpen && contentRef.current) {\n const firstFocusable = contentRef.current.querySelector<HTMLElement>(\n 'button, [href], input, select, textarea, [tabindex]:not([tabindex=\"-1\"])'\n );\n if (firstFocusable) {\n firstFocusable.focus();\n }\n }\n }, [isOpen]);\n\n return (\n <div ref={containerRef} className={cn(styles.container, className)} {...props}>\n <div className={styles.trigger} onClick={toggle}>\n {trigger}\n </div>\n {isOpen && (\n <div\n ref={contentRef}\n className={cn(styles.content, styles[placement], styles[`align-${align}`])}\n role=\"dialog\"\n aria-modal=\"false\"\n >\n {content}\n </div>\n )}\n </div>\n );\n}\n",".panel {\n font-family: var(--bazaar-font-family-sans);\n border: var(--bazaar-border-width-hairline) var(--bazaar-border-style-default) var(--bazaar-color-border-default);\n border-radius: var(--bazaar-radius-md);\n background-color: var(--bazaar-color-surface-default);\n overflow: hidden;\n}\n\n.trigger {\n display: flex;\n align-items: center;\n gap: var(--bazaar-space-2);\n width: 100%;\n padding: var(--bazaar-space-3) var(--bazaar-space-4);\n background: none;\n border: none;\n cursor: pointer;\n font-family: inherit;\n font-size: var(--bazaar-font-size-body-md);\n font-weight: var(--bazaar-font-weight-medium);\n line-height: var(--bazaar-line-height-body-md);\n color: var(--bazaar-color-text-primary);\n text-align: left;\n transition: background-color var(--bazaar-motion-duration-fast) var(--bazaar-motion-easing-standard);\n}\n\n.trigger:hover {\n background-color: var(--bazaar-color-surface-hover);\n}\n\n.trigger:focus-visible {\n outline: var(--bazaar-border-width-medium) solid var(--bazaar-focus-outline-color);\n outline-offset: calc(-1 * var(--bazaar-border-width-medium));\n box-shadow: var(--bazaar-shadow-focus);\n z-index: 1;\n position: relative;\n}\n\n.chevron {\n flex-shrink: 0;\n color: var(--bazaar-color-text-muted);\n transition: transform var(--bazaar-motion-duration-fast) var(--bazaar-motion-easing-standard);\n}\n\n.open .chevron {\n transform: rotate(90deg);\n}\n\n.title {\n flex: 1;\n min-width: 0;\n}\n\n.content {\n overflow: hidden;\n transition: height 200ms var(--bazaar-motion-easing-standard);\n}\n\n.contentInner {\n padding: 0 var(--bazaar-space-4) var(--bazaar-space-4);\n padding-left: calc(var(--bazaar-space-4) + 20px + var(--bazaar-space-2));\n font-size: var(--bazaar-font-size-body-sm);\n line-height: var(--bazaar-line-height-body-sm);\n color: var(--bazaar-color-text-secondary);\n}\n","import { useState, useRef, useEffect, type ReactNode } from 'react';\nimport { cn } from '../../utils/cn';\nimport styles from './CollapsiblePanel.module.css';\n\nexport interface CollapsiblePanelProps {\n /** Panel title */\n title: string;\n /** Whether panel is open by default (uncontrolled) */\n defaultOpen?: boolean;\n /** Controlled open state */\n open?: boolean;\n /** Callback when open state changes */\n onToggle?: (open: boolean) => void;\n /** Panel content */\n children: ReactNode;\n /** Additional className */\n className?: string;\n}\n\n/**\n * CollapsiblePanel — a single collapsible section with animated expand/collapse.\n *\n * Accessibility:\n * - Button trigger with aria-expanded\n * - Content region with aria-labelledby linking to the trigger\n * - Chevron icon rotates on expand/collapse\n * - Supports both controlled and uncontrolled modes\n */\nexport function CollapsiblePanel({\n title,\n defaultOpen = false,\n open: controlledOpen,\n onToggle,\n children,\n className,\n}: CollapsiblePanelProps) {\n const [internalOpen, setInternalOpen] = useState(defaultOpen);\n const isOpen = controlledOpen !== undefined ? controlledOpen : internalOpen;\n\n const contentRef = useRef<HTMLDivElement>(null);\n const [height, setHeight] = useState<number | undefined>(isOpen ? undefined : 0);\n\n const panelId = useRef(`collapsible-panel-${Math.random().toString(36).slice(2, 9)}`).current;\n const triggerId = `${panelId}-trigger`;\n\n useEffect(() => {\n if (!contentRef.current) return;\n if (isOpen) {\n setHeight(contentRef.current.scrollHeight);\n const timer = setTimeout(() => setHeight(undefined), 200);\n return () => clearTimeout(timer);\n } else {\n setHeight(contentRef.current.scrollHeight);\n requestAnimationFrame(() => {\n requestAnimationFrame(() => setHeight(0));\n });\n }\n }, [isOpen]);\n\n const handleToggle = () => {\n const next = !isOpen;\n if (controlledOpen === undefined) {\n setInternalOpen(next);\n }\n onToggle?.(next);\n };\n\n return (\n <div className={cn(styles.panel, isOpen && styles.open, className)}>\n <button\n type=\"button\"\n id={triggerId}\n className={styles.trigger}\n aria-expanded={isOpen}\n aria-controls={panelId}\n onClick={handleToggle}\n >\n <svg\n className={styles.chevron}\n width=\"20\"\n height=\"20\"\n viewBox=\"0 0 20 20\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n >\n <polyline points=\"8 4 14 10 8 16\" />\n </svg>\n <span className={styles.title}>{title}</span>\n </button>\n <div\n id={panelId}\n role=\"region\"\n aria-labelledby={triggerId}\n className={styles.content}\n style={{ height: height !== undefined ? `${height}px` : 'auto' }}\n hidden={!isOpen && height === 0}\n >\n <div ref={contentRef} className={styles.contentInner}>\n {children}\n </div>\n </div>\n </div>\n );\n}\n",".nav {\n font-family: var(--bazaar-font-family-sans);\n}\n\n.list {\n display: flex;\n align-items: center;\n flex-wrap: wrap;\n gap: var(--bazaar-space-1);\n list-style: none;\n margin: 0;\n padding: 0;\n}\n\n.item {\n display: flex;\n align-items: center;\n gap: var(--bazaar-space-1);\n}\n\n.separator {\n color: var(--bazaar-color-text-muted);\n font-size: var(--bazaar-font-size-body-sm);\n user-select: none;\n}\n\n.link {\n font-size: var(--bazaar-font-size-body-sm);\n line-height: var(--bazaar-line-height-body-sm);\n color: var(--bazaar-color-brand-primary-500);\n text-decoration: none;\n background: none;\n border: none;\n padding: 0;\n cursor: pointer;\n font-family: inherit;\n border-radius: var(--bazaar-radius-sm);\n transition: color var(--bazaar-motion-duration-fast) var(--bazaar-motion-easing-standard);\n}\n\n.link:hover {\n color: var(--bazaar-color-brand-primary-700);\n text-decoration: underline;\n}\n\n.link:focus-visible {\n outline: var(--bazaar-border-width-medium) solid var(--bazaar-focus-outline-color);\n outline-offset: 2px;\n box-shadow: var(--bazaar-shadow-focus);\n}\n\n.current {\n font-size: var(--bazaar-font-size-body-sm);\n line-height: var(--bazaar-line-height-body-sm);\n color: var(--bazaar-color-text-primary);\n font-weight: var(--bazaar-font-weight-medium);\n}\n","import { type ReactNode } from 'react';\nimport { cn } from '../../utils/cn';\nimport styles from './Breadcrumbs.module.css';\n\nexport interface BreadcrumbItem {\n /** Display label */\n label: string;\n /** Optional URL for link items */\n href?: string;\n /** Optional click handler */\n onClick?: () => void;\n}\n\nexport interface BreadcrumbsProps {\n /** Breadcrumb path items */\n items: BreadcrumbItem[];\n /** Separator between items */\n separator?: ReactNode;\n /** Additional className */\n className?: string;\n}\n\n/**\n * Breadcrumbs — navigational aid showing the current location within a hierarchy.\n *\n * Accessibility:\n * - Wrapped in <nav> with aria-label=\"Breadcrumb\"\n * - Uses semantic <ol>/<li> list structure\n * - Last item has aria-current=\"page\" to indicate current location\n * - Separator is aria-hidden so screen readers skip it\n */\nexport function Breadcrumbs({ items, separator = '/', className }: BreadcrumbsProps) {\n return (\n <nav aria-label=\"Breadcrumb\" className={cn(styles.nav, className)}>\n <ol className={styles.list}>\n {items.map((item, index) => {\n const isLast = index === items.length - 1;\n\n return (\n <li key={index} className={styles.item}>\n {index > 0 && (\n <span className={styles.separator} aria-hidden=\"true\">\n {separator}\n </span>\n )}\n {isLast ? (\n <span className={styles.current} aria-current=\"page\">\n {item.label}\n </span>\n ) : item.href ? (\n <a href={item.href} className={styles.link} onClick={item.onClick}>\n {item.label}\n </a>\n ) : (\n <button\n type=\"button\"\n className={styles.link}\n onClick={item.onClick}\n >\n {item.label}\n </button>\n )}\n </li>\n );\n })}\n </ol>\n </nav>\n );\n}\n",".dialog {\n position: fixed;\n inset: 0;\n border: none;\n padding: 0;\n background: transparent;\n max-width: 100vw;\n max-height: 100vh;\n width: 100vw;\n height: 100vh;\n}\n\n.dialog::backdrop {\n background-color: var(--bazaar-color-overlay-scrim);\n}\n\n.panel {\n position: fixed;\n top: 0;\n bottom: 0;\n display: flex;\n flex-direction: column;\n background-color: var(--bazaar-color-surface-default);\n box-shadow: var(--bazaar-shadow-lg);\n max-width: 90vw;\n}\n\n/* Position */\n.right .panel {\n right: 0;\n animation: bazaar-drawer-right-in var(--bazaar-motion-duration-slow) var(--bazaar-motion-easing-standard);\n}\n\n.left .panel {\n left: 0;\n animation: bazaar-drawer-left-in var(--bazaar-motion-duration-slow) var(--bazaar-motion-easing-standard);\n}\n\n/* Sizes */\n.sm .panel { width: 320px; }\n.md .panel { width: 480px; }\n.lg .panel { width: 640px; }\n\n.header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: var(--bazaar-space-6);\n border-bottom: var(--bazaar-border-width-hairline) solid var(--bazaar-color-border-default);\n flex-shrink: 0;\n}\n\n.title {\n margin: 0;\n font-family: var(--bazaar-font-family-sans);\n font-size: var(--bazaar-font-size-heading-md);\n font-weight: var(--bazaar-font-weight-semibold);\n line-height: var(--bazaar-line-height-heading-md);\n color: var(--bazaar-color-text-primary);\n}\n\n.close {\n display: flex;\n align-items: center;\n justify-content: center;\n width: var(--bazaar-size-control-sm);\n height: var(--bazaar-size-control-sm);\n border: none;\n border-radius: var(--bazaar-radius-md);\n background: transparent;\n color: var(--bazaar-color-text-muted);\n cursor: pointer;\n flex-shrink: 0;\n}\n\n.close:hover {\n background-color: var(--bazaar-color-surface-subtle);\n color: var(--bazaar-color-text-primary);\n}\n\n.close:focus-visible {\n outline: var(--bazaar-border-width-medium) solid var(--bazaar-focus-outline-color);\n outline-offset: var(--bazaar-focus-ring-offset);\n box-shadow: var(--bazaar-shadow-focus);\n}\n\n.body {\n padding: var(--bazaar-space-6);\n overflow-y: auto;\n flex: 1;\n font-family: var(--bazaar-font-family-sans);\n font-size: var(--bazaar-font-size-body-md);\n line-height: var(--bazaar-line-height-body-md);\n color: var(--bazaar-color-text-secondary);\n}\n\n.footer {\n display: flex;\n align-items: center;\n justify-content: flex-end;\n gap: var(--bazaar-space-3);\n padding: var(--bazaar-space-4) var(--bazaar-space-6);\n border-top: var(--bazaar-border-width-hairline) solid var(--bazaar-color-border-default);\n flex-shrink: 0;\n}\n\n@keyframes bazaar-drawer-right-in {\n from {\n transform: translateX(100%);\n }\n to {\n transform: translateX(0);\n }\n}\n\n@keyframes bazaar-drawer-left-in {\n from {\n transform: translateX(-100%);\n }\n to {\n transform: translateX(0);\n }\n}\n","import { useEffect, useRef, type ReactNode } from 'react';\nimport { cn } from '../../utils/cn';\nimport styles from './Drawer.module.css';\n\nexport interface DrawerProps {\n /** Additional className */\n className?: string;\n /** Whether the drawer is visible */\n open: boolean;\n /** Called when the drawer should close */\n onClose: () => void;\n /** Drawer title */\n title: ReactNode;\n /** Width preset */\n size?: 'sm' | 'md' | 'lg';\n /** Which side the drawer slides from */\n position?: 'left' | 'right';\n /** Footer actions */\n footer?: ReactNode;\n /** Drawer body content */\n children?: ReactNode;\n}\n\n/**\n * Drawer — side panel overlay for detail views and forms.\n *\n * Accessibility:\n * - Uses native <dialog> element for focus trapping\n * - Escape key closes the drawer\n * - aria-labelledby links to the title\n * - Scrim click closes the drawer\n * - Healthcare note: use drawers for patient detail views, order entry,\n * and contextual forms that don't require full-page navigation\n */\nexport function Drawer({\n open,\n onClose,\n title,\n size = 'md',\n position = 'right',\n footer,\n className,\n children,\n}: DrawerProps) {\n const dialogRef = useRef<HTMLDialogElement>(null);\n\n useEffect(() => {\n const dialog = dialogRef.current;\n if (!dialog) return;\n\n if (open && !dialog.open) {\n dialog.showModal();\n } else if (!open && dialog.open) {\n dialog.close();\n }\n }, [open]);\n\n useEffect(() => {\n const dialog = dialogRef.current;\n if (!dialog) return;\n\n const handleClose = () => onClose();\n dialog.addEventListener('close', handleClose);\n return () => dialog.removeEventListener('close', handleClose);\n }, [onClose]);\n\n const handleBackdropClick = (e: React.MouseEvent<HTMLDialogElement>) => {\n if (e.target === dialogRef.current) {\n onClose();\n }\n };\n\n return (\n <dialog\n ref={dialogRef}\n className={cn(styles.dialog, styles[position], styles[size], className)}\n aria-labelledby=\"bazaar-drawer-title\"\n onClick={handleBackdropClick}\n >\n <div className={styles.panel}>\n <header className={styles.header}>\n <h2 id=\"bazaar-drawer-title\" className={styles.title}>{title}</h2>\n <button\n className={styles.close}\n onClick={onClose}\n aria-label=\"Close drawer\"\n >\n <svg width=\"20\" height=\"20\" viewBox=\"0 0 20 20\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"1.75\" strokeLinecap=\"round\" aria-hidden=\"true\">\n <line x1=\"5\" y1=\"5\" x2=\"15\" y2=\"15\" />\n <line x1=\"15\" y1=\"5\" x2=\"5\" y2=\"15\" />\n </svg>\n </button>\n </header>\n <div className={styles.body}>{children}</div>\n {footer && <footer className={styles.footer}>{footer}</footer>}\n </div>\n </dialog>\n );\n}\n",".link {\n display: inline-flex;\n align-items: center;\n gap: var(--bazaar-space-1);\n font-family: var(--bazaar-font-family-sans);\n font-size: inherit;\n line-height: inherit;\n cursor: pointer;\n transition:\n color var(--bazaar-motion-duration-fast) var(--bazaar-motion-easing-standard),\n text-decoration-color var(--bazaar-motion-duration-fast) var(--bazaar-motion-easing-standard);\n}\n\n/* ---------- Colors ---------- */\n\n.color-primary {\n color: var(--bazaar-color-brand-primary-600);\n}\n\n.color-primary:hover {\n color: var(--bazaar-color-brand-primary-700);\n}\n\n.color-secondary {\n color: var(--bazaar-color-text-secondary);\n}\n\n.color-secondary:hover {\n color: var(--bazaar-color-text-primary);\n}\n\n.color-inherit {\n color: inherit;\n}\n\n.color-inherit:hover {\n opacity: 0.8;\n}\n\n/* ---------- Variants ---------- */\n\n.default {\n text-decoration: underline;\n text-decoration-thickness: 1px;\n text-underline-offset: 2px;\n text-decoration-color: currentColor;\n}\n\n.subtle {\n text-decoration: underline;\n text-decoration-thickness: 1px;\n text-underline-offset: 2px;\n text-decoration-color: transparent;\n}\n\n.subtle:hover {\n text-decoration-color: currentColor;\n}\n\n.standalone {\n text-decoration: none;\n font-weight: var(--bazaar-font-weight-medium);\n}\n\n.standalone:hover {\n text-decoration: none;\n}\n\n/* ---------- Focus ---------- */\n\n.link:focus-visible {\n outline: var(--bazaar-border-width-medium) solid var(--bazaar-focus-outline-color);\n outline-offset: 2px;\n border-radius: 2px;\n box-shadow: var(--bazaar-shadow-focus);\n}\n\n/* ---------- Disabled ---------- */\n\n.disabled {\n opacity: var(--bazaar-opacity-disabled);\n cursor: not-allowed;\n pointer-events: none;\n text-decoration: none;\n}\n\n/* ---------- Sub-elements ---------- */\n\n.startIcon {\n display: flex;\n align-items: center;\n flex-shrink: 0;\n}\n","import { forwardRef, type AnchorHTMLAttributes, type ReactNode } from 'react';\nimport { cn } from '../../utils/cn';\nimport styles from './Link.module.css';\n\nexport interface LinkProps extends AnchorHTMLAttributes<HTMLAnchorElement> {\n /** Visual variant */\n variant?: 'default' | 'subtle' | 'standalone';\n /** Color */\n color?: 'primary' | 'secondary' | 'inherit';\n /** Whether to show an external indicator */\n external?: boolean;\n /** Icon slot (leading) */\n startIcon?: ReactNode;\n /** Disabled state (prevents navigation) */\n disabled?: boolean;\n}\n\nconst ExternalIcon = () => (\n <svg width=\"12\" height=\"12\" viewBox=\"0 0 12 12\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"1.5\" strokeLinecap=\"round\" strokeLinejoin=\"round\" aria-hidden=\"true\" style={{ marginLeft: 2, flexShrink: 0 }}>\n <path d=\"M9 3L3 9\" />\n <path d=\"M4 3h5v5\" />\n </svg>\n);\n\n/**\n * Link — styled anchor primitive for navigation.\n *\n * Variants:\n * - `default` — underlined inline link\n * - `subtle` — underline on hover only\n * - `standalone` — no underline, bolder weight, for navigation items\n *\n * Accessibility:\n * - Uses native <a> element for full keyboard + screen reader support\n * - External links get target=\"_blank\" with rel=\"noopener noreferrer\"\n * - aria-disabled prevents interaction without removing from tab order\n */\nexport const Link = forwardRef<HTMLAnchorElement, LinkProps>(\n (\n {\n variant = 'default',\n color = 'primary',\n external = false,\n startIcon,\n disabled = false,\n className,\n children,\n ...props\n },\n ref,\n ) => (\n <a\n ref={ref}\n className={cn(\n styles.link,\n styles[variant],\n styles[`color-${color}`],\n disabled && styles.disabled,\n className,\n )}\n aria-disabled={disabled || undefined}\n tabIndex={disabled ? -1 : undefined}\n {...(external ? { target: '_blank', rel: 'noopener noreferrer' } : {})}\n {...props}\n >\n {startIcon && <span className={styles.startIcon} aria-hidden=\"true\">{startIcon}</span>}\n {children}\n {external && <ExternalIcon />}\n </a>\n ),\n);\n\nLink.displayName = 'Link';\n",".menuContainer {\n position: relative;\n display: inline-flex;\n}\n\n.trigger {\n display: inline-flex;\n}\n\n/* ---------- Menu surface ---------- */\n\n.menu {\n position: absolute;\n top: calc(100% + 4px);\n z-index: var(--bazaar-z-dropdown, 1100);\n min-width: 180px;\n max-height: 320px;\n overflow-y: auto;\n padding: var(--bazaar-space-1) 0;\n background-color: var(--bazaar-color-surface-default);\n border: var(--bazaar-border-width-hairline) var(--bazaar-border-style-default) var(--bazaar-color-border-default);\n border-radius: var(--bazaar-radius-md);\n box-shadow: var(--bazaar-shadow-lg);\n font-family: var(--bazaar-font-family-sans);\n animation: bazaar-menu-in var(--bazaar-motion-duration-fast) var(--bazaar-motion-easing-standard) both;\n}\n\n.align-start {\n left: 0;\n}\n\n.align-end {\n right: 0;\n}\n\n/* ---------- MenuItem ---------- */\n\n.menuItem {\n display: flex;\n align-items: center;\n gap: var(--bazaar-space-2);\n padding: var(--bazaar-space-2) var(--bazaar-space-4);\n font-size: var(--bazaar-font-size-body-sm);\n line-height: var(--bazaar-line-height-body-sm);\n color: var(--bazaar-color-text-primary);\n cursor: pointer;\n transition: background-color var(--bazaar-motion-duration-fast) var(--bazaar-motion-easing-standard);\n outline: none;\n}\n\n.menuItem:hover,\n.menuItem:focus-visible {\n background-color: var(--bazaar-color-surface-hover, var(--bazaar-color-neutral-50));\n}\n\n.menuItem:focus-visible {\n box-shadow: inset 2px 0 0 0 var(--bazaar-color-brand-primary-500);\n}\n\n/* Danger */\n.menuItem.danger {\n color: var(--bazaar-color-error-700);\n}\n\n.menuItem.danger:hover,\n.menuItem.danger:focus-visible {\n background-color: var(--bazaar-color-error-50);\n}\n\n/* Disabled */\n.menuItem.itemDisabled {\n opacity: var(--bazaar-opacity-disabled);\n cursor: not-allowed;\n}\n\n.menuItem.itemDisabled:hover {\n background-color: transparent;\n}\n\n/* Sub-elements */\n.itemIcon {\n display: flex;\n align-items: center;\n flex-shrink: 0;\n color: var(--bazaar-color-text-muted);\n}\n\n.menuItem.danger .itemIcon {\n color: var(--bazaar-color-error-500);\n}\n\n.itemLabel {\n flex: 1;\n min-width: 0;\n}\n\n.itemTrailing {\n flex-shrink: 0;\n font-size: var(--bazaar-font-size-caption);\n color: var(--bazaar-color-text-muted);\n}\n\n/* ---------- Divider ---------- */\n\n.divider {\n height: 1px;\n margin: var(--bazaar-space-1) 0;\n background-color: var(--bazaar-color-border-default);\n}\n\n/* ---------- Group label ---------- */\n\n.groupLabel {\n padding: var(--bazaar-space-2) var(--bazaar-space-4) var(--bazaar-space-1);\n font-size: var(--bazaar-font-size-caption);\n font-weight: var(--bazaar-font-weight-semibold);\n color: var(--bazaar-color-text-muted);\n text-transform: uppercase;\n letter-spacing: 0.04em;\n}\n\n/* ---------- Animation ---------- */\n\n@keyframes bazaar-menu-in {\n from {\n opacity: 0;\n transform: translateY(-4px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n}\n","import {\n useState,\n useRef,\n useEffect,\n useCallback,\n type HTMLAttributes,\n type ReactNode,\n type KeyboardEvent,\n type MouseEvent,\n} from 'react';\nimport { cn } from '../../utils/cn';\nimport styles from './Menu.module.css';\n\n/* ------------------------------------------------------------------ */\n/* MenuItem */\n/* ------------------------------------------------------------------ */\n\nexport interface MenuItemProps extends Omit<HTMLAttributes<HTMLDivElement>, 'onClick'> {\n /** Leading icon */\n icon?: ReactNode;\n /** Trailing content (shortcut, badge, etc.) */\n trailing?: ReactNode;\n /** Disabled state */\n disabled?: boolean;\n /** Destructive / danger styling */\n danger?: boolean;\n /** Click handler */\n onClick?: (e: MouseEvent<HTMLDivElement>) => void;\n}\n\nexport function MenuItem({\n icon,\n trailing,\n disabled = false,\n danger = false,\n onClick,\n className,\n children,\n ...props\n}: MenuItemProps) {\n return (\n <div\n role=\"menuitem\"\n tabIndex={disabled ? -1 : 0}\n aria-disabled={disabled || undefined}\n className={cn(\n styles.menuItem,\n danger && styles.danger,\n disabled && styles.itemDisabled,\n className,\n )}\n onClick={disabled ? undefined : onClick}\n onKeyDown={(e) => {\n if (disabled) return;\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n onClick?.(e as any);\n }\n }}\n {...props}\n >\n {icon && <span className={styles.itemIcon} aria-hidden=\"true\">{icon}</span>}\n <span className={styles.itemLabel}>{children}</span>\n {trailing && <span className={styles.itemTrailing}>{trailing}</span>}\n </div>\n );\n}\n\n/* ------------------------------------------------------------------ */\n/* MenuDivider */\n/* ------------------------------------------------------------------ */\n\nexport function MenuDivider() {\n return <div role=\"separator\" className={styles.divider} />;\n}\n\n/* ------------------------------------------------------------------ */\n/* MenuGroup */\n/* ------------------------------------------------------------------ */\n\nexport interface MenuGroupProps {\n /** Group label */\n label: string;\n children: ReactNode;\n}\n\nexport function MenuGroup({ label, children }: MenuGroupProps) {\n return (\n <div role=\"group\" aria-label={label}>\n <div className={styles.groupLabel}>{label}</div>\n {children}\n </div>\n );\n}\n\n/* ------------------------------------------------------------------ */\n/* Menu */\n/* ------------------------------------------------------------------ */\n\nexport interface MenuProps extends HTMLAttributes<HTMLDivElement> {\n /** The trigger element — a single React element */\n trigger: ReactNode;\n /** Horizontal alignment relative to trigger */\n align?: 'start' | 'end';\n /** Menu width */\n width?: number | 'trigger';\n}\n\n/**\n * Menu — dropdown action menu surface.\n *\n * Composes MenuItem, MenuDivider, and MenuGroup as children.\n *\n * Accessibility:\n * - role=\"menu\" on the dropdown, role=\"menuitem\" on each item\n * - Arrow-key navigation between items\n * - Escape closes the menu\n * - Focus returns to trigger on close\n * - Click outside closes the menu\n * - Healthcare note: ideal for patient action menus, record options,\n * context menus on rows\n */\nexport function Menu({\n trigger,\n align = 'start',\n width,\n className,\n children,\n ...props\n}: MenuProps) {\n const [open, setOpen] = useState(false);\n const triggerRef = useRef<HTMLDivElement>(null);\n const menuRef = useRef<HTMLDivElement>(null);\n\n const close = useCallback(() => {\n setOpen(false);\n triggerRef.current?.querySelector<HTMLElement>('[tabindex], button, a')?.focus();\n }, []);\n\n // Close on outside click\n useEffect(() => {\n if (!open) return;\n\n const handleClick = (e: Event) => {\n if (\n !menuRef.current?.contains(e.target as Node) &&\n !triggerRef.current?.contains(e.target as Node)\n ) {\n close();\n }\n };\n\n document.addEventListener('mousedown', handleClick);\n return () => document.removeEventListener('mousedown', handleClick);\n }, [open, close]);\n\n // Focus first item on open\n useEffect(() => {\n if (open) {\n const firstItem = menuRef.current?.querySelector<HTMLElement>('[role=\"menuitem\"]:not([aria-disabled])');\n firstItem?.focus();\n }\n }, [open]);\n\n const handleKeyDown = (e: KeyboardEvent) => {\n if (!open) {\n if (e.key === 'ArrowDown' || e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n setOpen(true);\n }\n return;\n }\n\n const items = Array.from(\n menuRef.current?.querySelectorAll<HTMLElement>('[role=\"menuitem\"]:not([aria-disabled])') || [],\n );\n const current = document.activeElement as HTMLElement;\n const idx = items.indexOf(current);\n\n switch (e.key) {\n case 'ArrowDown': {\n e.preventDefault();\n const next = idx < items.length - 1 ? idx + 1 : 0;\n items[next]?.focus();\n break;\n }\n case 'ArrowUp': {\n e.preventDefault();\n const prev = idx > 0 ? idx - 1 : items.length - 1;\n items[prev]?.focus();\n break;\n }\n case 'Escape':\n e.preventDefault();\n close();\n break;\n case 'Tab':\n close();\n break;\n }\n };\n\n return (\n <div className={cn(styles.menuContainer, className)} onKeyDown={handleKeyDown} {...props}>\n <div\n ref={triggerRef}\n className={styles.trigger}\n onClick={() => setOpen((prev) => !prev)}\n aria-haspopup=\"menu\"\n aria-expanded={open}\n >\n {trigger}\n </div>\n\n {open && (\n <div\n ref={menuRef}\n role=\"menu\"\n className={cn(styles.menu, styles[`align-${align}`])}\n style={width ? { width: width === 'trigger' ? undefined : width, minWidth: width === 'trigger' ? '100%' : undefined } : undefined}\n >\n {children}\n </div>\n )}\n </div>\n );\n}\n",".pagination {\n display: flex;\n align-items: center;\n gap: var(--bazaar-space-1);\n}\n\n.button {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n border: var(--bazaar-border-width-hairline) solid transparent;\n border-radius: var(--bazaar-radius-md);\n background: transparent;\n color: var(--bazaar-color-text-secondary);\n font-family: var(--bazaar-font-family-sans);\n font-weight: var(--bazaar-font-weight-medium);\n cursor: pointer;\n transition: background-color 0.15s ease, color 0.15s ease, border-color 0.15s ease;\n}\n\n/* Sizes */\n.sm .button {\n min-width: 28px;\n height: 28px;\n font-size: var(--bazaar-font-size-body-sm);\n padding: 0 var(--bazaar-space-1);\n}\n\n.md .button {\n min-width: 36px;\n height: 36px;\n font-size: var(--bazaar-font-size-body-md);\n padding: 0 var(--bazaar-space-2);\n}\n\n.button:hover:not(:disabled) {\n background-color: var(--bazaar-color-surface-subtle);\n color: var(--bazaar-color-text-primary);\n}\n\n.button:focus-visible {\n outline: var(--bazaar-border-width-medium) solid var(--bazaar-focus-outline-color);\n outline-offset: var(--bazaar-focus-ring-offset);\n box-shadow: var(--bazaar-shadow-focus);\n}\n\n.button:disabled {\n opacity: 0.4;\n cursor: not-allowed;\n}\n\n/* Active page */\n.active {\n background-color: var(--bazaar-color-brand-primary-500);\n color: white;\n border-color: var(--bazaar-color-brand-primary-500);\n}\n\n.active:hover:not(:disabled) {\n background-color: var(--bazaar-color-brand-primary-600);\n color: white;\n}\n\n/* Nav buttons */\n.nav {\n color: var(--bazaar-color-text-secondary);\n}\n\n.ellipsis {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n min-width: 28px;\n height: 28px;\n color: var(--bazaar-color-text-muted);\n font-family: var(--bazaar-font-family-sans);\n user-select: none;\n}\n","import { type HTMLAttributes } from 'react';\nimport { cn } from '../../utils/cn';\nimport styles from './Pagination.module.css';\n\nexport interface PaginationProps extends Omit<HTMLAttributes<HTMLElement>, 'onChange'> {\n /** Current active page (1-based) */\n currentPage: number;\n /** Total number of pages */\n totalPages: number;\n /** Callback when page changes */\n onPageChange: (page: number) => void;\n /** Number of sibling pages to show around the current page */\n siblingCount?: number;\n /** Size variant */\n size?: 'sm' | 'md';\n}\n\nfunction getPageRange(current: number, total: number, siblings: number): (number | 'ellipsis')[] {\n const totalNumbers = siblings * 2 + 3; // siblings + current + 2 boundaries\n const totalBlocks = totalNumbers + 2; // + 2 ellipsis slots\n\n if (total <= totalBlocks) {\n return Array.from({ length: total }, (_, i) => i + 1);\n }\n\n const leftSibling = Math.max(current - siblings, 1);\n const rightSibling = Math.min(current + siblings, total);\n\n const showLeftEllipsis = leftSibling > 2;\n const showRightEllipsis = rightSibling < total - 1;\n\n if (!showLeftEllipsis && showRightEllipsis) {\n const leftCount = 3 + 2 * siblings;\n const leftRange = Array.from({ length: leftCount }, (_, i) => i + 1);\n return [...leftRange, 'ellipsis', total];\n }\n\n if (showLeftEllipsis && !showRightEllipsis) {\n const rightCount = 3 + 2 * siblings;\n const rightRange = Array.from({ length: rightCount }, (_, i) => total - rightCount + i + 1);\n return [1, 'ellipsis', ...rightRange];\n }\n\n const middleRange = Array.from(\n { length: rightSibling - leftSibling + 1 },\n (_, i) => leftSibling + i\n );\n return [1, 'ellipsis', ...middleRange, 'ellipsis', total];\n}\n\n/**\n * Pagination — page navigation for paginated data.\n *\n * Accessibility:\n * - Wraps in <nav> with aria-label=\"Pagination\"\n * - Current page indicated with aria-current=\"page\"\n * - Previous/Next buttons disabled at boundaries\n * - Healthcare note: use pagination for patient lists, lab results,\n * and audit logs to keep pages manageable\n */\nexport function Pagination({\n currentPage,\n totalPages,\n onPageChange,\n siblingCount = 1,\n size = 'md',\n className,\n ...props\n}: PaginationProps) {\n const pages = getPageRange(currentPage, totalPages, siblingCount);\n\n if (totalPages <= 1) return null;\n\n return (\n <nav\n className={cn(styles.pagination, styles[size], className)}\n aria-label=\"Pagination\"\n {...props}\n >\n <button\n className={cn(styles.button, styles.nav)}\n onClick={() => onPageChange(currentPage - 1)}\n disabled={currentPage <= 1}\n aria-label=\"Previous page\"\n >\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"1.5\" strokeLinecap=\"round\" strokeLinejoin=\"round\" aria-hidden=\"true\">\n <polyline points=\"10 4 6 8 10 12\" />\n </svg>\n </button>\n\n {pages.map((page, idx) =>\n page === 'ellipsis' ? (\n <span key={`ellipsis-${idx}`} className={styles.ellipsis} aria-hidden=\"true\">\n …\n </span>\n ) : (\n <button\n key={page}\n className={cn(styles.button, page === currentPage && styles.active)}\n onClick={() => onPageChange(page)}\n aria-current={page === currentPage ? 'page' : undefined}\n aria-label={`Page ${page}`}\n >\n {page}\n </button>\n )\n )}\n\n <button\n className={cn(styles.button, styles.nav)}\n onClick={() => onPageChange(currentPage + 1)}\n disabled={currentPage >= totalPages}\n aria-label=\"Next page\"\n >\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"1.5\" strokeLinecap=\"round\" strokeLinejoin=\"round\" aria-hidden=\"true\">\n <polyline points=\"6 4 10 8 6 12\" />\n </svg>\n </button>\n </nav>\n );\n}\n",".sideNav {\n display: flex;\n flex-direction: column;\n width: 240px;\n background-color: var(--bazaar-color-surface-default);\n border-right: var(--bazaar-border-width-hairline) var(--bazaar-border-style-default) var(--bazaar-color-border-default);\n box-shadow: var(--bazaar-shadow-sm);\n font-family: var(--bazaar-font-family-sans);\n padding: var(--bazaar-space-2) 0;\n transition: width var(--bazaar-motion-duration-base) var(--bazaar-motion-easing-standard);\n}\n\n.collapsed {\n width: 56px;\n}\n\n.collapseToggle {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 100%;\n padding: var(--bazaar-space-2) var(--bazaar-space-3);\n background: none;\n border: none;\n cursor: pointer;\n color: var(--bazaar-color-text-muted);\n transition: color var(--bazaar-motion-duration-fast) var(--bazaar-motion-easing-standard);\n}\n\n.collapseToggle:hover {\n color: var(--bazaar-color-text-primary);\n}\n\n.collapseToggle:focus-visible {\n outline: var(--bazaar-border-width-medium) solid var(--bazaar-focus-outline-color);\n outline-offset: calc(-1 * var(--bazaar-border-width-medium));\n box-shadow: var(--bazaar-shadow-focus);\n border-radius: var(--bazaar-radius-sm);\n}\n\n.list {\n list-style: none;\n margin: 0;\n padding: 0;\n}\n\n.subList {\n list-style: none;\n margin: 0;\n padding: 0;\n}\n\n.navItem {\n display: flex;\n align-items: center;\n gap: var(--bazaar-space-3);\n width: 100%;\n padding: var(--bazaar-space-2) var(--bazaar-space-4);\n background: none;\n border: none;\n font-family: inherit;\n font-size: var(--bazaar-font-size-body-sm);\n line-height: var(--bazaar-line-height-body-sm);\n font-weight: var(--bazaar-font-weight-regular);\n color: var(--bazaar-color-text-secondary);\n text-decoration: none;\n cursor: pointer;\n text-align: left;\n transition:\n background-color var(--bazaar-motion-duration-fast) var(--bazaar-motion-easing-standard),\n color var(--bazaar-motion-duration-fast) var(--bazaar-motion-easing-standard);\n}\n\n.navItem:hover {\n background-color: var(--bazaar-color-surface-hover);\n color: var(--bazaar-color-text-primary);\n}\n\n.navItem:focus-visible {\n outline: var(--bazaar-border-width-medium) solid var(--bazaar-focus-outline-color);\n outline-offset: calc(-1 * var(--bazaar-border-width-medium));\n box-shadow: var(--bazaar-shadow-focus);\n border-radius: var(--bazaar-radius-sm);\n z-index: 1;\n position: relative;\n}\n\n.active {\n background-color: var(--bazaar-color-brand-primary-50);\n color: var(--bazaar-color-brand-primary-700);\n font-weight: var(--bazaar-font-weight-medium);\n}\n\n.active:hover {\n background-color: var(--bazaar-color-brand-primary-100);\n}\n\n.nested {\n padding-left: var(--bazaar-space-8);\n}\n\n.iconOnly {\n justify-content: center;\n padding: var(--bazaar-space-2);\n}\n\n.icon {\n display: flex;\n align-items: center;\n flex-shrink: 0;\n width: 20px;\n height: 20px;\n}\n\n.label {\n flex: 1;\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n","import { type ReactNode } from 'react';\nimport { cn } from '../../utils/cn';\nimport styles from './SideNav.module.css';\n\nexport interface SideNavItem {\n /** Display label */\n label: string;\n /** Optional URL */\n href?: string;\n /** Optional click handler */\n onClick?: () => void;\n /** Optional icon element */\n icon?: ReactNode;\n /** Whether this item is the active/current page */\n active?: boolean;\n /** Nested child items */\n children?: SideNavItem[];\n}\n\nexport interface SideNavProps {\n /** Navigation items */\n items: SideNavItem[];\n /** Whether the sidebar is collapsed to icon-only mode */\n collapsed?: boolean;\n /** Callback when collapse state changes */\n onCollapse?: (collapsed: boolean) => void;\n /** Additional className */\n className?: string;\n}\n\nfunction NavItem({ item, collapsed, depth = 0 }: { item: SideNavItem; collapsed?: boolean; depth?: number }) {\n const hasChildren = item.children && item.children.length > 0;\n\n const content = (\n <>\n {item.icon && (\n <span className={styles.icon} aria-hidden=\"true\">\n {item.icon}\n </span>\n )}\n {!collapsed && <span className={styles.label}>{item.label}</span>}\n </>\n );\n\n const commonProps = {\n className: cn(\n styles.navItem,\n item.active && styles.active,\n collapsed && styles.iconOnly,\n depth > 0 && styles.nested,\n ),\n ...(item.active ? { 'aria-current': 'page' as const } : {}),\n ...(collapsed ? { title: item.label } : {}),\n };\n\n return (\n <li>\n {item.href ? (\n <a href={item.href} onClick={item.onClick} {...commonProps}>\n {content}\n </a>\n ) : (\n <button type=\"button\" onClick={item.onClick} {...commonProps}>\n {content}\n </button>\n )}\n {hasChildren && !collapsed && (\n <ul className={styles.subList}>\n {item.children!.map((child, index) => (\n <NavItem key={index} item={child} collapsed={collapsed} depth={depth + 1} />\n ))}\n </ul>\n )}\n </li>\n );\n}\n\n/**\n * SideNav — vertical sidebar navigation for dashboard layouts.\n *\n * Accessibility:\n * - Semantic <nav> with <ul>/<li> structure\n * - aria-current=\"page\" on the active item\n * - Collapse toggle button with aria-label\n * - Title attribute on items when collapsed for tooltip-style labels\n * - Nested items rendered as sub-lists for proper hierarchy\n */\nexport function SideNav({ items, collapsed = false, onCollapse, className }: SideNavProps) {\n return (\n <nav aria-label=\"Side navigation\" className={cn(styles.sideNav, collapsed && styles.collapsed, className)}>\n {onCollapse && (\n <button\n type=\"button\"\n className={styles.collapseToggle}\n onClick={() => onCollapse(!collapsed)}\n aria-label={collapsed ? 'Expand navigation' : 'Collapse navigation'}\n >\n <svg\n width=\"20\"\n height=\"20\"\n viewBox=\"0 0 20 20\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n >\n {collapsed ? (\n <polyline points=\"8 4 14 10 8 16\" />\n ) : (\n <polyline points=\"12 4 6 10 12 16\" />\n )}\n </svg>\n </button>\n )}\n <ul className={styles.list}>\n {items.map((item, index) => (\n <NavItem key={index} item={item} collapsed={collapsed} />\n ))}\n </ul>\n </nav>\n );\n}\n",".stepper {\n width: 100%;\n}\n\n.list {\n display: flex;\n list-style: none;\n margin: 0;\n padding: 0;\n}\n\n.srOnly {\n position: absolute;\n width: 1px;\n height: 1px;\n padding: 0;\n margin: -1px;\n overflow: hidden;\n clip: rect(0, 0, 0, 0);\n white-space: nowrap;\n border: 0;\n}\n\n/* Horizontal layout */\n.horizontal .list {\n flex-direction: row;\n align-items: flex-start;\n}\n\n.horizontal .step {\n display: flex;\n align-items: flex-start;\n flex: 1;\n}\n\n.horizontal .stepButton {\n display: flex;\n flex-direction: column;\n align-items: center;\n text-align: center;\n gap: var(--bazaar-space-2);\n}\n\n.horizontal .connector {\n display: block;\n flex: 1;\n height: 2px;\n margin-top: 16px;\n margin-left: var(--bazaar-space-2);\n margin-right: var(--bazaar-space-2);\n background-color: var(--bazaar-color-border-default);\n transition: background-color var(--bazaar-motion-duration-normal) var(--bazaar-motion-easing-standard);\n}\n\n/* Vertical layout */\n.vertical .list {\n flex-direction: column;\n}\n\n.vertical .step {\n display: flex;\n flex-direction: column;\n}\n\n.vertical .stepButton {\n display: flex;\n flex-direction: row;\n align-items: center;\n gap: var(--bazaar-space-3);\n}\n\n.vertical .connector {\n display: block;\n width: 2px;\n height: 24px;\n margin-left: 15px;\n margin-top: var(--bazaar-space-1);\n margin-bottom: var(--bazaar-space-1);\n background-color: var(--bazaar-color-border-default);\n transition: background-color var(--bazaar-motion-duration-normal) var(--bazaar-motion-easing-standard);\n}\n\n/* Step button / container */\n.stepButton {\n border: none;\n background: transparent;\n cursor: pointer;\n padding: var(--bazaar-space-1);\n border-radius: var(--bazaar-radius-sm);\n transition: background-color var(--bazaar-motion-duration-fast) var(--bazaar-motion-easing-standard);\n font-family: var(--bazaar-font-family-sans);\n}\n\nbutton.stepButton:hover {\n background-color: var(--bazaar-color-surface-subtle);\n}\n\nbutton.stepButton:focus-visible {\n outline: var(--bazaar-border-width-medium) solid var(--bazaar-focus-outline-color);\n outline-offset: var(--bazaar-focus-ring-offset);\n box-shadow: var(--bazaar-shadow-focus);\n}\n\ndiv.stepButton {\n cursor: default;\n}\n\n/* Indicator circle */\n.indicator {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 32px;\n height: 32px;\n border-radius: var(--bazaar-radius-full);\n border: 2px solid var(--bazaar-color-border-default);\n background-color: var(--bazaar-color-surface-default);\n font-size: var(--bazaar-font-size-body-sm);\n font-weight: var(--bazaar-font-weight-medium);\n color: var(--bazaar-color-text-muted);\n flex-shrink: 0;\n transition:\n background-color var(--bazaar-motion-duration-normal) var(--bazaar-motion-easing-standard),\n border-color var(--bazaar-motion-duration-normal) var(--bazaar-motion-easing-standard),\n color var(--bazaar-motion-duration-normal) var(--bazaar-motion-easing-standard);\n}\n\n.indicatorCurrent {\n border-color: var(--bazaar-color-brand-primary-500);\n color: var(--bazaar-color-brand-primary-500);\n box-shadow: var(--bazaar-shadow-sm);\n}\n\n.indicatorCompleted {\n border-color: var(--bazaar-color-brand-primary-500);\n background-color: var(--bazaar-color-brand-primary-500);\n color: var(--bazaar-color-text-inverse);\n}\n\n/* Labels */\n.content {\n display: flex;\n flex-direction: column;\n gap: 2px;\n}\n\n.label {\n font-size: var(--bazaar-font-size-body-sm);\n font-weight: var(--bazaar-font-weight-medium);\n color: var(--bazaar-color-text-muted);\n line-height: var(--bazaar-line-height-body-sm);\n}\n\n.labelCurrent {\n color: var(--bazaar-color-text-primary);\n font-weight: var(--bazaar-font-weight-semibold);\n}\n\n.description {\n font-size: var(--bazaar-font-size-body-sm);\n color: var(--bazaar-color-text-muted);\n line-height: var(--bazaar-line-height-body-sm);\n font-weight: var(--bazaar-font-weight-regular);\n}\n\n/* Connector completed state */\n.connectorCompleted {\n background-color: var(--bazaar-color-brand-primary-500);\n}\n\n/* Step with connector */\n.stepWithConnector {\n position: relative;\n}\n","import { cn } from '../../utils/cn';\nimport styles from './Stepper.module.css';\n\nexport interface StepperStep {\n label: string;\n description?: string;\n}\n\nexport interface StepperProps {\n /** Array of step definitions */\n steps: StepperStep[];\n /** Currently active step (0-indexed) */\n activeStep: number;\n /** Layout orientation */\n orientation?: 'horizontal' | 'vertical';\n /** Callback when a step is clicked */\n onStepClick?: (stepIndex: number) => void;\n /** Additional CSS class */\n className?: string;\n}\n\n/**\n * Stepper — multi-step form progress indicator.\n *\n * Accessibility:\n * - Uses role=\"navigation\" with aria-label\n * - Each step is a button (when clickable) or div with aria-current=\"step\"\n * - Completed steps indicated via visual checkmark and sr-only text\n * - Step descriptions provide additional context\n */\nexport function Stepper({\n steps,\n activeStep,\n orientation = 'horizontal',\n onStepClick,\n className,\n}: StepperProps) {\n return (\n <nav\n className={cn(styles.stepper, styles[orientation], className)}\n aria-label=\"Progress\"\n >\n <ol className={styles.list}>\n {steps.map((step, index) => {\n const isCompleted = index < activeStep;\n const isCurrent = index === activeStep;\n const isClickable = Boolean(onStepClick);\n\n const stepContent = (\n <>\n <span\n className={cn(\n styles.indicator,\n isCompleted && styles.indicatorCompleted,\n isCurrent && styles.indicatorCurrent,\n )}\n >\n {isCompleted ? (\n <svg\n width=\"14\"\n height=\"14\"\n viewBox=\"0 0 14 14\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"M3 7l3 3 5-5\" />\n </svg>\n ) : (\n <span aria-hidden=\"true\">{index + 1}</span>\n )}\n </span>\n <span className={styles.content}>\n <span className={cn(styles.label, isCurrent && styles.labelCurrent)}>\n {step.label}\n </span>\n {step.description && (\n <span className={styles.description}>{step.description}</span>\n )}\n </span>\n {isCompleted && <span className={styles.srOnly}>(completed)</span>}\n {isCurrent && <span className={styles.srOnly}>(current step)</span>}\n </>\n );\n\n return (\n <li key={index} className={cn(styles.step, index < steps.length - 1 && styles.stepWithConnector)}>\n {isClickable ? (\n <button\n type=\"button\"\n className={styles.stepButton}\n onClick={() => onStepClick?.(index)}\n aria-current={isCurrent ? 'step' : undefined}\n >\n {stepContent}\n </button>\n ) : (\n <div\n className={styles.stepButton}\n aria-current={isCurrent ? 'step' : undefined}\n >\n {stepContent}\n </div>\n )}\n {index < steps.length - 1 && (\n <span\n className={cn(styles.connector, isCompleted && styles.connectorCompleted)}\n aria-hidden=\"true\"\n />\n )}\n </li>\n );\n })}\n </ol>\n </nav>\n );\n}\n",".wrapper {\n width: 100%;\n}\n\n.tabList {\n display: flex;\n gap: 0;\n border-bottom: var(--bazaar-border-width-hairline) var(--bazaar-border-style-default) var(--bazaar-color-border-default);\n}\n\n.tab {\n position: relative;\n padding: var(--bazaar-space-3) var(--bazaar-space-4);\n background: transparent;\n border: none;\n border-bottom: var(--bazaar-border-width-medium) solid transparent;\n margin-bottom: calc(-1 * var(--bazaar-border-width-hairline));\n font-family: var(--bazaar-font-family-sans);\n font-size: var(--bazaar-font-size-label-md);\n font-weight: var(--bazaar-font-weight-medium);\n color: var(--bazaar-color-text-muted);\n cursor: pointer;\n white-space: nowrap;\n transition:\n color var(--bazaar-motion-duration-base) var(--bazaar-motion-easing-standard),\n border-color var(--bazaar-motion-duration-base) var(--bazaar-motion-easing-standard),\n background-color var(--bazaar-motion-duration-base) var(--bazaar-motion-easing-standard);\n}\n\n.tab:hover:not(:disabled) {\n color: var(--bazaar-color-text-primary);\n background-color: var(--bazaar-color-surface-hover);\n}\n\n.tab:focus-visible {\n outline: var(--bazaar-border-width-medium) solid var(--bazaar-focus-outline-color);\n outline-offset: calc(-1 * var(--bazaar-border-width-medium));\n box-shadow: var(--bazaar-shadow-focus);\n border-radius: var(--bazaar-radius-sm) var(--bazaar-radius-sm) 0 0;\n}\n\n.tab:disabled {\n opacity: var(--bazaar-opacity-disabled);\n cursor: not-allowed;\n}\n\n.active {\n color: var(--bazaar-color-brand-primary-500);\n border-bottom-color: var(--bazaar-color-brand-primary-500);\n font-weight: var(--bazaar-font-weight-semibold);\n}\n\n.active:hover:not(:disabled) {\n color: var(--bazaar-color-brand-primary-600);\n background-color: transparent;\n}\n\n.panel {\n padding: var(--bazaar-space-4) 0;\n}\n\n.panel:focus {\n outline: none;\n}\n","import { useState, useRef, useCallback, type ReactNode, type KeyboardEvent } from 'react';\nimport { cn } from '../../utils/cn';\nimport styles from './Tabs.module.css';\n\nexport interface Tab {\n id: string;\n label: string;\n content: ReactNode;\n disabled?: boolean;\n}\n\nexport interface TabsProps {\n /** Tab definitions */\n tabs: Tab[];\n /** Controlled active tab id */\n activeTab?: string;\n /** Callback when tab changes */\n onTabChange?: (id: string) => void;\n /** Additional className for the wrapper */\n className?: string;\n}\n\n/**\n * Tabs — tabbed interface for switching between content panels.\n *\n * Accessibility:\n * - Full WAI-ARIA tabs pattern: role=\"tablist\", role=\"tab\", role=\"tabpanel\"\n * - Arrow key navigation between tabs\n * - Home/End keys jump to first/last tab\n * - aria-selected, aria-controls, aria-labelledby for AT relationships\n * - Only active panel is in the tab order (tabIndex=0 on active tab)\n */\nexport function Tabs({ tabs, activeTab, onTabChange, className }: TabsProps) {\n const [internalActive, setInternalActive] = useState(tabs[0]?.id ?? '');\n const tabListRef = useRef<HTMLDivElement>(null);\n\n const active = activeTab ?? internalActive;\n\n const setActive = useCallback(\n (id: string) => {\n if (!activeTab) setInternalActive(id);\n onTabChange?.(id);\n },\n [activeTab, onTabChange],\n );\n\n const enabledTabs = tabs.filter((t) => !t.disabled);\n\n const handleKeyDown = useCallback(\n (e: KeyboardEvent) => {\n const currentIndex = enabledTabs.findIndex((t) => t.id === active);\n let nextIndex = currentIndex;\n\n switch (e.key) {\n case 'ArrowRight':\n nextIndex = (currentIndex + 1) % enabledTabs.length;\n break;\n case 'ArrowLeft':\n nextIndex = (currentIndex - 1 + enabledTabs.length) % enabledTabs.length;\n break;\n case 'Home':\n nextIndex = 0;\n break;\n case 'End':\n nextIndex = enabledTabs.length - 1;\n break;\n default:\n return;\n }\n\n e.preventDefault();\n const nextTab = enabledTabs[nextIndex];\n setActive(nextTab.id);\n\n const button = tabListRef.current?.querySelector(`[data-tab-id=\"${nextTab.id}\"]`) as HTMLElement;\n button?.focus();\n },\n [active, enabledTabs, setActive],\n );\n\n const activePanel = tabs.find((t) => t.id === active);\n\n return (\n <div className={cn(styles.wrapper, className)}>\n <div\n ref={tabListRef}\n role=\"tablist\"\n className={styles.tabList}\n onKeyDown={handleKeyDown}\n >\n {tabs.map((tab) => (\n <button\n key={tab.id}\n role=\"tab\"\n data-tab-id={tab.id}\n id={`tab-${tab.id}`}\n className={cn(styles.tab, tab.id === active && styles.active)}\n aria-selected={tab.id === active}\n aria-controls={`panel-${tab.id}`}\n tabIndex={tab.id === active ? 0 : -1}\n disabled={tab.disabled}\n onClick={() => setActive(tab.id)}\n >\n {tab.label}\n </button>\n ))}\n </div>\n {activePanel && (\n <div\n key={activePanel.id}\n role=\"tabpanel\"\n id={`panel-${activePanel.id}`}\n aria-labelledby={`tab-${activePanel.id}`}\n className={styles.panel}\n tabIndex={0}\n >\n {activePanel.content}\n </div>\n )}\n </div>\n );\n}\n",".overlay {\n position: fixed;\n inset: 0;\n z-index: var(--bazaar-z-modal, 1000);\n display: flex;\n align-items: flex-start;\n justify-content: center;\n padding-top: min(20vh, 140px);\n background: rgba(0, 0, 0, 0.4);\n animation: fadeIn var(--bazaar-motion-duration-fast) var(--bazaar-motion-easing-standard);\n}\n\n@keyframes fadeIn {\n from { opacity: 0; }\n to { opacity: 1; }\n}\n\n.palette {\n width: min(560px, calc(100vw - 32px));\n max-height: min(420px, 60vh);\n display: flex;\n flex-direction: column;\n background: var(--bazaar-color-surface-default);\n border-radius: var(--bazaar-radius-lg);\n box-shadow: var(--bazaar-shadow-xl, 0 20px 60px rgba(0, 0, 0, 0.3));\n overflow: hidden;\n animation: slideUp var(--bazaar-motion-duration-normal) var(--bazaar-motion-easing-standard);\n}\n\n@keyframes slideUp {\n from { opacity: 0; transform: translateY(-8px) scale(0.98); }\n to { opacity: 1; transform: translateY(0) scale(1); }\n}\n\n/* Search input area */\n.inputWrapper {\n display: flex;\n align-items: center;\n gap: var(--bazaar-space-3);\n padding: var(--bazaar-space-3) var(--bazaar-space-4);\n border-bottom: var(--bazaar-border-width-hairline) var(--bazaar-border-style-default) var(--bazaar-color-border-default);\n color: var(--bazaar-color-text-muted);\n}\n\n.input {\n flex: 1;\n border: none;\n background: transparent;\n outline: none;\n font-family: var(--bazaar-font-family-sans);\n font-size: var(--bazaar-font-size-body-md);\n color: var(--bazaar-color-text-primary);\n}\n\n.input::placeholder {\n color: var(--bazaar-color-text-muted);\n}\n\n/* Results list */\n.list {\n flex: 1;\n overflow-y: auto;\n padding: var(--bazaar-space-2) 0;\n}\n\n.empty {\n padding: var(--bazaar-space-6) var(--bazaar-space-4);\n text-align: center;\n font-size: var(--bazaar-font-size-body-sm);\n color: var(--bazaar-color-text-muted);\n font-family: var(--bazaar-font-family-sans);\n}\n\n/* Group label */\n.groupLabel {\n padding: var(--bazaar-space-2) var(--bazaar-space-4) var(--bazaar-space-1);\n font-size: var(--bazaar-font-size-caption);\n font-weight: var(--bazaar-font-weight-medium);\n color: var(--bazaar-color-text-muted);\n font-family: var(--bazaar-font-family-sans);\n text-transform: uppercase;\n letter-spacing: 0.05em;\n}\n\n/* Command item */\n.item {\n display: flex;\n align-items: center;\n gap: var(--bazaar-space-3);\n padding: var(--bazaar-space-2) var(--bazaar-space-4);\n cursor: pointer;\n font-family: var(--bazaar-font-family-sans);\n transition: background-color var(--bazaar-motion-duration-fast) var(--bazaar-motion-easing-standard);\n}\n\n.item.active {\n background-color: var(--bazaar-color-brand-primary-50, rgba(26, 115, 232, 0.08));\n}\n\n.item.disabled {\n opacity: var(--bazaar-opacity-disabled);\n pointer-events: none;\n}\n\n.itemIcon {\n display: inline-flex;\n align-items: center;\n color: var(--bazaar-color-text-secondary);\n flex-shrink: 0;\n}\n\n.itemContent {\n flex: 1;\n min-width: 0;\n display: flex;\n flex-direction: column;\n}\n\n.itemLabel {\n font-size: var(--bazaar-font-size-body-sm);\n color: var(--bazaar-color-text-primary);\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.itemDescription {\n font-size: var(--bazaar-font-size-caption);\n color: var(--bazaar-color-text-muted);\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.shortcut {\n flex-shrink: 0;\n font-family: var(--bazaar-font-family-sans);\n font-size: var(--bazaar-font-size-caption);\n color: var(--bazaar-color-text-muted);\n background: var(--bazaar-color-neutral-100);\n padding: 1px var(--bazaar-space-2);\n border-radius: var(--bazaar-radius-sm);\n border: var(--bazaar-border-width-hairline) var(--bazaar-border-style-default) var(--bazaar-color-border-default);\n}\n","import {\n useState,\n useEffect,\n useRef,\n useCallback,\n forwardRef,\n type ReactNode,\n type KeyboardEvent,\n} from 'react';\nimport { cn } from '../../utils/cn';\nimport styles from './CommandPalette.module.css';\n\nexport interface CommandItem {\n /** Unique identifier */\n id: string;\n /** Display label */\n label: string;\n /** Optional description shown below the label */\n description?: string;\n /** Leading icon */\n icon?: ReactNode;\n /** Group/category name */\n group?: string;\n /** Keyboard shortcut hint */\n shortcut?: string;\n /** Whether the item is disabled */\n disabled?: boolean;\n /** Custom search keywords (in addition to label) */\n keywords?: string[];\n}\n\nexport interface CommandPaletteProps {\n /** Whether the palette is open */\n open: boolean;\n /** Called when the palette should close */\n onClose: () => void;\n /** Available commands */\n items: CommandItem[];\n /** Called when a command is selected */\n onSelect: (item: CommandItem) => void;\n /** Placeholder text for the search input */\n placeholder?: string;\n /** Empty state message */\n emptyMessage?: string;\n /** Additional className for the overlay */\n className?: string;\n}\n\nconst SearchIcon = () => (\n <svg width=\"18\" height=\"18\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" aria-hidden=\"true\">\n <circle cx=\"11\" cy=\"11\" r=\"8\" />\n <line x1=\"21\" y1=\"21\" x2=\"16.65\" y2=\"16.65\" />\n </svg>\n);\n\nfunction filterItems(items: CommandItem[], query: string): CommandItem[] {\n if (!query) return items;\n const lower = query.toLowerCase();\n return items.filter((item) => {\n if (item.label.toLowerCase().includes(lower)) return true;\n if (item.description?.toLowerCase().includes(lower)) return true;\n if (item.keywords?.some((k) => k.toLowerCase().includes(lower))) return true;\n return false;\n });\n}\n\nfunction groupItems(items: CommandItem[]): Map<string, CommandItem[]> {\n const groups = new Map<string, CommandItem[]>();\n for (const item of items) {\n const key = item.group ?? '';\n const list = groups.get(key) ?? [];\n list.push(item);\n groups.set(key, list);\n }\n return groups;\n}\n\n/**\n * CommandPalette — keyboard-driven command search dialog (Cmd+K pattern).\n *\n * Renders a modal search input with filterable command list,\n * grouped results, keyboard navigation, and shortcut hints.\n *\n * Accessibility:\n * - Uses combobox + listbox ARIA pattern\n * - Arrow keys navigate items, Enter selects\n * - Escape closes the palette\n * - Focus is trapped within the dialog\n * - aria-activedescendant tracks highlighted item\n */\nexport const CommandPalette = forwardRef<HTMLDivElement, CommandPaletteProps>(\n (\n {\n open,\n onClose,\n items,\n onSelect,\n placeholder = 'Search commands…',\n emptyMessage = 'No results found.',\n className,\n },\n ref,\n ) => {\n const [query, setQuery] = useState('');\n const [activeIndex, setActiveIndex] = useState(0);\n const inputRef = useRef<HTMLInputElement>(null);\n const listRef = useRef<HTMLDivElement>(null);\n\n const filtered = filterItems(items, query);\n const grouped = groupItems(filtered);\n const flatFiltered = filtered.filter((i) => !i.disabled);\n\n // Reset state when opening\n useEffect(() => {\n if (open) {\n setQuery('');\n setActiveIndex(0);\n // Delay focus to after render\n requestAnimationFrame(() => inputRef.current?.focus());\n }\n }, [open]);\n\n // Scroll active item into view\n useEffect(() => {\n if (!open || flatFiltered.length === 0) return;\n const activeId = flatFiltered[activeIndex]?.id;\n if (!activeId) return;\n const el = listRef.current?.querySelector(`[data-item-id=\"${activeId}\"]`);\n el?.scrollIntoView({ block: 'nearest' });\n }, [activeIndex, open, flatFiltered]);\n\n const handleKeyDown = useCallback(\n (e: KeyboardEvent) => {\n if (e.key === 'Escape') {\n e.preventDefault();\n onClose();\n return;\n }\n\n if (e.key === 'ArrowDown') {\n e.preventDefault();\n setActiveIndex((i) => (i + 1) % Math.max(flatFiltered.length, 1));\n } else if (e.key === 'ArrowUp') {\n e.preventDefault();\n setActiveIndex((i) => (i - 1 + flatFiltered.length) % Math.max(flatFiltered.length, 1));\n } else if (e.key === 'Enter') {\n e.preventDefault();\n const item = flatFiltered[activeIndex];\n if (item) {\n onSelect(item);\n onClose();\n }\n }\n },\n [flatFiltered, activeIndex, onSelect, onClose],\n );\n\n // Close on backdrop click\n const handleBackdropClick = useCallback(\n (e: React.MouseEvent) => {\n if (e.target === e.currentTarget) onClose();\n },\n [onClose],\n );\n\n // Reset active index when query changes\n useEffect(() => {\n setActiveIndex(0);\n }, [query]);\n\n if (!open) return null;\n\n const activeId = flatFiltered[activeIndex]?.id;\n\n return (\n <div\n ref={ref}\n className={cn(styles.overlay, className)}\n onClick={handleBackdropClick}\n role=\"presentation\"\n >\n <div\n className={styles.palette}\n role=\"dialog\"\n aria-label=\"Command palette\"\n onKeyDown={handleKeyDown}\n >\n <div className={styles.inputWrapper}>\n <SearchIcon />\n <input\n ref={inputRef}\n type=\"text\"\n className={styles.input}\n value={query}\n onChange={(e) => setQuery(e.target.value)}\n placeholder={placeholder}\n role=\"combobox\"\n aria-expanded={true}\n aria-controls=\"command-palette-list\"\n aria-activedescendant={activeId ? `command-${activeId}` : undefined}\n autoComplete=\"off\"\n spellCheck={false}\n />\n </div>\n\n <div ref={listRef} id=\"command-palette-list\" className={styles.list} role=\"listbox\">\n {filtered.length === 0 ? (\n <div className={styles.empty}>{emptyMessage}</div>\n ) : (\n Array.from(grouped.entries()).map(([group, groupItems]) => (\n <div key={group} role=\"group\" aria-label={group || undefined}>\n {group && <div className={styles.groupLabel}>{group}</div>}\n {groupItems.map((item) => {\n const isActive = item.id === activeId;\n return (\n <div\n key={item.id}\n id={`command-${item.id}`}\n data-item-id={item.id}\n className={cn(\n styles.item,\n isActive && styles.active,\n item.disabled && styles.disabled,\n )}\n role=\"option\"\n aria-selected={isActive}\n aria-disabled={item.disabled || undefined}\n onClick={() => {\n if (item.disabled) return;\n onSelect(item);\n onClose();\n }}\n onMouseEnter={() => {\n if (!item.disabled) {\n const idx = flatFiltered.findIndex((f) => f.id === item.id);\n if (idx >= 0) setActiveIndex(idx);\n }\n }}\n >\n {item.icon && <span className={styles.itemIcon}>{item.icon}</span>}\n <div className={styles.itemContent}>\n <span className={styles.itemLabel}>{item.label}</span>\n {item.description && (\n <span className={styles.itemDescription}>{item.description}</span>\n )}\n </div>\n {item.shortcut && <kbd className={styles.shortcut}>{item.shortcut}</kbd>}\n </div>\n );\n })}\n </div>\n ))\n )}\n </div>\n </div>\n </div>\n );\n },\n);\n\nCommandPalette.displayName = 'CommandPalette';\n",".label {\n display: block;\n font-family: var(--bazaar-font-family-sans);\n font-size: var(--bazaar-font-size-label-lg);\n font-weight: var(--bazaar-font-weight-medium);\n line-height: var(--bazaar-line-height-label-lg);\n color: var(--bazaar-color-text-primary);\n margin-bottom: var(--bazaar-space-1);\n}\n\n.required {\n color: var(--bazaar-color-error-500);\n}\n\n.srOnly {\n position: absolute;\n width: 1px;\n height: 1px;\n padding: 0;\n margin: -1px;\n overflow: hidden;\n clip: rect(0, 0, 0, 0);\n white-space: nowrap;\n border: 0;\n}\n","import { type LabelHTMLAttributes } from 'react';\nimport { cn } from '../../utils/cn';\nimport styles from './Label.module.css';\n\nexport interface LabelProps extends LabelHTMLAttributes<HTMLLabelElement> {\n /** Mark the field as required — adds visual indicator */\n required?: boolean;\n}\n\n/**\n * Label — form field label.\n *\n * Accessibility:\n * - Always associate with an input via htmlFor\n * - Required indicator uses both visual (*) and sr-only text\n */\nexport function Label({ required, className, children, ...props }: LabelProps) {\n return (\n <label className={cn(styles.label, className)} {...props}>\n {children}\n {required && (\n <>\n <span className={styles.required} aria-hidden=\"true\"> *</span>\n <span className={styles.srOnly}> (required)</span>\n </>\n )}\n </label>\n );\n}\n",".formField {\n display: flex;\n flex-direction: column;\n gap: 0;\n width: 100%;\n}\n\n.control {\n width: 100%;\n}\n\n.disabled {\n opacity: var(--bazaar-opacity-disabled);\n pointer-events: none;\n}\n","import { type ReactNode, useId } from 'react';\nimport { cn } from '../../utils/cn';\nimport { Label } from '../Label';\nimport { HelperText } from '../HelperText';\nimport styles from './FormField.module.css';\n\nexport interface FormFieldProps {\n /** Label text for the field */\n label?: string;\n /** HTML for attribute to associate label with input */\n htmlFor?: string;\n /** Mark field as required */\n required?: boolean;\n /** Error message string — renders HelperText in error state */\n error?: string;\n /** Helper text displayed below the input */\n helperText?: string;\n /** The form control element (Input, Select, Textarea, etc.) */\n children: ReactNode;\n /** Disabled state — visually dims the field */\n disabled?: boolean;\n /** Additional CSS class */\n className?: string;\n}\n\n/**\n * FormField — composable wrapper that renders Label + input + HelperText/error.\n *\n * Accessibility:\n * - Generates aria-describedby linking between input and helper/error text\n * - Error messages use role=\"alert\" via HelperText\n * - Required indicator on Label\n * - Disabled state dims the entire field\n */\nexport function FormField({\n label,\n htmlFor,\n required,\n error,\n helperText,\n children,\n disabled,\n className,\n}: FormFieldProps) {\n const generatedId = useId();\n const descriptionId = `${generatedId}-description`;\n const hasDescription = Boolean(error || helperText);\n\n return (\n <div className={cn(styles.formField, disabled && styles.disabled, className)}>\n {label && (\n <Label htmlFor={htmlFor} required={required}>\n {label}\n </Label>\n )}\n <div className={styles.control} data-describedby={hasDescription ? descriptionId : undefined}>\n {children}\n </div>\n {(error || helperText) && (\n <HelperText id={descriptionId} error={Boolean(error)}>\n {error || helperText}\n </HelperText>\n )}\n </div>\n );\n}\n",".container {\n width: 100%;\n}\n\n.centered {\n margin-left: auto;\n margin-right: auto;\n}\n\n/* Max-width presets */\n.max-sm { max-width: 640px; }\n.max-md { max-width: 768px; }\n.max-lg { max-width: 1024px; }\n.max-xl { max-width: 1280px; }\n.max-full { max-width: 100%; }\n\n/* Padding */\n.pad-sm { padding-left: var(--bazaar-space-4); padding-right: var(--bazaar-space-4); }\n.pad-md { padding-left: var(--bazaar-space-6); padding-right: var(--bazaar-space-6); }\n.pad-lg { padding-left: var(--bazaar-space-8); padding-right: var(--bazaar-space-8); }\n","import { forwardRef, type HTMLAttributes, type ElementType } from 'react';\nimport { cn } from '../../utils/cn';\nimport styles from './Container.module.css';\n\nexport interface ContainerProps extends HTMLAttributes<HTMLDivElement> {\n /** Max-width preset */\n maxWidth?: 'sm' | 'md' | 'lg' | 'xl' | 'full';\n /** Horizontal padding */\n padding?: 'none' | 'sm' | 'md' | 'lg';\n /** Center the container horizontally */\n centered?: boolean;\n /** Render as a different HTML element */\n as?: ElementType;\n}\n\n/**\n * Container — max-width content wrapper with responsive padding.\n *\n * Provides consistent horizontal padding and a constrained max-width\n * for page-level content sections.\n *\n * Accessibility:\n * - Purely presentational — no ARIA roles needed\n * - Use semantic HTML elements via the `as` prop (e.g., main, section)\n */\nexport const Container = forwardRef<HTMLDivElement, ContainerProps>(\n (\n {\n maxWidth = 'lg',\n padding = 'md',\n centered = true,\n as: Component = 'div',\n className,\n children,\n ...props\n },\n ref,\n ) => (\n <Component\n ref={ref}\n className={cn(\n styles.container,\n styles[`max-${maxWidth}`],\n padding !== 'none' && styles[`pad-${padding}`],\n centered && styles.centered,\n className,\n )}\n {...props}\n >\n {children}\n </Component>\n ),\n);\n\nContainer.displayName = 'Container';\n",".grid {\n display: grid;\n}\n\n.fixed {\n grid-template-columns: repeat(var(--grid-columns), 1fr);\n}\n\n.autoFill {\n grid-template-columns: repeat(auto-fill, minmax(var(--grid-min-item-width), 1fr));\n}\n\n/* Gap */\n.gap-sm { gap: var(--bazaar-space-2); }\n.gap-md { gap: var(--bazaar-space-4); }\n.gap-lg { gap: var(--bazaar-space-6); }\n.gap-xl { gap: var(--bazaar-space-8); }\n\n/* Align items */\n.align-start { align-items: start; }\n.align-center { align-items: center; }\n.align-end { align-items: end; }\n.align-stretch { align-items: stretch; }\n","import { forwardRef, type HTMLAttributes, type CSSProperties } from 'react';\nimport { cn } from '../../utils/cn';\nimport styles from './Grid.module.css';\n\nexport interface GridProps extends HTMLAttributes<HTMLDivElement> {\n /** Number of columns (1-12) or 'auto' for auto-fill */\n columns?: number | 'auto';\n /** Gap between grid items */\n gap?: 'none' | 'sm' | 'md' | 'lg' | 'xl';\n /** Minimum item width when columns='auto' */\n minItemWidth?: number;\n /** Align items vertically */\n alignItems?: 'start' | 'center' | 'end' | 'stretch';\n}\n\n/**\n * Grid — CSS grid layout primitive.\n *\n * Provides a responsive grid with preset column counts or auto-fill\n * behavior based on minimum item width.\n *\n * Accessibility:\n * - Purely presentational — no ARIA roles needed\n * - Grid layout does not affect reading order for screen readers\n */\nexport const Grid = forwardRef<HTMLDivElement, GridProps>(\n (\n {\n columns = 'auto',\n gap = 'md',\n minItemWidth = 240,\n alignItems = 'stretch',\n className,\n style,\n children,\n ...props\n },\n ref,\n ) => {\n const gridStyle: CSSProperties = {\n ...style,\n ...(columns === 'auto'\n ? { '--grid-min-item-width': `${minItemWidth}px` } as CSSProperties\n : { '--grid-columns': columns } as CSSProperties),\n };\n\n return (\n <div\n ref={ref}\n className={cn(\n styles.grid,\n columns === 'auto' ? styles.autoFill : styles.fixed,\n gap !== 'none' && styles[`gap-${gap}`],\n styles[`align-${alignItems}`],\n className,\n )}\n style={gridStyle}\n {...props}\n >\n {children}\n </div>\n );\n },\n);\n\nGrid.displayName = 'Grid';\n",".stack {\n display: flex;\n}\n\n.vertical { flex-direction: column; }\n.horizontal { flex-direction: row; }\n\n.wrap { flex-wrap: wrap; }\n\n/* Gap */\n.gap-xs { gap: var(--bazaar-space-1); }\n.gap-sm { gap: var(--bazaar-space-2); }\n.gap-md { gap: var(--bazaar-space-4); }\n.gap-lg { gap: var(--bazaar-space-6); }\n.gap-xl { gap: var(--bazaar-space-8); }\n\n/* Align (cross axis) */\n.align-start { align-items: flex-start; }\n.align-center { align-items: center; }\n.align-end { align-items: flex-end; }\n.align-stretch { align-items: stretch; }\n\n/* Justify (main axis) */\n.justify-start { justify-content: flex-start; }\n.justify-center { justify-content: center; }\n.justify-end { justify-content: flex-end; }\n.justify-between { justify-content: space-between; }\n.justify-around { justify-content: space-around; }\n","import { forwardRef, type HTMLAttributes, type ElementType } from 'react';\nimport { cn } from '../../utils/cn';\nimport styles from './Stack.module.css';\n\nexport interface StackProps extends HTMLAttributes<HTMLDivElement> {\n /** Stack direction */\n direction?: 'vertical' | 'horizontal';\n /** Gap between items */\n gap?: 'none' | 'xs' | 'sm' | 'md' | 'lg' | 'xl';\n /** Align items on the cross axis */\n align?: 'start' | 'center' | 'end' | 'stretch';\n /** Justify items on the main axis */\n justify?: 'start' | 'center' | 'end' | 'between' | 'around';\n /** Whether items should wrap */\n wrap?: boolean;\n /** Render as a different HTML element */\n as?: ElementType;\n}\n\n/**\n * Stack — flex layout primitive for vertical or horizontal spacing.\n *\n * The most common layout component: arranges children with consistent\n * gaps. Defaults to a vertical stack (column).\n *\n * Accessibility:\n * - Purely presentational — no ARIA roles needed\n * - Use semantic HTML via `as` prop when appropriate\n */\nexport const Stack = forwardRef<HTMLDivElement, StackProps>(\n (\n {\n direction = 'vertical',\n gap = 'md',\n align = 'stretch',\n justify = 'start',\n wrap = false,\n as: Component = 'div',\n className,\n children,\n ...props\n },\n ref,\n ) => (\n <Component\n ref={ref}\n className={cn(\n styles.stack,\n styles[direction],\n gap !== 'none' && styles[`gap-${gap}`],\n styles[`align-${align}`],\n styles[`justify-${justify}`],\n wrap && styles.wrap,\n className,\n )}\n {...props}\n >\n {children}\n </Component>\n ),\n);\n\nStack.displayName = 'Stack';\n",".group {\n display: flex;\n align-items: center;\n border-radius: var(--bazaar-radius-md);\n border: var(--bazaar-border-width-hairline) var(--bazaar-border-style-default) var(--bazaar-color-border-default);\n background-color: var(--bazaar-color-surface-default);\n font-family: var(--bazaar-font-family-sans);\n transition: border-color var(--bazaar-motion-duration-fast) var(--bazaar-motion-easing-standard);\n overflow: hidden;\n}\n\n.group:focus-within {\n border-color: var(--bazaar-color-brand-primary-500);\n box-shadow: 0 0 0 2px var(--bazaar-color-brand-primary-100);\n}\n\n.error {\n border-color: var(--bazaar-color-error-500);\n}\n\n.error:focus-within {\n box-shadow: 0 0 0 2px var(--bazaar-color-error-100);\n}\n\n.disabled {\n opacity: var(--bazaar-opacity-disabled);\n pointer-events: none;\n background-color: var(--bazaar-color-surface-sunken);\n}\n\n.addon {\n display: flex;\n align-items: center;\n padding: 0 var(--bazaar-space-3);\n color: var(--bazaar-color-text-muted);\n background-color: var(--bazaar-color-surface-sunken);\n border-color: inherit;\n white-space: nowrap;\n font-size: var(--bazaar-font-size-body-sm);\n align-self: stretch;\n}\n\n.addon:first-child {\n border-right: var(--bazaar-border-width-hairline) var(--bazaar-border-style-default) var(--bazaar-color-border-default);\n}\n\n.addon:last-child {\n border-left: var(--bazaar-border-width-hairline) var(--bazaar-border-style-default) var(--bazaar-color-border-default);\n}\n\n.input {\n flex: 1;\n min-width: 0;\n}\n\n/* Strip inner input borders when inside InputGroup */\n.input :global(input),\n.input :global(select) {\n border: none;\n border-radius: 0;\n box-shadow: none;\n outline: none;\n}\n\n/* Size */\n.sm { min-height: var(--bazaar-size-control-sm); }\n.md { min-height: var(--bazaar-size-control-md); }\n.lg { min-height: var(--bazaar-size-control-lg); }\n","import { type ReactNode } from 'react';\nimport { cn } from '../../utils/cn';\nimport styles from './InputGroup.module.css';\n\nexport interface InputGroupProps {\n /** Content rendered before the input (e.g., icon, label, currency symbol) */\n startAddon?: ReactNode;\n /** Content rendered after the input (e.g., icon, button, unit label) */\n endAddon?: ReactNode;\n /** Size variant — matches TextField sizes */\n size?: 'sm' | 'md' | 'lg';\n /** Error state */\n error?: boolean;\n /** Disabled state */\n disabled?: boolean;\n /** Additional className */\n className?: string;\n /** Input element */\n children: ReactNode;\n}\n\n/**\n * InputGroup — wrapper that adds prefix/suffix addons to an input.\n *\n * Wraps a TextField (or other input) with leading/trailing elements\n * like icons, currency symbols, units, or action buttons.\n *\n * Accessibility:\n * - Addons are presentational and should not duplicate input labels\n * - Use aria-describedby on the input to associate addon context\n */\nexport function InputGroup({\n startAddon,\n endAddon,\n size = 'md',\n error = false,\n disabled = false,\n className,\n children,\n}: InputGroupProps) {\n return (\n <div\n className={cn(\n styles.group,\n styles[size],\n error && styles.error,\n disabled && styles.disabled,\n className,\n )}\n >\n {startAddon && <span className={styles.addon}>{startAddon}</span>}\n <div className={styles.input}>{children}</div>\n {endAddon && <span className={styles.addon}>{endAddon}</span>}\n </div>\n );\n}\n",".toolbar {\n display: flex;\n align-items: center;\n gap: var(--bazaar-space-1);\n font-family: var(--bazaar-font-family-sans);\n background: var(--bazaar-color-surface-default);\n border-radius: var(--bazaar-radius-md);\n flex-wrap: wrap;\n}\n\n.sm { padding: var(--bazaar-space-1); }\n.md { padding: var(--bazaar-space-2); }\n\n.outlined {\n border: var(--bazaar-border-width-hairline) var(--bazaar-border-style-default) var(--bazaar-color-border-default);\n}\n\n/* Button sizing within toolbar */\n.sm :global(button) { min-height: 28px; min-width: 28px; }\n.md :global(button) { min-height: 32px; min-width: 32px; }\n\n/* Group */\n.group {\n display: flex;\n align-items: center;\n gap: var(--bazaar-space-1);\n}\n\n/* Vertical divider */\n.divider {\n width: 1px;\n align-self: stretch;\n min-height: 20px;\n background: var(--bazaar-color-border-default);\n margin: 0 var(--bazaar-space-1);\n}\n","import { forwardRef, type HTMLAttributes, type ReactNode } from 'react';\nimport { cn } from '../../utils/cn';\nimport styles from './Toolbar.module.css';\n\nexport interface ToolbarProps extends HTMLAttributes<HTMLDivElement> {\n /** Size variant — affects padding and child button sizing */\n size?: 'sm' | 'md';\n /** Visual variant */\n variant?: 'default' | 'outlined';\n /** Toolbar content (buttons, groups, dividers) */\n children: ReactNode;\n}\n\nexport interface ToolbarGroupProps extends HTMLAttributes<HTMLDivElement> {\n /** Group content */\n children: ReactNode;\n}\n\nexport interface ToolbarDividerProps extends HTMLAttributes<HTMLDivElement> {}\n\n/**\n * Toolbar — horizontal action bar with grouped controls.\n *\n * Use with ToolbarGroup to visually separate related actions\n * and ToolbarDivider for explicit separators.\n *\n * Accessibility:\n * - Uses toolbar ARIA role\n * - Children should be buttons or controls with labels\n */\nexport const Toolbar = forwardRef<HTMLDivElement, ToolbarProps>(\n ({ size = 'md', variant = 'default', className, children, ...props }, ref) => (\n <div\n ref={ref}\n role=\"toolbar\"\n className={cn(styles.toolbar, styles[size], styles[variant], className)}\n {...props}\n >\n {children}\n </div>\n ),\n);\n\nToolbar.displayName = 'Toolbar';\n\nexport const ToolbarGroup = forwardRef<HTMLDivElement, ToolbarGroupProps>(\n ({ className, children, ...props }, ref) => (\n <div ref={ref} role=\"group\" className={cn(styles.group, className)} {...props}>\n {children}\n </div>\n ),\n);\n\nToolbarGroup.displayName = 'ToolbarGroup';\n\nexport const ToolbarDivider = forwardRef<HTMLDivElement, ToolbarDividerProps>(\n ({ className, ...props }, ref) => (\n <div\n ref={ref}\n role=\"separator\"\n aria-orientation=\"vertical\"\n className={cn(styles.divider, className)}\n {...props}\n />\n ),\n);\n\nToolbarDivider.displayName = 'ToolbarDivider';\n",".visuallyHidden {\n position: absolute;\n width: 1px;\n height: 1px;\n padding: 0;\n margin: -1px;\n overflow: hidden;\n clip: rect(0, 0, 0, 0);\n white-space: nowrap;\n border: 0;\n}\n","import { type HTMLAttributes } from 'react';\nimport styles from './VisuallyHidden.module.css';\n\nexport interface VisuallyHiddenProps extends HTMLAttributes<HTMLSpanElement> {\n /** Render as a different element */\n as?: 'span' | 'div' | 'label';\n}\n\n/**\n * VisuallyHidden — renders content that is hidden visually but accessible\n * to screen readers and other assistive technology.\n *\n * Use for:\n * - Labels for icon-only buttons\n * - Additional context for screen readers\n * - Skip navigation links\n * - Form labels that are visually unnecessary but needed for a11y\n *\n * This uses the standard screen-reader-only CSS technique that keeps\n * content in the document flow for assistive tech while hiding it\n * from sighted users.\n */\nexport function VisuallyHidden({\n as: Component = 'span',\n children,\n ...props\n}: VisuallyHiddenProps) {\n return (\n <Component className={styles.visuallyHidden} {...props}>\n {children}\n </Component>\n );\n}\n","import { useState, useEffect, type ReactNode } from 'react';\nimport { createPortal } from 'react-dom';\n\nexport interface PortalProps {\n /** Content to render in the portal */\n children: ReactNode;\n /** Target container element (defaults to document.body) */\n container?: Element | null;\n /** Whether the portal is active (renders inline when false) */\n disabled?: boolean;\n}\n\n/**\n * Portal — renders children into a DOM node outside the parent hierarchy.\n *\n * Use for overlays, tooltips, modals, and other floating content that\n * needs to escape stacking context or overflow constraints.\n *\n * Falls back to inline rendering during SSR or when disabled.\n *\n * Accessibility:\n * - Portal does not affect the accessibility tree\n * - Focus management is the responsibility of the portal content\n * - Ensure ARIA relationships (aria-describedby, aria-labelledby)\n * still work across the portal boundary\n */\nexport function Portal({ children, container, disabled = false }: PortalProps) {\n const [mounted, setMounted] = useState(false);\n\n useEffect(() => {\n setMounted(true);\n }, []);\n\n if (disabled || !mounted) {\n return <>{children}</>;\n }\n\n return createPortal(children, container ?? document.body);\n}\n",".container {\n width: 100%;\n}\n\n/* Sticky header */\n.stickyHeader thead {\n position: sticky;\n top: 0;\n z-index: 2;\n background-color: var(--bazaar-color-surface-default);\n}\n\n/* Comfortable density */\n.comfortable th,\n.comfortable td {\n padding: var(--bazaar-space-4) var(--bazaar-space-5);\n height: var(--bazaar-size-control-lg);\n}\n\n/* Sort button */\n.sortButton {\n display: inline-flex;\n align-items: center;\n gap: var(--bazaar-space-1);\n border: none;\n background: transparent;\n cursor: pointer;\n padding: 0;\n font: inherit;\n color: inherit;\n font-weight: var(--bazaar-font-weight-medium);\n white-space: nowrap;\n}\n\n.sortButton:hover {\n color: var(--bazaar-color-text-primary);\n}\n\n.sortButton:focus-visible {\n outline: var(--bazaar-border-width-medium) solid var(--bazaar-focus-outline-color);\n outline-offset: 2px;\n border-radius: var(--bazaar-radius-sm);\n}\n\n.sortIcon {\n display: inline-flex;\n align-items: center;\n flex-shrink: 0;\n}\n\n/* Checkbox */\n.checkbox {\n width: 16px;\n height: 16px;\n cursor: pointer;\n accent-color: var(--bazaar-color-brand-primary-500);\n}\n\n/* Selected row */\n.selectedRow {\n background-color: var(--bazaar-color-brand-primary-50, rgba(59, 130, 246, 0.06)) !important;\n}\n\n/* Clickable row */\n.clickableRow {\n cursor: pointer;\n}\n\n.clickableRow:hover {\n background-color: var(--bazaar-color-neutral-100);\n}\n","import { type ReactNode, type HTMLAttributes, useCallback } from 'react';\nimport { cn } from '../../utils/cn';\nimport { Table, TableHead, TableBody, TableRow, TableHeaderCell, TableCell } from '../Table';\nimport { Skeleton } from '../Skeleton';\nimport { EmptyState } from '../EmptyState';\nimport styles from './DataGrid.module.css';\n\nexport interface DataGridColumn<T = Record<string, unknown>> {\n /** Unique key for the column, used as the data accessor */\n key: string;\n /** Column header label */\n header: ReactNode;\n /** Custom render function for cell content */\n render?: (value: unknown, row: T, rowIndex: number) => ReactNode;\n /** Whether this column is sortable */\n sortable?: boolean;\n /** Column width (CSS value) */\n width?: string | number;\n /** Text alignment */\n align?: 'left' | 'center' | 'right';\n}\n\nexport type SortDirection = 'asc' | 'desc';\n\nexport interface DataGridProps<T = Record<string, unknown>> extends Omit<HTMLAttributes<HTMLDivElement>, 'onSelect'> {\n /** Column definitions */\n columns: DataGridColumn<T>[];\n /** Data array */\n data: T[];\n /** Enable row selection with checkboxes */\n selectable?: boolean;\n /** Callback when selection changes, receives array of selected row indices */\n onSelectionChange?: (selectedIndices: number[]) => void;\n /** Currently selected row indices (controlled) */\n selectedRows?: number[];\n /** Current sort column key */\n sortColumn?: string;\n /** Current sort direction */\n sortDirection?: SortDirection;\n /** Callback when a sortable column header is clicked */\n onSort?: (column: string, direction: SortDirection) => void;\n /** Show loading skeleton */\n loading?: boolean;\n /** Message shown when data is empty */\n emptyMessage?: string;\n /** Row density */\n density?: 'default' | 'compact' | 'comfortable';\n /** Sticky header */\n stickyHeader?: boolean;\n /** Striped rows */\n striped?: boolean;\n /** Callback when a row is clicked */\n onRowClick?: (row: T, index: number) => void;\n}\n\n/**\n * DataGrid — composable data grid built on Table primitives.\n *\n * Accessibility:\n * - Built on semantic Table components (table/thead/tbody/tr/th/td)\n * - Sortable columns use aria-sort\n * - Selection checkboxes include accessible labels\n * - Loading state announced via aria-busy\n * - Healthcare note: designed for patient lists, lab results,\n * appointment schedules, and other clinical data views\n */\nexport function DataGrid<T extends Record<string, unknown>>({\n columns,\n data,\n selectable = false,\n onSelectionChange,\n selectedRows = [],\n sortColumn,\n sortDirection,\n onSort,\n loading = false,\n emptyMessage = 'No data available',\n density = 'default',\n stickyHeader = false,\n striped = false,\n onRowClick,\n className,\n ...props\n}: DataGridProps<T>) {\n const allSelected = data.length > 0 && selectedRows.length === data.length;\n const someSelected = selectedRows.length > 0 && !allSelected;\n\n const handleSelectAll = useCallback(() => {\n if (!onSelectionChange) return;\n if (allSelected) {\n onSelectionChange([]);\n } else {\n onSelectionChange(data.map((_, i) => i));\n }\n }, [allSelected, data, onSelectionChange]);\n\n const handleSelectRow = useCallback(\n (index: number) => {\n if (!onSelectionChange) return;\n if (selectedRows.includes(index)) {\n onSelectionChange(selectedRows.filter((i) => i !== index));\n } else {\n onSelectionChange([...selectedRows, index]);\n }\n },\n [selectedRows, onSelectionChange]\n );\n\n const handleSort = useCallback(\n (key: string) => {\n if (!onSort) return;\n const newDirection: SortDirection =\n sortColumn === key && sortDirection === 'asc' ? 'desc' : 'asc';\n onSort(key, newDirection);\n },\n [sortColumn, sortDirection, onSort]\n );\n\n const tableDensity = density === 'comfortable' ? 'default' : density;\n\n const getAriaSort = (key: string): 'ascending' | 'descending' | 'none' | undefined => {\n if (sortColumn !== key) return 'none';\n return sortDirection === 'asc' ? 'ascending' : 'descending';\n };\n\n // Accessor function to get nested values by dot-notation key\n const getValue = (row: T, key: string): unknown => {\n return key.split('.').reduce<unknown>((obj, k) => {\n if (obj && typeof obj === 'object') return (obj as Record<string, unknown>)[k];\n return undefined;\n }, row);\n };\n\n const loadingRows = 5;\n\n return (\n <div\n className={cn(styles.container, stickyHeader && styles.stickyHeader, className)}\n aria-busy={loading}\n {...props}\n >\n <Table\n density={tableDensity}\n striped={striped}\n className={cn(density === 'comfortable' && styles.comfortable)}\n >\n <TableHead>\n <TableRow>\n {selectable && (\n <TableHeaderCell style={{ width: 44 }}>\n <input\n type=\"checkbox\"\n checked={allSelected}\n ref={(el) => {\n if (el) el.indeterminate = someSelected;\n }}\n onChange={handleSelectAll}\n aria-label=\"Select all rows\"\n className={styles.checkbox}\n />\n </TableHeaderCell>\n )}\n {columns.map((col) => (\n <TableHeaderCell\n key={col.key}\n style={{\n width: col.width,\n textAlign: col.align,\n }}\n aria-sort={col.sortable ? getAriaSort(col.key) : undefined}\n >\n {col.sortable ? (\n <button\n className={styles.sortButton}\n onClick={() => handleSort(col.key)}\n style={{ textAlign: col.align }}\n >\n {col.header}\n <span className={styles.sortIcon} aria-hidden=\"true\">\n {sortColumn === col.key ? (\n sortDirection === 'asc' ? (\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"1.5\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <polyline points=\"4 8 7 5 10 8\" />\n </svg>\n ) : (\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"1.5\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <polyline points=\"4 6 7 9 10 6\" />\n </svg>\n )\n ) : (\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"1.5\" strokeLinecap=\"round\" strokeLinejoin=\"round\" opacity=\"0.3\">\n <polyline points=\"4 5 7 3 10 5\" />\n <polyline points=\"4 9 7 11 10 9\" />\n </svg>\n )}\n </span>\n </button>\n ) : (\n col.header\n )}\n </TableHeaderCell>\n ))}\n </TableRow>\n </TableHead>\n <TableBody>\n {loading ? (\n Array.from({ length: loadingRows }, (_, rowIdx) => (\n <TableRow key={`skeleton-${rowIdx}`}>\n {selectable && (\n <TableCell>\n <Skeleton variant=\"rectangular\" width={16} height={16} />\n </TableCell>\n )}\n {columns.map((col) => (\n <TableCell key={col.key}>\n <Skeleton variant=\"text\" width=\"80%\" />\n </TableCell>\n ))}\n </TableRow>\n ))\n ) : data.length === 0 ? (\n <tr>\n <td colSpan={columns.length + (selectable ? 1 : 0)}>\n <EmptyState title={emptyMessage} />\n </td>\n </tr>\n ) : (\n data.map((row, rowIdx) => {\n const isSelected = selectedRows.includes(rowIdx);\n return (\n <TableRow\n key={rowIdx}\n className={cn(\n isSelected && styles.selectedRow,\n onRowClick && styles.clickableRow\n )}\n onClick={onRowClick ? () => onRowClick(row, rowIdx) : undefined}\n >\n {selectable && (\n <TableCell>\n <input\n type=\"checkbox\"\n checked={isSelected}\n onChange={(e) => {\n e.stopPropagation();\n handleSelectRow(rowIdx);\n }}\n onClick={(e) => e.stopPropagation()}\n aria-label={`Select row ${rowIdx + 1}`}\n className={styles.checkbox}\n />\n </TableCell>\n )}\n {columns.map((col) => {\n const value = getValue(row, col.key);\n return (\n <TableCell key={col.key} style={{ textAlign: col.align }}>\n {col.render ? col.render(value, row, rowIdx) : (value as ReactNode)}\n </TableCell>\n );\n })}\n </TableRow>\n );\n })\n )}\n </TableBody>\n </Table>\n </div>\n );\n}\n",".wrapper {\n position: relative;\n display: inline-flex;\n align-items: center;\n width: auto;\n}\n\n.fullWidth {\n width: 100%;\n}\n\n.input {\n display: block;\n width: 100%;\n border: var(--bazaar-border-width-hairline) var(--bazaar-border-style-default) var(--bazaar-color-border-default);\n border-radius: var(--bazaar-radius-md);\n background-color: var(--bazaar-color-surface-default);\n color: var(--bazaar-color-text-primary);\n font-family: var(--bazaar-font-family-sans);\n transition:\n border-color var(--bazaar-motion-duration-fast) var(--bazaar-motion-easing-standard),\n box-shadow var(--bazaar-motion-duration-fast) var(--bazaar-motion-easing-standard);\n}\n\n.input:hover:not(:disabled):not(:focus) {\n border-color: var(--bazaar-color-border-strong);\n}\n\n.input:focus {\n outline: none;\n border-color: var(--bazaar-color-brand-primary-500);\n box-shadow: var(--bazaar-shadow-focus);\n}\n\n.input:disabled {\n cursor: not-allowed;\n opacity: var(--bazaar-opacity-disabled);\n background-color: var(--bazaar-color-surface-subtle);\n}\n\n/* Hide native calendar icon in WebKit browsers */\n.input::-webkit-calendar-picker-indicator {\n opacity: 0;\n position: absolute;\n right: 0;\n top: 0;\n width: 100%;\n height: 100%;\n cursor: pointer;\n}\n\n.icon {\n position: absolute;\n right: var(--bazaar-space-3);\n color: var(--bazaar-color-text-muted);\n pointer-events: none;\n flex-shrink: 0;\n}\n\n/* Sizes */\n.sm .input {\n height: var(--bazaar-size-control-sm);\n padding: 0 calc(var(--bazaar-space-3) + 20px) 0 var(--bazaar-space-3);\n font-size: var(--bazaar-font-size-body-sm);\n}\n\n.md .input {\n height: var(--bazaar-size-control-md);\n padding: 0 calc(var(--bazaar-space-4) + 20px) 0 var(--bazaar-space-4);\n font-size: var(--bazaar-font-size-body-md);\n}\n\n.lg .input {\n height: var(--bazaar-size-control-lg);\n padding: 0 calc(var(--bazaar-space-4) + 22px) 0 var(--bazaar-space-4);\n font-size: var(--bazaar-font-size-body-lg);\n}\n\n/* Error */\n.error {\n border-color: var(--bazaar-color-error-500);\n}\n\n.error:focus {\n border-color: var(--bazaar-color-error-500);\n box-shadow: 0 0 0 3px rgba(194, 58, 58, 0.2);\n}\n","import { forwardRef, type InputHTMLAttributes } from 'react';\nimport { cn } from '../../utils/cn';\nimport styles from './DatePicker.module.css';\n\nexport interface DatePickerProps extends Omit<InputHTMLAttributes<HTMLInputElement>, 'size' | 'type'> {\n /** Size variant */\n size?: 'sm' | 'md' | 'lg';\n /** Error state */\n error?: boolean;\n /** Full width */\n fullWidth?: boolean;\n /** Minimum date (ISO format YYYY-MM-DD) */\n min?: string;\n /** Maximum date (ISO format YYYY-MM-DD) */\n max?: string;\n}\n\n/**\n * DatePicker — styled native date input for consistent appearance.\n *\n * Accessibility:\n * - Uses native input[type=\"date\"] for built-in AT support\n * - Date picker popup provided by the browser\n * - aria-invalid signals error state\n * - Consistent sizing with other Bazaar form controls\n */\nexport const DatePicker = forwardRef<HTMLInputElement, DatePickerProps>(\n ({ size = 'md', error = false, fullWidth = false, className, min, max, ...props }, ref) => (\n <div className={cn(styles.wrapper, styles[size], fullWidth && styles.fullWidth, className)}>\n <input\n ref={ref}\n type=\"date\"\n className={cn(styles.input, error && styles.error)}\n min={min}\n max={max}\n aria-invalid={error || undefined}\n {...props}\n />\n <svg\n className={styles.icon}\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"1.5\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n >\n <rect x=\"2\" y=\"3\" width=\"12\" height=\"11\" rx=\"1\" />\n <path d=\"M5 1v3M11 1v3M2 7h12\" />\n </svg>\n </div>\n ),\n);\n\nDatePicker.displayName = 'DatePicker';\n",".wrapper {\n display: inline-flex;\n align-items: center;\n gap: var(--bazaar-space-3);\n}\n\n.ringBox {\n position: relative;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n}\n\n.svg {\n display: block;\n transform-origin: center;\n}\n\n.track {\n stroke: var(--bazaar-progress-track);\n}\n\n.fill {\n transition: stroke-dashoffset var(--bazaar-motion-duration-slow) var(--bazaar-motion-easing-standard);\n}\n\n.fill.default {\n stroke: var(--bazaar-progress-fill-default);\n}\n\n.fill.success {\n stroke: var(--bazaar-progress-fill-success);\n}\n\n.fill.reward {\n stroke: var(--bazaar-progress-fill-reward);\n}\n\n.center {\n position: absolute;\n inset: 0;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n font-family: var(--bazaar-font-family-sans);\n font-weight: var(--bazaar-font-weight-semibold);\n color: var(--bazaar-color-text-primary);\n font-variant-numeric: tabular-nums;\n}\n\n.label {\n font-family: var(--bazaar-font-family-sans);\n font-size: var(--bazaar-font-size-body-sm);\n color: var(--bazaar-color-text-secondary);\n}\n","import { type HTMLAttributes, type ReactNode } from 'react';\nimport { cn } from '../../utils/cn';\nimport styles from './ProgressRing.module.css';\n\nexport type ProgressRingTone = 'default' | 'success' | 'reward';\nexport type ProgressRingSize = 'sm' | 'md' | 'lg';\n\nexport interface ProgressRingProps extends HTMLAttributes<HTMLDivElement> {\n /** Current value (0-100) */\n value: number;\n /** Maximum value (defaults to 100) */\n max?: number;\n /** Size variant */\n size?: ProgressRingSize;\n /** Visual tone */\n tone?: ProgressRingTone;\n /** Optional label rendered alongside the ring */\n label?: string;\n /** Show the numeric percentage in the center */\n showValue?: boolean;\n /** Custom center content (overrides showValue) */\n centerContent?: ReactNode;\n}\n\nconst sizeMap: Record<ProgressRingSize, { box: number; stroke: number; font: number }> = {\n sm: { box: 40, stroke: 4, font: 11 },\n md: { box: 64, stroke: 6, font: 14 },\n lg: { box: 96, stroke: 8, font: 18 },\n};\n\n/**\n * ProgressRing — circular progress indicator.\n *\n * Bazaar learning surface — used in dashboards, course cards, and learner\n * profile summaries to show completion percentage in a glanceable form.\n *\n * Accessibility:\n * - role=\"progressbar\" with aria-valuenow / min / max\n * - When `label` is provided, it's announced via aria-label\n */\nexport function ProgressRing({\n value,\n max = 100,\n size = 'md',\n tone = 'default',\n label,\n showValue = true,\n centerContent,\n className,\n ...props\n}: ProgressRingProps) {\n const { box, stroke, font } = sizeMap[size];\n const radius = (box - stroke) / 2;\n const circumference = 2 * Math.PI * radius;\n const pct = Math.min(100, Math.max(0, (value / max) * 100));\n const dashOffset = circumference * (1 - pct / 100);\n const center = box / 2;\n\n return (\n <div\n className={cn(styles.wrapper, className)}\n role=\"progressbar\"\n aria-valuenow={Math.round(pct)}\n aria-valuemin={0}\n aria-valuemax={max}\n aria-label={label ?? `${Math.round(pct)} percent complete`}\n {...props}\n >\n <div className={styles.ringBox} style={{ width: box, height: box }}>\n <svg width={box} height={box} className={styles.svg} aria-hidden=\"true\">\n <circle\n cx={center}\n cy={center}\n r={radius}\n strokeWidth={stroke}\n className={styles.track}\n fill=\"none\"\n />\n <circle\n cx={center}\n cy={center}\n r={radius}\n strokeWidth={stroke}\n className={cn(styles.fill, styles[tone])}\n fill=\"none\"\n strokeDasharray={circumference}\n strokeDashoffset={dashOffset}\n strokeLinecap=\"round\"\n transform={`rotate(-90 ${center} ${center})`}\n />\n </svg>\n <span className={styles.center} style={{ fontSize: font }}>\n {centerContent ?? (showValue ? `${Math.round(pct)}%` : null)}\n </span>\n </div>\n {label && <span className={styles.label}>{label}</span>}\n </div>\n );\n}\n",".card {\n display: flex;\n flex-direction: column;\n background-color: var(--bazaar-color-surface-default);\n border: var(--bazaar-border-width-hairline) solid var(--bazaar-color-border-default);\n border-radius: var(--bazaar-radius-lg);\n box-shadow: var(--bazaar-shadow-sm);\n overflow: hidden;\n font-family: var(--bazaar-font-family-sans);\n transition: box-shadow var(--bazaar-motion-duration-base) var(--bazaar-motion-easing-standard);\n}\n\n.card:hover {\n box-shadow: var(--bazaar-shadow-md);\n}\n\n.comfortable {\n padding: var(--bazaar-space-6);\n gap: var(--bazaar-space-5);\n}\n\n.compact {\n padding: var(--bazaar-space-4);\n gap: var(--bazaar-space-3);\n}\n\n.header {\n display: flex;\n align-items: flex-start;\n justify-content: space-between;\n gap: var(--bazaar-space-4);\n}\n\n.headerText {\n display: flex;\n flex-direction: column;\n gap: var(--bazaar-space-1);\n min-width: 0;\n}\n\n.title {\n margin: 0;\n font-size: var(--bazaar-font-size-heading-sm);\n line-height: var(--bazaar-line-height-heading-sm);\n font-weight: var(--bazaar-font-weight-semibold);\n color: var(--bazaar-color-text-primary);\n letter-spacing: var(--bazaar-tracking-tight);\n}\n\n.subtitle {\n margin: 0;\n font-size: var(--bazaar-font-size-body-sm);\n line-height: var(--bazaar-line-height-body-sm);\n color: var(--bazaar-color-text-secondary);\n}\n\n.metricRow {\n display: flex;\n align-items: baseline;\n gap: var(--bazaar-space-3);\n margin-top: var(--bazaar-space-3);\n flex-wrap: wrap;\n}\n\n.metric {\n font-size: var(--bazaar-font-size-display-md);\n line-height: var(--bazaar-line-height-display-md);\n font-weight: var(--bazaar-font-weight-semibold);\n color: var(--bazaar-color-text-primary);\n letter-spacing: var(--bazaar-tracking-tight);\n font-variant-numeric: tabular-nums;\n}\n\n.trendSlot {\n display: inline-flex;\n align-items: center;\n gap: var(--bazaar-space-1);\n}\n\n.actions {\n display: flex;\n align-items: center;\n gap: var(--bazaar-space-2);\n flex-shrink: 0;\n}\n\n.body {\n position: relative;\n width: 100%;\n min-height: 200px;\n}\n\n.footer {\n border-top: var(--bazaar-border-width-hairline) solid var(--bazaar-color-border-subtle);\n padding-top: var(--bazaar-space-4);\n font-size: var(--bazaar-font-size-body-sm);\n color: var(--bazaar-color-text-secondary);\n}\n\n.placeholder {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n gap: var(--bazaar-space-3);\n min-height: 220px;\n padding: var(--bazaar-space-6);\n text-align: center;\n}\n\n.placeholderTitle {\n font-size: var(--bazaar-font-size-body-md);\n font-weight: var(--bazaar-font-weight-semibold);\n color: var(--bazaar-color-text-primary);\n}\n\n.placeholderText {\n font-size: var(--bazaar-font-size-body-sm);\n color: var(--bazaar-color-text-secondary);\n max-width: 320px;\n}\n\n.skeletonBars {\n display: flex;\n align-items: flex-end;\n gap: var(--bazaar-space-2);\n height: 80px;\n width: 200px;\n}\n\n.skeletonBars span {\n flex: 1;\n background: linear-gradient(\n 180deg,\n var(--bazaar-color-surface-sunken) 0%,\n var(--bazaar-color-surface-hover) 100%\n );\n border-radius: var(--bazaar-radius-sm);\n animation: skeleton-pulse 1.6s ease-in-out infinite;\n}\n\n.skeletonBars span:nth-child(1) {\n height: 40%;\n animation-delay: 0ms;\n}\n.skeletonBars span:nth-child(2) {\n height: 80%;\n animation-delay: 100ms;\n}\n.skeletonBars span:nth-child(3) {\n height: 55%;\n animation-delay: 200ms;\n}\n.skeletonBars span:nth-child(4) {\n height: 95%;\n animation-delay: 300ms;\n}\n.skeletonBars span:nth-child(5) {\n height: 65%;\n animation-delay: 400ms;\n}\n\n@keyframes skeleton-pulse {\n 0%, 100% {\n opacity: 0.55;\n }\n 50% {\n opacity: 1;\n }\n}\n\n@media (prefers-reduced-motion: reduce) {\n .skeletonBars span {\n animation: none;\n opacity: 0.7;\n }\n .card {\n transition: none;\n }\n}\n","import { type HTMLAttributes, type ReactNode } from 'react';\nimport { cn } from '../utils/cn';\nimport styles from './ChartCard.module.css';\n\nexport type ChartCardState = 'ready' | 'loading' | 'empty' | 'error';\n\nexport interface ChartCardProps extends Omit<HTMLAttributes<HTMLDivElement>, 'title'> {\n /** Card title (e.g. \"30-day patient adherence\") */\n title?: ReactNode;\n /** Optional subtitle / explanation */\n subtitle?: ReactNode;\n /** Headline metric displayed prominently in the header */\n metric?: ReactNode;\n /** Trend chip beside the metric (use the Bazaar Badge or any node) */\n trend?: ReactNode;\n /** Optional actions (filters, export, etc.) rendered in the header */\n actions?: ReactNode;\n /** Footer content rendered below the chart body */\n footer?: ReactNode;\n /** Visual padding density */\n density?: 'comfortable' | 'compact';\n /** Render state — controls whether children, loader, empty, or error renders */\n state?: ChartCardState;\n /** Custom empty-state node */\n emptyState?: ReactNode;\n /** Custom loading-state node */\n loadingState?: ReactNode;\n /** Custom error-state node */\n errorState?: ReactNode;\n /** Optional aria-label for the chart region */\n ariaLabel?: string;\n}\n\nconst defaultEmpty = (\n <div className={styles.placeholder}>\n <div className={styles.placeholderTitle}>No data available</div>\n <div className={styles.placeholderText}>\n There's nothing to display for the selected range.\n </div>\n </div>\n);\n\nconst defaultLoading = (\n <div className={styles.placeholder}>\n <div className={styles.skeletonBars} aria-hidden=\"true\">\n <span />\n <span />\n <span />\n <span />\n <span />\n </div>\n <div className={styles.placeholderText}>Loading chart…</div>\n </div>\n);\n\nconst defaultError = (\n <div className={styles.placeholder} role=\"alert\">\n <div className={styles.placeholderTitle}>Unable to load chart</div>\n <div className={styles.placeholderText}>\n Something went wrong while loading this data. Try again in a moment.\n </div>\n </div>\n);\n\n/**\n * ChartCard — the unifying shell for every Bazaar chart component.\n *\n * Provides a consistent header (title, subtitle, headline metric, trend chip,\n * actions), body slot, footer slot, and built-in loading / empty / error states.\n *\n * Every chart component in Bazaar composes this card so the system feels\n * cohesive and developers get visual states for free.\n */\nexport function ChartCard({\n title,\n subtitle,\n metric,\n trend,\n actions,\n footer,\n density = 'comfortable',\n state = 'ready',\n emptyState,\n loadingState,\n errorState,\n ariaLabel,\n className,\n children,\n ...props\n}: ChartCardProps) {\n const showHeader = title || subtitle || metric || trend || actions;\n\n return (\n <section\n className={cn(styles.card, styles[density], className)}\n aria-label={ariaLabel}\n {...props}\n >\n {showHeader && (\n <header className={styles.header}>\n <div className={styles.headerText}>\n {title && <h3 className={styles.title}>{title}</h3>}\n {subtitle && <p className={styles.subtitle}>{subtitle}</p>}\n {(metric || trend) && (\n <div className={styles.metricRow}>\n {metric && <span className={styles.metric}>{metric}</span>}\n {trend && <span className={styles.trendSlot}>{trend}</span>}\n </div>\n )}\n </div>\n {actions && <div className={styles.actions}>{actions}</div>}\n </header>\n )}\n\n <div className={styles.body}>\n {state === 'loading' && (loadingState ?? defaultLoading)}\n {state === 'empty' && (emptyState ?? defaultEmpty)}\n {state === 'error' && (errorState ?? defaultError)}\n {state === 'ready' && children}\n </div>\n\n {footer && <footer className={styles.footer}>{footer}</footer>}\n </section>\n );\n}\n","/**\n * Skyfall Bazaar — Chart Theme\n *\n * Centralized theme tokens for all Recharts-based components.\n * Reads from CSS custom properties so chart visuals stay in sync with\n * the rest of the Bazaar design system.\n */\n\n/**\n * The Bazaar chart series palette. Order is intentional — earlier colors\n * are used first so simple charts always pull from the most credible,\n * brand-aligned hues before moving into supporting accents.\n */\nexport const bazaarSeriesPalette = [\n 'var(--bazaar-data-vis-1)',\n 'var(--bazaar-data-vis-2)',\n 'var(--bazaar-data-vis-3)',\n 'var(--bazaar-data-vis-4)',\n 'var(--bazaar-data-vis-5)',\n] as const;\n\n/**\n * Resolve a series color by index, wrapping the palette if more series\n * exist than available colors. Accepts an explicit override.\n */\nexport function getSeriesColor(index: number, override?: string): string {\n if (override) return override;\n return bazaarSeriesPalette[index % bazaarSeriesPalette.length];\n}\n\n/**\n * Token-driven chart theme. Used to style axes, gridlines, tooltips,\n * legends, etc. so every chart in Bazaar feels like part of one system.\n */\nexport const bazaarChartTheme = {\n axis: {\n stroke: 'var(--bazaar-data-vis-axis)',\n fontSize: 12,\n fontFamily: 'var(--bazaar-font-family-sans)',\n tickColor: 'var(--bazaar-color-text-muted)',\n },\n grid: {\n stroke: 'var(--bazaar-data-vis-gridline)',\n strokeDasharray: '3 3',\n },\n tooltip: {\n background: 'var(--bazaar-color-surface-overlay)',\n border: 'var(--bazaar-color-border-default)',\n text: 'var(--bazaar-color-text-primary)',\n muted: 'var(--bazaar-color-text-secondary)',\n },\n reference: {\n stroke: 'var(--bazaar-color-text-muted)',\n strokeDasharray: '4 4',\n },\n} as const;\n\nexport type ChartSeries<T = Record<string, unknown>> = {\n /** Property key on the data row that holds the series value */\n dataKey: keyof T & string;\n /** Display label for tooltip / legend */\n label?: string;\n /** Optional explicit color (defaults to Bazaar palette) */\n color?: string;\n};\n\nexport type ValueFormatter = (value: number | string) => string;\n\n/** Default number formatter — locale-aware, with sensible compact behavior */\nexport const defaultValueFormatter: ValueFormatter = (value) => {\n if (typeof value !== 'number') return String(value);\n if (Math.abs(value) >= 1_000_000) return `${(value / 1_000_000).toFixed(1)}M`;\n if (Math.abs(value) >= 1_000) return `${(value / 1_000).toFixed(1)}k`;\n return value.toLocaleString();\n};\n",".tooltip {\n background-color: var(--bazaar-color-surface-overlay);\n border: var(--bazaar-border-width-hairline) solid var(--bazaar-color-border-default);\n border-radius: var(--bazaar-radius-md);\n box-shadow: var(--bazaar-shadow-md);\n padding: var(--bazaar-space-3) var(--bazaar-space-4);\n min-width: 160px;\n font-family: var(--bazaar-font-family-sans);\n pointer-events: none;\n}\n\n.label {\n font-size: var(--bazaar-font-size-caption);\n font-weight: var(--bazaar-font-weight-semibold);\n color: var(--bazaar-color-text-secondary);\n text-transform: uppercase;\n letter-spacing: var(--bazaar-tracking-wide);\n margin-bottom: var(--bazaar-space-2);\n padding-bottom: var(--bazaar-space-2);\n border-bottom: var(--bazaar-border-width-hairline) solid var(--bazaar-color-border-subtle);\n}\n\n.list {\n list-style: none;\n margin: 0;\n padding: 0;\n display: flex;\n flex-direction: column;\n gap: var(--bazaar-space-1);\n}\n\n.row {\n display: flex;\n align-items: center;\n gap: var(--bazaar-space-2);\n font-size: var(--bazaar-font-size-body-sm);\n color: var(--bazaar-color-text-primary);\n}\n\n.swatch {\n width: 10px;\n height: 10px;\n border-radius: var(--bazaar-radius-sm);\n flex-shrink: 0;\n}\n\n.name {\n flex: 1;\n color: var(--bazaar-color-text-secondary);\n}\n\n.value {\n font-family: var(--bazaar-font-family-mono);\n font-weight: var(--bazaar-font-weight-semibold);\n color: var(--bazaar-color-text-primary);\n font-variant-numeric: tabular-nums;\n}\n","import type { TooltipProps } from 'recharts';\nimport { defaultValueFormatter, type ValueFormatter } from './chartTheme';\nimport styles from './ChartTooltip.module.css';\n\nexport interface ChartTooltipProps extends TooltipProps<number, string> {\n /** Optional formatter for displayed values */\n valueFormatter?: ValueFormatter;\n /** Optional formatter for the tooltip label (e.g. axis category) */\n labelFormatter?: (label: string) => string;\n}\n\n/**\n * Bazaar-styled tooltip used by every chart in the system.\n *\n * Pass directly to Recharts `<Tooltip content={<ChartTooltip />} />`.\n */\nexport function ChartTooltip({\n active,\n payload,\n label,\n valueFormatter = defaultValueFormatter,\n labelFormatter,\n}: ChartTooltipProps) {\n if (!active || !payload || payload.length === 0) return null;\n\n const displayLabel = labelFormatter && label != null ? labelFormatter(String(label)) : label;\n\n return (\n <div className={styles.tooltip} role=\"tooltip\">\n {displayLabel != null && <div className={styles.label}>{displayLabel}</div>}\n <ul className={styles.list}>\n {payload.map((entry, index) => (\n <li key={`${entry.dataKey}-${index}`} className={styles.row}>\n <span\n className={styles.swatch}\n style={{ backgroundColor: entry.color }}\n aria-hidden=\"true\"\n />\n <span className={styles.name}>{entry.name}</span>\n <span className={styles.value}>\n {entry.value != null ? valueFormatter(entry.value as number) : '—'}\n </span>\n </li>\n ))}\n </ul>\n </div>\n );\n}\n",".legend {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: var(--bazaar-space-4);\n list-style: none;\n margin: 0;\n padding: var(--bazaar-space-3) 0 0;\n font-family: var(--bazaar-font-family-sans);\n}\n\n.item {\n display: inline-flex;\n align-items: center;\n gap: var(--bazaar-space-2);\n}\n\n.swatch {\n width: 10px;\n height: 10px;\n border-radius: var(--bazaar-radius-sm);\n flex-shrink: 0;\n}\n\n.label {\n font-size: var(--bazaar-font-size-body-sm);\n color: var(--bazaar-color-text-secondary);\n font-weight: var(--bazaar-font-weight-medium);\n}\n","import type { LegendProps } from 'recharts';\nimport styles from './ChartLegend.module.css';\n\n/**\n * Bazaar-styled chart legend. Pass to Recharts via:\n * <Legend content={<ChartLegend />} />\n */\nexport function ChartLegend({ payload }: LegendProps) {\n if (!payload || payload.length === 0) return null;\n\n return (\n <ul className={styles.legend}>\n {payload.map((entry, index) => (\n <li key={`${entry.value}-${index}`} className={styles.item}>\n <span\n className={styles.swatch}\n style={{ backgroundColor: entry.color }}\n aria-hidden=\"true\"\n />\n <span className={styles.label}>{entry.value}</span>\n </li>\n ))}\n </ul>\n );\n}\n","import {\n CartesianGrid,\n Legend,\n Line,\n LineChart as RechartsLineChart,\n ReferenceLine,\n ResponsiveContainer,\n Tooltip,\n XAxis,\n YAxis,\n} from 'recharts';\nimport { ChartCard, type ChartCardProps } from './ChartCard';\nimport { ChartLegend } from './ChartLegend';\nimport { ChartTooltip } from './ChartTooltip';\nimport {\n bazaarChartTheme,\n defaultValueFormatter,\n getSeriesColor,\n type ChartSeries,\n type ValueFormatter,\n} from './chartTheme';\n\nexport interface LineChartProps<T extends Record<string, unknown>>\n extends Omit<ChartCardProps, 'children'> {\n /** Row-shaped data — each row represents one x-axis category */\n data: T[];\n /** Property name on each row used for the x-axis */\n xKey: keyof T & string;\n /** One or more series definitions */\n series: ChartSeries<T>[];\n /** Chart height in pixels (defaults to 280) */\n height?: number;\n /** Show legend (defaults to true when more than one series) */\n showLegend?: boolean;\n /** Show grid (defaults to true) */\n showGrid?: boolean;\n /** Format values in tooltip / axis */\n valueFormatter?: ValueFormatter;\n /** Optional reference line value(s) (e.g. target threshold) */\n referenceLines?: { value: number; label?: string }[];\n /** Smooth curves (defaults to true) */\n smooth?: boolean;\n}\n\n/**\n * Bazaar LineChart — wraps Recharts with Bazaar tokens, shell, and states.\n *\n * Time-series and trend visualization for dashboards. Pair with KpiStatCard\n * for headline metrics or use standalone in a ChartCard layout.\n */\nexport function LineChart<T extends Record<string, unknown>>({\n data,\n xKey,\n series,\n height = 280,\n showLegend,\n showGrid = true,\n valueFormatter = defaultValueFormatter,\n referenceLines,\n smooth = true,\n state,\n ...cardProps\n}: LineChartProps<T>) {\n const effectiveState = state ?? (data.length === 0 ? 'empty' : 'ready');\n const showLegendFinal = showLegend ?? series.length > 1;\n\n return (\n <ChartCard state={effectiveState} {...cardProps}>\n <ResponsiveContainer width=\"100%\" height={height}>\n <RechartsLineChart data={data} margin={{ top: 8, right: 16, left: 0, bottom: 0 }}>\n {showGrid && (\n <CartesianGrid\n vertical={false}\n stroke={bazaarChartTheme.grid.stroke}\n strokeDasharray={bazaarChartTheme.grid.strokeDasharray}\n />\n )}\n <XAxis\n dataKey={xKey}\n stroke={bazaarChartTheme.axis.stroke}\n tick={{ fill: bazaarChartTheme.axis.tickColor, fontSize: bazaarChartTheme.axis.fontSize }}\n tickLine={false}\n axisLine={{ stroke: bazaarChartTheme.grid.stroke }}\n />\n <YAxis\n stroke={bazaarChartTheme.axis.stroke}\n tick={{ fill: bazaarChartTheme.axis.tickColor, fontSize: bazaarChartTheme.axis.fontSize }}\n tickLine={false}\n axisLine={false}\n tickFormatter={(v) => valueFormatter(v as number)}\n width={48}\n />\n <Tooltip\n cursor={{ stroke: bazaarChartTheme.grid.stroke, strokeWidth: 1 }}\n content={<ChartTooltip valueFormatter={valueFormatter} />}\n />\n {showLegendFinal && <Legend content={<ChartLegend />} />}\n {referenceLines?.map((ref, i) => (\n <ReferenceLine\n key={`ref-${i}`}\n y={ref.value}\n stroke={bazaarChartTheme.reference.stroke}\n strokeDasharray={bazaarChartTheme.reference.strokeDasharray}\n label={\n ref.label\n ? {\n value: ref.label,\n position: 'insideTopRight',\n fill: bazaarChartTheme.tooltip.muted,\n fontSize: 11,\n }\n : undefined\n }\n />\n ))}\n {series.map((s, index) => {\n const color = getSeriesColor(index, s.color);\n return (\n <Line\n key={s.dataKey}\n type={smooth ? 'monotone' : 'linear'}\n dataKey={s.dataKey}\n name={s.label ?? s.dataKey}\n stroke={color}\n strokeWidth={2}\n dot={{ r: 0, fill: color }}\n activeDot={{ r: 5, strokeWidth: 0 }}\n isAnimationActive={false}\n />\n );\n })}\n </RechartsLineChart>\n </ResponsiveContainer>\n </ChartCard>\n );\n}\n","import {\n Bar,\n BarChart as RechartsBarChart,\n CartesianGrid,\n Legend,\n ReferenceLine,\n ResponsiveContainer,\n Tooltip,\n XAxis,\n YAxis,\n} from 'recharts';\nimport { ChartCard, type ChartCardProps } from './ChartCard';\nimport { ChartLegend } from './ChartLegend';\nimport { ChartTooltip } from './ChartTooltip';\nimport {\n bazaarChartTheme,\n defaultValueFormatter,\n getSeriesColor,\n type ChartSeries,\n type ValueFormatter,\n} from './chartTheme';\n\nexport interface BarChartProps<T extends Record<string, unknown>>\n extends Omit<ChartCardProps, 'children'> {\n data: T[];\n xKey: keyof T & string;\n series: ChartSeries<T>[];\n height?: number;\n showLegend?: boolean;\n showGrid?: boolean;\n /** Stack bars (renders as a stacked bar chart) */\n stacked?: boolean;\n /** Render bars horizontally */\n horizontal?: boolean;\n valueFormatter?: ValueFormatter;\n referenceLines?: { value: number; label?: string }[];\n}\n\n/**\n * Bazaar BarChart — for categorical comparisons.\n *\n * Set `stacked` for stacked bars, `horizontal` for horizontal layout\n * (better for long category labels).\n */\nexport function BarChart<T extends Record<string, unknown>>({\n data,\n xKey,\n series,\n height = 280,\n showLegend,\n showGrid = true,\n stacked = false,\n horizontal = false,\n valueFormatter = defaultValueFormatter,\n referenceLines,\n state,\n ...cardProps\n}: BarChartProps<T>) {\n const effectiveState = state ?? (data.length === 0 ? 'empty' : 'ready');\n const showLegendFinal = showLegend ?? series.length > 1;\n\n return (\n <ChartCard state={effectiveState} {...cardProps}>\n <ResponsiveContainer width=\"100%\" height={height}>\n <RechartsBarChart\n data={data}\n layout={horizontal ? 'vertical' : 'horizontal'}\n margin={{ top: 8, right: 16, left: 0, bottom: 0 }}\n barCategoryGap=\"22%\"\n >\n {showGrid && (\n <CartesianGrid\n vertical={horizontal}\n horizontal={!horizontal}\n stroke={bazaarChartTheme.grid.stroke}\n strokeDasharray={bazaarChartTheme.grid.strokeDasharray}\n />\n )}\n {horizontal ? (\n <>\n <XAxis\n type=\"number\"\n stroke={bazaarChartTheme.axis.stroke}\n tick={{\n fill: bazaarChartTheme.axis.tickColor,\n fontSize: bazaarChartTheme.axis.fontSize,\n }}\n tickLine={false}\n axisLine={false}\n tickFormatter={(v) => valueFormatter(v as number)}\n />\n <YAxis\n type=\"category\"\n dataKey={xKey}\n stroke={bazaarChartTheme.axis.stroke}\n tick={{\n fill: bazaarChartTheme.axis.tickColor,\n fontSize: bazaarChartTheme.axis.fontSize,\n }}\n tickLine={false}\n axisLine={{ stroke: bazaarChartTheme.grid.stroke }}\n width={96}\n />\n </>\n ) : (\n <>\n <XAxis\n dataKey={xKey}\n stroke={bazaarChartTheme.axis.stroke}\n tick={{\n fill: bazaarChartTheme.axis.tickColor,\n fontSize: bazaarChartTheme.axis.fontSize,\n }}\n tickLine={false}\n axisLine={{ stroke: bazaarChartTheme.grid.stroke }}\n />\n <YAxis\n stroke={bazaarChartTheme.axis.stroke}\n tick={{\n fill: bazaarChartTheme.axis.tickColor,\n fontSize: bazaarChartTheme.axis.fontSize,\n }}\n tickLine={false}\n axisLine={false}\n tickFormatter={(v) => valueFormatter(v as number)}\n width={48}\n />\n </>\n )}\n <Tooltip\n cursor={{ fill: 'var(--bazaar-state-hover-overlay)' }}\n content={<ChartTooltip valueFormatter={valueFormatter} />}\n />\n {showLegendFinal && <Legend content={<ChartLegend />} />}\n {referenceLines?.map((ref, i) => (\n <ReferenceLine\n key={`ref-${i}`}\n {...(horizontal ? { x: ref.value } : { y: ref.value })}\n stroke={bazaarChartTheme.reference.stroke}\n strokeDasharray={bazaarChartTheme.reference.strokeDasharray}\n label={\n ref.label\n ? {\n value: ref.label,\n position: 'insideTopRight',\n fill: bazaarChartTheme.tooltip.muted,\n fontSize: 11,\n }\n : undefined\n }\n />\n ))}\n {series.map((s, index) => {\n const color = getSeriesColor(index, s.color);\n return (\n <Bar\n key={s.dataKey}\n dataKey={s.dataKey}\n name={s.label ?? s.dataKey}\n fill={color}\n radius={[4, 4, 0, 0]}\n stackId={stacked ? 'bazaar-stack' : undefined}\n isAnimationActive={false}\n />\n );\n })}\n </RechartsBarChart>\n </ResponsiveContainer>\n </ChartCard>\n );\n}\n","import {\n Area,\n AreaChart,\n Line,\n LineChart,\n ResponsiveContainer,\n} from 'recharts';\nimport { getSeriesColor } from './chartTheme';\n\nexport interface SparklineProps {\n /** Array of numeric values OR row objects */\n data: number[] | Record<string, unknown>[];\n /** Property name when `data` is row-shaped (defaults to \"value\") */\n dataKey?: string;\n /** Render style */\n variant?: 'line' | 'area';\n /** Width in px (defaults to 120) — accepts any CSS length */\n width?: number | string;\n /** Height in px (defaults to 36) */\n height?: number | string;\n /** Line/area color (defaults to first Bazaar series color) */\n color?: string;\n /** Stroke width (defaults to 2) */\n strokeWidth?: number;\n /** Optional accessible label */\n ariaLabel?: string;\n}\n\n/**\n * Bazaar Sparkline — minimal inline trend chart for KPIs and table cells.\n *\n * Pure visual: no axes, grid, tooltip, or legend. Designed to live inside\n * stat cards, data grid cells, and dense dashboard surfaces.\n */\nexport function Sparkline({\n data,\n dataKey = 'value',\n variant = 'line',\n width = 120,\n height = 36,\n color,\n strokeWidth = 2,\n ariaLabel,\n}: SparklineProps) {\n const normalized: Record<string, number>[] =\n typeof data[0] === 'number'\n ? (data as number[]).map((v, i) => ({ x: i, [dataKey]: v }))\n : (data as Record<string, number>[]);\n\n const stroke = getSeriesColor(0, color);\n const gradientId = `bazaar-spark-${dataKey}-${Math.random().toString(36).slice(2, 8)}`;\n\n return (\n <div\n style={{ width, height, display: 'inline-block' }}\n role={ariaLabel ? 'img' : undefined}\n aria-label={ariaLabel}\n >\n <ResponsiveContainer width=\"100%\" height=\"100%\">\n {variant === 'area' ? (\n <AreaChart data={normalized} margin={{ top: 2, right: 2, left: 2, bottom: 2 }}>\n <defs>\n <linearGradient id={gradientId} x1=\"0\" y1=\"0\" x2=\"0\" y2=\"1\">\n <stop offset=\"0%\" stopColor={stroke} stopOpacity={0.32} />\n <stop offset=\"100%\" stopColor={stroke} stopOpacity={0} />\n </linearGradient>\n </defs>\n <Area\n type=\"monotone\"\n dataKey={dataKey}\n stroke={stroke}\n strokeWidth={strokeWidth}\n fill={`url(#${gradientId})`}\n isAnimationActive={false}\n dot={false}\n />\n </AreaChart>\n ) : (\n <LineChart data={normalized} margin={{ top: 2, right: 2, left: 2, bottom: 2 }}>\n <Line\n type=\"monotone\"\n dataKey={dataKey}\n stroke={stroke}\n strokeWidth={strokeWidth}\n dot={false}\n isAnimationActive={false}\n />\n </LineChart>\n )}\n </ResponsiveContainer>\n </div>\n );\n}\n",".card {\n display: flex;\n flex-direction: column;\n background-color: var(--bazaar-color-surface-default);\n border: var(--bazaar-border-width-hairline) solid var(--bazaar-color-border-default);\n border-radius: var(--bazaar-radius-lg);\n box-shadow: var(--bazaar-shadow-sm);\n font-family: var(--bazaar-font-family-sans);\n transition: box-shadow var(--bazaar-motion-duration-base) var(--bazaar-motion-easing-standard),\n transform var(--bazaar-motion-duration-base) var(--bazaar-motion-easing-standard);\n}\n\n.card:hover {\n box-shadow: var(--bazaar-shadow-md);\n}\n\n.comfortable {\n padding: var(--bazaar-space-5);\n gap: var(--bazaar-space-4);\n}\n\n.compact {\n padding: var(--bazaar-space-4);\n gap: var(--bazaar-space-3);\n}\n\n.header {\n display: flex;\n align-items: flex-start;\n justify-content: space-between;\n gap: var(--bazaar-space-3);\n}\n\n.label {\n font-size: var(--bazaar-font-size-label-md);\n font-weight: var(--bazaar-font-weight-medium);\n color: var(--bazaar-color-text-secondary);\n text-transform: uppercase;\n letter-spacing: var(--bazaar-tracking-wide);\n}\n\n.icon {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 32px;\n height: 32px;\n border-radius: var(--bazaar-radius-md);\n background-color: var(--bazaar-color-surface-subtle);\n color: var(--bazaar-color-text-secondary);\n}\n\n.valueRow {\n display: flex;\n align-items: baseline;\n gap: var(--bazaar-space-2);\n}\n\n.value {\n font-size: var(--bazaar-font-size-display-md);\n line-height: var(--bazaar-line-height-display-md);\n font-weight: var(--bazaar-font-weight-semibold);\n color: var(--bazaar-color-text-primary);\n letter-spacing: var(--bazaar-tracking-tight);\n font-variant-numeric: tabular-nums;\n}\n\n.unit {\n font-size: var(--bazaar-font-size-body-md);\n font-weight: var(--bazaar-font-weight-medium);\n color: var(--bazaar-color-text-muted);\n}\n\n.footer {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: var(--bazaar-space-3);\n min-height: 40px;\n}\n\n.trend {\n display: inline-flex;\n align-items: center;\n gap: var(--bazaar-space-1);\n font-size: var(--bazaar-font-size-body-sm);\n font-weight: var(--bazaar-font-weight-semibold);\n font-variant-numeric: tabular-nums;\n flex-wrap: wrap;\n}\n\n.trendIcon {\n display: inline-flex;\n}\n\n.trendValue {\n font-weight: var(--bazaar-font-weight-semibold);\n}\n\n.up {\n color: var(--bazaar-color-success-700);\n}\n\n.down {\n color: var(--bazaar-color-error-700);\n}\n\n.neutral {\n color: var(--bazaar-color-text-muted);\n}\n\n.changeLabel {\n margin-left: var(--bazaar-space-1);\n color: var(--bazaar-color-text-muted);\n font-weight: var(--bazaar-font-weight-regular);\n}\n\n.sparkSlot {\n flex: 1;\n min-width: 0;\n max-width: 50%;\n display: flex;\n justify-content: flex-end;\n}\n\n.srOnly {\n position: absolute;\n width: 1px;\n height: 1px;\n padding: 0;\n margin: -1px;\n overflow: hidden;\n clip: rect(0, 0, 0, 0);\n white-space: nowrap;\n border: 0;\n}\n\n@media (prefers-reduced-motion: reduce) {\n .card {\n transition: none;\n }\n}\n","import { type HTMLAttributes, type ReactNode } from 'react';\nimport { cn } from '../utils/cn';\nimport { Sparkline, type SparklineProps } from './Sparkline';\nimport styles from './KpiStatCard.module.css';\n\nexport type TrendDirection = 'up' | 'down' | 'neutral';\n\nexport interface KpiStatCardProps extends HTMLAttributes<HTMLDivElement> {\n /** Metric label (e.g. \"Active patients\") */\n label: string;\n /** Headline value (e.g. 1284 or \"98.2%\") */\n value: ReactNode;\n /** Optional unit/suffix shown next to the value */\n unit?: ReactNode;\n /** Percent change (number) — positive renders as up, negative as down */\n change?: number;\n /** Label for the change context (e.g. \"vs last 30 days\") */\n changeLabel?: string;\n /** Override trend direction (otherwise inferred from `change`) */\n trend?: TrendDirection;\n /**\n * For success-positive metrics, set `inverse` to flip color semantics\n * (e.g. \"wait time\" — a decrease is good).\n */\n inverse?: boolean;\n /** Optional icon rendered top-right */\n icon?: ReactNode;\n /** Optional sparkline data — when present, renders an inline trend chart */\n sparklineData?: SparklineProps['data'];\n /** Sparkline color override */\n sparklineColor?: string;\n /** Sparkline render variant */\n sparklineVariant?: SparklineProps['variant'];\n /** Density variant */\n density?: 'comfortable' | 'compact';\n}\n\nfunction inferTrend(change?: number): TrendDirection {\n if (change == null || change === 0) return 'neutral';\n return change > 0 ? 'up' : 'down';\n}\n\nconst trendIcons: Record<TrendDirection, ReactNode> = {\n up: (\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 16 16\" fill=\"currentColor\" aria-hidden=\"true\">\n <path d=\"M3 11l5-6 5 6H3z\" />\n </svg>\n ),\n down: (\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 16 16\" fill=\"currentColor\" aria-hidden=\"true\">\n <path d=\"M3 5l5 6 5-6H3z\" />\n </svg>\n ),\n neutral: (\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 16 16\" fill=\"currentColor\" aria-hidden=\"true\">\n <path d=\"M3 7h10v2H3z\" />\n </svg>\n ),\n};\n\n/**\n * KpiStatCard — premium stat card with optional inline sparkline.\n *\n * The chart-aware evolution of StatCard. Use for headline KPIs in\n * dashboards. Pair with `inverse` for metrics where a decrease is positive\n * (e.g. wait time, error rate).\n *\n * Accessibility:\n * - Trend icons are aria-hidden; meaning is conveyed in visible text plus an\n * sr-only direction phrase.\n * - Sparkline accepts `aria-label` for screen reader trend description.\n */\nexport function KpiStatCard({\n label,\n value,\n unit,\n change,\n changeLabel,\n trend,\n inverse = false,\n icon,\n sparklineData,\n sparklineColor,\n sparklineVariant = 'area',\n density = 'comfortable',\n className,\n ...props\n}: KpiStatCardProps) {\n const direction = trend ?? inferTrend(change);\n const semantic: TrendDirection =\n inverse && direction === 'up' ? 'down' : inverse && direction === 'down' ? 'up' : direction;\n\n const formattedChange =\n change !== undefined ? `${change > 0 ? '+' : ''}${change}%` : undefined;\n\n return (\n <div className={cn(styles.card, styles[density], className)} {...props}>\n <div className={styles.header}>\n <span className={styles.label}>{label}</span>\n {icon && (\n <span className={styles.icon} aria-hidden=\"true\">\n {icon}\n </span>\n )}\n </div>\n\n <div className={styles.valueRow}>\n <span className={styles.value}>{value}</span>\n {unit && <span className={styles.unit}>{unit}</span>}\n </div>\n\n {(formattedChange || sparklineData) && (\n <div className={styles.footer}>\n {formattedChange && (\n <div className={cn(styles.trend, styles[semantic])}>\n <span className={styles.trendIcon}>{trendIcons[direction]}</span>\n <span className={styles.trendValue}>{formattedChange}</span>\n {changeLabel && <span className={styles.changeLabel}>{changeLabel}</span>}\n <span className={styles.srOnly}>\n {direction === 'up'\n ? 'increase'\n : direction === 'down'\n ? 'decrease'\n : 'no change'}\n </span>\n </div>\n )}\n {sparklineData && (\n <div className={styles.sparkSlot}>\n <Sparkline\n data={sparklineData}\n color={sparklineColor}\n variant={sparklineVariant}\n width=\"100%\"\n height={40}\n ariaLabel={`${label} trend`}\n />\n </div>\n )}\n </div>\n )}\n </div>\n );\n}\n",".card {\n display: flex;\n flex-direction: column;\n background-color: var(--bazaar-color-surface-default);\n border: var(--bazaar-border-width-hairline) solid var(--bazaar-color-border-default);\n border-radius: var(--bazaar-radius-lg);\n box-shadow: var(--bazaar-shadow-sm);\n padding: var(--bazaar-space-5);\n gap: var(--bazaar-space-2);\n font-family: var(--bazaar-font-family-sans);\n transition: box-shadow var(--bazaar-motion-duration-base) var(--bazaar-motion-easing-standard);\n overflow: hidden;\n}\n\n.card:hover {\n box-shadow: var(--bazaar-shadow-md);\n}\n\n.header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: var(--bazaar-space-3);\n}\n\n.label {\n font-size: var(--bazaar-font-size-label-md);\n font-weight: var(--bazaar-font-weight-medium);\n color: var(--bazaar-color-text-secondary);\n text-transform: uppercase;\n letter-spacing: var(--bazaar-tracking-wide);\n}\n\n.chip {\n display: inline-flex;\n align-items: center;\n gap: var(--bazaar-space-1);\n padding: 2px var(--bazaar-space-2);\n border-radius: var(--bazaar-radius-full);\n font-size: var(--bazaar-font-size-caption);\n font-weight: var(--bazaar-font-weight-semibold);\n border: var(--bazaar-border-width-hairline) solid currentColor;\n background-color: transparent;\n}\n\n.up {\n color: var(--bazaar-color-success-700);\n background-color: var(--bazaar-color-success-50);\n border-color: var(--bazaar-color-border-success);\n}\n\n.down {\n color: var(--bazaar-color-error-700);\n background-color: var(--bazaar-color-error-50);\n border-color: var(--bazaar-color-border-error);\n}\n\n.neutral {\n color: var(--bazaar-color-text-muted);\n background-color: var(--bazaar-color-surface-subtle);\n border-color: var(--bazaar-color-border-default);\n}\n\n.valueRow {\n display: flex;\n align-items: baseline;\n gap: var(--bazaar-space-2);\n margin-top: var(--bazaar-space-1);\n}\n\n.value {\n font-size: var(--bazaar-font-size-display-md);\n line-height: var(--bazaar-line-height-display-md);\n font-weight: var(--bazaar-font-weight-semibold);\n color: var(--bazaar-color-text-primary);\n letter-spacing: var(--bazaar-tracking-tight);\n font-variant-numeric: tabular-nums;\n}\n\n.unit {\n font-size: var(--bazaar-font-size-body-md);\n color: var(--bazaar-color-text-muted);\n font-weight: var(--bazaar-font-weight-medium);\n}\n\n.changeLabel {\n font-size: var(--bazaar-font-size-caption);\n color: var(--bazaar-color-text-muted);\n}\n\n.chartWrap {\n width: calc(100% + var(--bazaar-space-10));\n margin: var(--bazaar-space-2) calc(var(--bazaar-space-5) * -1) calc(var(--bazaar-space-5) * -1);\n}\n\n@media (prefers-reduced-motion: reduce) {\n .card {\n transition: none;\n }\n}\n","import { type HTMLAttributes, type ReactNode } from 'react';\nimport { cn } from '../utils/cn';\nimport {\n Area,\n AreaChart,\n ResponsiveContainer,\n Tooltip,\n XAxis,\n YAxis,\n} from 'recharts';\nimport { ChartTooltip } from './ChartTooltip';\nimport {\n defaultValueFormatter,\n getSeriesColor,\n type ValueFormatter,\n} from './chartTheme';\nimport styles from './TrendStatCard.module.css';\n\nexport type TrendDirection = 'up' | 'down' | 'neutral';\n\nexport interface TrendStatCardProps<T extends Record<string, unknown>>\n extends HTMLAttributes<HTMLDivElement> {\n /** Metric label (e.g. \"30-day readmissions\") */\n label: string;\n /** Headline value */\n value: ReactNode;\n /** Optional unit (e.g. \"%\", \"patients\") */\n unit?: ReactNode;\n /** Trend chart data — row-shaped */\n data: T[];\n /** X-axis key on each row */\n xKey: keyof T & string;\n /** Y value key on each row */\n yKey: keyof T & string;\n /** Percent change value */\n change?: number;\n /** Change context label */\n changeLabel?: string;\n /** Inverse semantics — set true when a decrease is \"good\" */\n inverse?: boolean;\n /** Color override for the trend area */\n color?: string;\n /** Format values shown in tooltip */\n valueFormatter?: ValueFormatter;\n /** Chart height (defaults to 80) */\n chartHeight?: number;\n}\n\nfunction inferTrend(change?: number): TrendDirection {\n if (change == null || change === 0) return 'neutral';\n return change > 0 ? 'up' : 'down';\n}\n\nconst trendIcons: Record<TrendDirection, ReactNode> = {\n up: (\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 16 16\" fill=\"currentColor\" aria-hidden=\"true\">\n <path d=\"M3 11l5-6 5 6H3z\" />\n </svg>\n ),\n down: (\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 16 16\" fill=\"currentColor\" aria-hidden=\"true\">\n <path d=\"M3 5l5 6 5-6H3z\" />\n </svg>\n ),\n neutral: (\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 16 16\" fill=\"currentColor\" aria-hidden=\"true\">\n <path d=\"M3 7h10v2H3z\" />\n </svg>\n ),\n};\n\n/**\n * TrendStatCard — KPI card with a prominent trend chart underneath.\n *\n * Larger than KpiStatCard's inline sparkline, designed to fill more space\n * in dashboard rows where a trend story is the primary message.\n */\nexport function TrendStatCard<T extends Record<string, unknown>>({\n label,\n value,\n unit,\n data,\n xKey,\n yKey,\n change,\n changeLabel,\n inverse = false,\n color,\n valueFormatter = defaultValueFormatter,\n chartHeight = 80,\n className,\n ...props\n}: TrendStatCardProps<T>) {\n const direction = inferTrend(change);\n const semantic: TrendDirection =\n inverse && direction === 'up' ? 'down' : inverse && direction === 'down' ? 'up' : direction;\n const stroke = getSeriesColor(0, color);\n const formattedChange =\n change !== undefined ? `${change > 0 ? '+' : ''}${change}%` : undefined;\n const gradientId = `trend-stat-${String(yKey)}-${Math.random().toString(36).slice(2, 8)}`;\n\n return (\n <div className={cn(styles.card, className)} {...props}>\n <div className={styles.header}>\n <span className={styles.label}>{label}</span>\n {formattedChange && (\n <span className={cn(styles.chip, styles[semantic])}>\n {trendIcons[direction]}\n <span>{formattedChange}</span>\n </span>\n )}\n </div>\n <div className={styles.valueRow}>\n <span className={styles.value}>{value}</span>\n {unit && <span className={styles.unit}>{unit}</span>}\n </div>\n {changeLabel && <div className={styles.changeLabel}>{changeLabel}</div>}\n <div className={styles.chartWrap} style={{ height: chartHeight }}>\n <ResponsiveContainer width=\"100%\" height=\"100%\">\n <AreaChart data={data} margin={{ top: 4, right: 0, left: 0, bottom: 0 }}>\n <defs>\n <linearGradient id={gradientId} x1=\"0\" y1=\"0\" x2=\"0\" y2=\"1\">\n <stop offset=\"0%\" stopColor={stroke} stopOpacity={0.32} />\n <stop offset=\"100%\" stopColor={stroke} stopOpacity={0} />\n </linearGradient>\n </defs>\n <XAxis dataKey={xKey} hide />\n <YAxis hide />\n <Tooltip content={<ChartTooltip valueFormatter={valueFormatter} />} />\n <Area\n type=\"monotone\"\n dataKey={yKey}\n stroke={stroke}\n strokeWidth={2}\n fill={`url(#${gradientId})`}\n isAnimationActive={false}\n dot={false}\n />\n </AreaChart>\n </ResponsiveContainer>\n </div>\n </div>\n );\n}\n","import type { Money } from './types';\n\n/**\n * Format a Money value for display. Prefers the caller-supplied `display`\n * string, otherwise uses Intl.NumberFormat with currency style.\n */\nexport function formatMoney(money: Money, locale = 'en-US'): string {\n if (money.display) return money.display;\n try {\n return new Intl.NumberFormat(locale, {\n style: 'currency',\n currency: money.currency,\n // Hide trailing .00 for whole amounts to feel more editorial.\n minimumFractionDigits: Number.isInteger(money.amount) ? 0 : 2,\n maximumFractionDigits: 2,\n }).format(money.amount);\n } catch {\n return `${money.currency} ${money.amount.toFixed(2)}`;\n }\n}\n\n/** Percent savings between compareAt and price. Returns rounded integer or null. */\nexport function percentOff(price: Money, compareAt?: Money): number | null {\n if (!compareAt || compareAt.amount <= price.amount) return null;\n return Math.round(((compareAt.amount - price.amount) / compareAt.amount) * 100);\n}\n",".root {\n position: relative;\n display: flex;\n align-items: center;\n justify-content: center;\n overflow: hidden;\n background:\n linear-gradient(135deg, var(--g1, #E8E2D6) 0%, var(--g2, #C9BFAE) 100%);\n color: rgba(255, 255, 255, 0.92);\n font-family: var(--bazaar-font-family-sans);\n font-weight: 500;\n letter-spacing: 0.02em;\n user-select: none;\n}\n\n.root::after {\n content: '';\n position: absolute;\n inset: 0;\n background:\n radial-gradient(\n circle at 30% 20%,\n rgba(255, 255, 255, 0.35),\n transparent 55%\n ),\n radial-gradient(\n circle at 80% 80%,\n rgba(0, 0, 0, 0.12),\n transparent 50%\n );\n pointer-events: none;\n}\n\n.label {\n position: relative;\n z-index: 1;\n padding: var(--bazaar-space-4, 16px) var(--bazaar-space-6, 24px);\n text-align: center;\n font-size: 0.8125rem;\n text-transform: uppercase;\n letter-spacing: 0.12em;\n text-shadow: 0 1px 2px rgba(0, 0, 0, 0.12);\n max-width: 80%;\n}\n\n.image {\n width: 100%;\n height: 100%;\n object-fit: cover;\n display: block;\n}\n","import type { CSSProperties, HTMLAttributes } from 'react';\nimport { cn } from '../utils/cn';\nimport styles from './MediaPlaceholder.module.css';\n\n/**\n * Deterministically pick a warm-neutral gradient pair from a seed string so\n * stories render consistent, brand-aligned placeholders without needing\n * bundled imagery. When `src` is provided it short-circuits to a real <img>.\n */\nconst GRADIENTS: Array<[string, string]> = [\n ['#E8DFCC', '#B8A484'], // sand → dune\n ['#D9CBB7', '#8F7A5C'], // oat → walnut\n ['#E4D5C1', '#A8856B'], // cream → almond\n ['#C9BFAE', '#6B5B47'], // taupe → espresso\n ['#DCD0BA', '#9E8668'], // bone → clay\n ['#E8E1D1', '#7A6A55'], // linen → umber\n ['#D1C3A8', '#5D4E3C'], // ecru → cocoa\n ['#EFE6D4', '#B3996F'], // shell → caramel\n];\n\nfunction hashSeed(seed: string): number {\n let h = 0;\n for (let i = 0; i < seed.length; i += 1) {\n h = (h * 31 + seed.charCodeAt(i)) | 0;\n }\n return Math.abs(h);\n}\n\nexport interface MediaPlaceholderProps extends HTMLAttributes<HTMLDivElement> {\n /** If provided, renders an actual <img> instead of the gradient placeholder. */\n src?: string;\n /** Alt / label. Shown as overlay text on the gradient and as alt on the img. */\n alt: string;\n /** Seed used to pick the gradient pair deterministically. Defaults to alt. */\n seed?: string;\n /** CSS aspect ratio (e.g. \"4 / 5\", \"1 / 1\"). Defaults to 4 / 5 (portrait product). */\n aspectRatio?: string;\n /** Optional explicit size (width/height) via style. */\n width?: string | number;\n height?: string | number;\n}\n\nexport function MediaPlaceholder({\n src,\n alt,\n seed,\n aspectRatio = '4 / 5',\n width,\n height,\n className,\n style,\n ...rest\n}: MediaPlaceholderProps) {\n const key = seed ?? alt;\n const idx = hashSeed(key) % GRADIENTS.length;\n const [g1, g2] = GRADIENTS[idx];\n\n const merged: CSSProperties = {\n aspectRatio,\n width,\n height,\n // CSS custom props consumed by the stylesheet gradient.\n ['--g1' as any]: g1,\n ['--g2' as any]: g2,\n ...style,\n };\n\n return (\n <div className={cn(styles.root, className)} style={merged} {...rest}>\n {src ? (\n <img src={src} alt={alt} className={styles.image} loading=\"lazy\" />\n ) : (\n <span className={styles.label} aria-hidden=\"false\">\n {alt}\n </span>\n )}\n </div>\n );\n}\n",".root {\n display: inline-flex;\n align-items: baseline;\n gap: var(--bazaar-space-2, 8px);\n font-family: var(--bazaar-font-family-sans);\n line-height: 1.2;\n}\n\n.root.stacked {\n flex-direction: column;\n align-items: flex-start;\n gap: var(--bazaar-space-1, 4px);\n}\n\n.current {\n color: var(--bazaar-color-text-primary);\n font-weight: 600;\n font-size: 1.125rem;\n letter-spacing: -0.01em;\n}\n\n.current.sale {\n color: var(--bazaar-color-sale, var(--bazaar-color-error-500, #873F1C));\n}\n\n.size-sm .current { font-size: 0.9375rem; }\n.size-md .current { font-size: 1.125rem; }\n.size-lg .current { font-size: 1.375rem; }\n.size-xl .current { font-size: 1.75rem; }\n\n.compareAt {\n color: var(--bazaar-color-text-muted);\n text-decoration: line-through;\n font-size: 0.875em;\n font-weight: 400;\n}\n\n.percent {\n display: inline-flex;\n align-items: center;\n padding: 2px 8px;\n border-radius: var(--bazaar-radius-full, 999px);\n font-size: 0.6875rem;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.06em;\n background: var(--bazaar-color-sale-bg, #FBEDEB);\n color: var(--bazaar-color-sale, var(--bazaar-color-error-700, #7A1E24));\n white-space: nowrap;\n}\n\n.fromLabel {\n color: var(--bazaar-color-text-muted);\n font-size: 0.8125rem;\n margin-right: var(--bazaar-space-1, 4px);\n}\n","import type { HTMLAttributes } from 'react';\nimport { cn } from '../utils/cn';\nimport type { Money } from './types';\nimport { formatMoney, percentOff } from './money';\nimport styles from './PriceBlock.module.css';\n\nexport interface PriceBlockProps extends HTMLAttributes<HTMLDivElement> {\n price: Money;\n compareAtPrice?: Money;\n /** Show a \"From\" prefix — useful when a product has a price range across variants. */\n from?: boolean;\n /** Show a percent-off pill when compareAtPrice is present. */\n showPercent?: boolean;\n size?: 'sm' | 'md' | 'lg' | 'xl';\n /** Stack current price above compareAt + percent on a second line. */\n stacked?: boolean;\n locale?: string;\n}\n\n/**\n * PriceBlock — canonical way to render a price in Bazaar.\n *\n * Handles current + compare-at + percent-off with consistent hierarchy,\n * so cards, buy boxes, cart lines, and summaries all feel the same.\n */\nexport function PriceBlock({\n price,\n compareAtPrice,\n from = false,\n showPercent = true,\n size = 'md',\n stacked = false,\n locale,\n className,\n ...rest\n}: PriceBlockProps) {\n const onSale = Boolean(compareAtPrice && compareAtPrice.amount > price.amount);\n const percent = onSale ? percentOff(price, compareAtPrice) : null;\n\n return (\n <div\n className={cn(styles.root, styles[`size-${size}`], stacked && styles.stacked, className)}\n {...rest}\n >\n {from && <span className={styles.fromLabel}>From</span>}\n <span className={cn(styles.current, onSale && styles.sale)}>\n {formatMoney(price, locale)}\n </span>\n {onSale && (\n <>\n <span className={styles.compareAt}>{formatMoney(compareAtPrice!, locale)}</span>\n {showPercent && percent !== null && (\n <span className={styles.percent}>−{percent}%</span>\n )}\n </>\n )}\n </div>\n );\n}\n",".root {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n padding: 4px 10px;\n border-radius: var(--bazaar-radius-full, 999px);\n font-family: var(--bazaar-font-family-sans);\n font-size: 0.6875rem;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.08em;\n line-height: 1;\n white-space: nowrap;\n}\n\n.tone-new {\n background: var(--bazaar-color-surface-default, #FFFFFF);\n color: var(--bazaar-color-text-primary, #1F1C17);\n box-shadow: inset 0 0 0 1px var(--bazaar-color-border-strong, #B8AE97);\n}\n\n.tone-sale {\n background: var(--bazaar-color-sale-bg, #FBEDEB);\n color: var(--bazaar-color-sale, #873F1C);\n}\n\n.tone-bestSeller {\n background: var(--bazaar-color-accent-amber-50, #FFF6E2);\n color: var(--bazaar-color-accent-amber-700, #7A4D0D);\n}\n\n.tone-lowStock {\n background: var(--bazaar-color-warning-50, #FFF4DC);\n color: var(--bazaar-color-warning-700, #8E5B0F);\n}\n\n.tone-soldOut {\n background: var(--bazaar-color-neutral-100, #ECE7DC);\n color: var(--bazaar-color-text-muted, #8A816B);\n}\n\n.tone-exclusive {\n background: var(--bazaar-color-text-primary, #1F1C17);\n color: var(--bazaar-color-text-inverse, #FFFFFF);\n}\n\n.size-sm { padding: 3px 8px; font-size: 0.625rem; }\n.size-md { padding: 4px 10px; font-size: 0.6875rem; }\n.size-lg { padding: 6px 12px; font-size: 0.75rem; }\n","import type { HTMLAttributes } from 'react';\nimport { cn } from '../utils/cn';\nimport type { ProductBadgeTone } from './types';\nimport styles from './ProductBadge.module.css';\n\nexport interface ProductBadgeProps extends HTMLAttributes<HTMLSpanElement> {\n label: string;\n tone?: ProductBadgeTone;\n size?: 'sm' | 'md' | 'lg';\n}\n\n/**\n * ProductBadge — compact merchandising badge for cards, tiles, and PDPs.\n * Differs from the generic <Badge /> in that it uses commerce-specific tones\n * (new, sale, bestSeller, lowStock, soldOut, exclusive) and typography suited\n * to overlaying product imagery.\n */\nexport function ProductBadge({\n label,\n tone = 'new',\n size = 'md',\n className,\n ...rest\n}: ProductBadgeProps) {\n return (\n <span\n className={cn(styles.root, styles[`tone-${tone}`], styles[`size-${size}`], className)}\n {...rest}\n >\n {label}\n </span>\n );\n}\n",".root {\n display: inline-flex;\n align-items: center;\n gap: var(--bazaar-space-2, 8px);\n font-family: var(--bazaar-font-family-sans);\n color: var(--bazaar-color-text-secondary, #433D32);\n font-size: 0.875rem;\n line-height: 1.2;\n}\n\n.value {\n font-weight: 600;\n color: var(--bazaar-color-text-primary);\n}\n\n.count {\n color: var(--bazaar-color-text-muted);\n font-variant-numeric: tabular-nums;\n}\n\n.divider {\n color: var(--bazaar-color-border-strong, #B8AE97);\n}\n\n.stars {\n display: inline-flex;\n color: var(--bazaar-color-accent-amber-500, #C9831A);\n gap: 1px;\n}\n\n.size-sm { font-size: 0.8125rem; }\n.size-md { font-size: 0.875rem; }\n.size-lg { font-size: 1rem; }\n","import type { HTMLAttributes } from 'react';\nimport { cn } from '../utils/cn';\nimport styles from './ReviewsSummary.module.css';\n\nexport interface ReviewsSummaryProps extends HTMLAttributes<HTMLDivElement> {\n /** Average rating, 0–5 (supports decimals). */\n value: number;\n /** Total review count. */\n count: number;\n size?: 'sm' | 'md' | 'lg';\n /** Hide stars — useful in dense contexts (cards, cart lines). */\n hideStars?: boolean;\n /** Format the count (e.g. compact 1.2k). */\n formatCount?: (n: number) => string;\n}\n\nfunction defaultFormatCount(n: number): string {\n if (n >= 1000) return `${(n / 1000).toFixed(1).replace(/\\.0$/, '')}k`;\n return String(n);\n}\n\nfunction Star({ fill }: { fill: 'full' | 'half' | 'empty' }) {\n return (\n <svg width=\"1em\" height=\"1em\" viewBox=\"0 0 20 20\" aria-hidden=\"true\">\n <defs>\n <linearGradient id={`star-${fill}`} x1=\"0\" x2=\"1\" y1=\"0\" y2=\"0\">\n <stop offset={fill === 'half' ? '50%' : fill === 'full' ? '100%' : '0%'} stopColor=\"currentColor\" />\n <stop offset={fill === 'half' ? '50%' : fill === 'full' ? '100%' : '0%'} stopColor=\"transparent\" />\n </linearGradient>\n </defs>\n <polygon\n points=\"10 1.5 12.6 7.2 18.8 8 14.2 12.3 15.4 18.5 10 15.4 4.6 18.5 5.8 12.3 1.2 8 7.4 7.2\"\n fill={`url(#star-${fill})`}\n stroke=\"currentColor\"\n strokeWidth=\"0.75\"\n strokeLinejoin=\"round\"\n />\n </svg>\n );\n}\n\nexport function ReviewsSummary({\n value,\n count,\n size = 'md',\n hideStars = false,\n formatCount = defaultFormatCount,\n className,\n ...rest\n}: ReviewsSummaryProps) {\n const rounded = Math.round(value * 2) / 2; // snap to half stars\n const label = `${value.toFixed(1)} out of 5 — ${count} reviews`;\n return (\n <div className={cn(styles.root, styles[`size-${size}`], className)} aria-label={label} {...rest}>\n <span className={styles.value}>{value.toFixed(1)}</span>\n {!hideStars && (\n <span className={styles.stars} aria-hidden=\"true\">\n {[0, 1, 2, 3, 4].map((i) => {\n const diff = rounded - i;\n const fill = diff >= 1 ? 'full' : diff >= 0.5 ? 'half' : 'empty';\n return <Star key={i} fill={fill} />;\n })}\n </span>\n )}\n <span className={styles.divider} aria-hidden=\"true\">·</span>\n <span className={styles.count}>{formatCount(count)} reviews</span>\n </div>\n );\n}\n","import type { SVGProps } from 'react';\n\n/**\n * Small inline commerce icon set. Lucide-style outlines, currentColor-driven.\n * Kept inline so the kit has no icon-library dependency.\n */\n\ntype IconProps = SVGProps<SVGSVGElement>;\n\nconst base = {\n width: '1em',\n height: '1em',\n viewBox: '0 0 24 24',\n fill: 'none',\n stroke: 'currentColor',\n strokeWidth: 1.5,\n strokeLinecap: 'round' as const,\n strokeLinejoin: 'round' as const,\n 'aria-hidden': true,\n};\n\nexport const TruckIcon = (p: IconProps) => (\n <svg {...base} {...p}>\n <path d=\"M1 3h15v13H1z\" />\n <path d=\"M16 8h4l3 3v5h-7\" />\n <circle cx=\"6\" cy=\"18\" r=\"2\" />\n <circle cx=\"18\" cy=\"18\" r=\"2\" />\n </svg>\n);\n\nexport const ReturnIcon = (p: IconProps) => (\n <svg {...base} {...p}>\n <polyline points=\"1 4 1 10 7 10\" />\n <path d=\"M3.51 15a9 9 0 1 0 2.13-9.36L1 10\" />\n </svg>\n);\n\nexport const ShieldCheckIcon = (p: IconProps) => (\n <svg {...base} {...p}>\n <path d=\"M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z\" />\n <polyline points=\"9 12 11 14 15 10\" />\n </svg>\n);\n\nexport const LockIcon = (p: IconProps) => (\n <svg {...base} {...p}>\n <rect x=\"4\" y=\"11\" width=\"16\" height=\"10\" rx=\"2\" />\n <path d=\"M8 11V7a4 4 0 0 1 8 0v4\" />\n </svg>\n);\n\nexport const LeafIcon = (p: IconProps) => (\n <svg {...base} {...p}>\n <path d=\"M20 3s-9 0-13 4-4 14 0 14 14 0 14-14V3z\" />\n <path d=\"M4 20c2-8 8-12 14-14\" />\n </svg>\n);\n\nexport const BagIcon = (p: IconProps) => (\n <svg {...base} {...p}>\n <path d=\"M6 7h12l-1 13H7L6 7z\" />\n <path d=\"M9 7a3 3 0 0 1 6 0\" />\n </svg>\n);\n\nexport const HeartIcon = (p: IconProps) => (\n <svg {...base} {...p}>\n <path d=\"M20.84 4.61a5.5 5.5 0 0 0-7.78 0L12 5.67l-1.06-1.06a5.5 5.5 0 0 0-7.78 7.78l1.06 1.06L12 21.23l7.78-7.78 1.06-1.06a5.5 5.5 0 0 0 0-7.78z\" />\n </svg>\n);\n\nexport const HeartFilledIcon = (p: IconProps) => (\n <svg {...base} fill=\"currentColor\" {...p}>\n <path d=\"M20.84 4.61a5.5 5.5 0 0 0-7.78 0L12 5.67l-1.06-1.06a5.5 5.5 0 0 0-7.78 7.78l1.06 1.06L12 21.23l7.78-7.78 1.06-1.06a5.5 5.5 0 0 0 0-7.78z\" />\n </svg>\n);\n\nexport const StarIcon = (p: IconProps) => (\n <svg {...base} {...p}>\n <polygon points=\"12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2\" />\n </svg>\n);\n\nexport const CheckIcon = (p: IconProps) => (\n <svg {...base} {...p}>\n <polyline points=\"20 6 9 17 4 12\" />\n </svg>\n);\n\nexport const XIcon = (p: IconProps) => (\n <svg {...base} {...p}>\n <line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\" />\n <line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\" />\n </svg>\n);\n\nexport const PlusIcon = (p: IconProps) => (\n <svg {...base} {...p}>\n <line x1=\"12\" y1=\"5\" x2=\"12\" y2=\"19\" />\n <line x1=\"5\" y1=\"12\" x2=\"19\" y2=\"12\" />\n </svg>\n);\n\nexport const MinusIcon = (p: IconProps) => (\n <svg {...base} {...p}>\n <line x1=\"5\" y1=\"12\" x2=\"19\" y2=\"12\" />\n </svg>\n);\n\nexport const ChevronRightIcon = (p: IconProps) => (\n <svg {...base} {...p}>\n <polyline points=\"9 18 15 12 9 6\" />\n </svg>\n);\n\nexport const ChevronLeftIcon = (p: IconProps) => (\n <svg {...base} {...p}>\n <polyline points=\"15 18 9 12 15 6\" />\n </svg>\n);\n\nexport const ChevronDownIcon = (p: IconProps) => (\n <svg {...base} {...p}>\n <polyline points=\"6 9 12 15 18 9\" />\n </svg>\n);\n\nexport const SearchIcon = (p: IconProps) => (\n <svg {...base} {...p}>\n <circle cx=\"11\" cy=\"11\" r=\"8\" />\n <line x1=\"21\" y1=\"21\" x2=\"16.65\" y2=\"16.65\" />\n </svg>\n);\n\nexport const SlidersIcon = (p: IconProps) => (\n <svg {...base} {...p}>\n <line x1=\"4\" y1=\"6\" x2=\"20\" y2=\"6\" />\n <circle cx=\"9\" cy=\"6\" r=\"2\" />\n <line x1=\"4\" y1=\"12\" x2=\"20\" y2=\"12\" />\n <circle cx=\"15\" cy=\"12\" r=\"2\" />\n <line x1=\"4\" y1=\"18\" x2=\"20\" y2=\"18\" />\n <circle cx=\"9\" cy=\"18\" r=\"2\" />\n </svg>\n);\n\nexport const PackageIcon = (p: IconProps) => (\n <svg {...base} {...p}>\n <path d=\"M16.5 9.4L7.55 4.24\" />\n <path d=\"M21 16V8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16z\" />\n <polyline points=\"3.27 6.96 12 12.01 20.73 6.96\" />\n <line x1=\"12\" y1=\"22.08\" x2=\"12\" y2=\"12\" />\n </svg>\n);\n\nexport const CreditCardIcon = (p: IconProps) => (\n <svg {...base} {...p}>\n <rect x=\"2\" y=\"5\" width=\"20\" height=\"14\" rx=\"2\" />\n <line x1=\"2\" y1=\"10\" x2=\"22\" y2=\"10\" />\n </svg>\n);\n\nexport const MapPinIcon = (p: IconProps) => (\n <svg {...base} {...p}>\n <path d=\"M21 10c0 7-9 13-9 13s-9-6-9-13a9 9 0 0 1 18 0z\" />\n <circle cx=\"12\" cy=\"10\" r=\"3\" />\n </svg>\n);\n\nexport const ClockIcon = (p: IconProps) => (\n <svg {...base} {...p}>\n <circle cx=\"12\" cy=\"12\" r=\"10\" />\n <polyline points=\"12 6 12 12 16 14\" />\n </svg>\n);\n\nexport const TagIcon = (p: IconProps) => (\n <svg {...base} {...p}>\n <path d=\"M20.59 13.41l-7.17 7.17a2 2 0 0 1-2.83 0L2 12V2h10l8.59 8.59a2 2 0 0 1 0 2.82z\" />\n <line x1=\"7\" y1=\"7\" x2=\"7.01\" y2=\"7\" />\n </svg>\n);\n\nexport const UserIcon = (p: IconProps) => (\n <svg {...base} {...p}>\n <path d=\"M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2\" />\n <circle cx=\"12\" cy=\"7\" r=\"4\" />\n </svg>\n);\n\nexport const GiftIcon = (p: IconProps) => (\n <svg {...base} {...p}>\n <polyline points=\"20 12 20 22 4 22 4 12\" />\n <rect x=\"2\" y=\"7\" width=\"20\" height=\"5\" />\n <line x1=\"12\" y1=\"22\" x2=\"12\" y2=\"7\" />\n <path d=\"M12 7H7.5a2.5 2.5 0 0 1 0-5C11 2 12 7 12 7z\" />\n <path d=\"M12 7h4.5a2.5 2.5 0 0 0 0-5C13 2 12 7 12 7z\" />\n </svg>\n);\n\nexport const InfoIcon = (p: IconProps) => (\n <svg {...base} {...p}>\n <circle cx=\"12\" cy=\"12\" r=\"10\" />\n <line x1=\"12\" y1=\"16\" x2=\"12\" y2=\"12\" />\n <line x1=\"12\" y1=\"8\" x2=\"12.01\" y2=\"8\" />\n </svg>\n);\n\nexport const ZoomInIcon = (p: IconProps) => (\n <svg {...base} {...p}>\n <circle cx=\"11\" cy=\"11\" r=\"8\" />\n <line x1=\"21\" y1=\"21\" x2=\"16.65\" y2=\"16.65\" />\n <line x1=\"11\" y1=\"8\" x2=\"11\" y2=\"14\" />\n <line x1=\"8\" y1=\"11\" x2=\"14\" y2=\"11\" />\n </svg>\n);\n\nexport const PlayIcon = (p: IconProps) => (\n <svg {...base} fill=\"currentColor\" stroke=\"none\" {...p}>\n <polygon points=\"6 3 20 12 6 21 6 3\" />\n </svg>\n);\n",".root {\n position: relative;\n display: flex;\n flex-direction: column;\n background: var(--bazaar-color-surface-default, #FFFFFF);\n border-radius: var(--bazaar-radius-lg, 12px);\n overflow: hidden;\n font-family: var(--bazaar-font-family-sans);\n color: var(--bazaar-color-text-primary);\n text-decoration: none;\n transition:\n transform 220ms var(--bazaar-motion-easing-standard, ease),\n box-shadow 220ms var(--bazaar-motion-easing-standard, ease);\n}\n\n.root:hover {\n transform: translateY(-2px);\n}\n\n.root:hover .mediaWrap {\n box-shadow: var(--bazaar-shadow-sm, 0 4px 12px rgba(0, 0, 0, 0.06));\n}\n\n.mediaWrap {\n position: relative;\n width: 100%;\n border-radius: var(--bazaar-radius-md, 10px);\n overflow: hidden;\n background: var(--bazaar-color-surface-subtle, #F4F2EC);\n transition: box-shadow 220ms ease;\n}\n\n.badges {\n position: absolute;\n top: var(--bazaar-space-3, 12px);\n left: var(--bazaar-space-3, 12px);\n display: flex;\n flex-direction: column;\n gap: 6px;\n z-index: 2;\n}\n\n.quickActions {\n position: absolute;\n top: var(--bazaar-space-3, 12px);\n right: var(--bazaar-space-3, 12px);\n display: flex;\n flex-direction: column;\n gap: 6px;\n z-index: 2;\n opacity: 0;\n transition: opacity 180ms ease;\n}\n\n.root:hover .quickActions,\n.root:focus-within .quickActions {\n opacity: 1;\n}\n\n.iconAction {\n width: 36px;\n height: 36px;\n border-radius: 999px;\n border: 1px solid var(--bazaar-color-border-default, rgba(0, 0, 0, 0.08));\n background: var(--bazaar-color-surface-default, #FFFFFF);\n color: var(--bazaar-color-text-primary);\n display: inline-flex;\n align-items: center;\n justify-content: center;\n cursor: pointer;\n font-size: 16px;\n transition: transform 120ms ease, color 120ms ease, background 120ms ease;\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.06);\n}\n\n.iconAction:hover {\n transform: scale(1.05);\n color: var(--bazaar-color-brand-primary-600, #AB5428);\n}\n\n.iconAction[aria-pressed=\"true\"] {\n color: var(--bazaar-color-sale, #873F1C);\n}\n\n.quickAdd {\n position: absolute;\n left: var(--bazaar-space-3, 12px);\n right: var(--bazaar-space-3, 12px);\n bottom: var(--bazaar-space-3, 12px);\n padding: 10px 14px;\n border: none;\n border-radius: var(--bazaar-radius-full, 999px);\n background: var(--bazaar-color-text-primary, #1F1C17);\n color: var(--bazaar-color-text-inverse, #FFFFFF);\n font-family: inherit;\n font-weight: 600;\n font-size: 0.8125rem;\n letter-spacing: 0.04em;\n text-transform: uppercase;\n cursor: pointer;\n opacity: 0;\n transform: translateY(8px);\n transition: opacity 180ms ease, transform 180ms ease;\n z-index: 2;\n}\n\n.root:hover .quickAdd,\n.root:focus-within .quickAdd {\n opacity: 1;\n transform: translateY(0);\n}\n\n.body {\n display: flex;\n flex-direction: column;\n gap: 2px;\n padding-top: var(--bazaar-space-3, 12px);\n}\n\n.brand {\n font-size: 0.75rem;\n text-transform: uppercase;\n letter-spacing: 0.08em;\n color: var(--bazaar-color-text-muted);\n}\n\n.title {\n font-size: 0.9375rem;\n font-weight: 500;\n line-height: 1.35;\n color: var(--bazaar-color-text-primary);\n margin: 2px 0 6px;\n display: -webkit-box;\n -webkit-box-orient: vertical;\n -webkit-line-clamp: 2;\n overflow: hidden;\n}\n\n.tagline {\n font-size: 0.8125rem;\n color: var(--bazaar-color-text-muted);\n line-height: 1.4;\n margin: 0 0 8px;\n}\n\n.meta {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 8px;\n margin-top: 4px;\n}\n\n.swatches {\n display: inline-flex;\n gap: 4px;\n margin-top: 6px;\n}\n\n.swatch {\n width: 14px;\n height: 14px;\n border-radius: 999px;\n border: 1px solid rgba(0, 0, 0, 0.1);\n}\n\n.swatchOverflow {\n font-size: 0.6875rem;\n color: var(--bazaar-color-text-muted);\n align-self: center;\n margin-left: 2px;\n}\n\n/* Size variants */\n.size-sm .title { font-size: 0.875rem; }\n.size-lg .title { font-size: 1rem; }\n\n/* Density variants */\n.density-minimal .brand { display: none; }\n.density-minimal .tagline { display: none; }\n.density-minimal .quickAdd { display: none; }\n","import { type HTMLAttributes, type MouseEvent } from 'react';\nimport { cn } from '../utils/cn';\nimport type { Product } from './types';\nimport { MediaPlaceholder } from './MediaPlaceholder';\nimport { PriceBlock } from './PriceBlock';\nimport { ProductBadge } from './ProductBadge';\nimport { ReviewsSummary } from './ReviewsSummary';\nimport { HeartIcon, HeartFilledIcon, ZoomInIcon } from './icons';\nimport styles from './ProductCard.module.css';\n\nexport interface ProductCardProps extends Omit<HTMLAttributes<HTMLElement>, 'onClick' | 'onSelect'> {\n product: Product;\n /** Card element renders as <a> when provided, otherwise <article>. */\n href?: string;\n /** Called when the card surface is clicked. */\n onSelect?: (product: Product) => void;\n /** Wishlist state — controlled. */\n wishlisted?: boolean;\n onWishlistToggle?: (product: Product) => void;\n onQuickView?: (product: Product) => void;\n onQuickAdd?: (product: Product) => void;\n /** Hide the hover \"Quick add\" button. */\n hideQuickAdd?: boolean;\n size?: 'sm' | 'md' | 'lg';\n /** Visual density — \"minimal\" hides brand, tagline, quick-add (editorial pages). */\n density?: 'default' | 'minimal';\n /** Aspect ratio for the media area. Defaults to 4/5 (portrait) for apparel. */\n mediaAspectRatio?: string;\n}\n\nfunction ColorSwatches({ product }: { product: Product }) {\n const axis = product.variants?.find((v) => v.kind === 'color');\n if (!axis) return null;\n const visible = axis.options.slice(0, 5);\n const extra = axis.options.length - visible.length;\n return (\n <div className={styles.swatches} aria-label={`${axis.options.length} colors`}>\n {visible.map((o) => (\n <span\n key={o.value}\n className={styles.swatch}\n style={{ background: o.swatchColor ?? '#ccc' }}\n title={o.label}\n />\n ))}\n {extra > 0 && <span className={styles.swatchOverflow}>+{extra}</span>}\n </div>\n );\n}\n\n/**\n * ProductCard — image-first merchandising tile.\n *\n * Composes MediaPlaceholder, ProductBadge, PriceBlock, and ReviewsSummary\n * into the canonical Bazaar product presentation. Quick actions (wishlist,\n * quick view, quick add) appear on hover or focus.\n */\nexport function ProductCard({\n product,\n href,\n onSelect,\n wishlisted = false,\n onWishlistToggle,\n onQuickView,\n onQuickAdd,\n hideQuickAdd = false,\n size = 'md',\n density = 'default',\n mediaAspectRatio = '4 / 5',\n className,\n ...rest\n}: ProductCardProps) {\n const Tag: any = href ? 'a' : 'article';\n const primaryImage = product.images[0];\n const inStock = product.inStock !== false;\n\n const handleCardClick = (e: MouseEvent) => {\n if (onSelect) {\n e.preventDefault();\n onSelect(product);\n }\n };\n\n const stop = (fn?: (p: Product) => void) => (e: MouseEvent) => {\n e.preventDefault();\n e.stopPropagation();\n fn?.(product);\n };\n\n return (\n <Tag\n href={href}\n onClick={handleCardClick}\n className={cn(\n styles.root,\n styles[`size-${size}`],\n density !== 'default' && styles[`density-${density}`],\n className,\n )}\n {...rest}\n >\n <div className={styles.mediaWrap}>\n <MediaPlaceholder\n src={primaryImage?.src}\n alt={primaryImage?.alt ?? product.name}\n seed={primaryImage?.seed}\n aspectRatio={mediaAspectRatio}\n />\n\n {product.badges && product.badges.length > 0 && (\n <div className={styles.badges}>\n {product.badges.map((b, i) => (\n <ProductBadge key={i} label={b.label} tone={b.tone} size=\"sm\" />\n ))}\n </div>\n )}\n\n <div className={styles.quickActions}>\n {onWishlistToggle && (\n <button\n type=\"button\"\n className={styles.iconAction}\n aria-label={wishlisted ? 'Remove from wishlist' : 'Add to wishlist'}\n aria-pressed={wishlisted}\n onClick={stop(onWishlistToggle)}\n >\n {wishlisted ? <HeartFilledIcon /> : <HeartIcon />}\n </button>\n )}\n {onQuickView && (\n <button\n type=\"button\"\n className={styles.iconAction}\n aria-label=\"Quick view\"\n onClick={stop(onQuickView)}\n >\n <ZoomInIcon />\n </button>\n )}\n </div>\n\n {!hideQuickAdd && onQuickAdd && inStock && (\n <button\n type=\"button\"\n className={styles.quickAdd}\n onClick={stop(onQuickAdd)}\n >\n Quick add\n </button>\n )}\n </div>\n\n <div className={styles.body}>\n {product.brand && <span className={styles.brand}>{product.brand}</span>}\n <h3 className={styles.title}>{product.name}</h3>\n {product.tagline && density === 'default' && (\n <p className={styles.tagline}>{product.tagline}</p>\n )}\n <div className={styles.meta}>\n <PriceBlock\n price={product.price}\n compareAtPrice={product.compareAtPrice}\n size=\"sm\"\n />\n {product.rating && (\n <ReviewsSummary\n value={product.rating.value}\n count={product.rating.count}\n size=\"sm\"\n hideStars\n />\n )}\n </div>\n <ColorSwatches product={product} />\n </div>\n </Tag>\n );\n}\n",".root {\n display: grid;\n gap: var(--bazaar-space-6, 24px) var(--bazaar-space-4, 20px);\n grid-template-columns: repeat(var(--pg-cols, 4), minmax(0, 1fr));\n}\n\n@media (max-width: 1024px) {\n .root {\n grid-template-columns: repeat(var(--pg-cols-md, 3), minmax(0, 1fr));\n }\n}\n\n@media (max-width: 640px) {\n .root {\n grid-template-columns: repeat(var(--pg-cols-sm, 2), minmax(0, 1fr));\n gap: var(--bazaar-space-5, 20px) var(--bazaar-space-3, 12px);\n }\n}\n\n.loose {\n gap: var(--bazaar-space-10, 40px) var(--bazaar-space-6, 24px);\n}\n\n.tight {\n gap: var(--bazaar-space-4, 16px) var(--bazaar-space-2, 8px);\n}\n","import type { CSSProperties, HTMLAttributes, ReactNode } from 'react';\nimport { cn } from '../utils/cn';\nimport styles from './ProductGrid.module.css';\n\nexport interface ProductGridProps extends HTMLAttributes<HTMLDivElement> {\n /** Desktop column count (default 4). Responsive breakpoints downshift to `mdColumns` and `smColumns`. */\n columns?: 2 | 3 | 4 | 5 | 6;\n mdColumns?: 2 | 3 | 4;\n smColumns?: 1 | 2;\n density?: 'default' | 'loose' | 'tight';\n children?: ReactNode;\n}\n\n/**\n * ProductGrid — responsive grid shell for ProductCards.\n *\n * Unopinionated about what lives inside so it can also host recommendation\n * rails, editorial tiles, or empty-state placeholders.\n */\nexport function ProductGrid({\n columns = 4,\n mdColumns = 3,\n smColumns = 2,\n density = 'default',\n className,\n style,\n children,\n ...rest\n}: ProductGridProps) {\n const merged: CSSProperties = {\n ['--pg-cols' as any]: columns,\n ['--pg-cols-md' as any]: mdColumns,\n ['--pg-cols-sm' as any]: smColumns,\n ...style,\n };\n return (\n <div\n className={cn(styles.root, density !== 'default' && styles[density], className)}\n style={merged}\n {...rest}\n >\n {children}\n </div>\n );\n}\n",".root {\n font-family: var(--bazaar-font-family-sans);\n color: var(--bazaar-color-text-primary);\n display: flex;\n flex-direction: column;\n gap: var(--bazaar-space-2, 8px);\n}\n\n.header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 0 0 var(--bazaar-space-3, 12px);\n border-bottom: 1px solid var(--bazaar-color-border-default, #E5E0D3);\n margin-bottom: var(--bazaar-space-3, 12px);\n}\n\n.title {\n font-size: 0.875rem;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.08em;\n}\n\n.clear {\n background: none;\n border: none;\n color: var(--bazaar-color-text-muted);\n font-family: inherit;\n font-size: 0.8125rem;\n cursor: pointer;\n text-decoration: underline;\n text-underline-offset: 3px;\n}\n\n.clear:disabled {\n opacity: 0.4;\n cursor: not-allowed;\n}\n\n.group {\n padding: var(--bazaar-space-3, 12px) 0;\n border-bottom: 1px solid var(--bazaar-color-border-default, #E5E0D3);\n}\n\n.group:last-child {\n border-bottom: none;\n}\n\n.groupHeader {\n display: flex;\n align-items: center;\n justify-content: space-between;\n width: 100%;\n background: none;\n border: none;\n padding: 0;\n font-family: inherit;\n color: inherit;\n cursor: pointer;\n font-size: 0.9375rem;\n font-weight: 500;\n}\n\n.groupHeader[aria-expanded=\"true\"] .caret {\n transform: rotate(180deg);\n}\n\n.caret {\n color: var(--bazaar-color-text-muted);\n transition: transform 180ms ease;\n}\n\n.groupBody {\n padding-top: var(--bazaar-space-3, 12px);\n display: flex;\n flex-direction: column;\n gap: var(--bazaar-space-2, 8px);\n}\n\n.option {\n display: flex;\n align-items: center;\n gap: var(--bazaar-space-2, 8px);\n padding: 4px 0;\n font-size: 0.875rem;\n color: var(--bazaar-color-text-secondary, #433D32);\n cursor: pointer;\n}\n\n.option input {\n accent-color: var(--bazaar-color-text-primary);\n}\n\n.count {\n color: var(--bazaar-color-text-muted);\n margin-left: auto;\n font-variant-numeric: tabular-nums;\n font-size: 0.8125rem;\n}\n\n.swatchGroup {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(40px, 1fr));\n gap: 8px;\n}\n\n.swatchBtn {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 4px;\n padding: 4px 2px;\n background: none;\n border: none;\n cursor: pointer;\n font-family: inherit;\n font-size: 0.6875rem;\n color: var(--bazaar-color-text-muted);\n border-radius: var(--bazaar-radius-sm, 6px);\n}\n\n.swatchBtn[aria-pressed=\"true\"] {\n color: var(--bazaar-color-text-primary);\n}\n\n.swatchBtn[aria-pressed=\"true\"] .swatch {\n box-shadow: 0 0 0 2px var(--bazaar-color-surface-default), 0 0 0 3px var(--bazaar-color-text-primary);\n}\n\n.swatch {\n width: 24px;\n height: 24px;\n border-radius: 999px;\n border: 1px solid rgba(0, 0, 0, 0.1);\n transition: box-shadow 120ms ease;\n}\n\n.priceInputs {\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.priceInputs input {\n width: 100%;\n padding: 8px 10px;\n border: 1px solid var(--bazaar-color-border-default, #E5E0D3);\n border-radius: var(--bazaar-radius-sm, 6px);\n background: var(--bazaar-color-surface-default);\n font-family: inherit;\n font-size: 0.875rem;\n color: inherit;\n}\n\n.priceInputs span {\n color: var(--bazaar-color-text-muted);\n}\n","import { useState, type HTMLAttributes } from 'react';\nimport { cn } from '../utils/cn';\nimport { ChevronDownIcon } from './icons';\nimport styles from './FilterPanel.module.css';\n\nexport type FilterKind = 'checkbox' | 'swatch' | 'price' | 'rating';\n\nexport interface FilterOption {\n value: string;\n label: string;\n /** Shown as the subtle count on the right (e.g. 42). */\n count?: number;\n /** For swatch filters — CSS color. */\n swatchColor?: string;\n}\n\nexport interface FilterGroup {\n id: string;\n title: string;\n kind: FilterKind;\n options?: FilterOption[];\n /** For price groups — current low/high in major units. */\n min?: number;\n max?: number;\n /** Initial expanded state (default true). */\n defaultExpanded?: boolean;\n}\n\nexport interface FilterPanelProps extends Omit<HTMLAttributes<HTMLDivElement>, 'onChange'> {\n groups: FilterGroup[];\n /** Map of group id -> selected values (or for price: [min, max]). */\n selected?: Record<string, string[] | [number, number] | undefined>;\n onChange?: (groupId: string, next: string[] | [number, number]) => void;\n onClearAll?: () => void;\n title?: string;\n}\n\n/**\n * FilterPanel — left-rail faceted navigation for collection pages.\n *\n * Supports checkbox, color-swatch, and price-range facets. Controlled via\n * `selected` + `onChange` so callers own query-string state.\n */\nexport function FilterPanel({\n groups,\n selected = {},\n onChange,\n onClearAll,\n title = 'Filter',\n className,\n ...rest\n}: FilterPanelProps) {\n const totalSelected = Object.values(selected).reduce(\n (n, v) => n + (Array.isArray(v) ? v.length : 0),\n 0,\n );\n\n return (\n <aside className={cn(styles.root, className)} {...rest}>\n <div className={styles.header}>\n <span className={styles.title}>{title}</span>\n <button\n type=\"button\"\n className={styles.clear}\n onClick={onClearAll}\n disabled={totalSelected === 0}\n >\n Clear all\n </button>\n </div>\n\n {groups.map((g) => (\n <FilterGroupBlock\n key={g.id}\n group={g}\n selected={selected[g.id]}\n onChange={(next) => onChange?.(g.id, next)}\n />\n ))}\n </aside>\n );\n}\n\nfunction FilterGroupBlock({\n group,\n selected,\n onChange,\n}: {\n group: FilterGroup;\n selected?: string[] | [number, number];\n onChange: (next: string[] | [number, number]) => void;\n}) {\n const [open, setOpen] = useState(group.defaultExpanded !== false);\n\n const toggleValue = (v: string) => {\n const current = (selected as string[] | undefined) ?? [];\n const next = current.includes(v) ? current.filter((x) => x !== v) : [...current, v];\n onChange(next);\n };\n\n const isSelected = (v: string) => {\n return Array.isArray(selected) && (selected as string[]).includes(v);\n };\n\n return (\n <section className={styles.group}>\n <button\n type=\"button\"\n className={styles.groupHeader}\n aria-expanded={open}\n onClick={() => setOpen((o) => !o)}\n >\n {group.title}\n <span className={styles.caret}>\n <ChevronDownIcon />\n </span>\n </button>\n\n {open && (\n <div className={styles.groupBody}>\n {group.kind === 'checkbox' &&\n group.options?.map((o) => (\n <label key={o.value} className={styles.option}>\n <input\n type=\"checkbox\"\n checked={isSelected(o.value)}\n onChange={() => toggleValue(o.value)}\n />\n <span>{o.label}</span>\n {o.count !== undefined && <span className={styles.count}>{o.count}</span>}\n </label>\n ))}\n\n {group.kind === 'swatch' && (\n <div className={styles.swatchGroup}>\n {group.options?.map((o) => (\n <button\n key={o.value}\n type=\"button\"\n className={styles.swatchBtn}\n aria-pressed={isSelected(o.value)}\n onClick={() => toggleValue(o.value)}\n >\n <span className={styles.swatch} style={{ background: o.swatchColor }} />\n <span>{o.label}</span>\n </button>\n ))}\n </div>\n )}\n\n {group.kind === 'price' && (\n <div className={styles.priceInputs}>\n <input\n type=\"number\"\n placeholder={group.min !== undefined ? `$${group.min}` : 'Min'}\n aria-label=\"Minimum price\"\n value={(selected as [number, number])?.[0] ?? ''}\n onChange={(e) =>\n onChange([Number(e.target.value), (selected as [number, number])?.[1] ?? 0])\n }\n />\n <span>—</span>\n <input\n type=\"number\"\n placeholder={group.max !== undefined ? `$${group.max}` : 'Max'}\n aria-label=\"Maximum price\"\n value={(selected as [number, number])?.[1] ?? ''}\n onChange={(e) =>\n onChange([(selected as [number, number])?.[0] ?? 0, Number(e.target.value)])\n }\n />\n </div>\n )}\n </div>\n )}\n </section>\n );\n}\n",".root {\n position: relative;\n display: inline-block;\n font-family: var(--bazaar-font-family-sans);\n}\n\n.trigger {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 8px 14px;\n background: var(--bazaar-color-surface-default);\n border: 1px solid var(--bazaar-color-border-default, #E5E0D3);\n border-radius: var(--bazaar-radius-full, 999px);\n color: var(--bazaar-color-text-primary);\n font-family: inherit;\n font-size: 0.8125rem;\n cursor: pointer;\n transition: border-color 120ms ease, background 120ms ease;\n}\n\n.trigger:hover {\n border-color: var(--bazaar-color-border-strong, #C0B9A5);\n}\n\n.trigger[aria-expanded=\"true\"] {\n background: var(--bazaar-color-surface-subtle);\n}\n\n.label {\n color: var(--bazaar-color-text-muted);\n}\n\n.value {\n font-weight: 500;\n}\n\n.menu {\n position: absolute;\n right: 0;\n top: calc(100% + 6px);\n min-width: 220px;\n padding: 6px;\n background: var(--bazaar-color-surface-default);\n border: 1px solid var(--bazaar-color-border-default, #E5E0D3);\n border-radius: var(--bazaar-radius-md, 10px);\n box-shadow: var(--bazaar-shadow-md, 0 8px 24px rgba(0, 0, 0, 0.08));\n z-index: 10;\n}\n\n.item {\n display: flex;\n align-items: center;\n justify-content: space-between;\n width: 100%;\n padding: 8px 12px;\n background: none;\n border: none;\n border-radius: var(--bazaar-radius-sm, 6px);\n font-family: inherit;\n font-size: 0.875rem;\n color: var(--bazaar-color-text-primary);\n cursor: pointer;\n text-align: left;\n}\n\n.item:hover {\n background: var(--bazaar-color-surface-subtle);\n}\n\n.item[aria-selected=\"true\"] {\n color: var(--bazaar-color-text-primary);\n font-weight: 600;\n}\n\n.checkmark {\n color: var(--bazaar-color-text-primary);\n}\n","import { useEffect, useRef, useState, type HTMLAttributes } from 'react';\nimport { cn } from '../utils/cn';\nimport { CheckIcon, ChevronDownIcon } from './icons';\nimport styles from './SortMenu.module.css';\n\nexport interface SortOption {\n value: string;\n label: string;\n}\n\nexport interface SortMenuProps extends Omit<HTMLAttributes<HTMLDivElement>, 'onChange'> {\n options: SortOption[];\n value: string;\n onChange: (value: string) => void;\n label?: string;\n}\n\nexport function SortMenu({\n options,\n value,\n onChange,\n label = 'Sort',\n className,\n ...rest\n}: SortMenuProps) {\n const [open, setOpen] = useState(false);\n const ref = useRef<HTMLDivElement>(null);\n const selected = options.find((o) => o.value === value) ?? options[0];\n\n useEffect(() => {\n if (!open) return;\n const handle = (e: MouseEvent) => {\n if (ref.current && !ref.current.contains(e.target as Node)) setOpen(false);\n };\n document.addEventListener('mousedown', handle);\n return () => document.removeEventListener('mousedown', handle);\n }, [open]);\n\n return (\n <div ref={ref} className={cn(styles.root, className)} {...rest}>\n <button\n type=\"button\"\n className={styles.trigger}\n aria-haspopup=\"listbox\"\n aria-expanded={open}\n onClick={() => setOpen((o) => !o)}\n >\n <span className={styles.label}>{label}:</span>\n <span className={styles.value}>{selected.label}</span>\n <ChevronDownIcon />\n </button>\n\n {open && (\n <div className={styles.menu} role=\"listbox\" aria-label={label}>\n {options.map((o) => (\n <button\n key={o.value}\n type=\"button\"\n role=\"option\"\n aria-selected={o.value === value}\n className={styles.item}\n onClick={() => {\n onChange(o.value);\n setOpen(false);\n }}\n >\n <span>{o.label}</span>\n {o.value === value && <CheckIcon className={styles.checkmark} />}\n </button>\n ))}\n </div>\n )}\n </div>\n );\n}\n",".root {\n display: flex;\n flex-direction: column;\n gap: var(--bazaar-space-3, 12px);\n padding: var(--bazaar-space-4, 16px) 0;\n border-bottom: 1px solid var(--bazaar-color-border-default, #E5E0D3);\n font-family: var(--bazaar-font-family-sans);\n color: var(--bazaar-color-text-primary);\n}\n\n.row {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: var(--bazaar-space-4, 16px);\n flex-wrap: wrap;\n}\n\n.headline {\n display: flex;\n flex-direction: column;\n gap: 4px;\n}\n\n.title {\n font-size: 1.25rem;\n font-weight: 600;\n letter-spacing: -0.01em;\n margin: 0;\n}\n\n.meta {\n font-size: 0.875rem;\n color: var(--bazaar-color-text-muted);\n}\n\n.meta strong {\n color: var(--bazaar-color-text-primary);\n font-weight: 600;\n}\n\n.controls {\n display: flex;\n align-items: center;\n gap: var(--bazaar-space-2, 8px);\n flex-wrap: wrap;\n}\n\n.chips {\n display: flex;\n flex-wrap: wrap;\n gap: 6px;\n}\n\n.chip {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 4px 10px;\n border-radius: var(--bazaar-radius-full, 999px);\n background: var(--bazaar-color-surface-subtle, #F4F2EC);\n color: var(--bazaar-color-text-secondary, #433D32);\n font-size: 0.75rem;\n font-family: inherit;\n border: 1px solid transparent;\n}\n\n.chipClose {\n display: inline-flex;\n background: none;\n border: none;\n color: inherit;\n cursor: pointer;\n padding: 0;\n line-height: 0;\n}\n","import type { HTMLAttributes, ReactNode } from 'react';\nimport { cn } from '../utils/cn';\nimport { XIcon } from './icons';\nimport styles from './SearchResultsHeader.module.css';\n\nexport interface ActiveFilterChip {\n id: string;\n label: string;\n}\n\nexport interface SearchResultsHeaderProps extends HTMLAttributes<HTMLDivElement> {\n /** Main heading (e.g., \"Results for 'linen'\" or \"All women's apparel\"). */\n title: string;\n /** Result count. Used in the subtext line with the optional query. */\n count: number;\n /** Optional search query echo. */\n query?: string;\n /** Active filter chips. */\n activeFilters?: ActiveFilterChip[];\n onRemoveFilter?: (id: string) => void;\n /** Controls on the right side (SortMenu, layout toggles, etc.). */\n rightSlot?: ReactNode;\n}\n\nfunction formatCount(n: number): string {\n return n.toLocaleString();\n}\n\nexport function SearchResultsHeader({\n title,\n count,\n query,\n activeFilters,\n onRemoveFilter,\n rightSlot,\n className,\n ...rest\n}: SearchResultsHeaderProps) {\n return (\n <div className={cn(styles.root, className)} {...rest}>\n <div className={styles.row}>\n <div className={styles.headline}>\n <h1 className={styles.title}>{title}</h1>\n <span className={styles.meta}>\n <strong>{formatCount(count)}</strong> {count === 1 ? 'result' : 'results'}\n {query && (\n <>\n {' '}\n for <strong>“{query}”</strong>\n </>\n )}\n </span>\n </div>\n {rightSlot && <div className={styles.controls}>{rightSlot}</div>}\n </div>\n\n {activeFilters && activeFilters.length > 0 && (\n <div className={styles.chips}>\n {activeFilters.map((f) => (\n <span key={f.id} className={styles.chip}>\n {f.label}\n {onRemoveFilter && (\n <button\n type=\"button\"\n className={styles.chipClose}\n aria-label={`Remove filter ${f.label}`}\n onClick={() => onRemoveFilter(f.id)}\n >\n <XIcon width={12} height={12} />\n </button>\n )}\n </span>\n ))}\n </div>\n )}\n </div>\n );\n}\n",".root {\n position: relative;\n width: 100%;\n border-radius: var(--bazaar-radius-lg, 12px);\n overflow: hidden;\n font-family: var(--bazaar-font-family-sans);\n color: var(--bazaar-color-text-primary);\n background: var(--bazaar-color-surface-subtle, #F4F2EC);\n isolation: isolate;\n}\n\n.media {\n position: absolute;\n inset: 0;\n z-index: 0;\n}\n\n.media > * {\n width: 100%;\n height: 100%;\n}\n\n.scrim {\n position: absolute;\n inset: 0;\n background: linear-gradient(\n 180deg,\n rgba(0, 0, 0, 0) 30%,\n rgba(0, 0, 0, 0.28) 100%\n );\n z-index: 1;\n}\n\n.content {\n position: relative;\n z-index: 2;\n padding: clamp(24px, 5vw, 80px) clamp(20px, 5vw, 64px);\n max-width: 640px;\n display: flex;\n flex-direction: column;\n gap: var(--bazaar-space-3, 12px);\n}\n\n.eyebrow {\n font-size: 0.75rem;\n text-transform: uppercase;\n letter-spacing: 0.14em;\n color: var(--bazaar-color-text-muted);\n margin: 0;\n}\n\n.title {\n font-family: var(--bazaar-font-family-display, var(--bazaar-font-family-sans));\n font-size: clamp(1.75rem, 4vw, 3rem);\n font-weight: 600;\n line-height: 1.05;\n letter-spacing: -0.02em;\n margin: 0;\n}\n\n.description {\n font-size: 1rem;\n line-height: 1.55;\n color: var(--bazaar-color-text-secondary, #433D32);\n margin: 0;\n max-width: 48ch;\n}\n\n.actions {\n display: flex;\n flex-wrap: wrap;\n gap: var(--bazaar-space-2, 8px);\n margin-top: var(--bazaar-space-2, 8px);\n}\n\n/* Overlay tone — puts content on top of imagery with light text. */\n.tone-overlay {\n min-height: clamp(300px, 40vw, 480px);\n color: var(--bazaar-color-text-inverse, #FFFFFF);\n}\n.tone-overlay .eyebrow { color: rgba(255, 255, 255, 0.85); }\n.tone-overlay .description { color: rgba(255, 255, 255, 0.92); }\n\n/* Side tone — media beside content, both opaque. */\n.tone-side {\n display: grid;\n grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);\n align-items: stretch;\n min-height: clamp(280px, 36vw, 420px);\n}\n\n.tone-side .media {\n position: relative;\n inset: auto;\n grid-column: 2;\n}\n\n.tone-side .scrim { display: none; }\n\n.tone-side .content {\n grid-column: 1;\n justify-content: center;\n padding: clamp(24px, 4vw, 56px);\n}\n\n@media (max-width: 720px) {\n .tone-side {\n grid-template-columns: 1fr;\n }\n .tone-side .media {\n grid-column: 1;\n height: 260px;\n }\n .tone-side .content {\n grid-column: 1;\n }\n}\n","import type { HTMLAttributes, ReactNode } from 'react';\nimport { cn } from '../utils/cn';\nimport { MediaPlaceholder } from './MediaPlaceholder';\nimport styles from './CollectionHero.module.css';\n\nexport interface CollectionHeroProps extends HTMLAttributes<HTMLElement> {\n title: string;\n description?: string;\n eyebrow?: string;\n /** Image src — falls back to MediaPlaceholder gradient if omitted. */\n imageSrc?: string;\n imageAlt?: string;\n imageSeed?: string;\n /** Layout tone. \"overlay\" = image behind content; \"side\" = 2-column. */\n tone?: 'overlay' | 'side';\n /** CTA slot — usually 1–2 Buttons. */\n actions?: ReactNode;\n}\n\nexport function CollectionHero({\n title,\n description,\n eyebrow,\n imageSrc,\n imageAlt = title,\n imageSeed,\n tone = 'overlay',\n actions,\n className,\n ...rest\n}: CollectionHeroProps) {\n return (\n <section\n className={cn(styles.root, styles[`tone-${tone}`], className)}\n {...rest}\n >\n <div className={styles.media}>\n <MediaPlaceholder\n src={imageSrc}\n alt={imageAlt}\n seed={imageSeed ?? title}\n aspectRatio={tone === 'overlay' ? '16 / 7' : '4 / 5'}\n />\n </div>\n <div className={styles.scrim} />\n <div className={styles.content}>\n {eyebrow && <p className={styles.eyebrow}>{eyebrow}</p>}\n <h2 className={styles.title}>{title}</h2>\n {description && <p className={styles.description}>{description}</p>}\n {actions && <div className={styles.actions}>{actions}</div>}\n </div>\n </section>\n );\n}\n",".root {\n font-family: var(--bazaar-font-family-sans);\n color: var(--bazaar-color-text-primary);\n display: flex;\n flex-direction: column;\n gap: var(--bazaar-space-4, 16px);\n}\n\n.header {\n display: flex;\n align-items: baseline;\n justify-content: space-between;\n gap: var(--bazaar-space-3, 12px);\n flex-wrap: wrap;\n}\n\n.title {\n font-family: var(--bazaar-font-family-display, var(--bazaar-font-family-sans));\n font-size: 1.375rem;\n font-weight: 600;\n letter-spacing: -0.01em;\n margin: 0;\n}\n\n.subtitle {\n font-size: 0.9375rem;\n color: var(--bazaar-color-text-muted);\n margin: 2px 0 0;\n}\n\n.nav {\n display: inline-flex;\n gap: 6px;\n}\n\n.navBtn {\n width: 36px;\n height: 36px;\n border-radius: 999px;\n border: 1px solid var(--bazaar-color-border-default, #E5E0D3);\n background: var(--bazaar-color-surface-default);\n color: var(--bazaar-color-text-primary);\n display: inline-flex;\n align-items: center;\n justify-content: center;\n cursor: pointer;\n transition: background 120ms, border-color 120ms;\n}\n\n.navBtn:hover:not(:disabled) {\n background: var(--bazaar-color-surface-subtle);\n}\n\n.navBtn:disabled {\n opacity: 0.35;\n cursor: not-allowed;\n}\n\n.track {\n display: grid;\n grid-auto-flow: column;\n grid-auto-columns: minmax(240px, 1fr);\n gap: var(--bazaar-space-4, 16px);\n overflow-x: auto;\n scroll-snap-type: x mandatory;\n scroll-padding: 0;\n padding-bottom: 4px;\n scrollbar-width: thin;\n}\n\n.track > * {\n scroll-snap-align: start;\n}\n\n@media (min-width: 1024px) {\n .track {\n grid-auto-columns: minmax(0, 1fr);\n grid-template-columns: repeat(var(--rr-cols, 4), minmax(0, 1fr));\n overflow: visible;\n }\n}\n","import { useRef, type CSSProperties, type HTMLAttributes, type ReactNode } from 'react';\nimport { cn } from '../utils/cn';\nimport { ChevronLeftIcon, ChevronRightIcon } from './icons';\nimport type { Product } from './types';\nimport { ProductCard } from './ProductCard';\nimport styles from './RecommendationRail.module.css';\n\nexport interface RecommendationRailProps extends HTMLAttributes<HTMLElement> {\n title: string;\n subtitle?: string;\n products?: Product[];\n /** Desktop column count (default 4). */\n columns?: 3 | 4 | 5;\n /** Custom children — when provided, `products` is ignored. */\n children?: ReactNode;\n onSelectProduct?: (product: Product) => void;\n onWishlistToggle?: (product: Product) => void;\n}\n\nexport function RecommendationRail({\n title,\n subtitle,\n products,\n columns = 4,\n children,\n onSelectProduct,\n onWishlistToggle,\n className,\n style,\n ...rest\n}: RecommendationRailProps) {\n const trackRef = useRef<HTMLDivElement>(null);\n\n const scroll = (dir: -1 | 1) => {\n const track = trackRef.current;\n if (!track) return;\n track.scrollBy({ left: dir * track.clientWidth * 0.8, behavior: 'smooth' });\n };\n\n const merged: CSSProperties = { ['--rr-cols' as any]: columns, ...style };\n\n return (\n <section className={cn(styles.root, className)} style={merged} {...rest}>\n <div className={styles.header}>\n <div>\n <h2 className={styles.title}>{title}</h2>\n {subtitle && <p className={styles.subtitle}>{subtitle}</p>}\n </div>\n <div className={styles.nav}>\n <button\n type=\"button\"\n className={styles.navBtn}\n aria-label=\"Previous\"\n onClick={() => scroll(-1)}\n >\n <ChevronLeftIcon />\n </button>\n <button\n type=\"button\"\n className={styles.navBtn}\n aria-label=\"Next\"\n onClick={() => scroll(1)}\n >\n <ChevronRightIcon />\n </button>\n </div>\n </div>\n\n <div ref={trackRef} className={styles.track}>\n {children ??\n products?.map((p) => (\n <ProductCard\n key={p.id}\n product={p}\n onSelect={onSelectProduct}\n onWishlistToggle={onWishlistToggle}\n />\n ))}\n </div>\n </section>\n );\n}\n",".root {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: var(--bazaar-space-3, 12px);\n padding: 10px var(--bazaar-space-4, 16px);\n background: var(--bazaar-color-text-primary, #1F1C17);\n color: var(--bazaar-color-text-inverse, #FFFFFF);\n font-family: var(--bazaar-font-family-sans);\n font-size: 0.8125rem;\n letter-spacing: 0.04em;\n text-align: center;\n line-height: 1.4;\n}\n\n.icon {\n display: inline-flex;\n opacity: 0.85;\n}\n\n.message {\n font-weight: 500;\n}\n\n.cta {\n color: inherit;\n text-decoration: underline;\n text-underline-offset: 3px;\n font-weight: 600;\n background: none;\n border: none;\n font-family: inherit;\n font-size: inherit;\n cursor: pointer;\n padding: 0;\n}\n\n.close {\n margin-left: auto;\n background: none;\n border: none;\n color: inherit;\n cursor: pointer;\n padding: 0;\n opacity: 0.8;\n display: inline-flex;\n}\n\n.close:hover { opacity: 1; }\n\n.tone-subtle {\n background: var(--bazaar-color-surface-subtle, #F4F2EC);\n color: var(--bazaar-color-text-primary, #1F1C17);\n}\n\n.tone-accent {\n background: var(--bazaar-color-accent-amber-100, #F4E5C2);\n color: var(--bazaar-color-accent-amber-700, #7A4D0D);\n}\n","import { useState, type HTMLAttributes, type ReactNode } from 'react';\nimport { cn } from '../utils/cn';\nimport { XIcon } from './icons';\nimport styles from './PromoStrip.module.css';\n\nexport interface PromoStripProps extends HTMLAttributes<HTMLDivElement> {\n message: ReactNode;\n /** Optional leading icon. */\n icon?: ReactNode;\n /** Inline CTA — rendered as a link-styled button. */\n ctaLabel?: string;\n onCta?: () => void;\n /** Allow the strip to be dismissed (client-side only). */\n dismissible?: boolean;\n tone?: 'dark' | 'subtle' | 'accent';\n}\n\nexport function PromoStrip({\n message,\n icon,\n ctaLabel,\n onCta,\n dismissible = false,\n tone = 'dark',\n className,\n ...rest\n}: PromoStripProps) {\n const [hidden, setHidden] = useState(false);\n if (hidden) return null;\n\n return (\n <div\n className={cn(styles.root, tone !== 'dark' && styles[`tone-${tone}`], className)}\n role=\"region\"\n aria-label=\"Site promotion\"\n {...rest}\n >\n {icon && <span className={styles.icon}>{icon}</span>}\n <span className={styles.message}>{message}</span>\n {ctaLabel && (\n <button type=\"button\" className={styles.cta} onClick={onCta}>\n {ctaLabel}\n </button>\n )}\n {dismissible && (\n <button\n type=\"button\"\n className={styles.close}\n aria-label=\"Dismiss promotion\"\n onClick={() => setHidden(true)}\n >\n <XIcon width={14} height={14} />\n </button>\n )}\n </div>\n );\n}\n",".root {\n display: grid;\n gap: var(--bazaar-space-3, 12px);\n font-family: var(--bazaar-font-family-sans);\n}\n\n.layout-left {\n grid-template-columns: 72px 1fr;\n}\n\n.layout-below {\n grid-template-columns: 1fr;\n grid-template-rows: auto auto;\n}\n\n.thumbs {\n display: flex;\n gap: 8px;\n}\n\n.layout-left .thumbs {\n flex-direction: column;\n}\n\n.layout-below .thumbs {\n flex-direction: row;\n overflow-x: auto;\n scrollbar-width: none;\n order: 2;\n}\n\n.layout-below .thumbs::-webkit-scrollbar {\n display: none;\n}\n\n.thumb {\n position: relative;\n width: 100%;\n padding: 0;\n border: 1px solid transparent;\n border-radius: var(--bazaar-radius-sm, 6px);\n background: transparent;\n overflow: hidden;\n cursor: pointer;\n transition: border-color 150ms ease, transform 150ms ease;\n}\n\n.layout-below .thumb {\n width: 64px;\n flex: 0 0 auto;\n}\n\n.thumb:hover {\n border-color: var(--bazaar-color-border-default, rgba(0, 0, 0, 0.12));\n}\n\n.thumbActive {\n border-color: var(--bazaar-color-text-primary, #1F1C17);\n}\n\n.thumbMedia {\n border-radius: inherit;\n}\n\n.thumbVideoBadge {\n position: absolute;\n top: 4px;\n right: 4px;\n width: 18px;\n height: 18px;\n border-radius: 999px;\n background: rgba(0, 0, 0, 0.7);\n color: #FFFFFF;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n}\n\n.hero {\n position: relative;\n border-radius: var(--bazaar-radius-lg, 12px);\n overflow: hidden;\n background: var(--bazaar-color-surface-subtle, #F4F2EC);\n}\n\n.layout-below .hero {\n order: 1;\n}\n\n.heroMedia {\n border-radius: inherit;\n}\n\n.nav {\n position: absolute;\n top: 50%;\n transform: translateY(-50%);\n width: 40px;\n height: 40px;\n border-radius: 999px;\n border: 1px solid var(--bazaar-color-border-default, rgba(0, 0, 0, 0.08));\n background: var(--bazaar-color-surface-default, #FFFFFF);\n color: var(--bazaar-color-text-primary);\n display: inline-flex;\n align-items: center;\n justify-content: center;\n cursor: pointer;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);\n transition: transform 120ms ease;\n}\n\n.nav:hover {\n transform: translateY(-50%) scale(1.05);\n}\n\n.navPrev { left: 12px; }\n.navNext { right: 12px; }\n\n.zoomBtn {\n position: absolute;\n top: 12px;\n right: 12px;\n width: 36px;\n height: 36px;\n border-radius: 999px;\n border: 1px solid var(--bazaar-color-border-default, rgba(0, 0, 0, 0.08));\n background: var(--bazaar-color-surface-default, #FFFFFF);\n color: var(--bazaar-color-text-primary);\n display: inline-flex;\n align-items: center;\n justify-content: center;\n cursor: pointer;\n}\n\n.playBtn {\n position: absolute;\n inset: 0;\n margin: auto;\n width: 64px;\n height: 64px;\n border: none;\n border-radius: 999px;\n background: rgba(0, 0, 0, 0.6);\n color: #FFFFFF;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n cursor: pointer;\n}\n\n.counter {\n position: absolute;\n bottom: 12px;\n left: 12px;\n padding: 4px 10px;\n border-radius: 999px;\n background: rgba(0, 0, 0, 0.55);\n color: #FFFFFF;\n font-size: 0.75rem;\n letter-spacing: 0.04em;\n}\n","import { useState, type HTMLAttributes } from 'react';\nimport { cn } from '../utils/cn';\nimport { MediaPlaceholder } from './MediaPlaceholder';\nimport { ChevronLeftIcon, ChevronRightIcon, ZoomInIcon, PlayIcon } from './icons';\nimport type { ProductImage } from './types';\nimport styles from './ProductMediaGallery.module.css';\n\nexport interface ProductMediaGalleryProps extends HTMLAttributes<HTMLDivElement> {\n images: ProductImage[];\n /** Thumbnail layout — left rail (desktop) or below (mobile-first). */\n thumbLayout?: 'left' | 'below';\n /** CSS aspect-ratio for the hero tile. */\n aspectRatio?: string;\n onZoom?: (index: number) => void;\n /** Index of a video frame (rendered with a play-indicator overlay). */\n videoIndex?: number;\n}\n\n/**\n * ProductMediaGallery — hero image plus thumbnail strip with keyboard nav.\n *\n * Uncontrolled active index with arrow-key support; pair with a Lightbox\n * via the `onZoom` callback to open a zoomed view.\n */\nexport function ProductMediaGallery({\n images,\n thumbLayout = 'left',\n aspectRatio = '4 / 5',\n onZoom,\n videoIndex,\n className,\n ...rest\n}: ProductMediaGalleryProps) {\n const [active, setActive] = useState(0);\n const total = images.length;\n const go = (n: number) => setActive(((n % total) + total) % total);\n const current = images[active];\n\n return (\n <div\n className={cn(styles.root, styles[`layout-${thumbLayout}`], className)}\n {...rest}\n >\n <div className={styles.thumbs} role=\"listbox\" aria-label=\"Product images\">\n {images.map((img, i) => (\n <button\n key={i}\n type=\"button\"\n role=\"option\"\n aria-selected={i === active}\n className={cn(styles.thumb, i === active && styles.thumbActive)}\n onClick={() => setActive(i)}\n >\n <MediaPlaceholder\n src={img.src}\n alt={img.alt}\n seed={img.seed}\n aspectRatio=\"1 / 1\"\n className={styles.thumbMedia}\n />\n {i === videoIndex && (\n <span className={styles.thumbVideoBadge} aria-hidden>\n <PlayIcon width={12} height={12} />\n </span>\n )}\n </button>\n ))}\n </div>\n\n <div className={styles.hero}>\n <MediaPlaceholder\n src={current?.src}\n alt={current?.alt ?? ''}\n seed={current?.seed}\n aspectRatio={aspectRatio}\n className={styles.heroMedia}\n />\n\n {active === videoIndex && (\n <button type=\"button\" className={styles.playBtn} aria-label=\"Play video\">\n <PlayIcon width={20} height={20} />\n </button>\n )}\n\n {onZoom && (\n <button\n type=\"button\"\n className={styles.zoomBtn}\n aria-label=\"Zoom image\"\n onClick={() => onZoom(active)}\n >\n <ZoomInIcon />\n </button>\n )}\n\n {total > 1 && (\n <>\n <button\n type=\"button\"\n className={cn(styles.nav, styles.navPrev)}\n aria-label=\"Previous image\"\n onClick={() => go(active - 1)}\n >\n <ChevronLeftIcon />\n </button>\n <button\n type=\"button\"\n className={cn(styles.nav, styles.navNext)}\n aria-label=\"Next image\"\n onClick={() => go(active + 1)}\n >\n <ChevronRightIcon />\n </button>\n </>\n )}\n\n <div className={styles.counter} aria-live=\"polite\">\n {active + 1} / {total}\n </div>\n </div>\n </div>\n );\n}\n",".root {\n display: flex;\n flex-direction: column;\n gap: 8px;\n font-family: var(--bazaar-font-family-sans);\n}\n\n.header {\n display: flex;\n align-items: baseline;\n justify-content: space-between;\n gap: 8px;\n}\n\n.label {\n font-size: 0.8125rem;\n font-weight: 600;\n color: var(--bazaar-color-text-primary);\n text-transform: uppercase;\n letter-spacing: 0.06em;\n}\n\n.selection {\n font-weight: 400;\n color: var(--bazaar-color-text-muted);\n text-transform: none;\n letter-spacing: 0;\n}\n\n.helper {\n font-size: 0.8125rem;\n color: var(--bazaar-color-text-muted);\n}\n\n.group {\n display: flex;\n flex-wrap: wrap;\n gap: 8px;\n}\n\n.group-pills {\n gap: 8px;\n}\n\n.pill {\n min-width: 48px;\n padding: 10px 14px;\n border: 1px solid var(--bazaar-color-border-default, rgba(0, 0, 0, 0.14));\n border-radius: var(--bazaar-radius-sm, 6px);\n background: var(--bazaar-color-surface-default, #FFFFFF);\n color: var(--bazaar-color-text-primary);\n font-family: inherit;\n font-size: 0.875rem;\n cursor: pointer;\n transition: border-color 120ms ease, background 120ms ease;\n}\n\n.pill:hover:not(:disabled) {\n border-color: var(--bazaar-color-text-primary);\n}\n\n.pillActive {\n border-color: var(--bazaar-color-text-primary, #1F1C17);\n background: var(--bazaar-color-text-primary, #1F1C17);\n color: var(--bazaar-color-text-inverse, #FFFFFF);\n}\n\n.swatch {\n width: 40px;\n height: 40px;\n padding: 3px;\n border: 1.5px solid transparent;\n border-radius: 999px;\n background: transparent;\n cursor: pointer;\n transition: border-color 120ms ease;\n}\n\n.swatch:hover:not(:disabled) {\n border-color: var(--bazaar-color-border-default, rgba(0, 0, 0, 0.2));\n}\n\n.swatchActive {\n border-color: var(--bazaar-color-text-primary);\n}\n\n.swatchChip {\n display: block;\n width: 100%;\n height: 100%;\n border-radius: 999px;\n border: 1px solid rgba(0, 0, 0, 0.1);\n}\n\n.imageSwatch {\n width: 64px;\n padding: 3px;\n border: 1.5px solid transparent;\n border-radius: var(--bazaar-radius-sm, 6px);\n background: transparent;\n cursor: pointer;\n display: flex;\n flex-direction: column;\n gap: 4px;\n transition: border-color 120ms ease;\n}\n\n.imageSwatch:hover:not(:disabled) {\n border-color: var(--bazaar-color-border-default, rgba(0, 0, 0, 0.2));\n}\n\n.imageSwatchActive {\n border-color: var(--bazaar-color-text-primary);\n}\n\n.imageSwatchMedia {\n width: 100%;\n aspect-ratio: 1 / 1;\n border-radius: var(--bazaar-radius-xs, 4px);\n border: 1px solid rgba(0, 0, 0, 0.08);\n}\n\n.imageSwatchLabel {\n font-size: 0.6875rem;\n color: var(--bazaar-color-text-muted);\n text-align: center;\n}\n\n.unavailable {\n opacity: 0.45;\n cursor: not-allowed;\n position: relative;\n}\n\n.unavailable.pill {\n text-decoration: line-through;\n}\n\n.unavailable.swatch .swatchChip::after,\n.unavailable.imageSwatch .imageSwatchMedia::after {\n content: '';\n position: absolute;\n inset: 0;\n background: linear-gradient(\n to top left,\n transparent calc(50% - 1px),\n rgba(0, 0, 0, 0.5) calc(50% - 1px),\n rgba(0, 0, 0, 0.5) calc(50% + 1px),\n transparent calc(50% + 1px)\n );\n border-radius: inherit;\n pointer-events: none;\n}\n\n.select {\n padding: 10px 12px;\n border: 1px solid var(--bazaar-color-border-default, rgba(0, 0, 0, 0.14));\n border-radius: var(--bazaar-radius-sm, 6px);\n background: var(--bazaar-color-surface-default, #FFFFFF);\n color: var(--bazaar-color-text-primary);\n font-family: inherit;\n font-size: 0.875rem;\n cursor: pointer;\n}\n","import type { HTMLAttributes } from 'react';\nimport { cn } from '../utils/cn';\nimport type { VariantAxis, VariantOption } from './types';\nimport styles from './VariantSelector.module.css';\n\nexport interface VariantSelectorProps extends Omit<HTMLAttributes<HTMLDivElement>, 'onChange'> {\n axis: VariantAxis;\n /** Currently-selected option value. */\n value?: string;\n onChange?: (option: VariantOption) => void;\n /** Optional right-side helper slot, e.g. \"Size guide\". */\n helper?: React.ReactNode;\n /** Show the selected option label next to the axis name. */\n showSelectionLabel?: boolean;\n}\n\n/**\n * VariantSelector — renders a single variant axis (color, size, material...).\n *\n * The axis's `style` drives layout: `swatches` for color chips, `pills` for\n * size buttons, `dropdown` for a native select, `image-swatches` for product\n * thumbnails. Unavailable options render with a strikethrough indicator.\n */\nexport function VariantSelector({\n axis,\n value,\n onChange,\n helper,\n showSelectionLabel = true,\n className,\n ...rest\n}: VariantSelectorProps) {\n const style = axis.style ?? (axis.kind === 'color' ? 'swatches' : 'pills');\n const selected = axis.options.find((o) => o.value === value);\n\n const pick = (opt: VariantOption) => {\n if (opt.available === false) return;\n onChange?.(opt);\n };\n\n return (\n <div className={cn(styles.root, className)} {...rest}>\n <div className={styles.header}>\n <span className={styles.label}>\n {axis.name}\n {showSelectionLabel && selected && (\n <span className={styles.selection}> · {selected.label}</span>\n )}\n </span>\n {helper && <span className={styles.helper}>{helper}</span>}\n </div>\n\n {style === 'dropdown' ? (\n <select\n className={styles.select}\n value={value ?? ''}\n onChange={(e) => {\n const next = axis.options.find((o) => o.value === e.target.value);\n if (next) pick(next);\n }}\n aria-label={axis.name}\n >\n <option value=\"\" disabled>\n Choose {axis.name.toLowerCase()}\n </option>\n {axis.options.map((o) => (\n <option key={o.value} value={o.value} disabled={o.available === false}>\n {o.label}\n {o.available === false ? ' — out of stock' : ''}\n </option>\n ))}\n </select>\n ) : (\n <div\n className={cn(styles.group, styles[`group-${style}`])}\n role=\"radiogroup\"\n aria-label={axis.name}\n >\n {axis.options.map((o) => {\n const isActive = o.value === value;\n const unavailable = o.available === false;\n\n if (style === 'swatches') {\n return (\n <button\n key={o.value}\n type=\"button\"\n role=\"radio\"\n aria-checked={isActive}\n aria-label={o.label}\n disabled={unavailable}\n title={o.label}\n className={cn(\n styles.swatch,\n isActive && styles.swatchActive,\n unavailable && styles.unavailable,\n )}\n onClick={() => pick(o)}\n >\n <span\n className={styles.swatchChip}\n style={{\n background:\n o.swatchImage ? `url(${o.swatchImage}) center/cover` : o.swatchColor ?? '#CCC',\n }}\n />\n </button>\n );\n }\n\n if (style === 'image-swatches') {\n return (\n <button\n key={o.value}\n type=\"button\"\n role=\"radio\"\n aria-checked={isActive}\n aria-label={o.label}\n disabled={unavailable}\n className={cn(\n styles.imageSwatch,\n isActive && styles.imageSwatchActive,\n unavailable && styles.unavailable,\n )}\n onClick={() => pick(o)}\n >\n <span\n className={styles.imageSwatchMedia}\n style={{\n background:\n o.swatchImage ? `url(${o.swatchImage}) center/cover` : o.swatchColor ?? '#E8DFCC',\n }}\n />\n <span className={styles.imageSwatchLabel}>{o.label}</span>\n </button>\n );\n }\n\n return (\n <button\n key={o.value}\n type=\"button\"\n role=\"radio\"\n aria-checked={isActive}\n disabled={unavailable}\n className={cn(\n styles.pill,\n isActive && styles.pillActive,\n unavailable && styles.unavailable,\n )}\n onClick={() => pick(o)}\n >\n {o.label}\n </button>\n );\n })}\n </div>\n )}\n </div>\n );\n}\n",".root {\n display: inline-flex;\n align-items: center;\n gap: 8px;\n font-family: var(--bazaar-font-family-sans);\n color: var(--bazaar-color-text-primary);\n}\n\n.size-sm { font-size: 0.75rem; }\n.size-md { font-size: 0.875rem; }\n\n.dot {\n width: 8px;\n height: 8px;\n border-radius: 999px;\n flex: 0 0 auto;\n box-shadow: 0 0 0 3px rgba(0, 0, 0, 0);\n}\n\n.dot-inStock {\n background: #4A7C59;\n box-shadow: 0 0 0 3px rgba(59, 125, 79, 0.15);\n}\n\n.dot-lowStock {\n background: #C97A2A;\n box-shadow: 0 0 0 3px rgba(201, 122, 42, 0.18);\n}\n\n.dot-outOfStock {\n background: #8A8A8A;\n}\n\n.dot-preorder {\n background: #446E9B;\n box-shadow: 0 0 0 3px rgba(68, 110, 155, 0.18);\n}\n\n.dot-backorder {\n background: #8E6B38;\n box-shadow: 0 0 0 3px rgba(142, 107, 56, 0.18);\n}\n\n.label {\n color: inherit;\n}\n","import type { HTMLAttributes } from 'react';\nimport { cn } from '../utils/cn';\nimport type { InventoryState } from './types';\nimport styles from './InventoryIndicator.module.css';\n\nexport interface InventoryIndicatorProps extends HTMLAttributes<HTMLDivElement> {\n state: InventoryState;\n /** Size variant. */\n size?: 'sm' | 'md';\n}\n\nconst DOT_TONE: Record<string, string> = {\n 'in-stock': 'inStock',\n 'low-stock': 'lowStock',\n 'out-of-stock': 'outOfStock',\n preorder: 'preorder',\n backorder: 'backorder',\n};\n\nfunction defaultLabel(state: InventoryState): string {\n switch (state.status) {\n case 'in-stock':\n return 'In stock';\n case 'low-stock':\n return state.remaining\n ? `Only ${state.remaining} left`\n : 'Low stock — order soon';\n case 'out-of-stock':\n return 'Out of stock';\n case 'preorder':\n return state.expectedDate ? `Pre-order · ships ${state.expectedDate}` : 'Pre-order';\n case 'backorder':\n return state.expectedDate ? `Backordered · ${state.expectedDate}` : 'Backordered';\n default:\n return '';\n }\n}\n\n/**\n * InventoryIndicator — compact stock-state pill with a tone-coded dot.\n *\n * Pairs with a ProductBuyBox to answer the \"should I buy this?\" question\n * at a glance.\n */\nexport function InventoryIndicator({\n state,\n size = 'md',\n className,\n children,\n ...rest\n}: InventoryIndicatorProps) {\n const tone = DOT_TONE[state.status] ?? 'inStock';\n return (\n <div\n className={cn(styles.root, styles[`size-${size}`], className)}\n role=\"status\"\n {...rest}\n >\n <span className={cn(styles.dot, styles[`dot-${tone}`])} aria-hidden />\n <span className={styles.label}>{children ?? defaultLabel(state)}</span>\n </div>\n );\n}\n",".root {\n font-family: var(--bazaar-font-family-sans);\n color: var(--bazaar-color-text-primary);\n}\n\n.layout-stacked {\n display: flex;\n flex-direction: column;\n gap: 12px;\n}\n\n.layout-row {\n display: flex;\n flex-wrap: wrap;\n gap: 20px;\n}\n\n.layout-grid {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));\n gap: 16px;\n}\n\n.item {\n display: flex;\n align-items: flex-start;\n gap: 12px;\n}\n\n.icon {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 32px;\n height: 32px;\n border-radius: 999px;\n background: var(--bazaar-color-surface-subtle, #F4F2EC);\n color: var(--bazaar-color-brand-primary-700, #7A5A30);\n flex: 0 0 auto;\n}\n\n.body {\n display: flex;\n flex-direction: column;\n gap: 2px;\n}\n\n.title {\n font-size: 0.875rem;\n font-weight: 500;\n color: var(--bazaar-color-text-primary);\n}\n\n.description {\n font-size: 0.8125rem;\n color: var(--bazaar-color-text-muted);\n line-height: 1.4;\n}\n","import type { HTMLAttributes, ReactNode } from 'react';\nimport { cn } from '../utils/cn';\nimport { TruckIcon, ReturnIcon, ShieldCheckIcon, LeafIcon, PackageIcon } from './icons';\nimport styles from './ShippingReassurance.module.css';\n\nexport interface ReassuranceItem {\n icon?: ReactNode;\n title: string;\n description?: string;\n}\n\nexport interface ShippingReassuranceProps extends HTMLAttributes<HTMLDivElement> {\n items?: ReassuranceItem[];\n /** Layout — inline row for PDP sidebar, stacked for cart. */\n layout?: 'row' | 'stacked' | 'grid';\n}\n\nconst DEFAULT_ITEMS: ReassuranceItem[] = [\n {\n icon: <TruckIcon />,\n title: 'Free shipping over $75',\n description: 'Arrives in 3–5 business days',\n },\n {\n icon: <ReturnIcon />,\n title: '60-day free returns',\n description: 'No questions asked',\n },\n {\n icon: <ShieldCheckIcon />,\n title: 'Secure checkout',\n description: 'Backed by our lifetime guarantee',\n },\n];\n\n/**\n * ShippingReassurance — trust signals shown near the buy button.\n *\n * Renders a compact list of benefits (free shipping, easy returns, secure\n * checkout). Callers can override the default items for campaign-specific\n * messaging.\n */\nexport function ShippingReassurance({\n items = DEFAULT_ITEMS,\n layout = 'stacked',\n className,\n ...rest\n}: ShippingReassuranceProps) {\n return (\n <div\n className={cn(styles.root, styles[`layout-${layout}`], className)}\n role=\"list\"\n {...rest}\n >\n {items.map((item, i) => (\n <div key={i} className={styles.item} role=\"listitem\">\n {item.icon && <span className={styles.icon}>{item.icon}</span>}\n <div className={styles.body}>\n <span className={styles.title}>{item.title}</span>\n {item.description && (\n <span className={styles.description}>{item.description}</span>\n )}\n </div>\n </div>\n ))}\n </div>\n );\n}\n\n// Re-export helper icons so callers can compose custom reassurance lists.\nexport const ReassuranceIcons = {\n Truck: TruckIcon,\n Return: ReturnIcon,\n Shield: ShieldCheckIcon,\n Leaf: LeafIcon,\n Package: PackageIcon,\n};\n",".root {\n display: flex;\n flex-direction: column;\n gap: 16px;\n font-family: var(--bazaar-font-family-sans);\n color: var(--bazaar-color-text-primary);\n}\n\n.badges {\n display: flex;\n gap: 6px;\n flex-wrap: wrap;\n}\n\n.brand {\n font-size: 0.8125rem;\n font-weight: 500;\n letter-spacing: 0.08em;\n text-transform: uppercase;\n color: var(--bazaar-color-text-muted);\n}\n\n.title {\n font-family: var(--bazaar-font-family-display, var(--bazaar-font-family-sans));\n font-size: 1.75rem;\n line-height: 1.2;\n font-weight: 500;\n margin: 0;\n color: var(--bazaar-color-text-primary);\n}\n\n.tagline {\n font-size: 1rem;\n line-height: 1.5;\n color: var(--bazaar-color-text-muted);\n margin: -8px 0 0;\n}\n\n.meta {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 12px;\n padding-bottom: 8px;\n border-bottom: 1px solid var(--bazaar-color-border-subtle, rgba(0, 0, 0, 0.06));\n}\n\n.variant {\n /* spacing handled by root gap */\n}\n\n.quantity {\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n\n.qtyLabel {\n font-size: 0.8125rem;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.06em;\n}\n\n.qtyControl {\n display: inline-flex;\n align-items: center;\n border: 1px solid var(--bazaar-color-border-default, rgba(0, 0, 0, 0.14));\n border-radius: var(--bazaar-radius-sm, 6px);\n width: fit-content;\n}\n\n.qtyControl button {\n width: 40px;\n height: 40px;\n background: transparent;\n border: none;\n color: var(--bazaar-color-text-primary);\n cursor: pointer;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n font-size: 1rem;\n}\n\n.qtyControl button:disabled {\n opacity: 0.35;\n cursor: not-allowed;\n}\n\n.qtyValue {\n min-width: 36px;\n text-align: center;\n font-size: 0.9375rem;\n font-variant-numeric: tabular-nums;\n}\n\n.inventory {\n margin-top: -4px;\n}\n\n.express {\n display: flex;\n flex-direction: column;\n gap: 8px;\n padding-bottom: 12px;\n border-bottom: 1px solid var(--bazaar-color-border-subtle, rgba(0, 0, 0, 0.06));\n}\n\n.ctaRow {\n display: flex;\n gap: 10px;\n align-items: stretch;\n}\n\n.cta {\n flex: 1;\n padding: 14px 20px;\n border: none;\n border-radius: var(--bazaar-radius-full, 999px);\n background: var(--bazaar-color-text-primary, #1F1C17);\n color: var(--bazaar-color-text-inverse, #FFFFFF);\n font-family: inherit;\n font-weight: 600;\n font-size: 0.9375rem;\n letter-spacing: 0.04em;\n text-transform: uppercase;\n cursor: pointer;\n transition: transform 120ms ease, background 120ms ease;\n}\n\n.cta:hover:not(.ctaDisabled) {\n transform: translateY(-1px);\n}\n\n.ctaDisabled {\n background: var(--bazaar-color-surface-muted, #D9D5CC);\n color: var(--bazaar-color-text-primary);\n cursor: default;\n}\n\n.wishlist {\n width: 52px;\n height: 52px;\n border-radius: 999px;\n border: 1px solid var(--bazaar-color-border-default, rgba(0, 0, 0, 0.14));\n background: var(--bazaar-color-surface-default, #FFFFFF);\n color: var(--bazaar-color-text-primary);\n cursor: pointer;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n transition: transform 120ms ease, color 120ms ease;\n}\n\n.wishlist:hover {\n transform: scale(1.04);\n}\n\n.wishlist[aria-pressed=\"true\"] {\n color: var(--bazaar-color-sale, #873F1C);\n border-color: var(--bazaar-color-sale, #873F1C);\n}\n\n.reassurance {\n padding-top: 12px;\n border-top: 1px solid var(--bazaar-color-border-subtle, rgba(0, 0, 0, 0.06));\n}\n","import { useState, type HTMLAttributes, type ReactNode } from 'react';\nimport { cn } from '../utils/cn';\nimport { PriceBlock } from './PriceBlock';\nimport { ReviewsSummary } from './ReviewsSummary';\nimport { ProductBadge } from './ProductBadge';\nimport { VariantSelector } from './VariantSelector';\nimport { InventoryIndicator } from './InventoryIndicator';\nimport { HeartIcon, HeartFilledIcon, MinusIcon, PlusIcon } from './icons';\nimport type { Product, InventoryState, VariantOption } from './types';\nimport styles from './ProductBuyBox.module.css';\n\nexport interface ProductBuyBoxProps extends HTMLAttributes<HTMLDivElement> {\n product: Product;\n /** Selected variant values keyed by axis name (e.g. { Color: 'sand', Size: 'm' }). */\n selection?: Record<string, string>;\n onVariantChange?: (axisName: string, option: VariantOption) => void;\n inventory?: InventoryState;\n wishlisted?: boolean;\n onWishlistToggle?: (product: Product) => void;\n onAddToCart?: (product: Product, quantity: number) => void;\n /** Optional alternate primary CTA label (e.g. \"Pre-order\", \"Notify me\"). */\n ctaLabel?: string;\n /** Slot below the CTA — commonly used for ShippingReassurance. */\n reassuranceSlot?: ReactNode;\n /** Helper content above variants (e.g. color: \"Sand\"). Auto-generated by default. */\n showQuantity?: boolean;\n /** Render an Express Checkout block (Apple Pay, PayPal, etc.) above the main CTA. */\n expressSlot?: ReactNode;\n}\n\n/**\n * ProductBuyBox — composite that orchestrates PriceBlock, VariantSelectors,\n * quantity, CTAs, and trust signals for a product detail page.\n *\n * Controlled variant selection: pass `selection` + `onVariantChange`. The\n * component does not enforce a \"complete selection required to buy\" rule —\n * wire that in via the parent if needed.\n */\nexport function ProductBuyBox({\n product,\n selection = {},\n onVariantChange,\n inventory,\n wishlisted = false,\n onWishlistToggle,\n onAddToCart,\n ctaLabel,\n reassuranceSlot,\n showQuantity = true,\n expressSlot,\n className,\n ...rest\n}: ProductBuyBoxProps) {\n const [qty, setQty] = useState(1);\n const outOfStock =\n inventory?.status === 'out-of-stock' || product.inStock === false;\n const primaryLabel =\n ctaLabel ??\n (inventory?.status === 'preorder'\n ? 'Pre-order'\n : outOfStock\n ? 'Notify me when back'\n : 'Add to cart');\n\n return (\n <div className={cn(styles.root, className)} {...rest}>\n {product.badges && product.badges.length > 0 && (\n <div className={styles.badges}>\n {product.badges.map((b, i) => (\n <ProductBadge key={i} label={b.label} tone={b.tone} size=\"sm\" />\n ))}\n </div>\n )}\n\n {product.brand && <span className={styles.brand}>{product.brand}</span>}\n <h1 className={styles.title}>{product.name}</h1>\n {product.tagline && <p className={styles.tagline}>{product.tagline}</p>}\n\n <div className={styles.meta}>\n <PriceBlock\n price={product.price}\n compareAtPrice={product.compareAtPrice}\n size=\"lg\"\n />\n {product.rating && (\n <ReviewsSummary\n value={product.rating.value}\n count={product.rating.count}\n size=\"sm\"\n />\n )}\n </div>\n\n {product.variants?.map((axis) => (\n <VariantSelector\n key={axis.name}\n axis={axis}\n value={selection[axis.name]}\n onChange={(o) => onVariantChange?.(axis.name, o)}\n className={styles.variant}\n />\n ))}\n\n {showQuantity && !outOfStock && (\n <div className={styles.quantity}>\n <span className={styles.qtyLabel}>Quantity</span>\n <div className={styles.qtyControl}>\n <button\n type=\"button\"\n onClick={() => setQty((q) => Math.max(1, q - 1))}\n aria-label=\"Decrease quantity\"\n disabled={qty <= 1}\n >\n <MinusIcon />\n </button>\n <span className={styles.qtyValue} aria-live=\"polite\">\n {qty}\n </span>\n <button\n type=\"button\"\n onClick={() => setQty((q) => q + 1)}\n aria-label=\"Increase quantity\"\n >\n <PlusIcon />\n </button>\n </div>\n </div>\n )}\n\n {inventory && (\n <InventoryIndicator state={inventory} className={styles.inventory} />\n )}\n\n {expressSlot && <div className={styles.express}>{expressSlot}</div>}\n\n <div className={styles.ctaRow}>\n <button\n type=\"button\"\n className={cn(styles.cta, outOfStock && styles.ctaDisabled)}\n onClick={() => onAddToCart?.(product, qty)}\n >\n {primaryLabel}\n </button>\n {onWishlistToggle && (\n <button\n type=\"button\"\n className={styles.wishlist}\n aria-label={wishlisted ? 'Remove from wishlist' : 'Add to wishlist'}\n aria-pressed={wishlisted}\n onClick={() => onWishlistToggle(product)}\n >\n {wishlisted ? <HeartFilledIcon /> : <HeartIcon />}\n </button>\n )}\n </div>\n\n {reassuranceSlot && <div className={styles.reassurance}>{reassuranceSlot}</div>}\n </div>\n );\n}\n",".root {\n display: flex;\n flex-direction: column;\n font-family: var(--bazaar-font-family-sans);\n color: var(--bazaar-color-text-primary);\n border-top: 1px solid var(--bazaar-color-border-subtle, rgba(0, 0, 0, 0.08));\n}\n\n.section {\n border-bottom: 1px solid var(--bazaar-color-border-subtle, rgba(0, 0, 0, 0.08));\n}\n\n.header {\n width: 100%;\n padding: 16px 4px;\n background: transparent;\n border: none;\n display: flex;\n align-items: center;\n justify-content: space-between;\n cursor: pointer;\n font-family: inherit;\n color: inherit;\n}\n\n.title {\n font-size: 0.9375rem;\n font-weight: 500;\n letter-spacing: 0.02em;\n}\n\n.caret {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 24px;\n height: 24px;\n color: var(--bazaar-color-text-muted);\n transition: transform 180ms ease;\n}\n\n.caretOpen {\n transform: rotate(180deg);\n}\n\n.body {\n padding: 0 4px 20px;\n font-size: 0.875rem;\n line-height: 1.6;\n color: var(--bazaar-color-text-primary);\n}\n","import { useState, type HTMLAttributes, type ReactNode } from 'react';\nimport { cn } from '../utils/cn';\nimport { ChevronDownIcon } from './icons';\nimport styles from './ProductDetailsAccordion.module.css';\n\nexport interface ProductDetailsSection {\n id: string;\n title: string;\n /** Rendered content — body copy, spec tables, care instructions, etc. */\n content: ReactNode;\n /** Start expanded. */\n defaultOpen?: boolean;\n}\n\nexport interface ProductDetailsAccordionProps extends HTMLAttributes<HTMLDivElement> {\n sections: ProductDetailsSection[];\n /** Allow multiple sections open at once (default true). */\n allowMultiple?: boolean;\n}\n\n/**\n * ProductDetailsAccordion — stacked disclosure sections for long-form PDP\n * content: description, materials, care, shipping, returns.\n */\nexport function ProductDetailsAccordion({\n sections,\n allowMultiple = true,\n className,\n ...rest\n}: ProductDetailsAccordionProps) {\n const initial = new Set(\n sections.filter((s) => s.defaultOpen).map((s) => s.id),\n );\n const [open, setOpen] = useState<Set<string>>(initial);\n\n const toggle = (id: string) => {\n setOpen((prev) => {\n const next = new Set(allowMultiple ? prev : []);\n if (prev.has(id)) next.delete(id);\n else next.add(id);\n return next;\n });\n };\n\n return (\n <div className={cn(styles.root, className)} {...rest}>\n {sections.map((s) => {\n const isOpen = open.has(s.id);\n return (\n <section key={s.id} className={styles.section}>\n <button\n type=\"button\"\n className={styles.header}\n aria-expanded={isOpen}\n aria-controls={`accordion-body-${s.id}`}\n onClick={() => toggle(s.id)}\n >\n <span className={styles.title}>{s.title}</span>\n <span className={cn(styles.caret, isOpen && styles.caretOpen)} aria-hidden>\n <ChevronDownIcon />\n </span>\n </button>\n {isOpen && (\n <div id={`accordion-body-${s.id}`} className={styles.body}>\n {s.content}\n </div>\n )}\n </section>\n );\n })}\n </div>\n );\n}\n",".root {\n font-family: var(--bazaar-font-family-sans);\n color: var(--bazaar-color-text-primary);\n}\n\n.header {\n display: grid;\n grid-template-columns: auto 1fr auto;\n align-items: start;\n gap: 32px;\n padding-bottom: 20px;\n border-bottom: 1px solid var(--bazaar-color-border-subtle, rgba(0, 0, 0, 0.08));\n}\n\n@media (max-width: 640px) {\n .header {\n grid-template-columns: 1fr;\n }\n}\n\n.summary {\n display: flex;\n flex-direction: column;\n gap: 4px;\n}\n\n.summaryValue {\n font-family: var(--bazaar-font-family-display, var(--bazaar-font-family-sans));\n font-size: 2.25rem;\n font-weight: 500;\n line-height: 1;\n color: var(--bazaar-color-text-primary);\n}\n\n.distribution {\n display: flex;\n flex-direction: column;\n gap: 6px;\n min-width: 220px;\n}\n\n.distRow {\n display: grid;\n grid-template-columns: 32px 1fr 32px;\n align-items: center;\n gap: 10px;\n}\n\n.distLabel {\n font-size: 0.8125rem;\n color: var(--bazaar-color-text-muted);\n}\n\n.distBar {\n position: relative;\n height: 6px;\n border-radius: 999px;\n background: var(--bazaar-color-surface-subtle, #F4F2EC);\n overflow: hidden;\n}\n\n.distFill {\n display: block;\n height: 100%;\n background: var(--bazaar-color-text-primary, #1F1C17);\n border-radius: inherit;\n}\n\n.distCount {\n font-size: 0.75rem;\n color: var(--bazaar-color-text-muted);\n text-align: right;\n font-variant-numeric: tabular-nums;\n}\n\n.write {\n align-self: start;\n padding: 10px 16px;\n border-radius: var(--bazaar-radius-full, 999px);\n border: 1px solid var(--bazaar-color-text-primary, #1F1C17);\n background: transparent;\n color: var(--bazaar-color-text-primary);\n font-family: inherit;\n font-weight: 500;\n font-size: 0.8125rem;\n letter-spacing: 0.04em;\n text-transform: uppercase;\n cursor: pointer;\n}\n\n.list {\n list-style: none;\n padding: 0;\n margin: 0;\n display: flex;\n flex-direction: column;\n}\n\n.item {\n padding: 20px 0;\n border-bottom: 1px solid var(--bazaar-color-border-subtle, rgba(0, 0, 0, 0.06));\n}\n\n.itemHeader {\n display: flex;\n align-items: center;\n gap: 10px;\n margin-bottom: 4px;\n}\n\n.stars {\n display: inline-flex;\n gap: 2px;\n color: var(--bazaar-color-brand-primary-700, #7A5A30);\n}\n\n.itemTitle {\n font-size: 0.9375rem;\n font-weight: 500;\n}\n\n.itemMeta {\n display: flex;\n flex-wrap: wrap;\n gap: 10px;\n font-size: 0.75rem;\n color: var(--bazaar-color-text-muted);\n margin-bottom: 8px;\n}\n\n.itemAuthor {\n font-weight: 500;\n color: var(--bazaar-color-text-primary);\n}\n\n.verified {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n color: #4A7C59;\n}\n\n.itemDate {\n color: var(--bazaar-color-text-muted);\n}\n\n.itemBody {\n margin: 0;\n font-size: 0.875rem;\n line-height: 1.55;\n}\n\n.helpful {\n margin-top: 10px;\n font-size: 0.75rem;\n color: var(--bazaar-color-text-muted);\n}\n\n.more {\n margin-top: 20px;\n padding: 12px 20px;\n width: 100%;\n background: transparent;\n border: 1px solid var(--bazaar-color-border-default, rgba(0, 0, 0, 0.14));\n border-radius: var(--bazaar-radius-sm, 6px);\n font-family: inherit;\n font-weight: 500;\n font-size: 0.875rem;\n cursor: pointer;\n}\n","import { useMemo, useState, type HTMLAttributes } from 'react';\nimport { cn } from '../utils/cn';\nimport { ReviewsSummary } from './ReviewsSummary';\nimport { StarIcon, CheckIcon } from './icons';\nimport type { RatingSummary, Review } from './types';\nimport styles from './ReviewsList.module.css';\n\nexport interface ReviewsListProps extends HTMLAttributes<HTMLDivElement> {\n summary: RatingSummary;\n reviews: Review[];\n /** Distribution — counts keyed 1..5. Used for the histogram. */\n distribution?: Record<1 | 2 | 3 | 4 | 5, number>;\n onWriteReview?: () => void;\n /** Max reviews shown before \"Show more\" — 0 disables the limit. */\n pageSize?: number;\n}\n\nfunction Stars({ value }: { value: number }) {\n return (\n <span className={styles.stars} aria-hidden>\n {[1, 2, 3, 4, 5].map((i) => (\n <StarIcon\n key={i}\n width={14}\n height={14}\n style={{ opacity: i <= Math.round(value) ? 1 : 0.25 }}\n />\n ))}\n </span>\n );\n}\n\n/**\n * ReviewsList — aggregate rating, star-distribution histogram, and paged\n * review feed. Presentational only — filtering/sorting live upstream.\n */\nexport function ReviewsList({\n summary,\n reviews,\n distribution,\n onWriteReview,\n pageSize = 4,\n className,\n ...rest\n}: ReviewsListProps) {\n const [shown, setShown] = useState(pageSize || reviews.length);\n const visible = useMemo(\n () => (pageSize ? reviews.slice(0, shown) : reviews),\n [reviews, shown, pageSize],\n );\n\n const dist = distribution ?? { 1: 0, 2: 0, 3: 0, 4: 0, 5: 0 };\n const totalForDist = Object.values(dist).reduce((a, b) => a + b, 0) || 1;\n\n return (\n <div className={cn(styles.root, className)} {...rest}>\n <div className={styles.header}>\n <div className={styles.summary}>\n <div className={styles.summaryValue}>{summary.value.toFixed(1)}</div>\n <ReviewsSummary value={summary.value} count={summary.count} size=\"sm\" />\n </div>\n\n {distribution && (\n <div className={styles.distribution} role=\"list\">\n {[5, 4, 3, 2, 1].map((star) => {\n const n = dist[star as 1 | 2 | 3 | 4 | 5] ?? 0;\n const pct = Math.round((n / totalForDist) * 100);\n return (\n <div key={star} className={styles.distRow} role=\"listitem\">\n <span className={styles.distLabel}>{star}★</span>\n <span className={styles.distBar}>\n <span className={styles.distFill} style={{ width: `${pct}%` }} />\n </span>\n <span className={styles.distCount}>{n}</span>\n </div>\n );\n })}\n </div>\n )}\n\n {onWriteReview && (\n <button type=\"button\" className={styles.write} onClick={onWriteReview}>\n Write a review\n </button>\n )}\n </div>\n\n <ul className={styles.list}>\n {visible.map((r) => (\n <li key={r.id} className={styles.item}>\n <div className={styles.itemHeader}>\n <Stars value={r.rating} />\n {r.title && <span className={styles.itemTitle}>{r.title}</span>}\n </div>\n <div className={styles.itemMeta}>\n <span className={styles.itemAuthor}>{r.author}</span>\n {r.verified && (\n <span className={styles.verified}>\n <CheckIcon width={12} height={12} />\n Verified buyer\n </span>\n )}\n <span className={styles.itemDate}>{r.date}</span>\n </div>\n <p className={styles.itemBody}>{r.body}</p>\n {r.helpful !== undefined && (\n <div className={styles.helpful}>Helpful · {r.helpful}</div>\n )}\n </li>\n ))}\n </ul>\n\n {pageSize > 0 && shown < reviews.length && (\n <button\n type=\"button\"\n className={styles.more}\n onClick={() => setShown((s) => s + pageSize)}\n >\n Show more reviews\n </button>\n )}\n </div>\n );\n}\n",".root {\n font-family: var(--bazaar-font-family-sans);\n color: var(--bazaar-color-text-primary);\n display: flex;\n flex-direction: column;\n gap: 20px;\n}\n\n.header {\n display: flex;\n align-items: flex-start;\n justify-content: space-between;\n gap: 20px;\n}\n\n.title {\n font-family: var(--bazaar-font-family-display, var(--bazaar-font-family-sans));\n font-size: 1.25rem;\n font-weight: 500;\n margin: 0 0 6px;\n}\n\n.intro {\n font-size: 0.875rem;\n line-height: 1.5;\n color: var(--bazaar-color-text-muted);\n margin: 0;\n max-width: 56ch;\n}\n\n.units {\n display: inline-flex;\n border: 1px solid var(--bazaar-color-border-default, rgba(0, 0, 0, 0.14));\n border-radius: var(--bazaar-radius-full, 999px);\n padding: 2px;\n}\n\n.unitBtn {\n padding: 6px 14px;\n border: none;\n background: transparent;\n color: var(--bazaar-color-text-primary);\n font-family: inherit;\n font-size: 0.8125rem;\n border-radius: 999px;\n cursor: pointer;\n}\n\n.unitBtnActive {\n background: var(--bazaar-color-text-primary, #1F1C17);\n color: var(--bazaar-color-text-inverse, #FFFFFF);\n}\n\n.illustration {\n padding: 20px;\n border-radius: var(--bazaar-radius-md, 10px);\n background: var(--bazaar-color-surface-subtle, #F4F2EC);\n display: flex;\n align-items: center;\n justify-content: center;\n}\n\n.tableWrap {\n overflow-x: auto;\n}\n\n.table {\n width: 100%;\n border-collapse: collapse;\n font-size: 0.875rem;\n}\n\n.table th,\n.table td {\n padding: 10px 12px;\n text-align: left;\n border-bottom: 1px solid var(--bazaar-color-border-subtle, rgba(0, 0, 0, 0.08));\n}\n\n.table thead th {\n font-weight: 600;\n font-size: 0.75rem;\n letter-spacing: 0.06em;\n text-transform: uppercase;\n color: var(--bazaar-color-text-muted);\n border-bottom-color: var(--bazaar-color-border-default, rgba(0, 0, 0, 0.14));\n}\n\n.colLabel {\n display: block;\n}\n\n.colNote {\n display: block;\n font-size: 0.6875rem;\n font-weight: 400;\n color: var(--bazaar-color-text-muted);\n text-transform: none;\n letter-spacing: 0;\n margin-top: 2px;\n}\n\n.rowLabel {\n font-weight: 600;\n background: var(--bazaar-color-surface-subtle, #F4F2EC);\n}\n\n.cornerCell {\n background: var(--bazaar-color-surface-subtle, #F4F2EC);\n border-bottom-color: var(--bazaar-color-border-default, rgba(0, 0, 0, 0.14));\n}\n","import { useState, type HTMLAttributes, type ReactNode } from 'react';\nimport { cn } from '../utils/cn';\nimport styles from './SizeGuide.module.css';\n\nexport interface SizeGuideColumn {\n /** Column header, e.g. \"Chest\", \"Waist\". */\n label: string;\n /** Optional note shown below the label. */\n note?: string;\n}\n\nexport interface SizeGuideRow {\n /** Row label — e.g. size name \"S\". */\n size: string;\n /** Values by column index, aligned with `columns`. */\n values: (string | number)[];\n}\n\nexport interface SizeGuideUnit {\n id: string;\n label: string;\n}\n\nexport interface SizeGuideProps extends HTMLAttributes<HTMLDivElement> {\n title?: string;\n /** Short intro copy. */\n intro?: ReactNode;\n columns: SizeGuideColumn[];\n /** Map of unit id (e.g. \"in\", \"cm\") -> rows. */\n rowsByUnit: Record<string, SizeGuideRow[]>;\n units?: SizeGuideUnit[];\n defaultUnit?: string;\n /** Optional illustration/diagram slot. */\n illustration?: ReactNode;\n}\n\n/**\n * SizeGuide — measurement table with unit toggle.\n *\n * Intended to render inside a modal, drawer, or accordion. Accepts rows\n * keyed by unit so \"in ↔ cm\" switching is instant and doesn't require\n * re-computing.\n */\nexport function SizeGuide({\n title = 'Size guide',\n intro,\n columns,\n rowsByUnit,\n units = [\n { id: 'in', label: 'in' },\n { id: 'cm', label: 'cm' },\n ],\n defaultUnit,\n illustration,\n className,\n ...rest\n}: SizeGuideProps) {\n const firstUnit = defaultUnit ?? units[0]?.id ?? 'in';\n const [unit, setUnit] = useState(firstUnit);\n const rows = rowsByUnit[unit] ?? [];\n\n return (\n <div className={cn(styles.root, className)} {...rest}>\n <div className={styles.header}>\n <div>\n <h2 className={styles.title}>{title}</h2>\n {intro && <p className={styles.intro}>{intro}</p>}\n </div>\n {units.length > 1 && (\n <div className={styles.units} role=\"radiogroup\" aria-label=\"Units\">\n {units.map((u) => (\n <button\n key={u.id}\n type=\"button\"\n role=\"radio\"\n aria-checked={unit === u.id}\n className={cn(styles.unitBtn, unit === u.id && styles.unitBtnActive)}\n onClick={() => setUnit(u.id)}\n >\n {u.label}\n </button>\n ))}\n </div>\n )}\n </div>\n\n {illustration && <div className={styles.illustration}>{illustration}</div>}\n\n <div className={styles.tableWrap}>\n <table className={styles.table}>\n <thead>\n <tr>\n <th className={styles.cornerCell} />\n {columns.map((c, i) => (\n <th key={i}>\n <span className={styles.colLabel}>{c.label}</span>\n {c.note && <span className={styles.colNote}>{c.note}</span>}\n </th>\n ))}\n </tr>\n </thead>\n <tbody>\n {rows.map((r) => (\n <tr key={r.size}>\n <th scope=\"row\" className={styles.rowLabel}>{r.size}</th>\n {r.values.map((v, i) => (\n <td key={i}>{v}</td>\n ))}\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n </div>\n );\n}\n",".root {\n display: flex;\n flex-direction: column;\n gap: 16px;\n padding: 20px;\n border: 1px solid var(--bazaar-color-border-subtle, rgba(0, 0, 0, 0.08));\n border-radius: var(--bazaar-radius-lg, 12px);\n background: var(--bazaar-color-surface-default, #FFFFFF);\n font-family: var(--bazaar-font-family-sans);\n color: var(--bazaar-color-text-primary);\n}\n\n.title {\n font-size: 1rem;\n font-weight: 600;\n margin: 0;\n}\n\n.row {\n display: flex;\n align-items: flex-start;\n gap: 8px;\n flex-wrap: wrap;\n}\n\n.slot {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 8px;\n position: relative;\n width: 96px;\n}\n\n.tile {\n position: relative;\n width: 100%;\n padding: 0;\n border: 1.5px solid transparent;\n border-radius: var(--bazaar-radius-md, 10px);\n background: var(--bazaar-color-surface-subtle, #F4F2EC);\n cursor: pointer;\n overflow: hidden;\n transition: border-color 120ms ease;\n}\n\n.tile:hover:not(:disabled) {\n border-color: var(--bazaar-color-border-default, rgba(0, 0, 0, 0.14));\n}\n\n.tileActive {\n border-color: var(--bazaar-color-text-primary);\n}\n\n.tile:disabled {\n cursor: default;\n}\n\n.media {\n border-radius: inherit;\n}\n\n.check {\n position: absolute;\n top: 6px;\n right: 6px;\n width: 20px;\n height: 20px;\n border-radius: 999px;\n border: 1.5px solid rgba(0, 0, 0, 0.2);\n background: rgba(255, 255, 255, 0.9);\n display: inline-flex;\n align-items: center;\n justify-content: center;\n color: var(--bazaar-color-text-primary);\n}\n\n.checkActive {\n background: var(--bazaar-color-text-primary, #1F1C17);\n color: var(--bazaar-color-text-inverse, #FFFFFF);\n border-color: var(--bazaar-color-text-primary);\n}\n\n.meta {\n display: flex;\n flex-direction: column;\n gap: 2px;\n text-align: center;\n}\n\n.name {\n font-size: 0.75rem;\n line-height: 1.3;\n display: -webkit-box;\n -webkit-box-orient: vertical;\n -webkit-line-clamp: 2;\n overflow: hidden;\n}\n\n.price {\n font-size: 0.75rem;\n font-weight: 600;\n font-variant-numeric: tabular-nums;\n}\n\n.plus {\n position: absolute;\n top: 40px;\n right: -16px;\n width: 20px;\n height: 20px;\n border-radius: 999px;\n background: var(--bazaar-color-surface-default, #FFFFFF);\n border: 1px solid var(--bazaar-color-border-subtle, rgba(0, 0, 0, 0.1));\n color: var(--bazaar-color-text-muted);\n display: inline-flex;\n align-items: center;\n justify-content: center;\n}\n\n.summary {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 16px;\n padding-top: 12px;\n border-top: 1px solid var(--bazaar-color-border-subtle, rgba(0, 0, 0, 0.08));\n flex-wrap: wrap;\n}\n\n.summaryText {\n display: flex;\n flex-direction: column;\n gap: 2px;\n}\n\n.summaryLabel {\n font-size: 0.75rem;\n text-transform: uppercase;\n letter-spacing: 0.06em;\n color: var(--bazaar-color-text-muted);\n}\n\n.summaryPrices {\n display: flex;\n align-items: baseline;\n gap: 8px;\n flex-wrap: wrap;\n}\n\n.strikethrough {\n font-size: 0.875rem;\n text-decoration: line-through;\n color: var(--bazaar-color-text-muted);\n font-variant-numeric: tabular-nums;\n}\n\n.total {\n font-size: 1.25rem;\n font-weight: 600;\n font-variant-numeric: tabular-nums;\n}\n\n.saving {\n font-size: 0.75rem;\n color: var(--bazaar-color-sale, #873F1C);\n font-weight: 500;\n}\n\n.cta {\n padding: 12px 20px;\n border: none;\n border-radius: var(--bazaar-radius-full, 999px);\n background: var(--bazaar-color-text-primary, #1F1C17);\n color: var(--bazaar-color-text-inverse, #FFFFFF);\n font-family: inherit;\n font-weight: 600;\n font-size: 0.8125rem;\n letter-spacing: 0.04em;\n text-transform: uppercase;\n cursor: pointer;\n}\n\n.cta:disabled {\n background: var(--bazaar-color-surface-muted, #D9D5CC);\n cursor: not-allowed;\n}\n","import { useMemo, useState, type HTMLAttributes } from 'react';\nimport { cn } from '../utils/cn';\nimport { MediaPlaceholder } from './MediaPlaceholder';\nimport { formatMoney } from './money';\nimport { CheckIcon, PlusIcon } from './icons';\nimport type { Money, Product } from './types';\nimport styles from './BundleModule.module.css';\n\nexport interface BundleItem {\n product: Product;\n /** If true, user cannot deselect this item (the anchor product). */\n required?: boolean;\n /** Start selected (default true). */\n defaultSelected?: boolean;\n}\n\nexport interface BundleModuleProps extends HTMLAttributes<HTMLDivElement> {\n title?: string;\n items: BundleItem[];\n /** Percent discount applied to the bundle total (e.g. 10 for 10% off). */\n discountPercent?: number;\n /** Fixed amount bundled price — overrides discountPercent. */\n bundlePrice?: Money;\n onAddBundle?: (selected: Product[]) => void;\n ctaLabel?: string;\n}\n\n/**\n * BundleModule — \"frequently bought together\" / outfit-builder block.\n *\n * Renders media tiles joined by plus glyphs, each with a checkbox-style\n * toggle, and a summarised bundle price with discount relative to the sum\n * of individual prices.\n */\nexport function BundleModule({\n title = 'Complete the look',\n items,\n discountPercent,\n bundlePrice,\n onAddBundle,\n ctaLabel = 'Add bundle to cart',\n className,\n ...rest\n}: BundleModuleProps) {\n const [selected, setSelected] = useState<Set<string>>(\n () =>\n new Set(\n items\n .filter((i) => i.required || i.defaultSelected !== false)\n .map((i) => i.product.id),\n ),\n );\n\n const toggle = (item: BundleItem) => {\n if (item.required) return;\n setSelected((prev) => {\n const next = new Set(prev);\n if (next.has(item.product.id)) next.delete(item.product.id);\n else next.add(item.product.id);\n return next;\n });\n };\n\n const currency = items[0]?.product.price.currency ?? 'USD';\n\n const totals = useMemo(() => {\n const chosen = items.filter((i) => selected.has(i.product.id));\n const sum = chosen.reduce((acc, i) => acc + i.product.price.amount, 0);\n const discounted = bundlePrice\n ? bundlePrice.amount\n : discountPercent\n ? sum * (1 - discountPercent / 100)\n : sum;\n return { subtotal: sum, total: discounted, chosen: chosen.map((i) => i.product) };\n }, [items, selected, discountPercent, bundlePrice]);\n\n const subtotalMoney: Money = { amount: totals.subtotal, currency };\n const totalMoney: Money = { amount: totals.total, currency };\n const savings = totals.subtotal - totals.total;\n\n return (\n <div className={cn(styles.root, className)} {...rest}>\n <h3 className={styles.title}>{title}</h3>\n\n <div className={styles.row}>\n {items.map((item, i) => {\n const checked = selected.has(item.product.id);\n return (\n <div key={item.product.id} className={styles.slot}>\n <button\n type=\"button\"\n className={cn(styles.tile, checked && styles.tileActive)}\n aria-pressed={checked}\n onClick={() => toggle(item)}\n disabled={item.required}\n >\n <MediaPlaceholder\n src={item.product.images[0]?.src}\n alt={item.product.images[0]?.alt ?? item.product.name}\n seed={item.product.images[0]?.seed}\n aspectRatio=\"1 / 1\"\n className={styles.media}\n />\n <span className={cn(styles.check, checked && styles.checkActive)}>\n {checked ? <CheckIcon width={14} height={14} /> : null}\n </span>\n </button>\n <div className={styles.meta}>\n <span className={styles.name}>{item.product.name}</span>\n <span className={styles.price}>{formatMoney(item.product.price)}</span>\n </div>\n {i < items.length - 1 && (\n <span className={styles.plus} aria-hidden>\n <PlusIcon width={16} height={16} />\n </span>\n )}\n </div>\n );\n })}\n </div>\n\n <div className={styles.summary}>\n <div className={styles.summaryText}>\n <span className={styles.summaryLabel}>Bundle total</span>\n <div className={styles.summaryPrices}>\n {savings > 0 && (\n <span className={styles.strikethrough}>{formatMoney(subtotalMoney)}</span>\n )}\n <span className={styles.total}>{formatMoney(totalMoney)}</span>\n {savings > 0 && (\n <span className={styles.saving}>Save {formatMoney({ amount: savings, currency })}</span>\n )}\n </div>\n </div>\n <button\n type=\"button\"\n className={styles.cta}\n onClick={() => onAddBundle?.(totals.chosen)}\n disabled={totals.chosen.length === 0}\n >\n {ctaLabel}\n </button>\n </div>\n </div>\n );\n}\n",".root {\n position: sticky;\n bottom: 0;\n left: 0;\n right: 0;\n z-index: 40;\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 10px 14px;\n background: var(--bazaar-color-surface-default, #FFFFFF);\n border-top: 1px solid var(--bazaar-color-border-subtle, rgba(0, 0, 0, 0.08));\n box-shadow: 0 -8px 24px rgba(0, 0, 0, 0.06);\n font-family: var(--bazaar-font-family-sans);\n color: var(--bazaar-color-text-primary);\n}\n\n/* Hide on larger viewports unless .alwaysVisible */\n@media (min-width: 768px) {\n .root:not(.alwaysVisible) {\n display: none;\n }\n}\n\n.thumb {\n width: 44px;\n flex: 0 0 44px;\n border-radius: var(--bazaar-radius-sm, 6px);\n overflow: hidden;\n}\n\n.thumbMedia {\n border-radius: inherit;\n}\n\n.info {\n flex: 1;\n min-width: 0;\n display: flex;\n flex-direction: column;\n gap: 2px;\n}\n\n.name {\n font-size: 0.875rem;\n font-weight: 500;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.row {\n display: flex;\n align-items: center;\n gap: 6px;\n font-size: 0.75rem;\n color: var(--bazaar-color-text-muted);\n}\n\n.selection {\n font-size: 0.75rem;\n color: var(--bazaar-color-text-muted);\n}\n\n.cta {\n padding: 12px 18px;\n border: none;\n border-radius: var(--bazaar-radius-full, 999px);\n background: var(--bazaar-color-text-primary, #1F1C17);\n color: var(--bazaar-color-text-inverse, #FFFFFF);\n font-family: inherit;\n font-weight: 600;\n font-size: 0.8125rem;\n letter-spacing: 0.04em;\n text-transform: uppercase;\n cursor: pointer;\n white-space: nowrap;\n}\n\n.cta:disabled {\n background: var(--bazaar-color-surface-muted, #D9D5CC);\n cursor: not-allowed;\n}\n","import type { HTMLAttributes } from 'react';\nimport { cn } from '../utils/cn';\nimport { MediaPlaceholder } from './MediaPlaceholder';\nimport { PriceBlock } from './PriceBlock';\nimport type { Product } from './types';\nimport styles from './StickyMobileATC.module.css';\n\nexport interface StickyMobileATCProps extends HTMLAttributes<HTMLDivElement> {\n product: Product;\n /** Short selection summary, e.g. \"Sand · M\". */\n selectionLabel?: string;\n onAddToCart?: (product: Product) => void;\n ctaLabel?: string;\n /** Disable the CTA (e.g. selection incomplete). */\n disabled?: boolean;\n /** Force-display on larger viewports (bypass the mobile-only media query). */\n alwaysVisible?: boolean;\n}\n\n/**\n * StickyMobileATC — thin bottom-anchored bar for mobile product pages.\n *\n * On viewports < 768px it pins to the bottom of the viewport with a product\n * thumb, price, and primary CTA. On larger screens it hides itself unless\n * `alwaysVisible` is set (useful for stories).\n */\nexport function StickyMobileATC({\n product,\n selectionLabel,\n onAddToCart,\n ctaLabel,\n disabled = false,\n alwaysVisible = false,\n className,\n ...rest\n}: StickyMobileATCProps) {\n const primaryImage = product.images[0];\n return (\n <div\n className={cn(styles.root, alwaysVisible && styles.alwaysVisible, className)}\n role=\"region\"\n aria-label=\"Add to cart\"\n {...rest}\n >\n <div className={styles.thumb}>\n <MediaPlaceholder\n src={primaryImage?.src}\n alt={primaryImage?.alt ?? product.name}\n seed={primaryImage?.seed}\n aspectRatio=\"1 / 1\"\n className={styles.thumbMedia}\n />\n </div>\n <div className={styles.info}>\n <span className={styles.name}>{product.name}</span>\n <div className={styles.row}>\n <PriceBlock\n price={product.price}\n compareAtPrice={product.compareAtPrice}\n size=\"sm\"\n />\n {selectionLabel && <span className={styles.selection}>· {selectionLabel}</span>}\n </div>\n </div>\n <button\n type=\"button\"\n className={styles.cta}\n onClick={() => onAddToCart?.(product)}\n disabled={disabled}\n >\n {ctaLabel ?? 'Add to cart'}\n </button>\n </div>\n );\n}\n",".root {\n display: flex;\n gap: 14px;\n padding: 16px 0;\n font-family: var(--bazaar-font-family-sans);\n color: var(--bazaar-color-text-primary);\n border-bottom: 1px solid var(--bazaar-color-border-subtle, rgba(0, 0, 0, 0.06));\n}\n\n.density-compact {\n padding: 12px 0;\n gap: 12px;\n}\n\n.media {\n width: 84px;\n flex: 0 0 84px;\n border-radius: var(--bazaar-radius-sm, 6px);\n overflow: hidden;\n background: var(--bazaar-color-surface-subtle, #F4F2EC);\n}\n\n.density-compact .media {\n width: 64px;\n flex: 0 0 64px;\n}\n\n.body {\n flex: 1;\n min-width: 0;\n display: flex;\n flex-direction: column;\n gap: 6px;\n}\n\n.header {\n display: flex;\n align-items: flex-start;\n justify-content: space-between;\n gap: 12px;\n}\n\n.titleGroup {\n display: flex;\n flex-direction: column;\n gap: 2px;\n min-width: 0;\n}\n\n.brand {\n font-size: 0.6875rem;\n text-transform: uppercase;\n letter-spacing: 0.08em;\n color: var(--bazaar-color-text-muted);\n}\n\n.title {\n font-size: 0.9375rem;\n font-weight: 500;\n line-height: 1.3;\n display: -webkit-box;\n -webkit-box-orient: vertical;\n -webkit-line-clamp: 2;\n overflow: hidden;\n}\n\n.density-compact .title {\n font-size: 0.875rem;\n}\n\n.lineTotal {\n white-space: nowrap;\n}\n\n.options {\n display: flex;\n flex-wrap: wrap;\n gap: 10px;\n font-size: 0.8125rem;\n color: var(--bazaar-color-text-muted);\n}\n\n.option strong {\n font-weight: 500;\n color: var(--bazaar-color-text-primary);\n}\n\n.actions {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 12px;\n margin-top: 4px;\n}\n\n.qty {\n display: inline-flex;\n align-items: center;\n border: 1px solid var(--bazaar-color-border-default, rgba(0, 0, 0, 0.14));\n border-radius: var(--bazaar-radius-sm, 6px);\n}\n\n.qty button {\n width: 28px;\n height: 28px;\n background: transparent;\n border: none;\n color: var(--bazaar-color-text-primary);\n display: inline-flex;\n align-items: center;\n justify-content: center;\n cursor: pointer;\n}\n\n.qty button:disabled {\n opacity: 0.35;\n cursor: not-allowed;\n}\n\n.qty span {\n min-width: 28px;\n text-align: center;\n font-size: 0.875rem;\n font-variant-numeric: tabular-nums;\n}\n\n.qtyRO {\n font-size: 0.8125rem;\n color: var(--bazaar-color-text-muted);\n}\n\n.linkActions {\n display: flex;\n align-items: center;\n gap: 10px;\n}\n\n.linkAction {\n background: transparent;\n border: none;\n padding: 0;\n color: var(--bazaar-color-text-muted);\n font-family: inherit;\n font-size: 0.8125rem;\n text-decoration: underline;\n cursor: pointer;\n}\n\n.linkAction:hover {\n color: var(--bazaar-color-text-primary);\n}\n\n.remove {\n width: 28px;\n height: 28px;\n background: transparent;\n border: none;\n border-radius: 999px;\n color: var(--bazaar-color-text-muted);\n display: inline-flex;\n align-items: center;\n justify-content: center;\n cursor: pointer;\n}\n\n.remove:hover {\n color: var(--bazaar-color-text-primary);\n background: var(--bazaar-color-surface-subtle, #F4F2EC);\n}\n","import type { HTMLAttributes } from 'react';\nimport { cn } from '../utils/cn';\nimport { MediaPlaceholder } from './MediaPlaceholder';\nimport { PriceBlock } from './PriceBlock';\nimport { MinusIcon, PlusIcon, XIcon } from './icons';\nimport type { CartLine } from './types';\nimport styles from './CartLineItem.module.css';\n\nexport interface CartLineItemProps extends HTMLAttributes<HTMLDivElement> {\n line: CartLine;\n onQuantityChange?: (line: CartLine, next: number) => void;\n onRemove?: (line: CartLine) => void;\n onSaveForLater?: (line: CartLine) => void;\n /** Compact density for mini-cart / drawer. */\n density?: 'default' | 'compact';\n /** Hide per-line price column (used when rendering in a price-free summary). */\n hidePrice?: boolean;\n /** Disable quantity changes (e.g. saved-for-later). */\n readOnlyQuantity?: boolean;\n}\n\n/**\n * CartLineItem — thumbnail + title + option summary + quantity stepper +\n * line total. The visual backbone of MiniCart, CartPage and order summaries.\n */\nexport function CartLineItem({\n line,\n onQuantityChange,\n onRemove,\n onSaveForLater,\n density = 'default',\n hidePrice = false,\n readOnlyQuantity = false,\n className,\n ...rest\n}: CartLineItemProps) {\n const lineTotal = {\n amount: line.price.amount * line.quantity,\n currency: line.price.currency,\n };\n\n return (\n <div\n className={cn(styles.root, styles[`density-${density}`], className)}\n {...rest}\n >\n <div className={styles.media}>\n <MediaPlaceholder\n src={line.image?.src}\n alt={line.image?.alt ?? line.title}\n seed={line.image?.seed}\n aspectRatio=\"1 / 1\"\n />\n </div>\n\n <div className={styles.body}>\n <div className={styles.header}>\n <div className={styles.titleGroup}>\n {line.brand && <span className={styles.brand}>{line.brand}</span>}\n <span className={styles.title}>{line.title}</span>\n </div>\n {!hidePrice && (\n <PriceBlock price={lineTotal} size=\"sm\" className={styles.lineTotal} />\n )}\n </div>\n\n {line.options && line.options.length > 0 && (\n <div className={styles.options}>\n {line.options.map((o, i) => (\n <span key={i} className={styles.option}>\n {o.name}: <strong>{o.value}</strong>\n </span>\n ))}\n </div>\n )}\n\n <div className={styles.actions}>\n {!readOnlyQuantity ? (\n <div className={styles.qty}>\n <button\n type=\"button\"\n aria-label=\"Decrease quantity\"\n onClick={() => onQuantityChange?.(line, Math.max(1, line.quantity - 1))}\n disabled={line.quantity <= 1}\n >\n <MinusIcon width={14} height={14} />\n </button>\n <span aria-live=\"polite\">{line.quantity}</span>\n <button\n type=\"button\"\n aria-label=\"Increase quantity\"\n onClick={() => onQuantityChange?.(line, line.quantity + 1)}\n >\n <PlusIcon width={14} height={14} />\n </button>\n </div>\n ) : (\n <span className={styles.qtyRO}>Qty {line.quantity}</span>\n )}\n\n <div className={styles.linkActions}>\n {onSaveForLater && (\n <button\n type=\"button\"\n className={styles.linkAction}\n onClick={() => onSaveForLater(line)}\n >\n Save for later\n </button>\n )}\n {onRemove && (\n <button\n type=\"button\"\n className={styles.remove}\n aria-label=\"Remove item\"\n onClick={() => onRemove(line)}\n >\n <XIcon width={14} height={14} />\n </button>\n )}\n </div>\n </div>\n </div>\n </div>\n );\n}\n",".root {\n display: grid;\n grid-template-columns: auto 1fr;\n align-items: center;\n gap: 8px 10px;\n padding: 12px 14px;\n border-radius: var(--bazaar-radius-md, 10px);\n background: var(--bazaar-color-surface-subtle, #F4F2EC);\n font-family: var(--bazaar-font-family-sans);\n color: var(--bazaar-color-text-primary);\n}\n\n.size-sm { padding: 10px 12px; }\n\n.icon {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 24px;\n height: 24px;\n border-radius: 999px;\n background: var(--bazaar-color-surface-default, #FFFFFF);\n color: var(--bazaar-color-brand-primary-700, #7A5A30);\n}\n\n.message {\n font-size: 0.875rem;\n font-weight: 500;\n}\n\n.size-sm .message { font-size: 0.8125rem; }\n\n.bar {\n grid-column: 1 / -1;\n display: block;\n width: 100%;\n height: 6px;\n border-radius: 999px;\n background: rgba(0, 0, 0, 0.08);\n overflow: hidden;\n}\n\n.fill {\n display: block;\n height: 100%;\n background: var(--bazaar-color-text-primary, #1F1C17);\n border-radius: inherit;\n transition: width 320ms var(--bazaar-motion-easing-standard, ease);\n}\n\n.unlocked {\n background: rgba(59, 125, 79, 0.12);\n}\n\n.unlocked .icon {\n background: #4A7C59;\n color: #FFFFFF;\n}\n\n.unlocked .fill {\n background: #4A7C59;\n}\n","import type { HTMLAttributes } from 'react';\nimport { cn } from '../utils/cn';\nimport { formatMoney } from './money';\nimport { TruckIcon, CheckIcon } from './icons';\nimport type { Money } from './types';\nimport styles from './FreeShippingMeter.module.css';\n\nexport interface FreeShippingMeterProps extends HTMLAttributes<HTMLDivElement> {\n /** Current cart subtotal. */\n subtotal: Money;\n /** Threshold that unlocks free shipping. */\n threshold: Money;\n /** Override the \"You unlocked free shipping\" message. */\n unlockedMessage?: string;\n /** Override the progress message — receives the remaining Money value. */\n progressMessage?: (remaining: Money) => string;\n size?: 'sm' | 'md';\n}\n\n/**\n * FreeShippingMeter — progress indicator toward a free-shipping threshold.\n *\n * Animates to a green \"unlocked\" state when subtotal >= threshold. Intended\n * for placement above the cart list, in the mini-cart header, or at the top\n * of checkout.\n */\nexport function FreeShippingMeter({\n subtotal,\n threshold,\n unlockedMessage = 'Free shipping unlocked',\n progressMessage,\n size = 'md',\n className,\n ...rest\n}: FreeShippingMeterProps) {\n const pct = Math.min(100, Math.round((subtotal.amount / threshold.amount) * 100));\n const remaining: Money = {\n amount: Math.max(0, threshold.amount - subtotal.amount),\n currency: threshold.currency,\n };\n const unlocked = subtotal.amount >= threshold.amount;\n\n const message = unlocked\n ? unlockedMessage\n : progressMessage\n ? progressMessage(remaining)\n : `You're ${formatMoney(remaining)} away from free shipping`;\n\n return (\n <div\n className={cn(\n styles.root,\n styles[`size-${size}`],\n unlocked && styles.unlocked,\n className,\n )}\n role=\"status\"\n {...rest}\n >\n <span className={styles.icon} aria-hidden>\n {unlocked ? <CheckIcon width={14} height={14} /> : <TruckIcon width={14} height={14} />}\n </span>\n <span className={styles.message}>{message}</span>\n <span className={styles.bar} aria-hidden>\n <span className={styles.fill} style={{ width: `${pct}%` }} />\n </span>\n </div>\n );\n}\n",".root {\n display: flex;\n flex-direction: column;\n gap: 8px;\n font-family: var(--bazaar-font-family-sans);\n color: var(--bazaar-color-text-primary);\n}\n\n.disclosure {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n background: transparent;\n border: none;\n padding: 0;\n color: var(--bazaar-color-text-primary);\n font-family: inherit;\n font-size: 0.875rem;\n text-decoration: underline;\n cursor: pointer;\n}\n\n.applied {\n display: flex;\n flex-direction: column;\n gap: 6px;\n}\n\n.chip {\n display: inline-flex;\n align-items: center;\n gap: 8px;\n padding: 8px 10px;\n border-radius: var(--bazaar-radius-sm, 6px);\n background: rgba(59, 125, 79, 0.1);\n color: #2E5237;\n font-size: 0.8125rem;\n}\n\n.chip strong {\n font-weight: 600;\n letter-spacing: 0.04em;\n}\n\n.chip button {\n margin-left: auto;\n background: transparent;\n border: none;\n padding: 2px;\n color: inherit;\n cursor: pointer;\n display: inline-flex;\n}\n\n.inputRow {\n display: grid;\n grid-template-columns: 1fr auto;\n gap: 8px;\n}\n\n.input {\n padding: 12px 14px;\n border: 1px solid var(--bazaar-color-border-default, rgba(0, 0, 0, 0.14));\n border-radius: var(--bazaar-radius-sm, 6px);\n background: var(--bazaar-color-surface-default, #FFFFFF);\n font-family: inherit;\n font-size: 0.875rem;\n letter-spacing: 0.04em;\n text-transform: uppercase;\n color: var(--bazaar-color-text-primary);\n}\n\n.input:focus {\n outline: none;\n border-color: var(--bazaar-color-text-primary);\n}\n\n.inputError {\n border-color: var(--bazaar-color-sale, #873F1C);\n}\n\n.submit {\n padding: 0 18px;\n border: 1px solid var(--bazaar-color-text-primary);\n border-radius: var(--bazaar-radius-sm, 6px);\n background: var(--bazaar-color-text-primary, #1F1C17);\n color: var(--bazaar-color-text-inverse, #FFFFFF);\n font-family: inherit;\n font-weight: 600;\n font-size: 0.8125rem;\n letter-spacing: 0.04em;\n text-transform: uppercase;\n cursor: pointer;\n}\n\n.submit:disabled {\n background: var(--bazaar-color-surface-muted, #D9D5CC);\n border-color: var(--bazaar-color-surface-muted, #D9D5CC);\n cursor: not-allowed;\n}\n\n.error {\n font-size: 0.75rem;\n color: var(--bazaar-color-sale, #873F1C);\n}\n","import { useState, type FormEvent, type HTMLAttributes } from 'react';\nimport { cn } from '../utils/cn';\nimport { CheckIcon, XIcon, TagIcon } from './icons';\nimport styles from './CouponField.module.css';\n\nexport interface AppliedCoupon {\n code: string;\n /** Display label, e.g. \"10% off entire order\". */\n label: string;\n}\n\nexport interface CouponFieldProps extends Omit<HTMLAttributes<HTMLFormElement>, 'onSubmit'> {\n applied?: AppliedCoupon[];\n onApply?: (code: string) => void | Promise<void>;\n onRemove?: (code: string) => void;\n /** Error state set by the caller after failed validation. */\n error?: string;\n placeholder?: string;\n /** Render as a collapsed \"Have a code?\" link initially. */\n collapsible?: boolean;\n}\n\n/**\n * CouponField — promo/discount code entry with applied-code chips.\n *\n * Controlled error message for async validation. Pair with `collapsible`\n * to tuck the input behind a disclosure link on slimmer summary panels.\n */\nexport function CouponField({\n applied = [],\n onApply,\n onRemove,\n error,\n placeholder = 'Promo code',\n collapsible = false,\n className,\n ...rest\n}: CouponFieldProps) {\n const [code, setCode] = useState('');\n const [expanded, setExpanded] = useState(!collapsible);\n\n const submit = async (e: FormEvent) => {\n e.preventDefault();\n if (!code.trim()) return;\n await onApply?.(code.trim());\n setCode('');\n };\n\n if (collapsible && !expanded) {\n return (\n <button\n type=\"button\"\n className={cn(styles.disclosure, className)}\n onClick={() => setExpanded(true)}\n >\n <TagIcon width={14} height={14} />\n Have a promo code?\n </button>\n );\n }\n\n return (\n <form className={cn(styles.root, className)} onSubmit={submit} {...rest}>\n {applied.length > 0 && (\n <div className={styles.applied}>\n {applied.map((c) => (\n <span key={c.code} className={styles.chip}>\n <CheckIcon width={12} height={12} />\n <span>\n <strong>{c.code}</strong> · {c.label}\n </span>\n {onRemove && (\n <button\n type=\"button\"\n aria-label={`Remove ${c.code}`}\n onClick={() => onRemove(c.code)}\n >\n <XIcon width={12} height={12} />\n </button>\n )}\n </span>\n ))}\n </div>\n )}\n <div className={styles.inputRow}>\n <input\n type=\"text\"\n className={cn(styles.input, error && styles.inputError)}\n placeholder={placeholder}\n value={code}\n onChange={(e) => setCode(e.target.value.toUpperCase())}\n aria-label=\"Promo code\"\n aria-invalid={!!error}\n aria-describedby={error ? 'coupon-error' : undefined}\n />\n <button type=\"submit\" className={styles.submit} disabled={!code.trim()}>\n Apply\n </button>\n </div>\n {error && (\n <span id=\"coupon-error\" className={styles.error}>\n {error}\n </span>\n )}\n </form>\n );\n}\n",".root {\n display: flex;\n flex-direction: column;\n gap: 16px;\n padding: 20px;\n border: 1px solid var(--bazaar-color-border-subtle, rgba(0, 0, 0, 0.08));\n border-radius: var(--bazaar-radius-lg, 12px);\n background: var(--bazaar-color-surface-default, #FFFFFF);\n font-family: var(--bazaar-font-family-sans);\n color: var(--bazaar-color-text-primary);\n}\n\n.density-compact {\n padding: 16px;\n gap: 12px;\n}\n\n.top {\n display: flex;\n flex-direction: column;\n gap: 10px;\n}\n\n.lines {\n display: flex;\n flex-direction: column;\n gap: 8px;\n margin: 0;\n}\n\n.row {\n display: flex;\n align-items: baseline;\n justify-content: space-between;\n gap: 12px;\n font-size: 0.875rem;\n}\n\n.row dt {\n color: var(--bazaar-color-text-muted);\n margin: 0;\n}\n\n.row dd {\n margin: 0;\n font-variant-numeric: tabular-nums;\n text-align: right;\n}\n\n.tone-discount dd {\n color: #2E5237;\n}\n\n.tone-muted dd {\n color: var(--bazaar-color-text-muted);\n}\n\n.note {\n display: block;\n font-size: 0.75rem;\n color: var(--bazaar-color-text-muted);\n margin-top: 2px;\n}\n\n.total {\n display: flex;\n align-items: baseline;\n justify-content: space-between;\n padding-top: 12px;\n border-top: 1px solid var(--bazaar-color-border-subtle, rgba(0, 0, 0, 0.08));\n font-size: 1rem;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.04em;\n}\n\n.totalValue {\n font-size: 1.25rem;\n font-variant-numeric: tabular-nums;\n}\n\n.cta {\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n","import type { HTMLAttributes, ReactNode } from 'react';\nimport { cn } from '../utils/cn';\nimport { formatMoney } from './money';\nimport type { Money } from './types';\nimport styles from './CartSummary.module.css';\n\nexport interface CartSummaryLine {\n id: string;\n label: string;\n value: Money | string;\n /** Render as a discount (green + negative sign). */\n tone?: 'default' | 'discount' | 'muted';\n /** Small helper text below the value, e.g. \"Calculated at checkout\". */\n note?: string;\n}\n\nexport interface CartSummaryProps extends HTMLAttributes<HTMLDivElement> {\n subtotal: Money;\n /** Ordered list of adjustment lines between subtotal and total. */\n lines?: CartSummaryLine[];\n total: Money;\n totalLabel?: string;\n /** Slot for FreeShippingMeter, CouponField, terms copy, etc. */\n children?: ReactNode;\n /** Primary CTA slot (e.g. \"Checkout\" button). */\n ctaSlot?: ReactNode;\n /** Compact density for drawer / mini-cart use. */\n density?: 'default' | 'compact';\n}\n\nfunction renderValue(v: Money | string): string {\n return typeof v === 'string' ? v : formatMoney(v);\n}\n\n/**\n * CartSummary — subtotal, adjustments (shipping, taxes, discounts) and\n * total, plus optional slots for promos, reassurance and the primary CTA.\n */\nexport function CartSummary({\n subtotal,\n lines = [],\n total,\n totalLabel = 'Total',\n children,\n ctaSlot,\n density = 'default',\n className,\n ...rest\n}: CartSummaryProps) {\n return (\n <section\n className={cn(styles.root, styles[`density-${density}`], className)}\n aria-label=\"Order summary\"\n {...rest}\n >\n {children && <div className={styles.top}>{children}</div>}\n\n <dl className={styles.lines}>\n <div className={styles.row}>\n <dt>Subtotal</dt>\n <dd>{formatMoney(subtotal)}</dd>\n </div>\n\n {lines.map((ln) => (\n <div\n key={ln.id}\n className={cn(styles.row, ln.tone && styles[`tone-${ln.tone}`])}\n >\n <dt>{ln.label}</dt>\n <dd>\n <span>{renderValue(ln.value)}</span>\n {ln.note && <span className={styles.note}>{ln.note}</span>}\n </dd>\n </div>\n ))}\n </dl>\n\n <div className={styles.total}>\n <span>{totalLabel}</span>\n <span className={styles.totalValue}>{formatMoney(total)}</span>\n </div>\n\n {ctaSlot && <div className={styles.cta}>{ctaSlot}</div>}\n </section>\n );\n}\n",".root {\n width: 380px;\n max-width: 100%;\n background: var(--bazaar-color-surface-default, #FFFFFF);\n border: 1px solid var(--bazaar-color-border-subtle, rgba(0, 0, 0, 0.08));\n border-radius: var(--bazaar-radius-lg, 12px);\n box-shadow: 0 12px 32px rgba(0, 0, 0, 0.08);\n font-family: var(--bazaar-font-family-sans);\n color: var(--bazaar-color-text-primary);\n display: flex;\n flex-direction: column;\n overflow: hidden;\n}\n\n.header {\n padding: 16px 20px;\n border-bottom: 1px solid var(--bazaar-color-border-subtle, rgba(0, 0, 0, 0.08));\n}\n\n.title {\n font-size: 0.9375rem;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.04em;\n}\n\n.count {\n font-weight: 400;\n color: var(--bazaar-color-text-muted);\n text-transform: none;\n letter-spacing: 0;\n margin-left: 4px;\n}\n\n.top {\n padding: 12px 20px 0;\n}\n\n.list {\n padding: 0 20px;\n max-height: 360px;\n overflow-y: auto;\n}\n\n.footer {\n padding: 16px 20px;\n border-top: 1px solid var(--bazaar-color-border-subtle, rgba(0, 0, 0, 0.08));\n background: var(--bazaar-color-surface-subtle, #F4F2EC);\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n\n.subtotalRow {\n display: flex;\n align-items: baseline;\n justify-content: space-between;\n font-size: 0.9375rem;\n font-weight: 500;\n}\n\n.subtotalValue {\n font-variant-numeric: tabular-nums;\n font-weight: 600;\n}\n\n.footnote {\n margin: 0;\n font-size: 0.75rem;\n color: var(--bazaar-color-text-muted);\n}\n\n.ctaRow {\n display: grid;\n grid-template-columns: 1fr 1fr;\n gap: 8px;\n margin-top: 8px;\n}\n\n.primary,\n.secondary {\n padding: 12px 16px;\n border-radius: var(--bazaar-radius-full, 999px);\n font-family: inherit;\n font-weight: 600;\n font-size: 0.8125rem;\n letter-spacing: 0.04em;\n text-transform: uppercase;\n cursor: pointer;\n}\n\n.primary {\n border: none;\n background: var(--bazaar-color-text-primary, #1F1C17);\n color: var(--bazaar-color-text-inverse, #FFFFFF);\n}\n\n.secondary {\n border: 1px solid var(--bazaar-color-text-primary, #1F1C17);\n background: transparent;\n color: var(--bazaar-color-text-primary);\n}\n\n.empty {\n padding: 48px 24px;\n display: flex;\n flex-direction: column;\n align-items: center;\n text-align: center;\n gap: 8px;\n}\n\n.emptyIcon {\n width: 56px;\n height: 56px;\n border-radius: 999px;\n background: var(--bazaar-color-surface-subtle, #F4F2EC);\n color: var(--bazaar-color-text-muted);\n display: inline-flex;\n align-items: center;\n justify-content: center;\n}\n\n.emptyTitle {\n margin: 8px 0 0;\n font-size: 1rem;\n font-weight: 500;\n}\n\n.emptyBody {\n margin: 0;\n font-size: 0.875rem;\n color: var(--bazaar-color-text-muted);\n max-width: 32ch;\n}\n\n.emptyCta {\n margin-top: 12px;\n padding: 12px 24px;\n border-radius: var(--bazaar-radius-full, 999px);\n border: none;\n background: var(--bazaar-color-text-primary, #1F1C17);\n color: var(--bazaar-color-text-inverse, #FFFFFF);\n font-family: inherit;\n font-weight: 600;\n font-size: 0.8125rem;\n letter-spacing: 0.04em;\n text-transform: uppercase;\n cursor: pointer;\n}\n","import type { HTMLAttributes, ReactNode } from 'react';\nimport { cn } from '../utils/cn';\nimport { CartLineItem } from './CartLineItem';\nimport { formatMoney } from './money';\nimport { BagIcon } from './icons';\nimport type { CartLine, Money } from './types';\nimport styles from './MiniCart.module.css';\n\nexport interface MiniCartProps extends HTMLAttributes<HTMLDivElement> {\n lines: CartLine[];\n subtotal: Money;\n /** Slot above the list — commonly FreeShippingMeter. */\n topSlot?: ReactNode;\n onQuantityChange?: (line: CartLine, next: number) => void;\n onRemove?: (line: CartLine) => void;\n onViewCart?: () => void;\n onCheckout?: () => void;\n /** Empty-state CTA label. */\n emptyCta?: string;\n onEmptyCta?: () => void;\n}\n\n/**\n * MiniCart — dropdown/popover cart summary. Typically rendered inside a\n * CartDrawer or anchored popover from the header bag icon.\n *\n * Handles empty state internally; composes CartLineItem and renders a\n * compact summary footer with view-cart / checkout CTAs.\n */\nexport function MiniCart({\n lines,\n subtotal,\n topSlot,\n onQuantityChange,\n onRemove,\n onViewCart,\n onCheckout,\n emptyCta = 'Start shopping',\n onEmptyCta,\n className,\n ...rest\n}: MiniCartProps) {\n const count = lines.reduce((n, l) => n + l.quantity, 0);\n const empty = lines.length === 0;\n\n return (\n <div className={cn(styles.root, className)} {...rest}>\n <header className={styles.header}>\n <span className={styles.title}>\n Your bag {count > 0 && <span className={styles.count}>({count})</span>}\n </span>\n </header>\n\n {empty ? (\n <div className={styles.empty}>\n <span className={styles.emptyIcon} aria-hidden>\n <BagIcon width={28} height={28} />\n </span>\n <p className={styles.emptyTitle}>Your bag is empty</p>\n <p className={styles.emptyBody}>Saved items and past orders live in your account.</p>\n {onEmptyCta && (\n <button type=\"button\" className={styles.emptyCta} onClick={onEmptyCta}>\n {emptyCta}\n </button>\n )}\n </div>\n ) : (\n <>\n {topSlot && <div className={styles.top}>{topSlot}</div>}\n\n <div className={styles.list} role=\"list\">\n {lines.map((line) => (\n <div key={line.id} role=\"listitem\">\n <CartLineItem\n line={line}\n density=\"compact\"\n onQuantityChange={onQuantityChange}\n onRemove={onRemove}\n />\n </div>\n ))}\n </div>\n\n <footer className={styles.footer}>\n <div className={styles.subtotalRow}>\n <span>Subtotal</span>\n <span className={styles.subtotalValue}>{formatMoney(subtotal)}</span>\n </div>\n <p className={styles.footnote}>Shipping and taxes calculated at checkout.</p>\n <div className={styles.ctaRow}>\n {onViewCart && (\n <button type=\"button\" className={styles.secondary} onClick={onViewCart}>\n View bag\n </button>\n )}\n {onCheckout && (\n <button type=\"button\" className={styles.primary} onClick={onCheckout}>\n Checkout\n </button>\n )}\n </div>\n </footer>\n </>\n )}\n </div>\n );\n}\n",".root {\n position: fixed;\n inset: 0;\n z-index: 60;\n font-family: var(--bazaar-font-family-sans);\n color: var(--bazaar-color-text-primary);\n}\n\n.scrim {\n position: absolute;\n inset: 0;\n background: rgba(12, 14, 18, 0.45);\n animation: fadeIn 180ms var(--bazaar-motion-easing-standard, ease);\n}\n\n.panel {\n position: absolute;\n top: 0;\n bottom: 0;\n max-width: 100vw;\n background: var(--bazaar-color-surface-default, #FFFFFF);\n display: flex;\n flex-direction: column;\n box-shadow: -12px 0 32px rgba(0, 0, 0, 0.12);\n}\n\n.side-right {\n right: 0;\n animation: slideInRight 220ms var(--bazaar-motion-easing-standard, ease);\n}\n\n.side-left {\n left: 0;\n animation: slideInLeft 220ms var(--bazaar-motion-easing-standard, ease);\n box-shadow: 12px 0 32px rgba(0, 0, 0, 0.12);\n}\n\n.header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 16px 20px;\n border-bottom: 1px solid var(--bazaar-color-border-subtle, rgba(0, 0, 0, 0.08));\n}\n\n.title {\n font-family: var(--bazaar-font-family-display, var(--bazaar-font-family-sans));\n font-size: 1rem;\n font-weight: 500;\n letter-spacing: 0.04em;\n text-transform: uppercase;\n}\n\n.close {\n width: 36px;\n height: 36px;\n border-radius: 999px;\n border: 1px solid var(--bazaar-color-border-default, rgba(0, 0, 0, 0.12));\n background: transparent;\n color: var(--bazaar-color-text-primary);\n cursor: pointer;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n}\n\n.body {\n flex: 1;\n overflow-y: auto;\n}\n\n@keyframes fadeIn {\n from { opacity: 0; }\n to { opacity: 1; }\n}\n\n@keyframes slideInRight {\n from { transform: translateX(100%); }\n to { transform: translateX(0); }\n}\n\n@keyframes slideInLeft {\n from { transform: translateX(-100%); }\n to { transform: translateX(0); }\n}\n","import { useEffect, type HTMLAttributes, type ReactNode } from 'react';\nimport { cn } from '../utils/cn';\nimport { XIcon } from './icons';\nimport styles from './CartDrawer.module.css';\n\nexport interface CartDrawerProps extends HTMLAttributes<HTMLDivElement> {\n open: boolean;\n onClose: () => void;\n /** Drawer title — defaults to \"Your bag\". */\n title?: string;\n /** Side of the viewport to pin to. */\n side?: 'right' | 'left';\n /** Drawer width — CSS dimension. */\n width?: string;\n children?: ReactNode;\n}\n\n/**\n * CartDrawer — off-canvas container for MiniCart or custom cart views.\n *\n * Adds a scrim, close affordance, and Escape-to-close. Focus management\n * is the caller's responsibility — pair with your app's focus trap.\n */\nexport function CartDrawer({\n open,\n onClose,\n title = 'Your bag',\n side = 'right',\n width = '420px',\n children,\n className,\n ...rest\n}: CartDrawerProps) {\n useEffect(() => {\n if (!open) return;\n const onKey = (e: KeyboardEvent) => {\n if (e.key === 'Escape') onClose();\n };\n window.addEventListener('keydown', onKey);\n return () => window.removeEventListener('keydown', onKey);\n }, [open, onClose]);\n\n if (!open) return null;\n\n return (\n <div className={cn(styles.root, className)} {...rest}>\n <div\n className={styles.scrim}\n onClick={onClose}\n role=\"presentation\"\n aria-hidden\n />\n <aside\n className={cn(styles.panel, styles[`side-${side}`])}\n role=\"dialog\"\n aria-modal=\"true\"\n aria-label={title}\n style={{ width }}\n >\n <header className={styles.header}>\n <span className={styles.title}>{title}</span>\n <button\n type=\"button\"\n className={styles.close}\n aria-label=\"Close\"\n onClick={onClose}\n >\n <XIcon />\n </button>\n </header>\n <div className={styles.body}>{children}</div>\n </aside>\n </div>\n );\n}\n",".root {\n font-family: var(--bazaar-font-family-sans);\n color: var(--bazaar-color-text-primary);\n display: flex;\n flex-direction: column;\n gap: 24px;\n}\n\n.header {\n display: flex;\n align-items: baseline;\n justify-content: space-between;\n}\n\n.title {\n font-family: var(--bazaar-font-family-display, var(--bazaar-font-family-sans));\n font-size: 1.75rem;\n font-weight: 500;\n margin: 0;\n}\n\n.count {\n font-size: 1rem;\n font-weight: 400;\n color: var(--bazaar-color-text-muted);\n margin-left: 6px;\n}\n\n.grid {\n display: grid;\n grid-template-columns: minmax(0, 1fr) 360px;\n gap: 32px;\n align-items: start;\n}\n\n@media (max-width: 900px) {\n .grid {\n grid-template-columns: 1fr;\n }\n}\n\n.main {\n display: flex;\n flex-direction: column;\n gap: 24px;\n}\n\n.list {\n border-top: 1px solid var(--bazaar-color-border-subtle, rgba(0, 0, 0, 0.06));\n}\n\n.below {\n display: flex;\n flex-direction: column;\n gap: 24px;\n}\n\n.sidebar {\n position: sticky;\n top: 24px;\n display: flex;\n flex-direction: column;\n gap: 16px;\n}\n\n.emptyRoot {\n min-height: 60vh;\n align-items: center;\n justify-content: center;\n}\n\n.empty {\n max-width: 380px;\n margin: 80px auto;\n text-align: center;\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 6px;\n}\n\n.emptyIcon {\n width: 72px;\n height: 72px;\n border-radius: 999px;\n background: var(--bazaar-color-surface-subtle, #F4F2EC);\n color: var(--bazaar-color-text-muted);\n display: inline-flex;\n align-items: center;\n justify-content: center;\n margin-bottom: 8px;\n}\n\n.emptyTitle {\n font-family: var(--bazaar-font-family-display, var(--bazaar-font-family-sans));\n font-size: 1.5rem;\n font-weight: 500;\n margin: 0;\n}\n\n.emptyBody {\n font-size: 0.9375rem;\n color: var(--bazaar-color-text-muted);\n line-height: 1.5;\n margin: 0;\n}\n\n.emptyCta {\n margin-top: 16px;\n padding: 14px 28px;\n border-radius: var(--bazaar-radius-full, 999px);\n border: none;\n background: var(--bazaar-color-text-primary, #1F1C17);\n color: var(--bazaar-color-text-inverse, #FFFFFF);\n font-family: inherit;\n font-weight: 600;\n font-size: 0.8125rem;\n letter-spacing: 0.04em;\n text-transform: uppercase;\n cursor: pointer;\n}\n","import type { HTMLAttributes, ReactNode } from 'react';\nimport { cn } from '../utils/cn';\nimport { CartLineItem } from './CartLineItem';\nimport { BagIcon } from './icons';\nimport type { CartLine } from './types';\nimport styles from './CartPage.module.css';\n\nexport interface CartPageProps extends HTMLAttributes<HTMLDivElement> {\n lines: CartLine[];\n title?: string;\n /** Right-rail slot — typically a CartSummary. */\n sidebar: ReactNode;\n /** Content shown below the lines, above the footer — saved-for-later, cross-sells. */\n below?: ReactNode;\n /** Empty-state CTA. */\n emptyCta?: string;\n onEmptyCta?: () => void;\n onQuantityChange?: (line: CartLine, next: number) => void;\n onRemove?: (line: CartLine) => void;\n onSaveForLater?: (line: CartLine) => void;\n}\n\n/**\n * CartPage — full-width layout for the /cart route. Two-column on desktop\n * (lines + summary rail), stacked on mobile. Renders a friendly empty\n * state when no lines are present.\n */\nexport function CartPage({\n lines,\n title = 'Your bag',\n sidebar,\n below,\n emptyCta = 'Start shopping',\n onEmptyCta,\n onQuantityChange,\n onRemove,\n onSaveForLater,\n className,\n ...rest\n}: CartPageProps) {\n const count = lines.reduce((n, l) => n + l.quantity, 0);\n const empty = lines.length === 0;\n\n if (empty) {\n return (\n <div className={cn(styles.root, styles.emptyRoot, className)} {...rest}>\n <div className={styles.empty}>\n <span className={styles.emptyIcon} aria-hidden>\n <BagIcon width={32} height={32} />\n </span>\n <h1 className={styles.emptyTitle}>Your bag is empty</h1>\n <p className={styles.emptyBody}>\n Browse new arrivals or revisit your wishlist to continue.\n </p>\n {onEmptyCta && (\n <button type=\"button\" className={styles.emptyCta} onClick={onEmptyCta}>\n {emptyCta}\n </button>\n )}\n </div>\n </div>\n );\n }\n\n return (\n <div className={cn(styles.root, className)} {...rest}>\n <header className={styles.header}>\n <h1 className={styles.title}>\n {title} <span className={styles.count}>({count})</span>\n </h1>\n </header>\n\n <div className={styles.grid}>\n <div className={styles.main}>\n <div className={styles.list} role=\"list\">\n {lines.map((line) => (\n <div key={line.id} role=\"listitem\">\n <CartLineItem\n line={line}\n onQuantityChange={onQuantityChange}\n onRemove={onRemove}\n onSaveForLater={onSaveForLater}\n />\n </div>\n ))}\n </div>\n\n {below && <div className={styles.below}>{below}</div>}\n </div>\n\n <aside className={styles.sidebar}>{sidebar}</aside>\n </div>\n </div>\n );\n}\n",".root {\n padding-top: 24px;\n border-top: 1px solid var(--bazaar-color-border-subtle, rgba(0, 0, 0, 0.08));\n font-family: var(--bazaar-font-family-sans);\n color: var(--bazaar-color-text-primary);\n}\n\n.header {\n margin-bottom: 4px;\n}\n\n.title {\n font-family: var(--bazaar-font-family-display, var(--bazaar-font-family-sans));\n font-size: 1.125rem;\n font-weight: 500;\n margin: 0;\n}\n\n.count {\n font-size: 0.875rem;\n font-weight: 400;\n color: var(--bazaar-color-text-muted);\n margin-left: 4px;\n}\n\n.list {\n display: flex;\n flex-direction: column;\n}\n\n.row {\n position: relative;\n}\n\n.move {\n align-self: flex-start;\n margin: -4px 0 16px;\n padding: 0;\n background: transparent;\n border: none;\n color: var(--bazaar-color-text-primary);\n font-family: inherit;\n font-size: 0.8125rem;\n text-decoration: underline;\n cursor: pointer;\n}\n","import type { HTMLAttributes } from 'react';\nimport { cn } from '../utils/cn';\nimport { CartLineItem } from './CartLineItem';\nimport type { CartLine } from './types';\nimport styles from './SaveForLaterList.module.css';\n\nexport interface SaveForLaterListProps extends HTMLAttributes<HTMLDivElement> {\n lines: CartLine[];\n title?: string;\n onMoveToCart?: (line: CartLine) => void;\n onRemove?: (line: CartLine) => void;\n}\n\n/**\n * SaveForLaterList — secondary list below the cart of items the user\n * deferred. Each line swaps its \"Save for later\" action for \"Move to bag\".\n */\nexport function SaveForLaterList({\n lines,\n title = 'Saved for later',\n onMoveToCart,\n onRemove,\n className,\n ...rest\n}: SaveForLaterListProps) {\n if (lines.length === 0) return null;\n\n return (\n <section className={cn(styles.root, className)} aria-label={title} {...rest}>\n <header className={styles.header}>\n <h2 className={styles.title}>\n {title} <span className={styles.count}>({lines.length})</span>\n </h2>\n </header>\n <div className={styles.list} role=\"list\">\n {lines.map((line) => (\n <div key={line.id} role=\"listitem\" className={styles.row}>\n <CartLineItem\n line={line}\n readOnlyQuantity\n onRemove={onRemove}\n />\n {onMoveToCart && (\n <button\n type=\"button\"\n className={styles.move}\n onClick={() => onMoveToCart(line)}\n >\n Move to bag\n </button>\n )}\n </div>\n ))}\n </div>\n </section>\n );\n}\n",".root {\n font-family: var(--bazaar-font-family-sans);\n color: var(--bazaar-color-text-primary);\n display: flex;\n flex-direction: column;\n gap: 12px;\n}\n\n.title {\n font-family: var(--bazaar-font-family-display, var(--bazaar-font-family-sans));\n font-size: 1rem;\n font-weight: 500;\n margin: 0;\n}\n\n.list {\n list-style: none;\n padding: 0;\n margin: 0;\n display: flex;\n flex-direction: column;\n gap: 12px;\n}\n\n.item {\n display: grid;\n grid-template-columns: 64px 1fr auto;\n align-items: center;\n gap: 14px;\n padding: 10px;\n border-radius: var(--bazaar-radius-md, 10px);\n background: var(--bazaar-color-surface-default, #FFFFFF);\n border: 1px solid var(--bazaar-color-border-subtle, rgba(0, 0, 0, 0.06));\n}\n\n.media {\n width: 64px;\n height: 64px;\n padding: 0;\n border: none;\n background: transparent;\n border-radius: var(--bazaar-radius-sm, 6px);\n overflow: hidden;\n cursor: pointer;\n}\n\n.body {\n display: flex;\n flex-direction: column;\n gap: 2px;\n min-width: 0;\n}\n\n.brand {\n font-size: 0.6875rem;\n text-transform: uppercase;\n letter-spacing: 0.08em;\n color: var(--bazaar-color-text-muted);\n}\n\n.name {\n font-size: 0.875rem;\n font-weight: 500;\n line-height: 1.3;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.price {\n font-size: 0.8125rem;\n font-weight: 600;\n font-variant-numeric: tabular-nums;\n}\n\n.add {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n padding: 8px 12px;\n border: 1px solid var(--bazaar-color-text-primary);\n background: transparent;\n color: var(--bazaar-color-text-primary);\n border-radius: var(--bazaar-radius-full, 999px);\n font-family: inherit;\n font-weight: 600;\n font-size: 0.75rem;\n letter-spacing: 0.04em;\n text-transform: uppercase;\n cursor: pointer;\n}\n\n.add:hover {\n background: var(--bazaar-color-text-primary, #1F1C17);\n color: var(--bazaar-color-text-inverse, #FFFFFF);\n}\n","import type { HTMLAttributes } from 'react';\nimport { cn } from '../utils/cn';\nimport { MediaPlaceholder } from './MediaPlaceholder';\nimport { formatMoney } from './money';\nimport { PlusIcon } from './icons';\nimport type { Product } from './types';\nimport styles from './CrossSellStrip.module.css';\n\nexport interface CrossSellStripProps extends HTMLAttributes<HTMLElement> {\n title?: string;\n products: Product[];\n onAdd?: (product: Product) => void;\n onSelectProduct?: (product: Product) => void;\n}\n\n/**\n * CrossSellStrip — compact \"You might also like\" row used inline in a cart\n * or drawer. Each item exposes a one-tap add action (no variant pickers).\n */\nexport function CrossSellStrip({\n title = 'You might also like',\n products,\n onAdd,\n onSelectProduct,\n className,\n ...rest\n}: CrossSellStripProps) {\n if (products.length === 0) return null;\n return (\n <section className={cn(styles.root, className)} aria-label={title} {...rest}>\n <h3 className={styles.title}>{title}</h3>\n <ul className={styles.list}>\n {products.map((p) => (\n <li key={p.id} className={styles.item}>\n <button\n type=\"button\"\n className={styles.media}\n onClick={() => onSelectProduct?.(p)}\n aria-label={p.name}\n >\n <MediaPlaceholder\n src={p.images[0]?.src}\n alt={p.images[0]?.alt ?? p.name}\n seed={p.images[0]?.seed}\n aspectRatio=\"1 / 1\"\n />\n </button>\n <div className={styles.body}>\n {p.brand && <span className={styles.brand}>{p.brand}</span>}\n <span className={styles.name}>{p.name}</span>\n <span className={styles.price}>{formatMoney(p.price)}</span>\n </div>\n {onAdd && (\n <button\n type=\"button\"\n className={styles.add}\n aria-label={`Add ${p.name}`}\n onClick={() => onAdd(p)}\n >\n <PlusIcon width={14} height={14} />\n <span>Add</span>\n </button>\n )}\n </li>\n ))}\n </ul>\n </section>\n );\n}\n",".root {\n font-family: var(--bazaar-font-family-sans);\n color: var(--bazaar-color-text-primary);\n}\n\n.list {\n list-style: none;\n padding: 0;\n margin: 0;\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 8px;\n}\n\n@media (max-width: 640px) {\n .list { display: none; }\n .compact { display: block; }\n}\n\n@media (min-width: 641px) {\n .compact { display: none; }\n}\n\n.item {\n display: flex;\n align-items: center;\n flex: 1;\n min-width: 0;\n}\n\n.item:last-child { flex: 0 0 auto; }\n\n.step {\n display: inline-flex;\n align-items: center;\n gap: 10px;\n padding: 4px 0;\n background: transparent;\n border: none;\n font-family: inherit;\n color: inherit;\n cursor: default;\n}\n\n.item-done .step { cursor: pointer; }\n\n.circle {\n width: 28px;\n height: 28px;\n border-radius: 999px;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n font-size: 0.8125rem;\n font-weight: 600;\n flex: 0 0 auto;\n}\n\n.circle-upcoming {\n background: var(--bazaar-color-surface-subtle, #F4F2EC);\n color: var(--bazaar-color-text-muted);\n}\n\n.circle-current {\n background: var(--bazaar-color-text-primary, #1F1C17);\n color: var(--bazaar-color-text-inverse, #FFFFFF);\n}\n\n.circle-done {\n background: #4A7C59;\n color: #FFFFFF;\n}\n\n.label {\n font-size: 0.8125rem;\n font-weight: 500;\n letter-spacing: 0.04em;\n text-transform: uppercase;\n white-space: nowrap;\n}\n\n.item-upcoming .label { color: var(--bazaar-color-text-muted); }\n\n.line {\n flex: 1;\n height: 1px;\n background: var(--bazaar-color-border-subtle, rgba(0, 0, 0, 0.12));\n margin: 0 12px;\n}\n\n.item-done .line { background: #4A7C59; }\n\n.compact {\n font-size: 0.8125rem;\n letter-spacing: 0.04em;\n text-transform: uppercase;\n color: var(--bazaar-color-text-primary);\n}\n","import type { HTMLAttributes } from 'react';\nimport { cn } from '../utils/cn';\nimport { CheckIcon } from './icons';\nimport styles from './CheckoutStepper.module.css';\n\nexport interface CheckoutStep {\n id: string;\n label: string;\n}\n\nexport interface CheckoutStepperProps extends HTMLAttributes<HTMLElement> {\n steps: CheckoutStep[];\n currentStepId: string;\n /** Allow clicking a completed step to jump back. */\n onStepClick?: (step: CheckoutStep) => void;\n}\n\n/**\n * CheckoutStepper — numbered progress indicator for multi-step checkout.\n *\n * Collapses to a compact \"Step 2 of 4\" label on narrow viewports.\n */\nexport function CheckoutStepper({\n steps,\n currentStepId,\n onStepClick,\n className,\n ...rest\n}: CheckoutStepperProps) {\n const currentIndex = Math.max(\n 0,\n steps.findIndex((s) => s.id === currentStepId),\n );\n\n return (\n <nav className={cn(styles.root, className)} aria-label=\"Checkout progress\" {...rest}>\n <ol className={styles.list}>\n {steps.map((s, i) => {\n const state: 'done' | 'current' | 'upcoming' =\n i < currentIndex ? 'done' : i === currentIndex ? 'current' : 'upcoming';\n const clickable = state === 'done' && !!onStepClick;\n const ariaCurrent = state === 'current' ? 'step' : undefined;\n\n const Inner = (\n <>\n <span className={cn(styles.circle, styles[`circle-${state}`])} aria-hidden>\n {state === 'done' ? <CheckIcon width={12} height={12} /> : i + 1}\n </span>\n <span className={styles.label}>{s.label}</span>\n </>\n );\n\n return (\n <li key={s.id} className={cn(styles.item, styles[`item-${state}`])}>\n {clickable ? (\n <button\n type=\"button\"\n className={styles.step}\n onClick={() => onStepClick!(s)}\n aria-current={ariaCurrent}\n >\n {Inner}\n </button>\n ) : (\n <span className={styles.step} aria-current={ariaCurrent}>\n {Inner}\n </span>\n )}\n {i < steps.length - 1 && <span className={styles.line} aria-hidden />}\n </li>\n );\n })}\n </ol>\n <div className={styles.compact} aria-hidden>\n Step {currentIndex + 1} of {steps.length} · {steps[currentIndex]?.label}\n </div>\n </nav>\n );\n}\n",".root {\n display: flex;\n flex-direction: column;\n gap: 10px;\n font-family: var(--bazaar-font-family-sans);\n}\n\n.heading {\n font-size: 0.75rem;\n font-weight: 600;\n letter-spacing: 0.06em;\n text-transform: uppercase;\n color: var(--bazaar-color-text-muted);\n}\n\n.grid {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));\n gap: 8px;\n}\n\n.btn {\n padding: 12px 16px;\n border: none;\n border-radius: var(--bazaar-radius-sm, 6px);\n font-family: inherit;\n font-weight: 700;\n font-size: 0.875rem;\n letter-spacing: 0.02em;\n cursor: pointer;\n transition: transform 120ms ease, opacity 120ms ease;\n}\n\n.btn:hover { transform: translateY(-1px); opacity: 0.95; }\n\n.divider {\n position: relative;\n text-align: center;\n margin-top: 8px;\n font-size: 0.75rem;\n letter-spacing: 0.06em;\n text-transform: uppercase;\n color: var(--bazaar-color-text-muted);\n}\n\n.divider::before,\n.divider::after {\n content: '';\n position: absolute;\n top: 50%;\n width: calc(50% - 60px);\n height: 1px;\n background: var(--bazaar-color-border-subtle, rgba(0, 0, 0, 0.1));\n}\n\n.divider::before { left: 0; }\n.divider::after { right: 0; }\n","import type { HTMLAttributes } from 'react';\nimport { cn } from '../utils/cn';\nimport type { PaymentBrand } from './types';\nimport styles from './ExpressCheckout.module.css';\n\nexport interface ExpressMethod {\n brand: PaymentBrand;\n label?: string;\n onClick?: () => void;\n}\n\nexport interface ExpressCheckoutProps extends HTMLAttributes<HTMLDivElement> {\n methods: ExpressMethod[];\n /** Legend shown above the buttons. */\n heading?: string;\n /** Divider copy shown below (\"or\"). */\n divider?: string;\n}\n\nconst BRAND_STYLES: Record<PaymentBrand, { bg: string; fg: string; label: string }> = {\n visa: { bg: '#1A1F71', fg: '#FFFFFF', label: 'Visa Checkout' },\n mastercard: { bg: '#EB001B', fg: '#FFFFFF', label: 'Mastercard Click to Pay' },\n amex: { bg: '#006FCF', fg: '#FFFFFF', label: 'Amex Express Checkout' },\n discover: { bg: '#FF6000', fg: '#FFFFFF', label: 'Discover' },\n paypal: { bg: '#FFC439', fg: '#111', label: 'PayPal' },\n 'apple-pay': { bg: '#000000', fg: '#FFFFFF', label: 'Pay' },\n 'google-pay': { bg: '#000000', fg: '#FFFFFF', label: 'G Pay' },\n 'shop-pay': { bg: '#5A31F4', fg: '#FFFFFF', label: 'Shop Pay' },\n klarna: { bg: '#FFB3C7', fg: '#111', label: 'Klarna' },\n afterpay: { bg: '#B2FCE4', fg: '#111', label: 'Afterpay' },\n};\n\n/**\n * ExpressCheckout — row of wallet buttons that bypass the multi-step form.\n *\n * Presentational only: the actual wallet SDK integration is expected to live\n * in the `onClick` handler.\n */\nexport function ExpressCheckout({\n methods,\n heading = 'Express checkout',\n divider = 'Or pay with card',\n className,\n ...rest\n}: ExpressCheckoutProps) {\n return (\n <div className={cn(styles.root, className)} {...rest}>\n <span className={styles.heading}>{heading}</span>\n <div className={styles.grid}>\n {methods.map((m, i) => {\n const b = BRAND_STYLES[m.brand];\n return (\n <button\n key={i}\n type=\"button\"\n className={styles.btn}\n style={{ background: b.bg, color: b.fg }}\n onClick={m.onClick}\n aria-label={m.label ?? b.label}\n >\n {m.label ?? b.label}\n </button>\n );\n })}\n </div>\n <div className={styles.divider}>\n <span>{divider}</span>\n </div>\n </div>\n );\n}\n",".root {\n display: flex;\n flex-direction: column;\n gap: 14px;\n font-family: var(--bazaar-font-family-sans);\n color: var(--bazaar-color-text-primary);\n}\n\n.header {\n display: flex;\n align-items: baseline;\n justify-content: space-between;\n gap: 12px;\n}\n\n.title {\n font-family: var(--bazaar-font-family-display, var(--bazaar-font-family-sans));\n font-size: 1.125rem;\n font-weight: 500;\n margin: 0;\n}\n\n.signIn {\n font-size: 0.8125rem;\n color: var(--bazaar-color-text-muted);\n}\n\n.field {\n display: flex;\n flex-direction: column;\n gap: 6px;\n}\n\n.label {\n font-size: 0.75rem;\n font-weight: 600;\n letter-spacing: 0.06em;\n text-transform: uppercase;\n color: var(--bazaar-color-text-muted);\n}\n\n.input {\n padding: 12px 14px;\n border: 1px solid var(--bazaar-color-border-default, rgba(0, 0, 0, 0.14));\n border-radius: var(--bazaar-radius-sm, 6px);\n background: var(--bazaar-color-surface-default, #FFFFFF);\n font-family: inherit;\n font-size: 0.9375rem;\n color: var(--bazaar-color-text-primary);\n}\n\n.input:focus {\n outline: none;\n border-color: var(--bazaar-color-text-primary);\n}\n\n.inputError {\n border-color: var(--bazaar-color-sale, #873F1C);\n}\n\n.error {\n font-size: 0.75rem;\n color: var(--bazaar-color-sale, #873F1C);\n}\n\n.optin {\n display: inline-flex;\n align-items: center;\n gap: 10px;\n font-size: 0.875rem;\n color: var(--bazaar-color-text-primary);\n cursor: pointer;\n}\n","import { type HTMLAttributes } from 'react';\nimport { cn } from '../utils/cn';\nimport styles from './CheckoutContactStep.module.css';\n\nexport interface CheckoutContactValue {\n email: string;\n marketingOptIn?: boolean;\n}\n\nexport interface CheckoutContactStepProps extends Omit<HTMLAttributes<HTMLDivElement>, 'onChange'> {\n value: CheckoutContactValue;\n onChange: (next: CheckoutContactValue) => void;\n /** Validation error for the email field. */\n emailError?: string;\n title?: string;\n /** Slot for \"Already have an account? Sign in\" link. */\n signInSlot?: React.ReactNode;\n}\n\n/**\n * CheckoutContactStep — email capture and optional marketing opt-in.\n *\n * Fully controlled; validation is caller's responsibility — surface errors\n * via `emailError`.\n */\nexport function CheckoutContactStep({\n value,\n onChange,\n emailError,\n title = 'Contact',\n signInSlot,\n className,\n ...rest\n}: CheckoutContactStepProps) {\n return (\n <section className={cn(styles.root, className)} {...rest}>\n <header className={styles.header}>\n <h2 className={styles.title}>{title}</h2>\n {signInSlot && <div className={styles.signIn}>{signInSlot}</div>}\n </header>\n\n <label className={styles.field}>\n <span className={styles.label}>Email address</span>\n <input\n type=\"email\"\n autoComplete=\"email\"\n className={cn(styles.input, emailError && styles.inputError)}\n value={value.email}\n onChange={(e) => onChange({ ...value, email: e.target.value })}\n aria-invalid={!!emailError}\n aria-describedby={emailError ? 'contact-email-error' : undefined}\n />\n {emailError && (\n <span id=\"contact-email-error\" className={styles.error}>\n {emailError}\n </span>\n )}\n </label>\n\n <label className={styles.optin}>\n <input\n type=\"checkbox\"\n checked={!!value.marketingOptIn}\n onChange={(e) => onChange({ ...value, marketingOptIn: e.target.checked })}\n />\n <span>Email me with news and offers</span>\n </label>\n </section>\n );\n}\n",".root {\n border: none;\n padding: 0;\n margin: 0;\n display: flex;\n flex-direction: column;\n gap: 14px;\n font-family: var(--bazaar-font-family-sans);\n color: var(--bazaar-color-text-primary);\n}\n\n.title {\n padding: 0;\n font-family: var(--bazaar-font-family-display, var(--bazaar-font-family-sans));\n font-size: 1.125rem;\n font-weight: 500;\n margin: 0 0 6px;\n}\n\n.grid {\n display: grid;\n grid-template-columns: repeat(12, 1fr);\n gap: 12px;\n}\n\n@media (max-width: 480px) {\n .grid > * { grid-column: span 12 !important; }\n}\n\n.field {\n display: flex;\n flex-direction: column;\n gap: 6px;\n min-width: 0;\n}\n\n.label {\n font-size: 0.75rem;\n font-weight: 600;\n letter-spacing: 0.06em;\n text-transform: uppercase;\n color: var(--bazaar-color-text-muted);\n}\n\n.input {\n padding: 12px 14px;\n border: 1px solid var(--bazaar-color-border-default, rgba(0, 0, 0, 0.14));\n border-radius: var(--bazaar-radius-sm, 6px);\n background: var(--bazaar-color-surface-default, #FFFFFF);\n font-family: inherit;\n font-size: 0.9375rem;\n color: var(--bazaar-color-text-primary);\n}\n\n.input:focus {\n outline: none;\n border-color: var(--bazaar-color-text-primary);\n}\n\n.inputError {\n border-color: var(--bazaar-color-sale, #873F1C);\n}\n\n.error {\n font-size: 0.75rem;\n color: var(--bazaar-color-sale, #873F1C);\n}\n\n.optin {\n display: inline-flex;\n align-items: center;\n gap: 10px;\n font-size: 0.875rem;\n cursor: pointer;\n}\n","import { type HTMLAttributes } from 'react';\nimport { cn } from '../utils/cn';\nimport type { Address } from './types';\nimport styles from './AddressForm.module.css';\n\nexport interface AddressFormProps extends Omit<HTMLAttributes<HTMLFieldSetElement>, 'onChange'> {\n value: Partial<Address>;\n onChange: (next: Partial<Address>) => void;\n /** Field-level errors. */\n errors?: Partial<Record<keyof Address, string>>;\n title?: string;\n /** Country options — pass a string[] of labels or skip for the default. */\n countries?: string[];\n /** Show a \"Save this address to my account\" toggle below the form. */\n showSaveToggle?: boolean;\n /** Form is embedded inside a step; don't render an outer title. */\n compact?: boolean;\n}\n\nconst DEFAULT_COUNTRIES = ['United States', 'Canada', 'United Kingdom', 'Australia'];\n\n/**\n * AddressForm — shipping / billing address capture with a region-aware\n * grid. Fully controlled; callers own validation.\n */\nexport function AddressForm({\n value,\n onChange,\n errors = {},\n title = 'Shipping address',\n countries = DEFAULT_COUNTRIES,\n showSaveToggle = false,\n compact = false,\n className,\n ...rest\n}: AddressFormProps) {\n const set = <K extends keyof Address>(key: K, v: Address[K]) =>\n onChange({ ...value, [key]: v });\n\n const F = ({\n name,\n label,\n type = 'text',\n autoComplete,\n span = 6,\n }: {\n name: keyof Address;\n label: string;\n type?: string;\n autoComplete?: string;\n span?: number;\n }) => {\n const err = errors[name];\n return (\n <label className={styles.field} style={{ gridColumn: `span ${span}` }}>\n <span className={styles.label}>{label}</span>\n <input\n type={type}\n autoComplete={autoComplete}\n className={cn(styles.input, err && styles.inputError)}\n value={(value[name] as string | undefined) ?? ''}\n onChange={(e) => set(name, e.target.value as never)}\n aria-invalid={!!err}\n aria-describedby={err ? `addr-${name}-error` : undefined}\n />\n {err && (\n <span id={`addr-${name}-error`} className={styles.error}>\n {err}\n </span>\n )}\n </label>\n );\n };\n\n return (\n <fieldset className={cn(styles.root, className)} {...rest}>\n {!compact && <legend className={styles.title}>{title}</legend>}\n\n <div className={styles.grid}>\n <F name=\"name\" label=\"Full name\" autoComplete=\"name\" span={12} />\n <F name=\"line1\" label=\"Street address\" autoComplete=\"address-line1\" span={12} />\n <F name=\"line2\" label=\"Apt / suite (optional)\" autoComplete=\"address-line2\" span={12} />\n <F name=\"city\" label=\"City\" autoComplete=\"address-level2\" span={6} />\n <F name=\"region\" label=\"State / region\" autoComplete=\"address-level1\" span={3} />\n <F name=\"postalCode\" label=\"Postal code\" autoComplete=\"postal-code\" span={3} />\n\n <label className={styles.field} style={{ gridColumn: 'span 6' }}>\n <span className={styles.label}>Country</span>\n <select\n className={styles.input}\n autoComplete=\"country-name\"\n value={value.country ?? ''}\n onChange={(e) => set('country', e.target.value)}\n >\n <option value=\"\" disabled>Select country</option>\n {countries.map((c) => (\n <option key={c} value={c}>{c}</option>\n ))}\n </select>\n </label>\n <F name=\"phone\" label=\"Phone (for delivery updates)\" type=\"tel\" autoComplete=\"tel\" span={6} />\n </div>\n\n {showSaveToggle && (\n <label className={styles.optin}>\n <input\n type=\"checkbox\"\n checked={!!value.isDefault}\n onChange={(e) => set('isDefault', e.target.checked)}\n />\n <span>Save this address to my account</span>\n </label>\n )}\n </fieldset>\n );\n}\n",".root {\n display: flex;\n flex-direction: column;\n gap: 10px;\n font-family: var(--bazaar-font-family-sans);\n color: var(--bazaar-color-text-primary);\n}\n\n.title {\n font-family: var(--bazaar-font-family-display, var(--bazaar-font-family-sans));\n font-size: 1.125rem;\n font-weight: 500;\n margin: 0 0 4px;\n}\n\n.row {\n display: grid;\n grid-template-columns: auto 1fr auto;\n align-items: center;\n gap: 14px;\n padding: 14px 16px;\n border: 1px solid var(--bazaar-color-border-default, rgba(0, 0, 0, 0.12));\n border-radius: var(--bazaar-radius-md, 10px);\n background: var(--bazaar-color-surface-default, #FFFFFF);\n font-family: inherit;\n text-align: left;\n cursor: pointer;\n transition: border-color 120ms ease, background 120ms ease;\n}\n\n.row:hover {\n border-color: var(--bazaar-color-border-default, rgba(0, 0, 0, 0.25));\n}\n\n.rowActive {\n border-color: var(--bazaar-color-text-primary);\n background: var(--bazaar-color-surface-subtle, #F4F2EC);\n}\n\n.radio {\n width: 20px;\n height: 20px;\n border-radius: 999px;\n border: 1.5px solid var(--bazaar-color-border-default, rgba(0, 0, 0, 0.3));\n display: inline-flex;\n align-items: center;\n justify-content: center;\n color: transparent;\n}\n\n.radioActive {\n background: var(--bazaar-color-text-primary, #1F1C17);\n border-color: var(--bazaar-color-text-primary);\n color: #FFFFFF;\n}\n\n.body {\n display: flex;\n flex-direction: column;\n gap: 2px;\n min-width: 0;\n}\n\n.labelRow {\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.label {\n font-size: 0.9375rem;\n font-weight: 500;\n}\n\n.tag {\n padding: 2px 8px;\n border-radius: 999px;\n background: rgba(59, 125, 79, 0.15);\n color: #2E5237;\n font-size: 0.6875rem;\n font-weight: 600;\n letter-spacing: 0.04em;\n text-transform: uppercase;\n}\n\n.meta {\n font-size: 0.8125rem;\n color: var(--bazaar-color-text-muted);\n display: flex;\n gap: 4px;\n flex-wrap: wrap;\n}\n\n.description { color: var(--bazaar-color-text-muted); }\n\n.price {\n font-size: 0.9375rem;\n font-weight: 600;\n font-variant-numeric: tabular-nums;\n white-space: nowrap;\n}\n","import type { HTMLAttributes } from 'react';\nimport { cn } from '../utils/cn';\nimport { formatMoney } from './money';\nimport { CheckIcon } from './icons';\nimport type { ShippingMethod } from './types';\nimport styles from './ShippingMethodList.module.css';\n\nexport interface ShippingMethodListProps extends Omit<HTMLAttributes<HTMLDivElement>, 'onChange'> {\n methods: ShippingMethod[];\n value?: string;\n onChange?: (method: ShippingMethod) => void;\n title?: string;\n}\n\n/**\n * ShippingMethodList — radio-group of shipping rates. Each row shows price,\n * label, delivery estimate, and an optional \"Recommended\" tag.\n */\nexport function ShippingMethodList({\n methods,\n value,\n onChange,\n title,\n className,\n ...rest\n}: ShippingMethodListProps) {\n return (\n <div className={cn(styles.root, className)} role=\"radiogroup\" aria-label={title ?? 'Shipping method'} {...rest}>\n {title && <h3 className={styles.title}>{title}</h3>}\n {methods.map((m) => {\n const active = value === m.id;\n return (\n <button\n key={m.id}\n type=\"button\"\n role=\"radio\"\n aria-checked={active}\n className={cn(styles.row, active && styles.rowActive)}\n onClick={() => onChange?.(m)}\n >\n <span className={cn(styles.radio, active && styles.radioActive)} aria-hidden>\n {active && <CheckIcon width={12} height={12} />}\n </span>\n <div className={styles.body}>\n <div className={styles.labelRow}>\n <span className={styles.label}>{m.label}</span>\n {m.recommended && <span className={styles.tag}>Recommended</span>}\n </div>\n <div className={styles.meta}>\n {m.estimate && <span>{m.estimate}</span>}\n {m.description && <span className={styles.description}>· {m.description}</span>}\n </div>\n </div>\n <span className={styles.price}>\n {m.price.amount === 0 ? 'Free' : formatMoney(m.price)}\n </span>\n </button>\n );\n })}\n </div>\n );\n}\n",".root {\n display: flex;\n flex-direction: column;\n gap: 14px;\n font-family: var(--bazaar-font-family-sans);\n color: var(--bazaar-color-text-primary);\n}\n\n.header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 12px;\n}\n\n.title {\n font-family: var(--bazaar-font-family-display, var(--bazaar-font-family-sans));\n font-size: 1.125rem;\n font-weight: 500;\n margin: 0;\n}\n\n.lock {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n font-size: 0.75rem;\n color: var(--bazaar-color-text-muted);\n}\n\n.channels {\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n\n.channel {\n border: 1px solid var(--bazaar-color-border-default, rgba(0, 0, 0, 0.12));\n border-radius: var(--bazaar-radius-md, 10px);\n overflow: hidden;\n background: var(--bazaar-color-surface-default, #FFFFFF);\n transition: border-color 120ms ease;\n}\n\n.channelActive {\n border-color: var(--bazaar-color-text-primary);\n}\n\n.channelHeader {\n width: 100%;\n display: grid;\n grid-template-columns: auto 1fr auto;\n align-items: center;\n gap: 12px;\n padding: 14px 16px;\n background: transparent;\n border: none;\n cursor: pointer;\n font-family: inherit;\n text-align: left;\n}\n\n.radio {\n width: 20px;\n height: 20px;\n border-radius: 999px;\n border: 1.5px solid var(--bazaar-color-border-default, rgba(0, 0, 0, 0.3));\n display: inline-flex;\n align-items: center;\n justify-content: center;\n color: transparent;\n}\n\n.radioActive {\n background: var(--bazaar-color-text-primary, #1F1C17);\n border-color: var(--bazaar-color-text-primary);\n color: #FFFFFF;\n}\n\n.channelLabel {\n font-size: 0.9375rem;\n font-weight: 500;\n}\n\n.channelBrands {\n color: var(--bazaar-color-text-muted);\n}\n\n.savedList {\n display: flex;\n flex-direction: column;\n gap: 8px;\n padding: 12px 16px 16px;\n background: var(--bazaar-color-surface-subtle, #F4F2EC);\n border-top: 1px solid var(--bazaar-color-border-subtle, rgba(0, 0, 0, 0.08));\n}\n\n.savedRow {\n display: grid;\n grid-template-columns: auto auto 1fr auto;\n align-items: center;\n gap: 12px;\n padding: 10px 12px;\n border: 1px solid var(--bazaar-color-border-subtle, rgba(0, 0, 0, 0.1));\n border-radius: var(--bazaar-radius-sm, 6px);\n background: var(--bazaar-color-surface-default, #FFFFFF);\n cursor: pointer;\n font-family: inherit;\n text-align: left;\n}\n\n.savedRowActive {\n border-color: var(--bazaar-color-text-primary);\n}\n\n.brandChip {\n padding: 4px 8px;\n border-radius: 4px;\n color: #FFFFFF;\n font-size: 0.625rem;\n font-weight: 700;\n letter-spacing: 0.08em;\n}\n\n.savedLabel {\n font-size: 0.875rem;\n font-weight: 500;\n}\n\n.savedExpires {\n font-size: 0.75rem;\n color: var(--bazaar-color-text-muted);\n}\n\n.useNew {\n align-self: flex-start;\n padding: 0;\n background: transparent;\n border: none;\n color: var(--bazaar-color-text-primary);\n font-family: inherit;\n font-size: 0.8125rem;\n text-decoration: underline;\n cursor: pointer;\n}\n","import { useState, type HTMLAttributes } from 'react';\nimport { cn } from '../utils/cn';\nimport { CheckIcon, LockIcon, CreditCardIcon } from './icons';\nimport type { PaymentBrand, PaymentMethod } from './types';\nimport styles from './PaymentMethodSelector.module.css';\n\nexport type PaymentChannel = 'card' | 'paypal' | 'apple-pay' | 'klarna' | 'afterpay';\n\nexport interface PaymentMethodSelectorProps extends Omit<HTMLAttributes<HTMLDivElement>, 'onChange'> {\n /** Available channels (in display order). */\n channels?: PaymentChannel[];\n value?: PaymentChannel;\n onChange?: (channel: PaymentChannel) => void;\n /** Previously saved cards — shown under the \"card\" option. */\n savedMethods?: PaymentMethod[];\n savedMethodId?: string;\n onSavedMethodChange?: (method: PaymentMethod) => void;\n /** Called when the user opts into a new card (clears `savedMethodId` upstream). */\n onUseNewCard?: () => void;\n title?: string;\n}\n\nconst CHANNEL_LABELS: Record<PaymentChannel, string> = {\n card: 'Credit or debit card',\n paypal: 'PayPal',\n 'apple-pay': 'Apple Pay',\n klarna: 'Klarna — 4 interest-free payments',\n afterpay: 'Afterpay — 4 interest-free payments',\n};\n\nconst BRAND_COLORS: Partial<Record<PaymentBrand, string>> = {\n visa: '#1A1F71',\n mastercard: '#EB001B',\n amex: '#006FCF',\n discover: '#FF6000',\n};\n\n/**\n * PaymentMethodSelector — channel chooser (card, PayPal, wallets, BNPL)\n * plus a saved-card list when the card channel is active.\n *\n * The actual card form is not rendered here — compose a separate form (or\n * a PSP element) next to it, gated by `value === 'card'` and `!savedMethodId`.\n */\nexport function PaymentMethodSelector({\n channels = ['card', 'paypal', 'apple-pay', 'klarna'],\n value,\n onChange,\n savedMethods = [],\n savedMethodId,\n onSavedMethodChange,\n onUseNewCard,\n title = 'Payment',\n className,\n ...rest\n}: PaymentMethodSelectorProps) {\n const [internal, setInternal] = useState<PaymentChannel>(channels[0]);\n const active = value ?? internal;\n const set = (c: PaymentChannel) => {\n setInternal(c);\n onChange?.(c);\n };\n\n return (\n <div className={cn(styles.root, className)} {...rest}>\n <header className={styles.header}>\n <h2 className={styles.title}>{title}</h2>\n <span className={styles.lock}>\n <LockIcon width={12} height={12} />\n Secure checkout\n </span>\n </header>\n\n <div className={styles.channels} role=\"radiogroup\" aria-label={title}>\n {channels.map((c) => {\n const isActive = c === active;\n return (\n <div key={c} className={cn(styles.channel, isActive && styles.channelActive)}>\n <button\n type=\"button\"\n role=\"radio\"\n aria-checked={isActive}\n className={styles.channelHeader}\n onClick={() => set(c)}\n >\n <span className={cn(styles.radio, isActive && styles.radioActive)} aria-hidden>\n {isActive && <CheckIcon width={12} height={12} />}\n </span>\n <span className={styles.channelLabel}>{CHANNEL_LABELS[c]}</span>\n {c === 'card' && (\n <span className={styles.channelBrands} aria-hidden>\n <CreditCardIcon width={20} height={14} />\n </span>\n )}\n </button>\n\n {isActive && c === 'card' && savedMethods.length > 0 && (\n <div className={styles.savedList} role=\"radiogroup\" aria-label=\"Saved cards\">\n {savedMethods.map((m) => {\n const sActive = m.id === savedMethodId;\n return (\n <button\n key={m.id}\n type=\"button\"\n role=\"radio\"\n aria-checked={sActive}\n className={cn(styles.savedRow, sActive && styles.savedRowActive)}\n onClick={() => onSavedMethodChange?.(m)}\n >\n <span className={cn(styles.radio, sActive && styles.radioActive)} aria-hidden>\n {sActive && <CheckIcon width={12} height={12} />}\n </span>\n <span\n className={styles.brandChip}\n style={{ background: BRAND_COLORS[m.brand] ?? '#333' }}\n >\n {m.brand.toUpperCase()}\n </span>\n <span className={styles.savedLabel}>\n {m.label} · •••• {m.last4}\n </span>\n {m.expires && (\n <span className={styles.savedExpires}>Exp {m.expires}</span>\n )}\n </button>\n );\n })}\n {onUseNewCard && (\n <button\n type=\"button\"\n className={styles.useNew}\n onClick={onUseNewCard}\n >\n Use a different card\n </button>\n )}\n </div>\n )}\n </div>\n );\n })}\n </div>\n </div>\n );\n}\n",".root {\n display: flex;\n flex-direction: column;\n gap: 12px;\n font-family: var(--bazaar-font-family-sans);\n color: var(--bazaar-color-text-primary);\n}\n\n.toggle {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 10px 0;\n background: transparent;\n border: none;\n font-family: inherit;\n font-size: 0.875rem;\n color: var(--bazaar-color-text-primary);\n cursor: pointer;\n}\n\n.toggleCount {\n color: var(--bazaar-color-text-muted);\n}\n\n.caret {\n transition: transform 180ms ease;\n color: var(--bazaar-color-text-muted);\n display: inline-flex;\n}\n\n.caretOpen { transform: rotate(180deg); }\n\n.lines {\n border-top: 1px solid var(--bazaar-color-border-subtle, rgba(0, 0, 0, 0.08));\n border-bottom: 1px solid var(--bazaar-color-border-subtle, rgba(0, 0, 0, 0.08));\n}\n\n.summary {\n /* inherited from CartSummary */\n}\n\n.footer {\n margin-top: 6px;\n font-size: 0.75rem;\n color: var(--bazaar-color-text-muted);\n}\n","import { useState, type HTMLAttributes, type ReactNode } from 'react';\nimport { cn } from '../utils/cn';\nimport { CartLineItem } from './CartLineItem';\nimport { CartSummary, type CartSummaryLine } from './CartSummary';\nimport { ChevronDownIcon } from './icons';\nimport type { CartLine, Money } from './types';\nimport styles from './CheckoutOrderSummary.module.css';\n\nexport interface CheckoutOrderSummaryProps extends HTMLAttributes<HTMLDivElement> {\n lines: CartLine[];\n subtotal: Money;\n adjustments?: CartSummaryLine[];\n total: Money;\n /** Start with the line-item list expanded (default false on desktop, true on mobile). */\n defaultOpen?: boolean;\n /** Slot above totals — e.g. CouponField. */\n topSlot?: ReactNode;\n /** Slot below the totals — terms, reassurance, etc. */\n footerSlot?: ReactNode;\n}\n\n/**\n * CheckoutOrderSummary — the right-rail (or collapsible on mobile) recap of\n * the order during checkout. Combines line items with CartSummary math.\n */\nexport function CheckoutOrderSummary({\n lines,\n subtotal,\n adjustments = [],\n total,\n defaultOpen = true,\n topSlot,\n footerSlot,\n className,\n ...rest\n}: CheckoutOrderSummaryProps) {\n const [open, setOpen] = useState(defaultOpen);\n const itemCount = lines.reduce((n, l) => n + l.quantity, 0);\n\n return (\n <div className={cn(styles.root, className)} {...rest}>\n <button\n type=\"button\"\n className={styles.toggle}\n aria-expanded={open}\n onClick={() => setOpen((o) => !o)}\n >\n <span>\n {open ? 'Hide' : 'Show'} order summary\n <span className={styles.toggleCount}> ({itemCount})</span>\n </span>\n <span className={cn(styles.caret, open && styles.caretOpen)} aria-hidden>\n <ChevronDownIcon />\n </span>\n </button>\n\n {open && (\n <div className={styles.lines} role=\"list\">\n {lines.map((line) => (\n <div key={line.id} role=\"listitem\">\n <CartLineItem line={line} density=\"compact\" readOnlyQuantity hidePrice={false} />\n </div>\n ))}\n </div>\n )}\n\n <CartSummary\n subtotal={subtotal}\n lines={adjustments}\n total={total}\n density=\"compact\"\n className={styles.summary}\n >\n {topSlot}\n </CartSummary>\n\n {footerSlot && <div className={styles.footer}>{footerSlot}</div>}\n </div>\n );\n}\n",".root {\n min-height: 100vh;\n font-family: var(--bazaar-font-family-sans);\n color: var(--bazaar-color-text-primary);\n background: var(--bazaar-color-surface-default, #FFFFFF);\n display: flex;\n flex-direction: column;\n}\n\n.header {\n display: grid;\n grid-template-columns: 1fr auto 1fr;\n align-items: center;\n gap: 16px;\n padding: 20px 32px;\n border-bottom: 1px solid var(--bazaar-color-border-subtle, rgba(0, 0, 0, 0.08));\n}\n\n@media (max-width: 720px) {\n .header {\n grid-template-columns: 1fr;\n gap: 12px;\n padding: 16px 20px;\n }\n .header > * { justify-self: center; text-align: center; }\n}\n\n.brand {\n font-family: var(--bazaar-font-family-display, var(--bazaar-font-family-sans));\n font-size: 1.125rem;\n font-weight: 500;\n letter-spacing: 0.04em;\n}\n\n.stepper {\n min-width: 0;\n max-width: 520px;\n width: 100%;\n}\n\n.secure {\n justify-self: end;\n display: inline-flex;\n align-items: center;\n gap: 6px;\n font-size: 0.75rem;\n color: var(--bazaar-color-text-muted);\n letter-spacing: 0.04em;\n text-transform: uppercase;\n}\n\n@media (max-width: 720px) {\n .secure { justify-self: center; }\n}\n\n.main {\n flex: 1;\n display: grid;\n grid-template-columns: minmax(0, 1fr) 380px;\n gap: 48px;\n padding: 40px 32px;\n max-width: 1200px;\n margin: 0 auto;\n width: 100%;\n}\n\n@media (max-width: 900px) {\n .main {\n grid-template-columns: 1fr;\n gap: 24px;\n padding: 24px 20px;\n }\n}\n\n.form {\n display: flex;\n flex-direction: column;\n gap: 32px;\n}\n\n.sidebar {\n align-self: start;\n position: sticky;\n top: 24px;\n}\n\n.footer {\n padding: 24px 32px;\n border-top: 1px solid var(--bazaar-color-border-subtle, rgba(0, 0, 0, 0.08));\n font-size: 0.75rem;\n color: var(--bazaar-color-text-muted);\n text-align: center;\n}\n","import type { HTMLAttributes, ReactNode } from 'react';\nimport { cn } from '../utils/cn';\nimport { LockIcon } from './icons';\nimport styles from './CheckoutShell.module.css';\n\nexport interface CheckoutShellProps extends HTMLAttributes<HTMLDivElement> {\n /** Brand slot — logo or wordmark. */\n brand: ReactNode;\n /** CheckoutStepper instance, rendered centered below the brand on desktop. */\n stepperSlot?: ReactNode;\n /** Main step form. */\n children: ReactNode;\n /** Right-rail order summary. */\n sidebar?: ReactNode;\n /** Footer slot — small-print links, trust seal, etc. */\n footerSlot?: ReactNode;\n}\n\n/**\n * CheckoutShell — minimal, distraction-free layout for the checkout funnel.\n *\n * Strips global nav, pins the brand at top-left, optionally centers a\n * CheckoutStepper, and renders a two-column grid (form + order summary)\n * that stacks on mobile.\n */\nexport function CheckoutShell({\n brand,\n stepperSlot,\n children,\n sidebar,\n footerSlot,\n className,\n ...rest\n}: CheckoutShellProps) {\n return (\n <div className={cn(styles.root, className)} {...rest}>\n <header className={styles.header}>\n <div className={styles.brand}>{brand}</div>\n <div className={styles.stepper}>{stepperSlot}</div>\n <div className={styles.secure}>\n <LockIcon width={12} height={12} />\n <span>Secure checkout</span>\n </div>\n </header>\n\n <main className={styles.main}>\n <div className={styles.form}>{children}</div>\n {sidebar && <aside className={styles.sidebar}>{sidebar}</aside>}\n </main>\n\n {footerSlot && <footer className={styles.footer}>{footerSlot}</footer>}\n </div>\n );\n}\n",".root {\n max-width: 720px;\n margin: 0 auto;\n padding: 48px 24px;\n display: flex;\n flex-direction: column;\n gap: 32px;\n font-family: var(--bazaar-font-family-sans);\n color: var(--bazaar-color-text-primary);\n}\n\n.header {\n text-align: center;\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 10px;\n}\n\n.badge {\n width: 52px;\n height: 52px;\n border-radius: 999px;\n background: rgba(59, 125, 79, 0.15);\n color: #2E5237;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n}\n\n.title {\n font-family: var(--bazaar-font-family-display, var(--bazaar-font-family-sans));\n font-size: 1.75rem;\n font-weight: 500;\n margin: 0;\n line-height: 1.2;\n}\n\n.meta {\n margin: 0;\n font-size: 0.9375rem;\n color: var(--bazaar-color-text-muted);\n}\n\n.meta strong {\n font-weight: 500;\n color: var(--bazaar-color-text-primary);\n}\n\n.cards {\n display: grid;\n grid-template-columns: 1fr 1fr;\n gap: 12px;\n}\n\n@media (max-width: 560px) {\n .cards { grid-template-columns: 1fr; }\n}\n\n.card {\n padding: 18px;\n border: 1px solid var(--bazaar-color-border-subtle, rgba(0, 0, 0, 0.08));\n border-radius: var(--bazaar-radius-md, 10px);\n background: var(--bazaar-color-surface-default, #FFFFFF);\n display: flex;\n flex-direction: column;\n gap: 6px;\n}\n\n.cardLabel {\n font-size: 0.75rem;\n font-weight: 600;\n letter-spacing: 0.06em;\n text-transform: uppercase;\n color: var(--bazaar-color-text-muted);\n}\n\n.cardValue {\n font-size: 0.9375rem;\n line-height: 1.5;\n}\n\n.cardAddress {\n white-space: pre-line;\n}\n\n.items {\n display: flex;\n flex-direction: column;\n gap: 12px;\n}\n\n.sectionTitle {\n font-family: var(--bazaar-font-family-display, var(--bazaar-font-family-sans));\n font-size: 1.125rem;\n font-weight: 500;\n margin: 0;\n}\n\n.summary { /* CartSummary handles its own styling */ }\n\n.cta {\n display: flex;\n flex-direction: column;\n gap: 10px;\n align-items: center;\n}\n\n.extra {\n margin-top: 16px;\n}\n","import type { HTMLAttributes, ReactNode } from 'react';\nimport { cn } from '../utils/cn';\nimport { CartLineItem } from './CartLineItem';\nimport { CartSummary, type CartSummaryLine } from './CartSummary';\nimport { CheckIcon } from './icons';\nimport type { Address, CartLine, Money } from './types';\nimport styles from './OrderConfirmation.module.css';\n\nexport interface OrderConfirmationProps extends HTMLAttributes<HTMLDivElement> {\n orderNumber: string;\n email: string;\n /** Headline — defaults to a friendly thank-you. */\n headline?: string;\n /** Estimated arrival window copy — e.g. \"April 24 – April 26\". */\n estimatedDelivery?: string;\n shippingAddress?: Address;\n lines: CartLine[];\n subtotal: Money;\n adjustments?: CartSummaryLine[];\n total: Money;\n /** CTA slot — e.g. \"Track order\" link, \"Continue shopping\" button. */\n ctaSlot?: ReactNode;\n /** Optional post-purchase cross-sell or reassurance below the summary. */\n extraSlot?: ReactNode;\n}\n\nfunction formatAddress(addr?: Address): string | null {\n if (!addr) return null;\n const parts = [\n addr.name,\n addr.line1,\n addr.line2,\n `${addr.city}, ${addr.region} ${addr.postalCode}`,\n addr.country,\n ].filter(Boolean);\n return parts.join('\\n');\n}\n\n/**\n * OrderConfirmation — post-purchase \"thank you\" page. Presents a clear\n * confirmation, delivery summary, and an itemised receipt.\n */\nexport function OrderConfirmation({\n orderNumber,\n email,\n headline,\n estimatedDelivery,\n shippingAddress,\n lines,\n subtotal,\n adjustments = [],\n total,\n ctaSlot,\n extraSlot,\n className,\n ...rest\n}: OrderConfirmationProps) {\n const formattedAddress = formatAddress(shippingAddress);\n\n return (\n <div className={cn(styles.root, className)} {...rest}>\n <header className={styles.header}>\n <span className={styles.badge} aria-hidden>\n <CheckIcon width={18} height={18} />\n </span>\n <h1 className={styles.title}>{headline ?? 'Thank you — your order is confirmed'}</h1>\n <p className={styles.meta}>\n Order <strong>#{orderNumber}</strong> · A receipt has been sent to <strong>{email}</strong>\n </p>\n </header>\n\n <div className={styles.cards}>\n {estimatedDelivery && (\n <div className={styles.card}>\n <span className={styles.cardLabel}>Estimated delivery</span>\n <span className={styles.cardValue}>{estimatedDelivery}</span>\n </div>\n )}\n {formattedAddress && (\n <div className={styles.card}>\n <span className={styles.cardLabel}>Shipping to</span>\n <span className={cn(styles.cardValue, styles.cardAddress)}>{formattedAddress}</span>\n </div>\n )}\n </div>\n\n <section aria-label=\"Order items\" className={styles.items}>\n <h2 className={styles.sectionTitle}>Items</h2>\n <div role=\"list\">\n {lines.map((line) => (\n <div key={line.id} role=\"listitem\">\n <CartLineItem line={line} readOnlyQuantity />\n </div>\n ))}\n </div>\n </section>\n\n <CartSummary\n subtotal={subtotal}\n lines={adjustments}\n total={total}\n totalLabel=\"Total paid\"\n className={styles.summary}\n />\n\n {ctaSlot && <div className={styles.cta}>{ctaSlot}</div>}\n {extraSlot && <div className={styles.extra}>{extraSlot}</div>}\n </div>\n );\n}\n",".root {\n font-family: var(--bazaar-font-family-sans);\n color: var(--bazaar-color-text-primary);\n display: flex;\n flex-direction: column;\n gap: 20px;\n}\n\n.header {\n display: flex;\n align-items: baseline;\n justify-content: space-between;\n}\n\n.title {\n font-family: var(--bazaar-font-family-display, var(--bazaar-font-family-sans));\n font-size: 1.5rem;\n font-weight: 500;\n margin: 0;\n}\n\n.count {\n font-size: 1rem;\n font-weight: 400;\n color: var(--bazaar-color-text-muted);\n margin-left: 6px;\n}\n\n.empty {\n padding: 56px 24px;\n text-align: center;\n border: 1px dashed var(--bazaar-color-border-default, rgba(0, 0, 0, 0.14));\n border-radius: var(--bazaar-radius-lg, 12px);\n background: var(--bazaar-color-surface-subtle, #F4F2EC);\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 8px;\n}\n\n.emptyTitle {\n margin: 0;\n font-family: var(--bazaar-font-family-display, var(--bazaar-font-family-sans));\n font-size: 1.125rem;\n font-weight: 500;\n}\n\n.emptyBody {\n margin: 0;\n font-size: 0.9375rem;\n color: var(--bazaar-color-text-muted);\n max-width: 44ch;\n}\n","import type { HTMLAttributes } from 'react';\nimport { cn } from '../utils/cn';\nimport { ProductGrid } from './ProductGrid';\nimport { ProductCard } from './ProductCard';\nimport type { Product } from './types';\nimport styles from './WishlistGrid.module.css';\n\nexport interface WishlistGridProps extends HTMLAttributes<HTMLElement> {\n products: Product[];\n title?: string;\n onRemove?: (product: Product) => void;\n onAddToCart?: (product: Product) => void;\n onSelectProduct?: (product: Product) => void;\n /** Empty-state CTA slot. */\n emptyCta?: React.ReactNode;\n /** Override the default \"Your wishlist is empty\" copy. */\n emptyTitle?: string;\n emptyBody?: string;\n}\n\n/**\n * WishlistGrid — account-section presentation of saved products. Wraps\n * ProductGrid + ProductCard with per-card remove/add actions.\n */\nexport function WishlistGrid({\n products,\n title = 'Wishlist',\n onRemove,\n onAddToCart,\n onSelectProduct,\n emptyCta,\n emptyTitle = 'No saved items yet',\n emptyBody = 'Tap the heart on anything to keep it here for later.',\n className,\n ...rest\n}: WishlistGridProps) {\n return (\n <section className={cn(styles.root, className)} {...rest}>\n <header className={styles.header}>\n <h2 className={styles.title}>\n {title} <span className={styles.count}>({products.length})</span>\n </h2>\n </header>\n\n {products.length === 0 ? (\n <div className={styles.empty}>\n <p className={styles.emptyTitle}>{emptyTitle}</p>\n <p className={styles.emptyBody}>{emptyBody}</p>\n {emptyCta}\n </div>\n ) : (\n <ProductGrid columns={4} mdColumns={3} smColumns={2}>\n {products.map((p) => (\n <ProductCard\n key={p.id}\n product={p}\n wishlisted\n onWishlistToggle={onRemove}\n onQuickAdd={onAddToCart}\n onSelect={onSelectProduct}\n />\n ))}\n </ProductGrid>\n )}\n </section>\n );\n}\n",".root {\n font-family: var(--bazaar-font-family-sans);\n color: var(--bazaar-color-text-primary);\n display: flex;\n flex-direction: column;\n gap: 20px;\n}\n\n.header {\n display: flex;\n align-items: baseline;\n justify-content: space-between;\n}\n\n.title {\n font-family: var(--bazaar-font-family-display, var(--bazaar-font-family-sans));\n font-size: 1.5rem;\n font-weight: 500;\n margin: 0;\n}\n\n.count {\n font-size: 1rem;\n font-weight: 400;\n color: var(--bazaar-color-text-muted);\n margin-left: 6px;\n}\n\n.list {\n display: flex;\n flex-direction: column;\n gap: 16px;\n}\n\n.card {\n display: flex;\n flex-direction: column;\n gap: 16px;\n padding: 20px;\n border: 1px solid var(--bazaar-color-border-default, rgba(0, 0, 0, 0.1));\n border-radius: var(--bazaar-radius-lg, 12px);\n background: var(--bazaar-color-surface-default, #fff);\n}\n\n.cardHead {\n display: flex;\n justify-content: space-between;\n align-items: flex-start;\n gap: 12px;\n flex-wrap: wrap;\n}\n\n.metaGroup {\n display: flex;\n flex-direction: column;\n gap: 4px;\n min-width: 0;\n}\n\n.metaGroup:last-child {\n align-items: flex-end;\n text-align: right;\n}\n\n.status {\n display: inline-flex;\n align-items: center;\n align-self: flex-start;\n padding: 3px 10px;\n border-radius: 999px;\n font-size: 0.75rem;\n font-weight: 600;\n letter-spacing: 0.02em;\n text-transform: uppercase;\n}\n\n.tone-muted {\n background: var(--bazaar-color-surface-subtle, #F4F2EC);\n color: var(--bazaar-color-text-muted);\n}\n\n.tone-accent {\n background: rgba(19, 27, 40, 0.08);\n color: var(--bazaar-color-text-primary);\n}\n\n.tone-success {\n background: rgba(27, 104, 69, 0.1);\n color: #1B6845;\n}\n\n.tone-neutral {\n background: rgba(0, 0, 0, 0.06);\n color: var(--bazaar-color-text-muted);\n}\n\n.date {\n font-size: 0.875rem;\n color: var(--bazaar-color-text-muted);\n}\n\n.number {\n font-size: 0.8125rem;\n color: var(--bazaar-color-text-muted);\n font-variant-numeric: tabular-nums;\n}\n\n.total {\n font-size: 1.0625rem;\n font-weight: 600;\n font-variant-numeric: tabular-nums;\n}\n\n.thumbs {\n display: flex;\n gap: 8px;\n align-items: center;\n flex-wrap: wrap;\n}\n\n.thumb {\n width: 64px;\n height: 64px;\n border-radius: var(--bazaar-radius-md, 8px);\n overflow: hidden;\n flex: 0 0 auto;\n background: var(--bazaar-color-surface-subtle, #F4F2EC);\n}\n\n.more {\n width: 64px;\n height: 64px;\n border-radius: var(--bazaar-radius-md, 8px);\n background: var(--bazaar-color-surface-subtle, #F4F2EC);\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 0.875rem;\n font-weight: 600;\n color: var(--bazaar-color-text-muted);\n flex: 0 0 auto;\n}\n\n.actions {\n display: flex;\n gap: 8px;\n flex-wrap: wrap;\n align-items: center;\n padding-top: 4px;\n border-top: 1px solid var(--bazaar-color-border-subtle, rgba(0, 0, 0, 0.06));\n margin-top: 4px;\n padding-top: 16px;\n}\n\n.primary,\n.secondary {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 9px 18px;\n border-radius: 999px;\n font-family: inherit;\n font-size: 0.8125rem;\n font-weight: 600;\n letter-spacing: 0.03em;\n cursor: pointer;\n transition: background 120ms ease, border-color 120ms ease;\n}\n\n.primary {\n background: var(--bazaar-color-text-primary, #1F1C17);\n color: var(--bazaar-color-surface-default, #fff);\n border: 1px solid var(--bazaar-color-text-primary, #1F1C17);\n}\n\n.primary:hover {\n background: #000;\n}\n\n.secondary {\n background: transparent;\n color: var(--bazaar-color-text-primary);\n border: 1px solid var(--bazaar-color-border-default, rgba(0, 0, 0, 0.14));\n}\n\n.secondary:hover {\n border-color: var(--bazaar-color-text-primary, #1F1C17);\n}\n\n@media (max-width: 540px) {\n .cardHead {\n flex-direction: column;\n }\n\n .metaGroup:last-child {\n align-items: flex-start;\n text-align: left;\n }\n}\n","import type { HTMLAttributes } from 'react';\nimport { cn } from '../utils/cn';\nimport { MediaPlaceholder } from './MediaPlaceholder';\nimport { formatMoney } from './money';\nimport { ChevronRightIcon } from './icons';\nimport type { Order, OrderStatus } from './types';\nimport styles from './OrderHistoryList.module.css';\n\nexport interface OrderHistoryListProps extends HTMLAttributes<HTMLElement> {\n orders: Order[];\n title?: string;\n onSelectOrder?: (order: Order) => void;\n onReorder?: (order: Order) => void;\n onTrack?: (order: Order) => void;\n /** Max previews rendered inline — defaults to 3. */\n previewCount?: number;\n}\n\nconst STATUS_LABEL: Record<OrderStatus, string> = {\n placed: 'Placed',\n processing: 'Processing',\n shipped: 'Shipped',\n 'out-for-delivery': 'Out for delivery',\n delivered: 'Delivered',\n cancelled: 'Cancelled',\n returned: 'Returned',\n};\n\nconst STATUS_TONE: Record<OrderStatus, string> = {\n placed: 'muted',\n processing: 'accent',\n shipped: 'accent',\n 'out-for-delivery': 'accent',\n delivered: 'success',\n cancelled: 'neutral',\n returned: 'neutral',\n};\n\n/**\n * OrderHistoryList — stacked card list of past orders. Each card shows a\n * compact header (status, date, total, number), a thumbnail strip of the\n * first few items, and a row of contextual actions.\n */\nexport function OrderHistoryList({\n orders,\n title = 'Orders',\n onSelectOrder,\n onReorder,\n onTrack,\n previewCount = 4,\n className,\n ...rest\n}: OrderHistoryListProps) {\n return (\n <section className={cn(styles.root, className)} {...rest}>\n <header className={styles.header}>\n <h2 className={styles.title}>\n {title} <span className={styles.count}>({orders.length})</span>\n </h2>\n </header>\n\n <div className={styles.list}>\n {orders.map((order) => {\n const previews = order.lines.slice(0, previewCount);\n const extra = order.lines.length - previews.length;\n return (\n <article key={order.id} className={styles.card}>\n <header className={styles.cardHead}>\n <div className={styles.metaGroup}>\n <span className={cn(styles.status, styles[`tone-${STATUS_TONE[order.status]}`])}>\n {STATUS_LABEL[order.status]}\n </span>\n <span className={styles.date}>\n Ordered {new Date(order.placedAt).toLocaleDateString(undefined, {\n month: 'short',\n day: 'numeric',\n year: 'numeric',\n })}\n </span>\n </div>\n <div className={styles.metaGroup}>\n <span className={styles.number}>#{order.id}</span>\n <span className={styles.total}>{formatMoney(order.total)}</span>\n </div>\n </header>\n\n <div className={styles.thumbs}>\n {previews.map((line) => (\n <div key={line.id} className={styles.thumb} title={line.title}>\n <MediaPlaceholder\n src={line.image?.src}\n alt={line.image?.alt ?? line.title}\n seed={line.image?.seed}\n aspectRatio=\"1 / 1\"\n />\n </div>\n ))}\n {extra > 0 && <div className={styles.more}>+{extra}</div>}\n </div>\n\n <div className={styles.actions}>\n {order.status === 'shipped' || order.status === 'out-for-delivery' ? (\n <button\n type=\"button\"\n className={styles.primary}\n onClick={() => onTrack?.(order)}\n >\n Track package\n </button>\n ) : order.status === 'delivered' && onReorder ? (\n <button\n type=\"button\"\n className={styles.primary}\n onClick={() => onReorder(order)}\n >\n Buy again\n </button>\n ) : null}\n {onSelectOrder && (\n <button\n type=\"button\"\n className={styles.secondary}\n onClick={() => onSelectOrder(order)}\n >\n View details <ChevronRightIcon width={14} height={14} />\n </button>\n )}\n </div>\n </article>\n );\n })}\n </div>\n </section>\n );\n}\n",".root {\n font-family: var(--bazaar-font-family-sans);\n color: var(--bazaar-color-text-primary);\n display: flex;\n flex-direction: column;\n gap: 24px;\n padding: 24px;\n border: 1px solid var(--bazaar-color-border-default, rgba(0, 0, 0, 0.1));\n border-radius: var(--bazaar-radius-lg, 12px);\n background: var(--bazaar-color-surface-default, #fff);\n}\n\n.hero {\n display: flex;\n gap: 16px;\n align-items: flex-start;\n}\n\n.heroIcon {\n width: 44px;\n height: 44px;\n border-radius: 999px;\n background: var(--bazaar-color-surface-subtle, #F4F2EC);\n display: flex;\n align-items: center;\n justify-content: center;\n color: var(--bazaar-color-text-primary);\n flex: 0 0 auto;\n}\n\n.heroBody {\n display: flex;\n flex-direction: column;\n gap: 4px;\n min-width: 0;\n}\n\n.heroLabel {\n margin: 0;\n font-size: 0.75rem;\n font-weight: 600;\n letter-spacing: 0.08em;\n text-transform: uppercase;\n color: var(--bazaar-color-text-muted);\n}\n\n.heroValue {\n margin: 0;\n font-family: var(--bazaar-font-family-display, var(--bazaar-font-family-sans));\n font-size: 1.375rem;\n font-weight: 500;\n line-height: 1.2;\n}\n\n.heroMeta {\n margin: 0;\n font-size: 0.875rem;\n color: var(--bazaar-color-text-muted);\n}\n\n.carrier {\n display: flex;\n flex-wrap: wrap;\n gap: 12px;\n align-items: center;\n justify-content: space-between;\n padding: 14px 16px;\n border: 1px solid var(--bazaar-color-border-subtle, rgba(0, 0, 0, 0.08));\n border-radius: var(--bazaar-radius-md, 8px);\n background: var(--bazaar-color-surface-subtle, #F4F2EC);\n}\n\n.carrierRow {\n display: flex;\n flex-direction: column;\n gap: 2px;\n min-width: 0;\n}\n\n.carrierName {\n font-size: 0.875rem;\n font-weight: 600;\n}\n\n.trackingNumber {\n font-size: 0.8125rem;\n color: var(--bazaar-color-text-muted);\n font-variant-numeric: tabular-nums;\n font-family: var(--bazaar-font-family-mono, ui-monospace, Menlo, monospace);\n}\n\n.carrierActions {\n display: flex;\n gap: 8px;\n flex-wrap: wrap;\n}\n\n.primary,\n.ghost {\n padding: 9px 16px;\n border-radius: 999px;\n font-family: inherit;\n font-size: 0.8125rem;\n font-weight: 600;\n letter-spacing: 0.03em;\n cursor: pointer;\n transition: background 120ms ease, border-color 120ms ease;\n}\n\n.primary {\n background: var(--bazaar-color-text-primary, #1F1C17);\n color: var(--bazaar-color-surface-default, #fff);\n border: 1px solid var(--bazaar-color-text-primary, #1F1C17);\n}\n\n.primary:hover {\n background: #000;\n}\n\n.ghost {\n background: transparent;\n color: var(--bazaar-color-text-primary);\n border: 1px solid var(--bazaar-color-border-default, rgba(0, 0, 0, 0.14));\n}\n\n.ghost:hover {\n border-color: var(--bazaar-color-text-primary, #1F1C17);\n}\n\n.timeline {\n list-style: none;\n margin: 0;\n padding: 0;\n display: flex;\n flex-direction: column;\n}\n\n.step {\n position: relative;\n display: grid;\n grid-template-columns: 24px 1fr;\n gap: 14px;\n padding-bottom: 18px;\n}\n\n.step:last-child {\n padding-bottom: 0;\n}\n\n.step::before {\n content: '';\n position: absolute;\n left: 11px;\n top: 22px;\n bottom: -4px;\n width: 2px;\n background: var(--bazaar-color-border-subtle, rgba(0, 0, 0, 0.08));\n}\n\n.step:last-child::before {\n display: none;\n}\n\n.step-done::before {\n background: var(--bazaar-color-text-primary, #1F1C17);\n}\n\n.dot {\n width: 22px;\n height: 22px;\n border-radius: 999px;\n display: flex;\n align-items: center;\n justify-content: center;\n border: 2px solid var(--bazaar-color-border-default, rgba(0, 0, 0, 0.14));\n background: var(--bazaar-color-surface-default, #fff);\n color: var(--bazaar-color-surface-default, #fff);\n margin-top: 1px;\n}\n\n.dot-done {\n background: var(--bazaar-color-text-primary, #1F1C17);\n border-color: var(--bazaar-color-text-primary, #1F1C17);\n}\n\n.dot-current {\n background: var(--bazaar-color-surface-default, #fff);\n border-color: var(--bazaar-color-text-primary, #1F1C17);\n box-shadow: 0 0 0 4px rgba(19, 27, 40, 0.1);\n}\n\n.dot-current::after {\n content: '';\n width: 8px;\n height: 8px;\n border-radius: 999px;\n background: var(--bazaar-color-text-primary, #1F1C17);\n}\n\n.stepBody {\n display: flex;\n flex-direction: column;\n gap: 2px;\n min-width: 0;\n padding-top: 1px;\n}\n\n.stepLabel {\n margin: 0;\n font-size: 0.9375rem;\n font-weight: 500;\n}\n\n.step-upcoming .stepLabel {\n color: var(--bazaar-color-text-muted);\n font-weight: 400;\n}\n\n.stepDesc {\n margin: 0;\n font-size: 0.875rem;\n color: var(--bazaar-color-text-secondary, var(--bazaar-color-text-muted));\n}\n\n.stepMeta {\n margin: 0;\n font-size: 0.8125rem;\n color: var(--bazaar-color-text-muted);\n}\n","import type { HTMLAttributes } from 'react';\nimport { cn } from '../utils/cn';\nimport { CheckIcon, PackageIcon, TruckIcon } from './icons';\nimport type { Order, OrderStatus } from './types';\nimport styles from './OrderTracking.module.css';\n\nexport interface TrackingEvent {\n status: OrderStatus | 'label-created';\n label: string;\n description?: string;\n /** ISO timestamp. */\n at?: string;\n location?: string;\n}\n\nexport interface OrderTrackingProps extends HTMLAttributes<HTMLElement> {\n order: Order;\n /** Event history (latest last). When omitted, a default timeline is\n * synthesized from `order.status`. */\n events?: TrackingEvent[];\n onCopyTrackingNumber?: () => void;\n onOpenCarrier?: () => void;\n}\n\nconst DEFAULT_FLOW: { status: TrackingEvent['status']; label: string }[] = [\n { status: 'placed', label: 'Order placed' },\n { status: 'processing', label: 'Processing' },\n { status: 'shipped', label: 'Shipped' },\n { status: 'out-for-delivery', label: 'Out for delivery' },\n { status: 'delivered', label: 'Delivered' },\n];\n\nfunction deriveEvents(order: Order): TrackingEvent[] {\n const currentIdx = DEFAULT_FLOW.findIndex((s) => s.status === order.status);\n // Build synthetic events for every step up to and including current.\n const clamped = currentIdx === -1 ? DEFAULT_FLOW.length : currentIdx + 1;\n return DEFAULT_FLOW.slice(0, clamped).map((s) => ({\n status: s.status,\n label: s.label,\n }));\n}\n\nfunction formatDateTime(iso?: string): string | undefined {\n if (!iso) return undefined;\n const d = new Date(iso);\n if (Number.isNaN(d.getTime())) return iso;\n return d.toLocaleDateString(undefined, {\n month: 'short',\n day: 'numeric',\n hour: 'numeric',\n minute: '2-digit',\n });\n}\n\nfunction formatETA(iso?: string): string | undefined {\n if (!iso) return undefined;\n const d = new Date(iso);\n if (Number.isNaN(d.getTime())) return iso;\n return d.toLocaleDateString(undefined, {\n weekday: 'long',\n month: 'short',\n day: 'numeric',\n });\n}\n\n/**\n * OrderTracking — carrier, ETA and a step-by-step timeline for an in-flight\n * order. Renders a hero row with carrier + tracking number actions, a big\n * \"arriving\" callout and a vertical timeline with past/current/upcoming steps.\n */\nexport function OrderTracking({\n order,\n events,\n onCopyTrackingNumber,\n onOpenCarrier,\n className,\n ...rest\n}: OrderTrackingProps) {\n const timeline = events ?? deriveEvents(order);\n const flowStatuses = DEFAULT_FLOW.map((s) => s.status);\n const currentIndex = flowStatuses.indexOf(order.status as OrderStatus);\n const delivered = order.status === 'delivered';\n const eta = formatETA(order.tracking?.estimatedDelivery);\n\n return (\n <section className={cn(styles.root, className)} {...rest}>\n <header className={styles.hero}>\n <div className={styles.heroIcon} aria-hidden>\n {delivered ? (\n <PackageIcon width={22} height={22} />\n ) : (\n <TruckIcon width={22} height={22} />\n )}\n </div>\n <div className={styles.heroBody}>\n <p className={styles.heroLabel}>\n {delivered ? 'Delivered' : 'Arriving'}\n </p>\n <p className={styles.heroValue}>\n {delivered\n ? 'Your order has arrived'\n : eta ?? 'We’ll share a date as soon as it ships'}\n </p>\n <p className={styles.heroMeta}>\n Order #{order.id} · {order.lines.length}{' '}\n {order.lines.length === 1 ? 'item' : 'items'}\n </p>\n </div>\n </header>\n\n {order.tracking && (\n <div className={styles.carrier}>\n <div className={styles.carrierRow}>\n <span className={styles.carrierName}>{order.tracking.carrier}</span>\n <span className={styles.trackingNumber}>\n {order.tracking.number}\n </span>\n </div>\n <div className={styles.carrierActions}>\n {onCopyTrackingNumber && (\n <button\n type=\"button\"\n className={styles.ghost}\n onClick={onCopyTrackingNumber}\n >\n Copy tracking number\n </button>\n )}\n {(order.tracking.url || onOpenCarrier) && (\n <button\n type=\"button\"\n className={styles.primary}\n onClick={() => {\n if (onOpenCarrier) return onOpenCarrier();\n if (order.tracking?.url) window.open(order.tracking.url, '_blank');\n }}\n >\n Track on {order.tracking.carrier}\n </button>\n )}\n </div>\n </div>\n )}\n\n <ol className={styles.timeline}>\n {DEFAULT_FLOW.map((flow, i) => {\n const event = timeline.find((e) => e.status === flow.status);\n const state: 'done' | 'current' | 'upcoming' =\n i < currentIndex ? 'done' : i === currentIndex ? 'current' : 'upcoming';\n return (\n <li\n key={flow.status}\n className={cn(styles.step, styles[`step-${state}`])}\n >\n <span\n className={cn(styles.dot, styles[`dot-${state}`])}\n aria-hidden\n >\n {state === 'done' && <CheckIcon width={10} height={10} />}\n </span>\n <div className={styles.stepBody}>\n <p className={styles.stepLabel}>{flow.label}</p>\n {event?.description && (\n <p className={styles.stepDesc}>{event.description}</p>\n )}\n {(event?.at || event?.location) && (\n <p className={styles.stepMeta}>\n {formatDateTime(event.at)}\n {event.at && event.location ? ' · ' : ''}\n {event.location}\n </p>\n )}\n </div>\n </li>\n );\n })}\n </ol>\n </section>\n );\n}\n",".root {\n font-family: var(--bazaar-font-family-sans);\n color: var(--bazaar-color-text-primary);\n display: flex;\n flex-direction: column;\n gap: 20px;\n}\n\n.header {\n display: flex;\n align-items: baseline;\n justify-content: space-between;\n}\n\n.title {\n font-family: var(--bazaar-font-family-display, var(--bazaar-font-family-sans));\n font-size: 1.5rem;\n font-weight: 500;\n margin: 0;\n}\n\n.count {\n font-size: 1rem;\n font-weight: 400;\n color: var(--bazaar-color-text-muted);\n margin-left: 6px;\n}\n\n.grid {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));\n gap: 16px;\n}\n\n.card {\n display: flex;\n flex-direction: column;\n gap: 12px;\n padding: 18px;\n border: 1px solid var(--bazaar-color-border-default, rgba(0, 0, 0, 0.1));\n border-radius: var(--bazaar-radius-lg, 12px);\n background: var(--bazaar-color-surface-default, #fff);\n min-height: 200px;\n}\n\n.cardDefault {\n border-color: var(--bazaar-color-text-primary, #1F1C17);\n box-shadow: 0 0 0 1px var(--bazaar-color-text-primary, #1F1C17);\n}\n\n.cardHead {\n display: flex;\n align-items: center;\n justify-content: space-between;\n}\n\n.icon {\n width: 32px;\n height: 32px;\n border-radius: 999px;\n background: var(--bazaar-color-surface-subtle, #F4F2EC);\n display: flex;\n align-items: center;\n justify-content: center;\n}\n\n.badge {\n font-size: 0.6875rem;\n font-weight: 600;\n letter-spacing: 0.08em;\n text-transform: uppercase;\n color: var(--bazaar-color-text-primary);\n padding: 3px 10px;\n border-radius: 999px;\n background: rgba(19, 27, 40, 0.08);\n}\n\n.body {\n flex: 1 1 auto;\n display: flex;\n flex-direction: column;\n gap: 2px;\n font-size: 0.9375rem;\n line-height: 1.4;\n}\n\n.name {\n margin: 0;\n font-weight: 600;\n}\n\n.line {\n margin: 0;\n color: var(--bazaar-color-text-secondary, var(--bazaar-color-text-primary));\n}\n\n.phone {\n margin: 6px 0 0;\n color: var(--bazaar-color-text-muted);\n font-size: 0.875rem;\n}\n\n.actions {\n display: flex;\n gap: 14px;\n padding-top: 8px;\n border-top: 1px solid var(--bazaar-color-border-subtle, rgba(0, 0, 0, 0.06));\n flex-wrap: wrap;\n}\n\n.link {\n background: none;\n border: none;\n padding: 0;\n font-family: inherit;\n font-size: 0.8125rem;\n font-weight: 500;\n color: var(--bazaar-color-text-primary);\n text-decoration: underline;\n text-underline-offset: 3px;\n cursor: pointer;\n}\n\n.link:hover {\n opacity: 0.7;\n}\n\n.addCard {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n gap: 10px;\n padding: 18px;\n border: 1px dashed var(--bazaar-color-border-default, rgba(0, 0, 0, 0.2));\n border-radius: var(--bazaar-radius-lg, 12px);\n background: transparent;\n color: var(--bazaar-color-text-muted);\n font-family: inherit;\n font-size: 0.9375rem;\n font-weight: 500;\n min-height: 200px;\n cursor: pointer;\n transition: border-color 120ms ease, color 120ms ease;\n}\n\n.addCard:hover {\n border-color: var(--bazaar-color-text-primary, #1F1C17);\n color: var(--bazaar-color-text-primary);\n}\n\n.addIcon {\n width: 40px;\n height: 40px;\n border-radius: 999px;\n background: var(--bazaar-color-surface-subtle, #F4F2EC);\n display: flex;\n align-items: center;\n justify-content: center;\n color: var(--bazaar-color-text-primary);\n}\n\n.addLabel {\n letter-spacing: 0.02em;\n}\n","import type { HTMLAttributes } from 'react';\nimport { cn } from '../utils/cn';\nimport { PlusIcon, MapPinIcon } from './icons';\nimport type { Address } from './types';\nimport styles from './AddressBook.module.css';\n\nexport interface AddressBookProps extends HTMLAttributes<HTMLElement> {\n addresses: Address[];\n title?: string;\n onEdit?: (address: Address) => void;\n onRemove?: (address: Address) => void;\n onSetDefault?: (address: Address) => void;\n onAdd?: () => void;\n}\n\n/**\n * AddressBook — grid of saved shipping/billing addresses with a \"default\"\n * badge and per-card edit/remove/set-as-default actions. Includes a dashed\n * \"Add address\" tile as the final cell.\n */\nexport function AddressBook({\n addresses,\n title = 'Addresses',\n onEdit,\n onRemove,\n onSetDefault,\n onAdd,\n className,\n ...rest\n}: AddressBookProps) {\n return (\n <section className={cn(styles.root, className)} {...rest}>\n <header className={styles.header}>\n <h2 className={styles.title}>\n {title} <span className={styles.count}>({addresses.length})</span>\n </h2>\n </header>\n\n <div className={styles.grid}>\n {addresses.map((addr) => (\n <article\n key={addr.id ?? `${addr.name}-${addr.line1}`}\n className={cn(styles.card, addr.isDefault && styles.cardDefault)}\n >\n <header className={styles.cardHead}>\n <div className={styles.icon} aria-hidden>\n <MapPinIcon width={16} height={16} />\n </div>\n {addr.isDefault && <span className={styles.badge}>Default</span>}\n </header>\n <div className={styles.body}>\n <p className={styles.name}>{addr.name}</p>\n <p className={styles.line}>{addr.line1}</p>\n {addr.line2 && <p className={styles.line}>{addr.line2}</p>}\n <p className={styles.line}>\n {addr.city}, {addr.region} {addr.postalCode}\n </p>\n <p className={styles.line}>{addr.country}</p>\n {addr.phone && <p className={styles.phone}>{addr.phone}</p>}\n </div>\n <footer className={styles.actions}>\n {onEdit && (\n <button\n type=\"button\"\n className={styles.link}\n onClick={() => onEdit(addr)}\n >\n Edit\n </button>\n )}\n {onRemove && !addr.isDefault && (\n <button\n type=\"button\"\n className={styles.link}\n onClick={() => onRemove(addr)}\n >\n Remove\n </button>\n )}\n {onSetDefault && !addr.isDefault && (\n <button\n type=\"button\"\n className={styles.link}\n onClick={() => onSetDefault(addr)}\n >\n Set as default\n </button>\n )}\n </footer>\n </article>\n ))}\n\n {onAdd && (\n <button type=\"button\" className={styles.addCard} onClick={onAdd}>\n <span className={styles.addIcon} aria-hidden>\n <PlusIcon width={18} height={18} />\n </span>\n <span className={styles.addLabel}>Add new address</span>\n </button>\n )}\n </div>\n </section>\n );\n}\n",".root {\n font-family: var(--bazaar-font-family-sans);\n color: var(--bazaar-color-text-primary);\n display: flex;\n flex-direction: column;\n gap: 20px;\n}\n\n.header {\n display: flex;\n align-items: baseline;\n justify-content: space-between;\n}\n\n.title {\n font-family: var(--bazaar-font-family-display, var(--bazaar-font-family-sans));\n font-size: 1.5rem;\n font-weight: 500;\n margin: 0;\n}\n\n.count {\n font-size: 1rem;\n font-weight: 400;\n color: var(--bazaar-color-text-muted);\n margin-left: 6px;\n}\n\n.list {\n list-style: none;\n margin: 0;\n padding: 0;\n display: flex;\n flex-direction: column;\n gap: 12px;\n}\n\n.row {\n display: grid;\n grid-template-columns: auto 1fr auto;\n gap: 14px;\n align-items: center;\n padding: 16px;\n border: 1px solid var(--bazaar-color-border-default, rgba(0, 0, 0, 0.1));\n border-radius: var(--bazaar-radius-lg, 12px);\n background: var(--bazaar-color-surface-default, #fff);\n}\n\n.rowDefault {\n border-color: var(--bazaar-color-text-primary, #1F1C17);\n box-shadow: 0 0 0 1px var(--bazaar-color-text-primary, #1F1C17);\n}\n\n.brand {\n width: 44px;\n height: 30px;\n border-radius: 6px;\n display: flex;\n align-items: center;\n justify-content: center;\n color: #fff;\n flex: 0 0 auto;\n}\n\n.body {\n display: flex;\n flex-direction: column;\n gap: 2px;\n min-width: 0;\n}\n\n.nameRow {\n display: flex;\n gap: 8px;\n align-items: center;\n flex-wrap: wrap;\n}\n\n.brandName {\n font-size: 0.9375rem;\n font-weight: 600;\n}\n\n.last4 {\n font-size: 0.9375rem;\n color: var(--bazaar-color-text-secondary, var(--bazaar-color-text-primary));\n font-variant-numeric: tabular-nums;\n letter-spacing: 0.05em;\n}\n\n.badge {\n font-size: 0.6875rem;\n font-weight: 600;\n letter-spacing: 0.08em;\n text-transform: uppercase;\n color: var(--bazaar-color-text-primary);\n padding: 2px 8px;\n border-radius: 999px;\n background: rgba(19, 27, 40, 0.08);\n}\n\n.meta {\n display: flex;\n gap: 10px;\n flex-wrap: wrap;\n font-size: 0.8125rem;\n color: var(--bazaar-color-text-muted);\n}\n\n.label {\n max-width: 320px;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.expires {\n font-variant-numeric: tabular-nums;\n}\n\n.actions {\n display: flex;\n gap: 12px;\n flex-wrap: wrap;\n justify-content: flex-end;\n}\n\n.link {\n background: none;\n border: none;\n padding: 0;\n font-family: inherit;\n font-size: 0.8125rem;\n font-weight: 500;\n color: var(--bazaar-color-text-primary);\n text-decoration: underline;\n text-underline-offset: 3px;\n cursor: pointer;\n}\n\n.link:hover {\n opacity: 0.7;\n}\n\n.addRow {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 10px;\n padding: 14px;\n border: 1px dashed var(--bazaar-color-border-default, rgba(0, 0, 0, 0.2));\n border-radius: var(--bazaar-radius-lg, 12px);\n background: transparent;\n color: var(--bazaar-color-text-primary);\n font-family: inherit;\n font-size: 0.9375rem;\n font-weight: 500;\n cursor: pointer;\n transition: border-color 120ms ease;\n}\n\n.addRow:hover {\n border-color: var(--bazaar-color-text-primary, #1F1C17);\n}\n\n.addIcon {\n width: 28px;\n height: 28px;\n border-radius: 999px;\n background: var(--bazaar-color-surface-subtle, #F4F2EC);\n display: flex;\n align-items: center;\n justify-content: center;\n}\n\n@media (max-width: 540px) {\n .row {\n grid-template-columns: auto 1fr;\n }\n .actions {\n grid-column: 1 / -1;\n justify-content: flex-start;\n padding-top: 6px;\n border-top: 1px solid var(--bazaar-color-border-subtle, rgba(0, 0, 0, 0.06));\n }\n}\n","import type { HTMLAttributes } from 'react';\nimport { cn } from '../utils/cn';\nimport { CreditCardIcon, PlusIcon } from './icons';\nimport type { PaymentBrand, PaymentMethod } from './types';\nimport styles from './PaymentMethodsList.module.css';\n\nexport interface PaymentMethodsListProps extends HTMLAttributes<HTMLElement> {\n methods: PaymentMethod[];\n defaultMethodId?: string;\n title?: string;\n onEdit?: (method: PaymentMethod) => void;\n onRemove?: (method: PaymentMethod) => void;\n onSetDefault?: (method: PaymentMethod) => void;\n onAdd?: () => void;\n}\n\nconst BRAND_LABEL: Record<PaymentBrand, string> = {\n visa: 'Visa',\n mastercard: 'Mastercard',\n amex: 'American Express',\n discover: 'Discover',\n paypal: 'PayPal',\n 'apple-pay': 'Apple Pay',\n 'google-pay': 'Google Pay',\n 'shop-pay': 'Shop Pay',\n klarna: 'Klarna',\n afterpay: 'Afterpay',\n};\n\nconst BRAND_COLOR: Partial<Record<PaymentBrand, string>> = {\n visa: '#1A1F71',\n mastercard: '#EB001B',\n amex: '#006FCF',\n discover: '#FF6000',\n paypal: '#003087',\n 'apple-pay': '#000',\n 'google-pay': '#4285F4',\n 'shop-pay': '#5A31F4',\n klarna: '#FFB3C7',\n afterpay: '#B2FCE4',\n};\n\n/**\n * PaymentMethodsList — saved cards and wallets with default badge and\n * per-row edit/remove/set-default actions. Includes a final \"Add payment\n * method\" row.\n */\nexport function PaymentMethodsList({\n methods,\n defaultMethodId,\n title = 'Payment methods',\n onEdit,\n onRemove,\n onSetDefault,\n onAdd,\n className,\n ...rest\n}: PaymentMethodsListProps) {\n return (\n <section className={cn(styles.root, className)} {...rest}>\n <header className={styles.header}>\n <h2 className={styles.title}>\n {title} <span className={styles.count}>({methods.length})</span>\n </h2>\n </header>\n\n <ul className={styles.list}>\n {methods.map((m) => {\n const isDefault = m.id === defaultMethodId;\n return (\n <li key={m.id} className={cn(styles.row, isDefault && styles.rowDefault)}>\n <span\n className={styles.brand}\n style={{ background: BRAND_COLOR[m.brand] ?? '#131B28' }}\n aria-hidden\n >\n <CreditCardIcon width={16} height={16} />\n </span>\n <div className={styles.body}>\n <div className={styles.nameRow}>\n <span className={styles.brandName}>{BRAND_LABEL[m.brand]}</span>\n {m.last4 && <span className={styles.last4}>•••• {m.last4}</span>}\n {isDefault && <span className={styles.badge}>Default</span>}\n </div>\n <div className={styles.meta}>\n <span className={styles.label}>{m.label}</span>\n {m.expires && (\n <span className={styles.expires}>Exp {m.expires}</span>\n )}\n </div>\n </div>\n <div className={styles.actions}>\n {onSetDefault && !isDefault && (\n <button\n type=\"button\"\n className={styles.link}\n onClick={() => onSetDefault(m)}\n >\n Set default\n </button>\n )}\n {onEdit && (\n <button\n type=\"button\"\n className={styles.link}\n onClick={() => onEdit(m)}\n >\n Edit\n </button>\n )}\n {onRemove && !isDefault && (\n <button\n type=\"button\"\n className={styles.link}\n onClick={() => onRemove(m)}\n >\n Remove\n </button>\n )}\n </div>\n </li>\n );\n })}\n </ul>\n\n {onAdd && (\n <button type=\"button\" className={styles.addRow} onClick={onAdd}>\n <span className={styles.addIcon} aria-hidden>\n <PlusIcon width={16} height={16} />\n </span>\n Add payment method\n </button>\n )}\n </section>\n );\n}\n",".root {\n font-family: var(--bazaar-font-family-sans);\n color: var(--bazaar-color-text-primary);\n display: flex;\n flex-direction: column;\n gap: 20px;\n}\n\n.header {\n display: flex;\n align-items: baseline;\n justify-content: space-between;\n}\n\n.title {\n font-family: var(--bazaar-font-family-display, var(--bazaar-font-family-sans));\n font-size: 1.5rem;\n font-weight: 500;\n margin: 0;\n}\n\n.count {\n font-size: 1rem;\n font-weight: 400;\n color: var(--bazaar-color-text-muted);\n margin-left: 6px;\n}\n\n.list {\n list-style: none;\n margin: 0;\n padding: 0;\n display: flex;\n flex-direction: column;\n gap: 12px;\n}\n\n.row {\n display: grid;\n grid-template-columns: 80px 1fr auto;\n gap: 16px;\n padding: 16px;\n border: 1px solid var(--bazaar-color-border-default, rgba(0, 0, 0, 0.1));\n border-radius: var(--bazaar-radius-lg, 12px);\n background: var(--bazaar-color-surface-default, #fff);\n align-items: flex-start;\n}\n\n.rowDim {\n opacity: 0.72;\n}\n\n.thumb {\n width: 80px;\n height: 80px;\n border-radius: var(--bazaar-radius-md, 8px);\n overflow: hidden;\n background: var(--bazaar-color-surface-subtle, #F4F2EC);\n flex: 0 0 auto;\n}\n\n.body {\n display: flex;\n flex-direction: column;\n gap: 6px;\n min-width: 0;\n}\n\n.titleRow {\n display: flex;\n flex-direction: column;\n gap: 2px;\n}\n\n.brand {\n margin: 0;\n font-size: 0.75rem;\n font-weight: 600;\n letter-spacing: 0.08em;\n text-transform: uppercase;\n color: var(--bazaar-color-text-muted);\n}\n\n.productName {\n margin: 0;\n font-size: 1rem;\n font-weight: 500;\n}\n\n.variant {\n margin: 0;\n font-size: 0.8125rem;\n color: var(--bazaar-color-text-muted);\n}\n\n.meta {\n display: flex;\n gap: 8px;\n flex-wrap: wrap;\n align-items: center;\n font-size: 0.875rem;\n color: var(--bazaar-color-text-secondary, var(--bazaar-color-text-primary));\n}\n\n.price {\n font-weight: 600;\n font-variant-numeric: tabular-nums;\n}\n\n.sep {\n color: var(--bazaar-color-text-muted);\n}\n\n.next {\n display: inline-flex;\n gap: 4px;\n align-items: center;\n color: var(--bazaar-color-text-muted);\n}\n\n.status {\n display: inline-flex;\n align-self: flex-start;\n padding: 2px 10px;\n border-radius: 999px;\n font-size: 0.6875rem;\n font-weight: 600;\n letter-spacing: 0.08em;\n text-transform: uppercase;\n}\n\n.status-active {\n background: rgba(27, 104, 69, 0.12);\n color: #1B6845;\n}\n\n.status-paused {\n background: rgba(19, 27, 40, 0.08);\n color: var(--bazaar-color-text-primary);\n}\n\n.status-cancelled {\n background: rgba(0, 0, 0, 0.06);\n color: var(--bazaar-color-text-muted);\n}\n\n.actions {\n display: flex;\n gap: 12px;\n flex-wrap: wrap;\n justify-content: flex-end;\n padding-top: 4px;\n}\n\n.link {\n background: none;\n border: none;\n padding: 0;\n font-family: inherit;\n font-size: 0.8125rem;\n font-weight: 500;\n color: var(--bazaar-color-text-primary);\n text-decoration: underline;\n text-underline-offset: 3px;\n cursor: pointer;\n}\n\n.link:hover {\n opacity: 0.7;\n}\n\n.linkDanger {\n color: #A33A2A;\n}\n\n@media (max-width: 640px) {\n .row {\n grid-template-columns: 64px 1fr;\n }\n .thumb {\n width: 64px;\n height: 64px;\n }\n .actions {\n grid-column: 1 / -1;\n justify-content: flex-start;\n padding-top: 8px;\n border-top: 1px solid var(--bazaar-color-border-subtle, rgba(0, 0, 0, 0.06));\n }\n}\n","import type { HTMLAttributes } from 'react';\nimport { cn } from '../utils/cn';\nimport { MediaPlaceholder } from './MediaPlaceholder';\nimport { formatMoney } from './money';\nimport { ClockIcon } from './icons';\nimport type { Money, ProductImage } from './types';\nimport styles from './SubscriptionsList.module.css';\n\nexport type SubscriptionCadence =\n | 'weekly'\n | 'biweekly'\n | 'monthly'\n | 'bimonthly'\n | 'quarterly';\n\nexport type SubscriptionStatus = 'active' | 'paused' | 'cancelled';\n\nexport interface Subscription {\n id: string;\n title: string;\n brand?: string;\n image?: ProductImage;\n price: Money;\n cadence: SubscriptionCadence;\n /** ISO — next scheduled ship date. */\n nextDelivery?: string;\n status: SubscriptionStatus;\n /** Optional variant summary like \"Sand · Medium\". */\n variantSummary?: string;\n}\n\nexport interface SubscriptionsListProps\n extends Omit<HTMLAttributes<HTMLElement>, 'onPause' | 'onResume'> {\n subscriptions: Subscription[];\n title?: string;\n onPause?: (sub: Subscription) => void;\n onResume?: (sub: Subscription) => void;\n onSkip?: (sub: Subscription) => void;\n onCancel?: (sub: Subscription) => void;\n onEdit?: (sub: Subscription) => void;\n}\n\nconst CADENCE_LABEL: Record<SubscriptionCadence, string> = {\n weekly: 'Every week',\n biweekly: 'Every 2 weeks',\n monthly: 'Every month',\n bimonthly: 'Every 2 months',\n quarterly: 'Every 3 months',\n};\n\nconst STATUS_LABEL: Record<SubscriptionStatus, string> = {\n active: 'Active',\n paused: 'Paused',\n cancelled: 'Cancelled',\n};\n\nfunction formatDate(iso?: string): string | undefined {\n if (!iso) return undefined;\n const d = new Date(iso);\n if (Number.isNaN(d.getTime())) return iso;\n return d.toLocaleDateString(undefined, {\n weekday: 'short',\n month: 'short',\n day: 'numeric',\n });\n}\n\n/**\n * SubscriptionsList — recurring deliveries with cadence, next-ship date and\n * pause/skip/cancel actions. Muted styling applied when paused or cancelled.\n */\nexport function SubscriptionsList({\n subscriptions,\n title = 'Subscriptions',\n onPause,\n onResume,\n onSkip,\n onCancel,\n onEdit,\n className,\n ...rest\n}: SubscriptionsListProps) {\n return (\n <section className={cn(styles.root, className)} {...rest}>\n <header className={styles.header}>\n <h2 className={styles.title}>\n {title}{' '}\n <span className={styles.count}>({subscriptions.length})</span>\n </h2>\n </header>\n\n <ul className={styles.list}>\n {subscriptions.map((s) => {\n const dim = s.status !== 'active';\n return (\n <li\n key={s.id}\n className={cn(styles.row, dim && styles.rowDim)}\n >\n <div className={styles.thumb}>\n <MediaPlaceholder\n src={s.image?.src}\n alt={s.image?.alt ?? s.title}\n seed={s.image?.seed}\n aspectRatio=\"1 / 1\"\n />\n </div>\n\n <div className={styles.body}>\n <div className={styles.titleRow}>\n {s.brand && <p className={styles.brand}>{s.brand}</p>}\n <p className={styles.productName}>{s.title}</p>\n {s.variantSummary && (\n <p className={styles.variant}>{s.variantSummary}</p>\n )}\n </div>\n <div className={styles.meta}>\n <span className={styles.price}>{formatMoney(s.price)}</span>\n <span className={styles.sep} aria-hidden>·</span>\n <span>{CADENCE_LABEL[s.cadence]}</span>\n {s.nextDelivery && s.status === 'active' && (\n <>\n <span className={styles.sep} aria-hidden>·</span>\n <span className={styles.next}>\n <ClockIcon width={12} height={12} /> Next{' '}\n {formatDate(s.nextDelivery)}\n </span>\n </>\n )}\n </div>\n <span\n className={cn(\n styles.status,\n styles[`status-${s.status}`],\n )}\n >\n {STATUS_LABEL[s.status]}\n </span>\n </div>\n\n <div className={styles.actions}>\n {s.status === 'active' && onSkip && (\n <button\n type=\"button\"\n className={styles.link}\n onClick={() => onSkip(s)}\n >\n Skip next\n </button>\n )}\n {s.status === 'active' && onPause && (\n <button\n type=\"button\"\n className={styles.link}\n onClick={() => onPause(s)}\n >\n Pause\n </button>\n )}\n {s.status === 'paused' && onResume && (\n <button\n type=\"button\"\n className={styles.link}\n onClick={() => onResume(s)}\n >\n Resume\n </button>\n )}\n {onEdit && s.status !== 'cancelled' && (\n <button\n type=\"button\"\n className={styles.link}\n onClick={() => onEdit(s)}\n >\n Edit\n </button>\n )}\n {s.status !== 'cancelled' && onCancel && (\n <button\n type=\"button\"\n className={cn(styles.link, styles.linkDanger)}\n onClick={() => onCancel(s)}\n >\n Cancel\n </button>\n )}\n </div>\n </li>\n );\n })}\n </ul>\n </section>\n );\n}\n",".root {\n font-family: var(--bazaar-font-family-sans);\n color: var(--bazaar-color-text-primary);\n display: flex;\n flex-direction: column;\n gap: 22px;\n padding: 24px;\n border: 1px solid var(--bazaar-color-border-default, rgba(0, 0, 0, 0.1));\n border-radius: var(--bazaar-radius-lg, 12px);\n background: var(--bazaar-color-surface-default, #fff);\n}\n\n.header {\n display: flex;\n justify-content: space-between;\n align-items: flex-start;\n gap: 12px;\n flex-wrap: wrap;\n}\n\n.program {\n margin: 0;\n font-family: var(--bazaar-font-family-display, var(--bazaar-font-family-sans));\n font-size: 1.25rem;\n font-weight: 500;\n}\n\n.since {\n margin: 2px 0 0;\n font-size: 0.8125rem;\n color: var(--bazaar-color-text-muted);\n}\n\n.pointsBlock {\n display: flex;\n align-items: baseline;\n gap: 6px;\n}\n\n.pointsValue {\n font-family: var(--bazaar-font-family-display, var(--bazaar-font-family-sans));\n font-size: 2rem;\n font-weight: 500;\n line-height: 1;\n font-variant-numeric: tabular-nums;\n}\n\n.pointsLabel {\n font-size: 0.875rem;\n color: var(--bazaar-color-text-muted);\n text-transform: uppercase;\n letter-spacing: 0.08em;\n}\n\n.tierCard {\n display: flex;\n flex-direction: column;\n gap: 10px;\n padding: 18px;\n border-radius: var(--bazaar-radius-md, 8px);\n background: var(--bazaar-color-surface-subtle, #F4F2EC);\n}\n\n.tierRow {\n display: flex;\n justify-content: space-between;\n align-items: baseline;\n gap: 12px;\n}\n\n.tierName {\n font-size: 1.0625rem;\n font-weight: 600;\n}\n\n.tierNext {\n font-size: 0.8125rem;\n color: var(--bazaar-color-text-muted);\n font-variant-numeric: tabular-nums;\n}\n\n.track {\n position: relative;\n height: 6px;\n border-radius: 999px;\n background: rgba(19, 27, 40, 0.1);\n overflow: hidden;\n}\n\n.fill {\n position: absolute;\n inset: 0;\n background: var(--bazaar-color-text-primary, #1F1C17);\n border-radius: 999px;\n transition: width 300ms ease;\n}\n\n.tierList {\n list-style: none;\n margin: 4px 0 0;\n padding: 0;\n display: flex;\n justify-content: space-between;\n gap: 4px;\n}\n\n.tierPip {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 4px;\n color: var(--bazaar-color-text-muted);\n font-size: 0.75rem;\n font-weight: 500;\n letter-spacing: 0.02em;\n}\n\n.tierPipDot {\n width: 8px;\n height: 8px;\n border-radius: 999px;\n background: rgba(19, 27, 40, 0.2);\n}\n\n.tierPipReached .tierPipDot {\n background: var(--bazaar-color-text-primary, #1F1C17);\n}\n\n.tierPipReached {\n color: var(--bazaar-color-text-primary);\n}\n\n.tierPipCurrent .tierPipDot {\n box-shadow: 0 0 0 4px rgba(19, 27, 40, 0.15);\n}\n\n.tierPipCurrent {\n font-weight: 600;\n}\n\n.perks {\n display: flex;\n flex-direction: column;\n gap: 12px;\n}\n\n.perksTitle {\n margin: 0;\n font-size: 0.75rem;\n font-weight: 600;\n letter-spacing: 0.08em;\n text-transform: uppercase;\n color: var(--bazaar-color-text-muted);\n}\n\n.perksList {\n list-style: none;\n margin: 0;\n padding: 0;\n display: flex;\n flex-direction: column;\n gap: 10px;\n}\n\n.perk {\n display: grid;\n grid-template-columns: 32px 1fr;\n gap: 12px;\n align-items: flex-start;\n}\n\n.perkLocked {\n opacity: 0.55;\n}\n\n.perkIcon {\n width: 28px;\n height: 28px;\n border-radius: 999px;\n background: rgba(19, 27, 40, 0.08);\n display: flex;\n align-items: center;\n justify-content: center;\n color: var(--bazaar-color-text-primary);\n margin-top: 2px;\n}\n\n.perkBody {\n display: flex;\n flex-direction: column;\n gap: 2px;\n}\n\n.perkLabel {\n margin: 0;\n font-size: 0.9375rem;\n font-weight: 500;\n}\n\n.perkDesc {\n margin: 0;\n font-size: 0.8125rem;\n color: var(--bazaar-color-text-muted);\n}\n\n.perkLock {\n margin: 2px 0 0;\n font-size: 0.75rem;\n font-weight: 500;\n letter-spacing: 0.04em;\n text-transform: uppercase;\n color: var(--bazaar-color-text-muted);\n}\n\n.cta {\n padding-top: 4px;\n}\n","import type { HTMLAttributes, ReactNode } from 'react';\nimport { cn } from '../utils/cn';\nimport { GiftIcon, CheckIcon } from './icons';\nimport styles from './LoyaltyPanel.module.css';\n\nexport interface LoyaltyTier {\n id: string;\n name: string;\n /** Points needed to unlock this tier. */\n threshold: number;\n}\n\nexport interface LoyaltyPerk {\n label: string;\n description?: string;\n /** Lowest tier that unlocks the perk. Defaults to the first tier. */\n unlockTierId?: string;\n}\n\nexport interface LoyaltyPanelProps extends HTMLAttributes<HTMLElement> {\n /** Program name — e.g., \"House Circle\". */\n programName?: string;\n memberSince?: string;\n /** Ordered low→high. */\n tiers: LoyaltyTier[];\n currentTierId: string;\n points: number;\n perks?: LoyaltyPerk[];\n /** Optional call-to-action — e.g., open rewards catalog. */\n cta?: ReactNode;\n}\n\n/**\n * LoyaltyPanel — tier, progress-to-next-tier, current points, and a list\n * of perks with unlocked/locked state.\n */\nexport function LoyaltyPanel({\n programName = 'Rewards',\n memberSince,\n tiers,\n currentTierId,\n points,\n perks = [],\n cta,\n className,\n ...rest\n}: LoyaltyPanelProps) {\n const currentIdx = Math.max(\n 0,\n tiers.findIndex((t) => t.id === currentTierId),\n );\n const current = tiers[currentIdx];\n const next = tiers[currentIdx + 1];\n const tierFloor = current?.threshold ?? 0;\n const tierCeil = next?.threshold;\n const span = tierCeil ? tierCeil - tierFloor : 0;\n const inTierProgress = tierCeil ? Math.max(0, points - tierFloor) : 0;\n const pct = tierCeil\n ? Math.min(100, Math.round((inTierProgress / span) * 100))\n : 100;\n const pointsToNext = tierCeil ? Math.max(0, tierCeil - points) : 0;\n\n return (\n <section className={cn(styles.root, className)} {...rest}>\n <header className={styles.header}>\n <div>\n <p className={styles.program}>{programName}</p>\n {memberSince && (\n <p className={styles.since}>Member since {memberSince}</p>\n )}\n </div>\n <div className={styles.pointsBlock}>\n <span className={styles.pointsValue}>{points.toLocaleString()}</span>\n <span className={styles.pointsLabel}>points</span>\n </div>\n </header>\n\n <div className={styles.tierCard}>\n <div className={styles.tierRow}>\n <span className={styles.tierName}>{current?.name ?? '—'}</span>\n {next ? (\n <span className={styles.tierNext}>\n {pointsToNext.toLocaleString()} pts to {next.name}\n </span>\n ) : (\n <span className={styles.tierNext}>Top tier</span>\n )}\n </div>\n <div className={styles.track}>\n <div\n className={styles.fill}\n style={{ width: `${pct}%` }}\n role=\"progressbar\"\n aria-valuenow={pct}\n aria-valuemin={0}\n aria-valuemax={100}\n />\n </div>\n <ol className={styles.tierList}>\n {tiers.map((t, i) => (\n <li\n key={t.id}\n className={cn(\n styles.tierPip,\n i <= currentIdx && styles.tierPipReached,\n i === currentIdx && styles.tierPipCurrent,\n )}\n >\n <span className={styles.tierPipDot} aria-hidden />\n <span className={styles.tierPipLabel}>{t.name}</span>\n </li>\n ))}\n </ol>\n </div>\n\n {perks.length > 0 && (\n <div className={styles.perks}>\n <h3 className={styles.perksTitle}>Your perks</h3>\n <ul className={styles.perksList}>\n {perks.map((perk) => {\n const unlockIdx = perk.unlockTierId\n ? tiers.findIndex((t) => t.id === perk.unlockTierId)\n : 0;\n const unlocked = unlockIdx <= currentIdx;\n const unlockTier = tiers[unlockIdx];\n return (\n <li\n key={perk.label}\n className={cn(styles.perk, !unlocked && styles.perkLocked)}\n >\n <span className={styles.perkIcon} aria-hidden>\n {unlocked ? (\n <CheckIcon width={14} height={14} />\n ) : (\n <GiftIcon width={14} height={14} />\n )}\n </span>\n <div className={styles.perkBody}>\n <p className={styles.perkLabel}>{perk.label}</p>\n {perk.description && (\n <p className={styles.perkDesc}>{perk.description}</p>\n )}\n {!unlocked && unlockTier && (\n <p className={styles.perkLock}>\n Unlocks at {unlockTier.name}\n </p>\n )}\n </div>\n </li>\n );\n })}\n </ul>\n </div>\n )}\n\n {cta && <div className={styles.cta}>{cta}</div>}\n </section>\n );\n}\n",".root {\n font-family: var(--bazaar-font-family-sans);\n color: var(--bazaar-color-text-primary);\n display: flex;\n flex-direction: column;\n gap: 14px;\n}\n\n.eyebrow {\n margin: 0;\n font-size: 0.75rem;\n font-weight: 600;\n letter-spacing: 0.1em;\n text-transform: uppercase;\n color: var(--bazaar-color-text-muted);\n}\n\n.list {\n list-style: none;\n margin: 0;\n padding: 0;\n}\n\n.layout-card .list {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));\n gap: 12px;\n}\n\n.layout-card .item {\n display: flex;\n gap: 12px;\n padding: 16px;\n border: 1px solid var(--bazaar-color-border-default, rgba(0, 0, 0, 0.1));\n border-radius: var(--bazaar-radius-md, 8px);\n background: var(--bazaar-color-surface-default, #fff);\n}\n\n.layout-inline .list {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: 0;\n}\n\n.layout-inline .item {\n display: flex;\n gap: 10px;\n padding: 10px 20px;\n position: relative;\n align-items: center;\n flex: 1 1 180px;\n}\n\n.layout-inline .item:not(:first-child)::before {\n content: '';\n position: absolute;\n left: 0;\n top: 25%;\n bottom: 25%;\n width: 1px;\n background: var(--bazaar-color-border-subtle, rgba(0, 0, 0, 0.08));\n}\n\n.icon {\n width: 36px;\n height: 36px;\n border-radius: 999px;\n background: var(--bazaar-color-surface-subtle, #F4F2EC);\n display: flex;\n align-items: center;\n justify-content: center;\n color: var(--bazaar-color-text-primary);\n flex: 0 0 auto;\n}\n\n.layout-inline .icon {\n width: 32px;\n height: 32px;\n}\n\n.body {\n display: flex;\n flex-direction: column;\n gap: 2px;\n min-width: 0;\n}\n\n.label {\n margin: 0;\n font-size: 0.9375rem;\n font-weight: 600;\n line-height: 1.2;\n}\n\n.sublabel {\n margin: 0;\n font-size: 0.8125rem;\n color: var(--bazaar-color-text-muted);\n line-height: 1.35;\n}\n","import type { HTMLAttributes, ReactNode } from 'react';\nimport { cn } from '../utils/cn';\nimport {\n TruckIcon,\n ReturnIcon,\n ShieldCheckIcon,\n LockIcon,\n LeafIcon,\n PackageIcon,\n} from './icons';\nimport styles from './TrustBadgeCluster.module.css';\n\nexport interface TrustBadgeItem {\n id: string;\n icon?: ReactNode;\n label: string;\n sublabel?: string;\n}\n\nexport interface TrustBadgeClusterProps\n extends HTMLAttributes<HTMLElement> {\n items: TrustBadgeItem[];\n /** 'card' places each badge in its own bordered cell; 'inline' renders a\n * flat icon-and-text row separated by thin dividers. */\n layout?: 'card' | 'inline';\n /** Label displayed above the cluster (optional). */\n eyebrow?: string;\n}\n\n/**\n * Convenience preset — spread `DEFAULT_TRUST_BADGES` into `items` to get\n * Shipping, Returns, Secure, Sustainability, Packaging out of the box.\n */\nexport const DEFAULT_TRUST_BADGES: TrustBadgeItem[] = [\n {\n id: 'shipping',\n icon: <TruckIcon width={20} height={20} />,\n label: 'Free shipping',\n sublabel: 'On orders over $75',\n },\n {\n id: 'returns',\n icon: <ReturnIcon width={20} height={20} />,\n label: '60-day returns',\n sublabel: 'No questions asked',\n },\n {\n id: 'secure',\n icon: <LockIcon width={20} height={20} />,\n label: 'Secure checkout',\n sublabel: '256-bit encryption',\n },\n {\n id: 'sustain',\n icon: <LeafIcon width={20} height={20} />,\n label: 'Responsibly made',\n sublabel: 'Audited supply chain',\n },\n {\n id: 'packaging',\n icon: <PackageIcon width={20} height={20} />,\n label: 'Plastic-free packaging',\n },\n {\n id: 'quality',\n icon: <ShieldCheckIcon width={20} height={20} />,\n label: 'Lifetime repair',\n sublabel: 'We’ll fix what we made',\n },\n];\n\n/**\n * TrustBadgeCluster — a row (or grid) of reassurance badges. Use in a\n * footer band, on a PDP below the buy box, or on a cart / confirmation\n * page to underline policy.\n */\nexport function TrustBadgeCluster({\n items,\n layout = 'card',\n eyebrow,\n className,\n ...rest\n}: TrustBadgeClusterProps) {\n return (\n <section\n className={cn(styles.root, styles[`layout-${layout}`], className)}\n {...rest}\n >\n {eyebrow && <p className={styles.eyebrow}>{eyebrow}</p>}\n <ul className={styles.list}>\n {items.map((item) => (\n <li key={item.id} className={styles.item}>\n {item.icon && (\n <span className={styles.icon} aria-hidden>\n {item.icon}\n </span>\n )}\n <div className={styles.body}>\n <p className={styles.label}>{item.label}</p>\n {item.sublabel && (\n <p className={styles.sublabel}>{item.sublabel}</p>\n )}\n </div>\n </li>\n ))}\n </ul>\n </section>\n );\n}\n",".root {\n font-family: var(--bazaar-font-family-sans);\n color: var(--bazaar-color-text-primary);\n display: flex;\n gap: 14px;\n align-items: flex-start;\n padding: 14px 16px;\n border: 1px solid var(--bazaar-color-border-subtle, rgba(0, 0, 0, 0.08));\n border-radius: var(--bazaar-radius-md, 8px);\n background: var(--bazaar-color-surface-subtle, #F4F2EC);\n}\n\n.icon {\n width: 32px;\n height: 32px;\n border-radius: 999px;\n background: var(--bazaar-color-surface-default, #fff);\n display: flex;\n align-items: center;\n justify-content: center;\n flex: 0 0 auto;\n color: var(--bazaar-color-text-primary);\n}\n\n.body {\n flex: 1 1 auto;\n min-width: 0;\n display: flex;\n flex-direction: column;\n gap: 6px;\n}\n\n.headline {\n margin: 0;\n font-size: 0.9375rem;\n font-weight: 500;\n line-height: 1.35;\n}\n\n.headline strong {\n font-weight: 700;\n}\n\n.meta {\n list-style: none;\n margin: 0;\n padding: 0;\n display: flex;\n flex-direction: column;\n gap: 2px;\n font-size: 0.8125rem;\n color: var(--bazaar-color-text-muted);\n}\n\n.metaItem {\n display: flex;\n gap: 6px;\n align-items: center;\n flex-wrap: wrap;\n}\n\n.change {\n background: none;\n border: none;\n padding: 0;\n font-family: inherit;\n font-size: inherit;\n color: var(--bazaar-color-text-primary);\n text-decoration: underline;\n text-underline-offset: 3px;\n cursor: pointer;\n}\n\n.change:hover {\n opacity: 0.7;\n}\n\n.cta {\n align-self: center;\n padding: 8px 14px;\n border-radius: 999px;\n font-family: inherit;\n font-size: 0.8125rem;\n font-weight: 600;\n letter-spacing: 0.03em;\n color: var(--bazaar-color-surface-default, #fff);\n background: var(--bazaar-color-text-primary, #1F1C17);\n border: 1px solid var(--bazaar-color-text-primary, #1F1C17);\n cursor: pointer;\n flex: 0 0 auto;\n}\n\n.cta:hover {\n background: #000;\n}\n","import type { HTMLAttributes, ReactNode } from 'react';\nimport { cn } from '../utils/cn';\nimport { MapPinIcon, TruckIcon, ClockIcon, CheckIcon } from './icons';\nimport styles from './DeliveryEstimate.module.css';\n\nexport interface DeliveryEstimateProps\n extends Omit<HTMLAttributes<HTMLElement>, 'onChange'> {\n /** Destination description (e.g., \"Brooklyn, NY 11222\"). Leave blank to show the CTA. */\n destination?: string;\n /** ISO date of the soonest eligible delivery. */\n arrivesBy?: string;\n /** ISO cutoff for same-day processing — e.g. \"2026-04-15T15:00:00\". */\n orderByAt?: string;\n /** Shipping carrier (e.g., \"UPS Ground\"). */\n carrier?: string;\n /** Eligible shipping tier. */\n shippingTier?: 'standard' | 'express' | 'overnight';\n /** Additional promise copy, e.g. \"Free over $75\". */\n note?: ReactNode;\n /** Called when the user wants to change the ZIP/location. */\n onChangeLocation?: () => void;\n changeLocationLabel?: string;\n}\n\nconst TIER_LABEL: Record<\n NonNullable<DeliveryEstimateProps['shippingTier']>,\n string\n> = {\n standard: 'Standard shipping',\n express: 'Express shipping',\n overnight: 'Overnight',\n};\n\nfunction formatArrives(iso?: string): string | undefined {\n if (!iso) return undefined;\n const d = new Date(iso);\n if (Number.isNaN(d.getTime())) return iso;\n return d.toLocaleDateString(undefined, {\n weekday: 'long',\n month: 'short',\n day: 'numeric',\n });\n}\n\nfunction formatCutoff(iso?: string): string | undefined {\n if (!iso) return undefined;\n const d = new Date(iso);\n if (Number.isNaN(d.getTime())) return iso;\n return d.toLocaleTimeString(undefined, {\n hour: 'numeric',\n minute: '2-digit',\n });\n}\n\n/**\n * DeliveryEstimate — ZIP-based delivery promise block, shown on PDPs and\n * in the cart. Leads with \"Get it by {date}\" and supports a \"change\n * location\" affordance when already personalized.\n */\nexport function DeliveryEstimate({\n destination,\n arrivesBy,\n orderByAt,\n carrier,\n shippingTier,\n note,\n onChangeLocation,\n changeLocationLabel = 'Change',\n className,\n ...rest\n}: DeliveryEstimateProps) {\n const arrives = formatArrives(arrivesBy);\n const cutoff = formatCutoff(orderByAt);\n\n return (\n <section className={cn(styles.root, className)} {...rest}>\n <span className={styles.icon} aria-hidden>\n <TruckIcon width={18} height={18} />\n </span>\n <div className={styles.body}>\n {arrives ? (\n <p className={styles.headline}>\n Get it by <strong>{arrives}</strong>\n </p>\n ) : (\n <p className={styles.headline}>\n Enter a ZIP to see delivery dates\n </p>\n )}\n <ul className={styles.meta}>\n {destination && (\n <li className={styles.metaItem}>\n <MapPinIcon width={12} height={12} />\n <span>{destination}</span>\n {onChangeLocation && (\n <button\n type=\"button\"\n className={styles.change}\n onClick={onChangeLocation}\n >\n {changeLocationLabel}\n </button>\n )}\n </li>\n )}\n {shippingTier && (\n <li className={styles.metaItem}>\n <CheckIcon width={12} height={12} />\n <span>\n {TIER_LABEL[shippingTier]}\n {carrier && ` · ${carrier}`}\n </span>\n </li>\n )}\n {cutoff && (\n <li className={styles.metaItem}>\n <ClockIcon width={12} height={12} />\n <span>Order within next cutoff at {cutoff}</span>\n </li>\n )}\n {note && <li className={styles.metaItem}>{note}</li>}\n </ul>\n </div>\n {!destination && onChangeLocation && (\n <button\n type=\"button\"\n className={styles.cta}\n onClick={onChangeLocation}\n >\n Enter ZIP\n </button>\n )}\n </section>\n );\n}\n",".root {\n font-family: var(--bazaar-font-family-sans);\n color: var(--bazaar-color-text-primary);\n display: flex;\n flex-direction: column;\n gap: 18px;\n padding: 22px;\n border: 1px solid var(--bazaar-color-border-default, rgba(0, 0, 0, 0.1));\n border-radius: var(--bazaar-radius-lg, 12px);\n background: var(--bazaar-color-surface-default, #fff);\n}\n\n.header {\n display: flex;\n gap: 14px;\n align-items: flex-start;\n}\n\n.icon {\n width: 40px;\n height: 40px;\n border-radius: 999px;\n background: var(--bazaar-color-surface-subtle, #F4F2EC);\n display: flex;\n align-items: center;\n justify-content: center;\n flex: 0 0 auto;\n}\n\n.headline {\n margin: 0 0 2px;\n font-family: var(--bazaar-font-family-display, var(--bazaar-font-family-sans));\n font-size: 1.125rem;\n font-weight: 500;\n}\n\n.description {\n margin: 0;\n font-size: 0.9375rem;\n color: var(--bazaar-color-text-secondary, var(--bazaar-color-text-muted));\n line-height: 1.4;\n}\n\n.list {\n list-style: none;\n margin: 0;\n padding: 0;\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));\n gap: 16px;\n}\n\n.item {\n display: flex;\n flex-direction: column;\n gap: 4px;\n padding-left: 14px;\n border-left: 2px solid var(--bazaar-color-text-primary, #1F1C17);\n}\n\n.label {\n margin: 0;\n font-size: 0.9375rem;\n font-weight: 600;\n}\n\n.body {\n margin: 0;\n font-size: 0.875rem;\n color: var(--bazaar-color-text-muted);\n line-height: 1.45;\n}\n\n.footer {\n display: flex;\n gap: 14px;\n align-items: center;\n justify-content: space-between;\n padding-top: 10px;\n border-top: 1px solid var(--bazaar-color-border-subtle, rgba(0, 0, 0, 0.06));\n flex-wrap: wrap;\n}\n\n.link {\n background: none;\n border: none;\n padding: 0;\n font-family: inherit;\n font-size: 0.875rem;\n font-weight: 500;\n color: var(--bazaar-color-text-primary);\n text-decoration: underline;\n text-underline-offset: 3px;\n cursor: pointer;\n}\n\n.link:hover {\n opacity: 0.7;\n}\n","import type { HTMLAttributes, ReactNode } from 'react';\nimport { cn } from '../utils/cn';\nimport { ReturnIcon } from './icons';\nimport styles from './ReturnsPolicy.module.css';\n\nexport interface ReturnsPolicyBullet {\n id: string;\n label: string;\n body?: string;\n}\n\nexport interface ReturnsPolicyProps extends HTMLAttributes<HTMLElement> {\n /** Headline — e.g. \"60-day free returns\". */\n headline?: string;\n /** Sub-headline text describing the overall guarantee. */\n description?: string;\n bullets?: ReturnsPolicyBullet[];\n /** Optional affordance that links to the full policy page. */\n onReadFullPolicy?: () => void;\n readFullPolicyLabel?: string;\n /** Optional visual slot rendered at the end (e.g., signed-for illustration). */\n footer?: ReactNode;\n}\n\nconst DEFAULT_BULLETS: ReturnsPolicyBullet[] = [\n {\n id: 'window',\n label: '60 days from delivery',\n body: 'Try it at home. If it isn’t right, we make it easy.',\n },\n {\n id: 'free',\n label: 'Free return label',\n body: 'Pre-paid, no printer needed — drop at any carrier partner.',\n },\n {\n id: 'refund',\n label: 'Refund in 3–5 days',\n body: 'Back to your original method as soon as it scans.',\n },\n];\n\n/**\n * ReturnsPolicy — headline + bullet list of the returns promise. Slots\n * into PDPs (below the buy box), cart summaries and the order\n * confirmation page.\n */\nexport function ReturnsPolicy({\n headline = 'Returns are easy',\n description = 'Built to last — but if it isn’t right, we’ll make it right.',\n bullets = DEFAULT_BULLETS,\n onReadFullPolicy,\n readFullPolicyLabel = 'Read the full policy',\n footer,\n className,\n ...rest\n}: ReturnsPolicyProps) {\n return (\n <section className={cn(styles.root, className)} {...rest}>\n <header className={styles.header}>\n <span className={styles.icon} aria-hidden>\n <ReturnIcon width={20} height={20} />\n </span>\n <div>\n <h3 className={styles.headline}>{headline}</h3>\n {description && <p className={styles.description}>{description}</p>}\n </div>\n </header>\n\n <ul className={styles.list}>\n {bullets.map((b) => (\n <li key={b.id} className={styles.item}>\n <p className={styles.label}>{b.label}</p>\n {b.body && <p className={styles.body}>{b.body}</p>}\n </li>\n ))}\n </ul>\n\n {(onReadFullPolicy || footer) && (\n <footer className={styles.footer}>\n {footer}\n {onReadFullPolicy && (\n <button\n type=\"button\"\n className={styles.link}\n onClick={onReadFullPolicy}\n >\n {readFullPolicyLabel}\n </button>\n )}\n </footer>\n )}\n </section>\n );\n}\n",".root {\n font-family: var(--bazaar-font-family-sans);\n color: var(--bazaar-color-text-primary);\n display: flex;\n gap: 16px;\n align-items: center;\n padding: 16px 18px;\n border: 1px solid var(--bazaar-color-border-subtle, rgba(0, 0, 0, 0.08));\n border-radius: var(--bazaar-radius-md, 8px);\n background: var(--bazaar-color-surface-subtle, #F4F2EC);\n flex-wrap: wrap;\n}\n\n.layout-stack {\n flex-direction: column;\n align-items: flex-start;\n}\n\n.headline {\n display: flex;\n gap: 10px;\n align-items: center;\n}\n\n.headlineIcon {\n width: 28px;\n height: 28px;\n border-radius: 999px;\n background: var(--bazaar-color-surface-default, #fff);\n display: flex;\n align-items: center;\n justify-content: center;\n}\n\n.headlineText {\n margin: 0;\n font-size: 0.9375rem;\n font-weight: 600;\n}\n\n.compliance {\n margin: 1px 0 0;\n font-size: 0.75rem;\n color: var(--bazaar-color-text-muted);\n}\n\n.brands {\n list-style: none;\n margin: 0;\n padding: 0;\n display: flex;\n flex-wrap: wrap;\n gap: 6px;\n flex: 1 1 auto;\n}\n\n.layout-rail .brands {\n justify-content: flex-end;\n}\n\n.layout-stack .brands {\n justify-content: flex-start;\n}\n\n.brand {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n padding: 4px 10px;\n border-radius: 4px;\n color: #fff;\n font-size: 0.6875rem;\n font-weight: 600;\n letter-spacing: 0.04em;\n text-transform: uppercase;\n}\n\n.brandIcon {\n display: inline-flex;\n align-items: center;\n}\n\n.brandLabel {\n line-height: 1;\n}\n\n.trust {\n display: inline-flex;\n gap: 6px;\n align-items: center;\n font-size: 0.75rem;\n color: var(--bazaar-color-text-muted);\n}\n","import type { HTMLAttributes, ReactNode } from 'react';\nimport { cn } from '../utils/cn';\nimport { LockIcon, ShieldCheckIcon, CreditCardIcon } from './icons';\nimport type { PaymentBrand } from './types';\nimport styles from './PaymentConfidence.module.css';\n\nexport interface PaymentConfidenceProps extends HTMLAttributes<HTMLElement> {\n /** Brands to display as chips. Defaults to a standard set. */\n brands?: PaymentBrand[];\n /** Lead-in copy. */\n headline?: string;\n /** Optional compliance line. */\n compliance?: ReactNode;\n /** Layout — `rail` = brand row with secure chip; `stack` = split headline + chips below. */\n layout?: 'rail' | 'stack';\n}\n\nconst BRAND_LABEL: Record<PaymentBrand, string> = {\n visa: 'Visa',\n mastercard: 'Mastercard',\n amex: 'Amex',\n discover: 'Discover',\n paypal: 'PayPal',\n 'apple-pay': 'Apple Pay',\n 'google-pay': 'Google Pay',\n 'shop-pay': 'Shop Pay',\n klarna: 'Klarna',\n afterpay: 'Afterpay',\n};\n\nconst BRAND_COLOR: Partial<Record<PaymentBrand, string>> = {\n visa: '#1A1F71',\n mastercard: '#EB001B',\n amex: '#006FCF',\n discover: '#FF6000',\n paypal: '#003087',\n 'apple-pay': '#000',\n 'google-pay': '#4285F4',\n 'shop-pay': '#5A31F4',\n klarna: '#FFB3C7',\n afterpay: '#B2FCE4',\n};\n\nconst DEFAULT_BRANDS: PaymentBrand[] = [\n 'visa',\n 'mastercard',\n 'amex',\n 'paypal',\n 'apple-pay',\n 'shop-pay',\n];\n\n/**\n * PaymentConfidence — payment-brand rail plus a secure-checkout reassurance\n * block. Typically placed in a cart sidebar, checkout footer, or site footer.\n */\nexport function PaymentConfidence({\n brands = DEFAULT_BRANDS,\n headline = 'Secure checkout',\n compliance = 'PCI DSS compliant · 256-bit SSL encryption',\n layout = 'rail',\n className,\n ...rest\n}: PaymentConfidenceProps) {\n return (\n <section\n className={cn(styles.root, styles[`layout-${layout}`], className)}\n {...rest}\n >\n <div className={styles.headline}>\n <span className={styles.headlineIcon} aria-hidden>\n <LockIcon width={14} height={14} />\n </span>\n <div>\n <p className={styles.headlineText}>{headline}</p>\n {compliance && <p className={styles.compliance}>{compliance}</p>}\n </div>\n </div>\n\n <ul className={styles.brands} aria-label=\"Accepted payment methods\">\n {brands.map((b) => (\n <li\n key={b}\n className={styles.brand}\n style={{ background: BRAND_COLOR[b] ?? '#131B28' }}\n >\n <span className={styles.brandIcon} aria-hidden>\n <CreditCardIcon width={12} height={12} />\n </span>\n <span className={styles.brandLabel}>{BRAND_LABEL[b]}</span>\n </li>\n ))}\n </ul>\n\n <div className={styles.trust}>\n <ShieldCheckIcon width={12} height={12} />\n <span>Buyer protection on every order</span>\n </div>\n </section>\n );\n}\n",".root {\n font-family: var(--bazaar-font-family-sans);\n color: var(--bazaar-color-text-primary);\n display: flex;\n flex-direction: column;\n gap: 20px;\n}\n\n.header {\n display: flex;\n justify-content: space-between;\n align-items: baseline;\n gap: 16px;\n flex-wrap: wrap;\n}\n\n.headline {\n margin: 0;\n font-family: var(--bazaar-font-family-display, var(--bazaar-font-family-sans));\n font-size: 1.375rem;\n font-weight: 500;\n}\n\n.rating {\n display: flex;\n gap: 8px;\n align-items: center;\n}\n\n.stars {\n display: inline-flex;\n gap: 2px;\n}\n\n.star {\n color: rgba(19, 27, 40, 0.2);\n}\n\n.starFilled {\n color: #C48A2E;\n}\n\n.ratingText {\n font-size: 0.875rem;\n font-weight: 600;\n font-variant-numeric: tabular-nums;\n}\n\n.ratingCount {\n font-weight: 400;\n color: var(--bazaar-color-text-muted);\n}\n\n.stats {\n list-style: none;\n margin: 0;\n padding: 0;\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));\n gap: 0;\n border: 1px solid var(--bazaar-color-border-subtle, rgba(0, 0, 0, 0.08));\n border-radius: var(--bazaar-radius-md, 8px);\n overflow: hidden;\n}\n\n.stat {\n display: flex;\n flex-direction: column;\n gap: 4px;\n padding: 18px;\n text-align: left;\n background: var(--bazaar-color-surface-default, #fff);\n border-right: 1px solid var(--bazaar-color-border-subtle, rgba(0, 0, 0, 0.08));\n}\n\n.stat:last-child {\n border-right: none;\n}\n\n.statValue {\n font-family: var(--bazaar-font-family-display, var(--bazaar-font-family-sans));\n font-size: 1.625rem;\n font-weight: 500;\n font-variant-numeric: tabular-nums;\n line-height: 1;\n}\n\n.statLabel {\n font-size: 0.8125rem;\n color: var(--bazaar-color-text-muted);\n letter-spacing: 0.02em;\n}\n\n.quotes {\n list-style: none;\n margin: 0;\n padding: 0;\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));\n gap: 16px;\n}\n\n.quote {\n display: flex;\n flex-direction: column;\n gap: 8px;\n padding: 18px;\n background: var(--bazaar-color-surface-subtle, #F4F2EC);\n border-radius: var(--bazaar-radius-md, 8px);\n}\n\n.quoteText {\n margin: 0;\n font-family: var(--bazaar-font-family-display, var(--bazaar-font-family-sans));\n font-size: 1rem;\n line-height: 1.5;\n font-style: italic;\n}\n\n.quoteSource {\n margin: 0;\n font-size: 0.75rem;\n font-weight: 600;\n letter-spacing: 0.08em;\n text-transform: uppercase;\n color: var(--bazaar-color-text-muted);\n}\n\n.footer {\n padding-top: 8px;\n border-top: 1px solid var(--bazaar-color-border-subtle, rgba(0, 0, 0, 0.06));\n}\n","import type { HTMLAttributes, ReactNode } from 'react';\nimport { cn } from '../utils/cn';\nimport { StarIcon } from './icons';\nimport styles from './SocialProof.module.css';\n\nexport interface PressQuote {\n id: string;\n source: string;\n quote: string;\n}\n\nexport interface SocialProofStat {\n id: string;\n value: string;\n label: string;\n}\n\nexport interface SocialProofProps extends HTMLAttributes<HTMLElement> {\n /** Headline above the quote row. */\n headline?: string;\n quotes?: PressQuote[];\n /** Summary stats — e.g., \"4.8★ across 12k reviews\". */\n stats?: SocialProofStat[];\n /** Optional star rating to show next to the headline (0–5). */\n ratingValue?: number;\n ratingCount?: number;\n /** Optional footer slot — e.g., \"As featured in\" logo strip. */\n footer?: ReactNode;\n}\n\nfunction Stars({ value }: { value: number }) {\n const full = Math.floor(value);\n const half = value - full >= 0.5;\n const stars = Array.from({ length: 5 }, (_, i) => {\n const filled = i < full || (i === full && half);\n return (\n <span\n key={i}\n className={cn(styles.star, filled && styles.starFilled)}\n aria-hidden\n >\n <StarIcon width={14} height={14} />\n </span>\n );\n });\n return <span className={styles.stars}>{stars}</span>;\n}\n\n/**\n * SocialProof — a press/quote strip with optional stats and rating summary.\n * Meant for above-the-fold hero bands and mid-page reassurance blocks.\n */\nexport function SocialProof({\n headline = 'Loved by thousands',\n quotes = [],\n stats = [],\n ratingValue,\n ratingCount,\n footer,\n className,\n ...rest\n}: SocialProofProps) {\n return (\n <section className={cn(styles.root, className)} {...rest}>\n <header className={styles.header}>\n <h3 className={styles.headline}>{headline}</h3>\n {ratingValue !== undefined && (\n <div className={styles.rating}>\n <Stars value={ratingValue} />\n <span className={styles.ratingText}>\n {ratingValue.toFixed(1)}\n {ratingCount !== undefined && (\n <span className={styles.ratingCount}>\n {' '}· {ratingCount.toLocaleString()} reviews\n </span>\n )}\n </span>\n </div>\n )}\n </header>\n\n {stats.length > 0 && (\n <ul className={styles.stats}>\n {stats.map((s) => (\n <li key={s.id} className={styles.stat}>\n <span className={styles.statValue}>{s.value}</span>\n <span className={styles.statLabel}>{s.label}</span>\n </li>\n ))}\n </ul>\n )}\n\n {quotes.length > 0 && (\n <ul className={styles.quotes}>\n {quotes.map((q) => (\n <li key={q.id} className={styles.quote}>\n <p className={styles.quoteText}>“{q.quote}”</p>\n <p className={styles.quoteSource}>— {q.source}</p>\n </li>\n ))}\n </ul>\n )}\n\n {footer && <div className={styles.footer}>{footer}</div>}\n </section>\n );\n}\n",".root {\n font-family: var(--bazaar-font-family-sans);\n position: relative;\n overflow: hidden;\n border-radius: var(--bazaar-radius-lg, 12px);\n color: var(--bazaar-color-text-primary);\n background: var(--bazaar-color-surface-subtle, #F4F2EC);\n}\n\n.variant-overlay {\n display: block;\n}\n\n.variant-split-left,\n.variant-split-right {\n display: grid;\n grid-template-columns: 1fr 1fr;\n align-items: stretch;\n gap: 0;\n}\n\n.variant-split-right .media {\n order: 2;\n}\n\n.height-short .media {\n aspect-ratio: 21 / 9;\n}\n\n.height-medium .media {\n aspect-ratio: 16 / 9;\n}\n\n.height-tall .media {\n aspect-ratio: 4 / 5;\n}\n\n.variant-split-left .media,\n.variant-split-right .media {\n aspect-ratio: auto;\n min-height: 100%;\n}\n\n.media {\n position: relative;\n width: 100%;\n overflow: hidden;\n background: var(--bazaar-color-surface-subtle, #F4F2EC);\n}\n\n.variant-overlay .media {\n position: absolute;\n inset: 0;\n}\n\n.scrim {\n position: absolute;\n inset: 0;\n background: linear-gradient(\n 180deg,\n rgba(19, 27, 40, 0.1) 0%,\n rgba(19, 27, 40, 0.55) 100%\n );\n}\n\n.copy {\n position: relative;\n display: flex;\n flex-direction: column;\n gap: 14px;\n padding: 44px 36px;\n max-width: 560px;\n}\n\n.variant-overlay .copy {\n min-height: 420px;\n justify-content: flex-end;\n color: #fff;\n}\n\n.variant-split-left .copy,\n.variant-split-right .copy {\n justify-content: center;\n padding: 56px 44px;\n}\n\n.tone-dark.variant-overlay .copy {\n color: var(--bazaar-color-text-primary);\n}\n\n.eyebrow {\n margin: 0;\n font-size: 0.75rem;\n font-weight: 600;\n letter-spacing: 0.14em;\n text-transform: uppercase;\n opacity: 0.9;\n}\n\n.headline {\n margin: 0;\n font-family: var(--bazaar-font-family-display, var(--bazaar-font-family-sans));\n font-size: clamp(2rem, 4vw, 3.25rem);\n font-weight: 500;\n line-height: 1.05;\n letter-spacing: -0.01em;\n max-width: 20ch;\n}\n\n.body {\n font-size: 1rem;\n line-height: 1.5;\n max-width: 46ch;\n opacity: 0.92;\n}\n\n.ctas {\n display: flex;\n gap: 10px;\n margin-top: 8px;\n flex-wrap: wrap;\n}\n\n.cta {\n padding: 12px 24px;\n border-radius: 999px;\n font-family: inherit;\n font-size: 0.8125rem;\n font-weight: 600;\n letter-spacing: 0.04em;\n text-transform: uppercase;\n cursor: pointer;\n transition: background 120ms ease, color 120ms ease, border-color 120ms ease;\n}\n\n.cta-primary {\n background: var(--bazaar-color-surface-default, #fff);\n color: var(--bazaar-color-text-primary);\n border: 1px solid var(--bazaar-color-surface-default, #fff);\n}\n\n.variant-split-left .cta-primary,\n.variant-split-right .cta-primary,\n.tone-dark.variant-overlay .cta-primary {\n background: var(--bazaar-color-text-primary, #1F1C17);\n color: var(--bazaar-color-surface-default, #fff);\n border-color: var(--bazaar-color-text-primary, #1F1C17);\n}\n\n.cta-primary:hover {\n opacity: 0.9;\n}\n\n.cta-secondary {\n background: transparent;\n color: inherit;\n border: 1px solid currentColor;\n}\n\n.cta-secondary:hover {\n opacity: 0.85;\n}\n\n@media (max-width: 720px) {\n .variant-split-left,\n .variant-split-right {\n grid-template-columns: 1fr;\n }\n .variant-split-right .media {\n order: 0;\n }\n .variant-split-left .media,\n .variant-split-right .media {\n aspect-ratio: 16 / 9;\n min-height: auto;\n }\n .copy {\n padding: 32px 24px;\n }\n .variant-overlay .copy {\n min-height: 360px;\n padding: 32px 24px;\n }\n}\n","import type { HTMLAttributes, ReactNode } from 'react';\nimport { cn } from '../utils/cn';\nimport { MediaPlaceholder } from './MediaPlaceholder';\nimport styles from './CampaignHero.module.css';\n\nexport interface CampaignCTA {\n label: string;\n onClick?: () => void;\n /** Renders as an outline-style button. Default is solid. */\n variant?: 'primary' | 'secondary';\n}\n\nexport interface CampaignHeroProps extends HTMLAttributes<HTMLElement> {\n eyebrow?: string;\n headline: string;\n body?: ReactNode;\n /** Primary + optional secondary CTA. */\n ctas?: CampaignCTA[];\n /** Background image seed/alt (uses MediaPlaceholder when src is absent). */\n image?: { src?: string; alt: string; seed?: string };\n /** Placement of copy relative to the image. Defaults to 'overlay'. */\n variant?: 'overlay' | 'split-left' | 'split-right';\n /** Overlay scrim opacity for readability in 'overlay' mode (0..1). */\n scrim?: number;\n /** Shorter/taller crop. */\n height?: 'short' | 'medium' | 'tall';\n /** Eyebrow color tone — 'dark' for over light imagery. */\n tone?: 'light' | 'dark';\n}\n\n/**\n * CampaignHero — headline/CTA banner for the homepage or a collection\n * landing. Three layouts: overlay (copy on top of imagery), split-left\n * (copy on left, image on right), split-right (inverse).\n */\nexport function CampaignHero({\n eyebrow,\n headline,\n body,\n ctas = [],\n image,\n variant = 'overlay',\n scrim = 0.35,\n height = 'medium',\n tone = 'light',\n className,\n ...rest\n}: CampaignHeroProps) {\n const isOverlay = variant === 'overlay';\n\n return (\n <section\n className={cn(\n styles.root,\n styles[`variant-${variant}`],\n styles[`height-${height}`],\n styles[`tone-${tone}`],\n className,\n )}\n {...rest}\n >\n <div className={styles.media}>\n <MediaPlaceholder\n src={image?.src}\n alt={image?.alt ?? ''}\n seed={image?.seed}\n aspectRatio=\"auto\"\n />\n {isOverlay && (\n <span\n className={styles.scrim}\n style={{ opacity: scrim }}\n aria-hidden\n />\n )}\n </div>\n\n <div className={styles.copy}>\n {eyebrow && <p className={styles.eyebrow}>{eyebrow}</p>}\n <h1 className={styles.headline}>{headline}</h1>\n {body && <div className={styles.body}>{body}</div>}\n {ctas.length > 0 && (\n <div className={styles.ctas}>\n {ctas.map((cta, i) => (\n <button\n key={cta.label}\n type=\"button\"\n className={cn(\n styles.cta,\n styles[`cta-${cta.variant ?? (i === 0 ? 'primary' : 'secondary')}`],\n )}\n onClick={cta.onClick}\n >\n {cta.label}\n </button>\n ))}\n </div>\n )}\n </div>\n </section>\n );\n}\n",".root {\n font-family: var(--bazaar-font-family-sans);\n color: var(--bazaar-color-text-primary);\n display: grid;\n grid-template-columns: 1fr 1fr;\n gap: 48px;\n align-items: center;\n}\n\n.image-right {\n direction: rtl;\n}\n\n.image-right > * {\n direction: ltr;\n}\n\n.mediaWrap {\n margin: 0;\n display: flex;\n flex-direction: column;\n gap: 10px;\n}\n\n.media {\n border-radius: var(--bazaar-radius-lg, 12px);\n overflow: hidden;\n background: var(--bazaar-color-surface-subtle, #F4F2EC);\n}\n\n.caption {\n font-size: 0.75rem;\n color: var(--bazaar-color-text-muted);\n letter-spacing: 0.04em;\n}\n\n.copy {\n display: flex;\n flex-direction: column;\n gap: 16px;\n max-width: 48ch;\n}\n\n.eyebrow {\n margin: 0;\n font-size: 0.75rem;\n font-weight: 600;\n letter-spacing: 0.14em;\n text-transform: uppercase;\n color: var(--bazaar-color-text-muted);\n}\n\n.headline {\n margin: 0;\n font-family: var(--bazaar-font-family-display, var(--bazaar-font-family-sans));\n font-size: clamp(1.75rem, 3vw, 2.5rem);\n font-weight: 500;\n line-height: 1.1;\n letter-spacing: -0.01em;\n}\n\n.body {\n font-size: 1rem;\n line-height: 1.65;\n color: var(--bazaar-color-text-secondary, var(--bazaar-color-text-primary));\n}\n\n.body > * + * {\n margin-top: 0.85em;\n}\n\n.cta {\n align-self: flex-start;\n margin-top: 4px;\n background: none;\n border: none;\n padding: 0 0 3px;\n font-family: inherit;\n font-size: 0.9375rem;\n font-weight: 600;\n letter-spacing: 0.02em;\n color: var(--bazaar-color-text-primary);\n border-bottom: 1px solid currentColor;\n cursor: pointer;\n display: inline-flex;\n gap: 6px;\n align-items: center;\n}\n\n.cta:hover {\n opacity: 0.7;\n}\n\n@media (max-width: 768px) {\n .root {\n grid-template-columns: 1fr;\n gap: 28px;\n }\n .image-right {\n direction: ltr;\n }\n}\n","import type { HTMLAttributes, ReactNode } from 'react';\nimport { cn } from '../utils/cn';\nimport { MediaPlaceholder } from './MediaPlaceholder';\nimport styles from './SplitImageCopy.module.css';\n\nexport interface SplitImageCopyProps extends HTMLAttributes<HTMLElement> {\n eyebrow?: string;\n headline: string;\n body?: ReactNode;\n image: { src?: string; alt: string; seed?: string };\n /** Image on left ('image-left') or right ('image-right'). */\n imageSide?: 'image-left' | 'image-right';\n /** Aspect ratio of the image cell. */\n aspectRatio?: string;\n /** Optional CTA rendered inside the copy column. */\n cta?: { label: string; onClick?: () => void };\n /** Optional caption rendered under the image. */\n caption?: string;\n}\n\n/**\n * SplitImageCopy — 50/50 editorial block. Use for \"About the fabric\",\n * \"From the studio\", etc. Reverses direction on narrow viewports.\n */\nexport function SplitImageCopy({\n eyebrow,\n headline,\n body,\n image,\n imageSide = 'image-left',\n aspectRatio = '4 / 5',\n cta,\n caption,\n className,\n ...rest\n}: SplitImageCopyProps) {\n return (\n <section\n className={cn(styles.root, styles[imageSide], className)}\n {...rest}\n >\n <figure className={styles.mediaWrap}>\n <div className={styles.media}>\n <MediaPlaceholder\n src={image.src}\n alt={image.alt}\n seed={image.seed}\n aspectRatio={aspectRatio}\n />\n </div>\n {caption && <figcaption className={styles.caption}>{caption}</figcaption>}\n </figure>\n\n <div className={styles.copy}>\n {eyebrow && <p className={styles.eyebrow}>{eyebrow}</p>}\n <h2 className={styles.headline}>{headline}</h2>\n {body && <div className={styles.body}>{body}</div>}\n {cta && (\n <button type=\"button\" className={styles.cta} onClick={cta.onClick}>\n {cta.label} <span aria-hidden>→</span>\n </button>\n )}\n </div>\n </section>\n );\n}\n",".root {\n font-family: var(--bazaar-font-family-sans);\n color: var(--bazaar-color-text-primary);\n display: grid;\n gap: 28px;\n}\n\n.layout-image-left {\n grid-template-columns: minmax(260px, 420px) 1fr;\n gap: 36px;\n align-items: start;\n}\n\n.layout-image-right {\n grid-template-columns: 1fr minmax(260px, 420px);\n gap: 36px;\n align-items: start;\n}\n\n.layout-image-right .hero {\n order: 2;\n}\n\n.layout-stacked .hero {\n grid-template-columns: 1fr;\n gap: 20px;\n}\n\n.hero {\n display: flex;\n flex-direction: column;\n gap: 20px;\n}\n\n.layout-stacked .hero {\n flex-direction: column;\n gap: 14px;\n}\n\n.media {\n border-radius: var(--bazaar-radius-lg, 12px);\n overflow: hidden;\n background: var(--bazaar-color-surface-subtle, #F4F2EC);\n}\n\n.copy {\n display: flex;\n flex-direction: column;\n gap: 12px;\n}\n\n.eyebrow {\n margin: 0;\n font-size: 0.75rem;\n font-weight: 600;\n letter-spacing: 0.14em;\n text-transform: uppercase;\n color: var(--bazaar-color-text-muted);\n}\n\n.headline {\n margin: 0;\n font-family: var(--bazaar-font-family-display, var(--bazaar-font-family-sans));\n font-size: clamp(1.5rem, 2.5vw, 2.125rem);\n font-weight: 500;\n line-height: 1.1;\n letter-spacing: -0.01em;\n}\n\n.body {\n font-size: 0.9375rem;\n line-height: 1.55;\n color: var(--bazaar-color-text-secondary, var(--bazaar-color-text-primary));\n max-width: 44ch;\n}\n\n.cta {\n align-self: flex-start;\n margin-top: 2px;\n background: none;\n border: none;\n padding: 0 0 2px;\n font-family: inherit;\n font-size: 0.875rem;\n font-weight: 600;\n letter-spacing: 0.02em;\n color: var(--bazaar-color-text-primary);\n border-bottom: 1px solid currentColor;\n cursor: pointer;\n display: inline-flex;\n gap: 6px;\n align-items: center;\n}\n\n.cta:hover {\n opacity: 0.7;\n}\n\n.grid {\n display: grid;\n grid-template-columns: repeat(2, minmax(0, 1fr));\n gap: 20px;\n align-content: start;\n}\n\n.layout-stacked .grid {\n grid-template-columns: repeat(4, minmax(0, 1fr));\n}\n\n@media (max-width: 900px) {\n .layout-image-left,\n .layout-image-right {\n grid-template-columns: 1fr;\n }\n .layout-image-right .hero {\n order: 0;\n }\n}\n\n@media (max-width: 640px) {\n .grid {\n grid-template-columns: repeat(2, minmax(0, 1fr));\n }\n .layout-stacked .grid {\n grid-template-columns: repeat(2, minmax(0, 1fr));\n }\n}\n","import type { HTMLAttributes, ReactNode } from 'react';\nimport { cn } from '../utils/cn';\nimport { MediaPlaceholder } from './MediaPlaceholder';\nimport { ProductCard } from './ProductCard';\nimport type { Product } from './types';\nimport styles from './FeaturedCollection.module.css';\n\nexport interface FeaturedCollectionProps\n extends Omit<HTMLAttributes<HTMLElement>, 'onSelect'> {\n eyebrow?: string;\n headline: string;\n body?: ReactNode;\n /** Hero imagery for the collection. */\n image: { src?: string; alt: string; seed?: string };\n products: Product[];\n /** Layout — 'image-left' places hero on the left with products in a 2×2 grid. */\n layout?: 'image-left' | 'image-right' | 'stacked';\n cta?: { label: string; onClick?: () => void };\n onSelectProduct?: (product: Product) => void;\n}\n\n/**\n * FeaturedCollection — editorial collection module with a hero image, a\n * copy block and a tight grid of product cards. Use to merchandise a\n * drop or curation on the homepage.\n */\nexport function FeaturedCollection({\n eyebrow,\n headline,\n body,\n image,\n products,\n layout = 'image-left',\n cta,\n onSelectProduct,\n className,\n ...rest\n}: FeaturedCollectionProps) {\n return (\n <section\n className={cn(styles.root, styles[`layout-${layout}`], className)}\n {...rest}\n >\n <div className={styles.hero}>\n <div className={styles.media}>\n <MediaPlaceholder\n src={image.src}\n alt={image.alt}\n seed={image.seed}\n aspectRatio={layout === 'stacked' ? '21 / 9' : '4 / 5'}\n />\n </div>\n <div className={styles.copy}>\n {eyebrow && <p className={styles.eyebrow}>{eyebrow}</p>}\n <h2 className={styles.headline}>{headline}</h2>\n {body && <div className={styles.body}>{body}</div>}\n {cta && (\n <button type=\"button\" className={styles.cta} onClick={cta.onClick}>\n {cta.label} <span aria-hidden>→</span>\n </button>\n )}\n </div>\n </div>\n\n <div className={styles.grid}>\n {products.map((p) => (\n <ProductCard\n key={p.id}\n product={p}\n onSelect={onSelectProduct}\n />\n ))}\n </div>\n </section>\n );\n}\n",".root {\n font-family: var(--bazaar-font-family-sans);\n color: var(--bazaar-color-text-primary);\n display: flex;\n flex-direction: column;\n gap: 20px;\n}\n\n.header {\n display: flex;\n justify-content: space-between;\n align-items: baseline;\n}\n\n.title {\n margin: 0;\n font-family: var(--bazaar-font-family-display, var(--bazaar-font-family-sans));\n font-size: 1.5rem;\n font-weight: 500;\n}\n\n.grid {\n display: grid;\n grid-template-columns: minmax(0, 1.1fr) minmax(280px, 1fr);\n gap: 24px;\n align-items: start;\n}\n\n.media {\n position: relative;\n border-radius: var(--bazaar-radius-lg, 12px);\n overflow: hidden;\n background: var(--bazaar-color-surface-subtle, #F4F2EC);\n}\n\n.spot {\n position: absolute;\n transform: translate(-50%, -50%);\n width: 32px;\n height: 32px;\n border-radius: 999px;\n border: none;\n padding: 0;\n background: rgba(255, 255, 255, 0.95);\n color: var(--bazaar-color-text-primary);\n box-shadow: 0 2px 10px rgba(0, 0, 0, 0.2);\n cursor: pointer;\n transition: transform 120ms ease, box-shadow 120ms ease;\n}\n\n.spot::before {\n content: '';\n position: absolute;\n inset: -6px;\n border-radius: 999px;\n border: 2px solid rgba(255, 255, 255, 0.7);\n opacity: 0;\n transition: opacity 120ms ease;\n}\n\n.spotInner {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 100%;\n height: 100%;\n font-size: 0.8125rem;\n font-weight: 700;\n font-variant-numeric: tabular-nums;\n}\n\n.spotActive {\n transform: translate(-50%, -50%) scale(1.08);\n background: var(--bazaar-color-text-primary, #1F1C17);\n color: #fff;\n}\n\n.spotActive::before {\n opacity: 1;\n border-color: rgba(19, 27, 40, 0.35);\n}\n\n.rail {\n list-style: none;\n margin: 0;\n padding: 0;\n display: flex;\n flex-direction: column;\n gap: 10px;\n}\n\n.card {\n display: grid;\n grid-template-columns: 1fr auto;\n align-items: center;\n gap: 8px;\n padding: 8px;\n border: 1px solid var(--bazaar-color-border-subtle, rgba(0, 0, 0, 0.08));\n border-radius: var(--bazaar-radius-md, 8px);\n background: var(--bazaar-color-surface-default, #fff);\n transition: border-color 120ms ease, box-shadow 120ms ease;\n}\n\n.cardActive {\n border-color: var(--bazaar-color-text-primary, #1F1C17);\n box-shadow: 0 0 0 1px var(--bazaar-color-text-primary, #1F1C17);\n}\n\n.cardBody {\n display: grid;\n grid-template-columns: 20px 64px 1fr;\n gap: 12px;\n align-items: center;\n background: none;\n border: none;\n padding: 4px;\n font-family: inherit;\n color: inherit;\n text-align: left;\n cursor: pointer;\n width: 100%;\n min-width: 0;\n}\n\n.cardIdx {\n font-size: 0.75rem;\n font-weight: 700;\n color: var(--bazaar-color-text-muted);\n font-variant-numeric: tabular-nums;\n}\n\n.cardThumb {\n width: 64px;\n height: 64px;\n border-radius: var(--bazaar-radius-sm, 6px);\n overflow: hidden;\n background: var(--bazaar-color-surface-subtle, #F4F2EC);\n}\n\n.cardCopy {\n display: flex;\n flex-direction: column;\n gap: 2px;\n min-width: 0;\n}\n\n.cardBrand {\n font-size: 0.6875rem;\n font-weight: 600;\n letter-spacing: 0.08em;\n text-transform: uppercase;\n color: var(--bazaar-color-text-muted);\n}\n\n.cardName {\n font-size: 0.9375rem;\n font-weight: 500;\n line-height: 1.2;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.cardPrice {\n font-size: 0.875rem;\n font-weight: 600;\n font-variant-numeric: tabular-nums;\n}\n\n.add {\n width: 36px;\n height: 36px;\n border-radius: 999px;\n border: 1px solid var(--bazaar-color-border-default, rgba(0, 0, 0, 0.14));\n background: var(--bazaar-color-surface-default, #fff);\n color: var(--bazaar-color-text-primary);\n display: flex;\n align-items: center;\n justify-content: center;\n cursor: pointer;\n margin-right: 4px;\n transition: background 120ms ease, color 120ms ease;\n}\n\n.add:hover {\n background: var(--bazaar-color-text-primary, #1F1C17);\n color: #fff;\n border-color: var(--bazaar-color-text-primary, #1F1C17);\n}\n\n@media (max-width: 820px) {\n .grid {\n grid-template-columns: 1fr;\n }\n}\n","import { useState, type HTMLAttributes } from 'react';\nimport { cn } from '../utils/cn';\nimport { MediaPlaceholder } from './MediaPlaceholder';\nimport { formatMoney } from './money';\nimport { PlusIcon } from './icons';\nimport type { Product } from './types';\nimport styles from './ShopTheLook.module.css';\n\nexport interface LookHotspot {\n id: string;\n /** Position (%). */\n x: number;\n y: number;\n productId: string;\n label?: string;\n}\n\nexport interface ShopTheLookProps\n extends Omit<HTMLAttributes<HTMLElement>, 'onSelect'> {\n /** Editorial image the hotspots sit on. */\n image: { src?: string; alt: string; seed?: string };\n /** Products featured in the look (keyed by id). */\n products: Product[];\n hotspots: LookHotspot[];\n /** Selected hotspot id (controlled). */\n activeId?: string;\n onActiveChange?: (id: string) => void;\n title?: string;\n /** Called when the user clicks a product card's CTA. */\n onAddToCart?: (product: Product) => void;\n onSelectProduct?: (product: Product) => void;\n}\n\n/**\n * ShopTheLook — editorial image with numbered hotspots and a companion\n * product rail. Clicking a hotspot highlights the matching product card.\n */\nexport function ShopTheLook({\n image,\n products,\n hotspots,\n activeId,\n onActiveChange,\n title = 'Shop the look',\n onAddToCart,\n onSelectProduct,\n className,\n ...rest\n}: ShopTheLookProps) {\n const [internal, setInternal] = useState<string | undefined>(hotspots[0]?.id);\n const active = activeId ?? internal;\n const set = (id: string) => {\n setInternal(id);\n onActiveChange?.(id);\n };\n\n const byProductId = new Map(products.map((p) => [p.id, p]));\n\n return (\n <section className={cn(styles.root, className)} {...rest}>\n <header className={styles.header}>\n <h2 className={styles.title}>{title}</h2>\n </header>\n\n <div className={styles.grid}>\n <div className={styles.media}>\n <MediaPlaceholder\n src={image.src}\n alt={image.alt}\n seed={image.seed}\n aspectRatio=\"4 / 5\"\n />\n {hotspots.map((h, i) => (\n <button\n key={h.id}\n type=\"button\"\n className={cn(styles.spot, active === h.id && styles.spotActive)}\n style={{ left: `${h.x}%`, top: `${h.y}%` }}\n onClick={() => set(h.id)}\n aria-label={h.label ?? `View item ${i + 1}`}\n >\n <span className={styles.spotInner}>{i + 1}</span>\n </button>\n ))}\n </div>\n\n <ol className={styles.rail}>\n {hotspots.map((h, i) => {\n const product = byProductId.get(h.productId);\n if (!product) return null;\n const isActive = active === h.id;\n return (\n <li\n key={h.id}\n className={cn(styles.card, isActive && styles.cardActive)}\n >\n <button\n type=\"button\"\n className={styles.cardBody}\n onClick={() => {\n set(h.id);\n onSelectProduct?.(product);\n }}\n >\n <span className={styles.cardIdx}>{i + 1}</span>\n <span className={styles.cardThumb}>\n <MediaPlaceholder\n src={product.images[0]?.src}\n alt={product.images[0]?.alt ?? product.name}\n seed={product.images[0]?.seed}\n aspectRatio=\"1 / 1\"\n />\n </span>\n <span className={styles.cardCopy}>\n {product.brand && (\n <span className={styles.cardBrand}>{product.brand}</span>\n )}\n <span className={styles.cardName}>{product.name}</span>\n <span className={styles.cardPrice}>\n {formatMoney(product.price)}\n </span>\n </span>\n </button>\n {onAddToCart && (\n <button\n type=\"button\"\n className={styles.add}\n onClick={() => onAddToCart(product)}\n aria-label={`Add ${product.name} to cart`}\n >\n <PlusIcon width={14} height={14} />\n </button>\n )}\n </li>\n );\n })}\n </ol>\n </div>\n </section>\n );\n}\n",".root {\n font-family: var(--bazaar-font-family-sans);\n color: var(--bazaar-color-text-primary);\n display: flex;\n flex-direction: column;\n gap: 36px;\n}\n\n.header {\n display: flex;\n flex-direction: column;\n gap: 12px;\n max-width: 56ch;\n}\n\n.eyebrow {\n margin: 0;\n font-size: 0.75rem;\n font-weight: 600;\n letter-spacing: 0.14em;\n text-transform: uppercase;\n color: var(--bazaar-color-text-muted);\n}\n\n.headline {\n margin: 0;\n font-family: var(--bazaar-font-family-display, var(--bazaar-font-family-sans));\n font-size: clamp(2rem, 4vw, 3rem);\n font-weight: 500;\n line-height: 1.05;\n letter-spacing: -0.01em;\n}\n\n.intro {\n font-size: 1.0625rem;\n line-height: 1.6;\n color: var(--bazaar-color-text-secondary, var(--bazaar-color-text-primary));\n}\n\n.intro > * + * {\n margin-top: 1em;\n}\n\n.grid {\n display: grid;\n grid-template-columns: minmax(0, 1fr) 280px;\n gap: 48px;\n align-items: start;\n}\n\n.beats {\n display: flex;\n flex-direction: column;\n gap: 56px;\n}\n\n.beat {\n display: grid;\n grid-template-columns: 1fr 1fr;\n gap: 32px;\n align-items: center;\n}\n\n.beatReverse {\n direction: rtl;\n}\n\n.beatReverse > * {\n direction: ltr;\n}\n\n.beatMedia {\n margin: 0;\n display: flex;\n flex-direction: column;\n gap: 10px;\n}\n\n.beatImage {\n border-radius: var(--bazaar-radius-lg, 12px);\n overflow: hidden;\n background: var(--bazaar-color-surface-subtle, #F4F2EC);\n}\n\n.beatCaption {\n font-size: 0.75rem;\n color: var(--bazaar-color-text-muted);\n letter-spacing: 0.04em;\n}\n\n.beatCopy {\n display: flex;\n flex-direction: column;\n gap: 12px;\n max-width: 44ch;\n}\n\n.beatHeading {\n margin: 0;\n font-family: var(--bazaar-font-family-display, var(--bazaar-font-family-sans));\n font-size: 1.5rem;\n font-weight: 500;\n line-height: 1.15;\n}\n\n.beatBody {\n font-size: 1rem;\n line-height: 1.6;\n color: var(--bazaar-color-text-secondary, var(--bazaar-color-text-primary));\n}\n\n.beatBody > * + * {\n margin-top: 0.85em;\n}\n\n.rail {\n position: sticky;\n top: 24px;\n}\n\n.railInner {\n display: flex;\n flex-direction: column;\n gap: 8px;\n padding: 16px;\n border: 1px solid var(--bazaar-color-border-default, rgba(0, 0, 0, 0.1));\n border-radius: var(--bazaar-radius-lg, 12px);\n background: var(--bazaar-color-surface-default, #fff);\n}\n\n.railMedia {\n border-radius: var(--bazaar-radius-md, 8px);\n overflow: hidden;\n background: var(--bazaar-color-surface-subtle, #F4F2EC);\n margin-bottom: 4px;\n}\n\n.railBrand {\n margin: 0;\n font-size: 0.6875rem;\n font-weight: 600;\n letter-spacing: 0.08em;\n text-transform: uppercase;\n color: var(--bazaar-color-text-muted);\n}\n\n.railName {\n margin: 0;\n font-size: 0.9375rem;\n font-weight: 500;\n}\n\n.railPrice {\n margin: 0;\n font-size: 1rem;\n font-weight: 600;\n font-variant-numeric: tabular-nums;\n}\n\n.railCta {\n margin-top: 10px;\n padding: 12px 16px;\n border-radius: 999px;\n background: var(--bazaar-color-text-primary, #1F1C17);\n color: var(--bazaar-color-surface-default, #fff);\n border: 1px solid var(--bazaar-color-text-primary, #1F1C17);\n font-family: inherit;\n font-size: 0.8125rem;\n font-weight: 600;\n letter-spacing: 0.04em;\n text-transform: uppercase;\n cursor: pointer;\n}\n\n.railCta:hover {\n background: #000;\n}\n\n@media (max-width: 900px) {\n .grid {\n grid-template-columns: 1fr;\n }\n .beat {\n grid-template-columns: 1fr;\n gap: 18px;\n }\n .beatReverse {\n direction: ltr;\n }\n}\n","import type { HTMLAttributes, ReactNode } from 'react';\nimport { cn } from '../utils/cn';\nimport { MediaPlaceholder } from './MediaPlaceholder';\nimport { formatMoney } from './money';\nimport type { Product } from './types';\nimport styles from './EditorialProductStory.module.css';\n\nexport interface EditorialProductStoryBeat {\n id: string;\n image: { src?: string; alt: string; seed?: string };\n heading?: string;\n body?: ReactNode;\n caption?: string;\n}\n\nexport interface EditorialProductStoryProps extends HTMLAttributes<HTMLElement> {\n eyebrow?: string;\n headline: string;\n intro?: ReactNode;\n beats: EditorialProductStoryBeat[];\n /** Product the story is about — pinned to the sticky side-rail. */\n product: Product;\n onBuy?: (product: Product) => void;\n buyLabel?: string;\n}\n\n/**\n * EditorialProductStory — long-form editorial layout with a sticky product\n * rail that shadows the story. Alternates image-left / image-right beats.\n */\nexport function EditorialProductStory({\n eyebrow,\n headline,\n intro,\n beats,\n product,\n onBuy,\n buyLabel = 'Add to cart',\n className,\n ...rest\n}: EditorialProductStoryProps) {\n return (\n <section className={cn(styles.root, className)} {...rest}>\n <header className={styles.header}>\n {eyebrow && <p className={styles.eyebrow}>{eyebrow}</p>}\n <h2 className={styles.headline}>{headline}</h2>\n {intro && <div className={styles.intro}>{intro}</div>}\n </header>\n\n <div className={styles.grid}>\n <div className={styles.beats}>\n {beats.map((b, i) => (\n <article\n key={b.id}\n className={cn(\n styles.beat,\n i % 2 === 1 && styles.beatReverse,\n )}\n >\n <figure className={styles.beatMedia}>\n <div className={styles.beatImage}>\n <MediaPlaceholder\n src={b.image.src}\n alt={b.image.alt}\n seed={b.image.seed}\n aspectRatio=\"4 / 5\"\n />\n </div>\n {b.caption && (\n <figcaption className={styles.beatCaption}>\n {b.caption}\n </figcaption>\n )}\n </figure>\n <div className={styles.beatCopy}>\n {b.heading && <h3 className={styles.beatHeading}>{b.heading}</h3>}\n {b.body && <div className={styles.beatBody}>{b.body}</div>}\n </div>\n </article>\n ))}\n </div>\n\n <aside className={styles.rail}>\n <div className={styles.railInner}>\n <div className={styles.railMedia}>\n <MediaPlaceholder\n src={product.images[0]?.src}\n alt={product.images[0]?.alt ?? product.name}\n seed={product.images[0]?.seed}\n aspectRatio=\"1 / 1\"\n />\n </div>\n {product.brand && (\n <p className={styles.railBrand}>{product.brand}</p>\n )}\n <p className={styles.railName}>{product.name}</p>\n <p className={styles.railPrice}>{formatMoney(product.price)}</p>\n {onBuy && (\n <button\n type=\"button\"\n className={styles.railCta}\n onClick={() => onBuy(product)}\n >\n {buyLabel}\n </button>\n )}\n </div>\n </aside>\n </div>\n </section>\n );\n}\n",".root {\n font-family: var(--bazaar-font-family-sans);\n color: var(--bazaar-color-text-primary);\n display: flex;\n flex-direction: column;\n gap: 24px;\n}\n\n.header {\n display: flex;\n flex-direction: column;\n gap: 10px;\n max-width: 56ch;\n}\n\n.eyebrow {\n margin: 0;\n font-size: 0.75rem;\n font-weight: 600;\n letter-spacing: 0.14em;\n text-transform: uppercase;\n color: var(--bazaar-color-text-muted);\n}\n\n.headline {\n margin: 0;\n font-family: var(--bazaar-font-family-display, var(--bazaar-font-family-sans));\n font-size: clamp(1.75rem, 3vw, 2.5rem);\n font-weight: 500;\n line-height: 1.1;\n}\n\n.intro {\n font-size: 1rem;\n line-height: 1.5;\n color: var(--bazaar-color-text-muted);\n}\n\n.grid {\n list-style: none;\n margin: 0;\n padding: 0;\n display: grid;\n grid-template-columns: repeat(3, minmax(0, 1fr));\n gap: 12px;\n grid-auto-flow: dense;\n}\n\n.item {\n display: flex;\n}\n\n.span-2 {\n grid-column: span 2;\n}\n\n.span-3 {\n grid-column: span 3;\n}\n\n.cell {\n margin: 0;\n width: 100%;\n display: flex;\n flex-direction: column;\n gap: 8px;\n background: none;\n border: none;\n padding: 0;\n text-align: left;\n color: inherit;\n font-family: inherit;\n cursor: var(--lookbook-cursor, default);\n}\n\nbutton.cell {\n --lookbook-cursor: pointer;\n}\n\n.media {\n display: block;\n width: 100%;\n border-radius: var(--bazaar-radius-md, 8px);\n overflow: hidden;\n background: var(--bazaar-color-surface-subtle, #F4F2EC);\n transition: transform 220ms ease;\n}\n\nbutton.cell:hover .media {\n transform: scale(1.015);\n}\n\n.caption {\n font-size: 0.75rem;\n color: var(--bazaar-color-text-muted);\n letter-spacing: 0.04em;\n}\n\n@media (max-width: 720px) {\n .grid {\n grid-template-columns: repeat(2, minmax(0, 1fr));\n }\n .span-3 {\n grid-column: span 2;\n }\n}\n\n@media (max-width: 460px) {\n .grid {\n grid-template-columns: 1fr;\n }\n .span-2,\n .span-3 {\n grid-column: span 1;\n }\n}\n","import type { HTMLAttributes, ReactNode } from 'react';\nimport { cn } from '../utils/cn';\nimport { MediaPlaceholder } from './MediaPlaceholder';\nimport styles from './LookbookGallery.module.css';\n\nexport interface LookbookImage {\n id: string;\n alt: string;\n src?: string;\n seed?: string;\n caption?: string;\n /** Span in columns (1..3). Use sparingly. */\n span?: 1 | 2 | 3;\n /** Taller aspect cell. */\n tall?: boolean;\n}\n\nexport interface LookbookGalleryProps extends HTMLAttributes<HTMLElement> {\n eyebrow?: string;\n headline?: string;\n intro?: ReactNode;\n images: LookbookImage[];\n onImageClick?: (image: LookbookImage) => void;\n}\n\n/**\n * LookbookGallery — asymmetric editorial image grid. Variable cell spans\n * and tall variants create visual rhythm without turning into a single\n * magazine-mosaic preset.\n */\nexport function LookbookGallery({\n eyebrow,\n headline,\n intro,\n images,\n onImageClick,\n className,\n ...rest\n}: LookbookGalleryProps) {\n return (\n <section className={cn(styles.root, className)} {...rest}>\n {(eyebrow || headline || intro) && (\n <header className={styles.header}>\n {eyebrow && <p className={styles.eyebrow}>{eyebrow}</p>}\n {headline && <h2 className={styles.headline}>{headline}</h2>}\n {intro && <div className={styles.intro}>{intro}</div>}\n </header>\n )}\n\n <ul className={styles.grid}>\n {images.map((img) => {\n const Cell = onImageClick ? 'button' : 'figure';\n return (\n <li\n key={img.id}\n className={cn(\n styles.item,\n img.span && styles[`span-${img.span}`],\n img.tall && styles.tall,\n )}\n >\n <Cell\n className={styles.cell}\n {...(onImageClick\n ? { type: 'button' as const, onClick: () => onImageClick(img) }\n : {})}\n >\n <span className={styles.media}>\n <MediaPlaceholder\n src={img.src}\n alt={img.alt}\n seed={img.seed}\n aspectRatio={img.tall ? '4 / 5' : '1 / 1'}\n />\n </span>\n {img.caption && (\n <span className={styles.caption}>{img.caption}</span>\n )}\n </Cell>\n </li>\n );\n })}\n </ul>\n </section>\n );\n}\n",".root {\n font-family: var(--bazaar-font-family-sans);\n position: relative;\n display: flex;\n gap: 24px;\n align-items: center;\n padding: 22px 28px;\n border-radius: var(--bazaar-radius-lg, 12px);\n overflow: hidden;\n flex-wrap: wrap;\n}\n\n.tone-warm {\n background: linear-gradient(135deg, #F3E6D6 0%, #E8C9A6 100%);\n color: #3A2A1A;\n}\n\n.tone-sand {\n background: var(--bazaar-color-surface-subtle, #F4F2EC);\n color: var(--bazaar-color-text-primary);\n}\n\n.tone-ink {\n background: var(--bazaar-color-text-primary, #1F1C17);\n color: #fff;\n}\n\n.body {\n flex: 1 1 360px;\n display: flex;\n flex-direction: column;\n gap: 8px;\n min-width: 0;\n}\n\n.eyebrow {\n margin: 0;\n font-size: 0.75rem;\n font-weight: 600;\n letter-spacing: 0.14em;\n text-transform: uppercase;\n opacity: 0.7;\n}\n\n.headline {\n margin: 0;\n font-family: var(--bazaar-font-family-display, var(--bazaar-font-family-sans));\n font-size: clamp(1.5rem, 2.5vw, 2rem);\n font-weight: 500;\n line-height: 1.15;\n letter-spacing: -0.01em;\n}\n\n.copy {\n font-size: 0.9375rem;\n line-height: 1.5;\n opacity: 0.88;\n}\n\n.meta {\n display: flex;\n gap: 14px;\n align-items: center;\n flex-wrap: wrap;\n margin-top: 6px;\n}\n\n.code {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 6px 12px;\n border-radius: 999px;\n background: rgba(255, 255, 255, 0.65);\n color: inherit;\n font-size: 0.8125rem;\n font-weight: 700;\n letter-spacing: 0.1em;\n text-transform: uppercase;\n font-variant-numeric: tabular-nums;\n}\n\n.tone-ink .code {\n background: rgba(255, 255, 255, 0.15);\n}\n\n.countdown {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n font-size: 0.8125rem;\n font-weight: 500;\n font-variant-numeric: tabular-nums;\n}\n\n.cdUnit {\n font-weight: 600;\n}\n\n.cta {\n flex: 0 0 auto;\n padding: 12px 24px;\n border-radius: 999px;\n background: rgba(0, 0, 0, 0.8);\n color: #fff;\n border: none;\n font-family: inherit;\n font-size: 0.8125rem;\n font-weight: 600;\n letter-spacing: 0.04em;\n text-transform: uppercase;\n cursor: pointer;\n}\n\n.tone-ink .cta {\n background: #fff;\n color: var(--bazaar-color-text-primary, #1F1C17);\n}\n\n.cta:hover {\n opacity: 0.9;\n}\n\n.close {\n position: absolute;\n top: 10px;\n right: 12px;\n width: 28px;\n height: 28px;\n border-radius: 999px;\n background: rgba(0, 0, 0, 0.1);\n color: inherit;\n border: none;\n font-size: 1.125rem;\n line-height: 1;\n cursor: pointer;\n}\n\n.tone-ink .close {\n background: rgba(255, 255, 255, 0.15);\n}\n\n.close:hover {\n background: rgba(0, 0, 0, 0.2);\n}\n","import { useEffect, useState, type HTMLAttributes, type ReactNode } from 'react';\nimport { cn } from '../utils/cn';\nimport { TagIcon, ClockIcon } from './icons';\nimport styles from './SeasonalPromo.module.css';\n\nexport interface SeasonalPromoProps extends HTMLAttributes<HTMLElement> {\n eyebrow?: string;\n headline: string;\n body?: ReactNode;\n /** Coupon / promo code chip. */\n code?: string;\n /** Optional deadline (ISO). Drives the countdown. */\n endsAt?: string;\n cta?: { label: string; onClick?: () => void };\n /** Visual tone. */\n tone?: 'warm' | 'sand' | 'ink';\n /** Dismissible — shows a close button when true. */\n dismissible?: boolean;\n onDismiss?: () => void;\n}\n\nfunction useCountdown(endsAt?: string) {\n const [now, setNow] = useState(() => Date.now());\n useEffect(() => {\n if (!endsAt) return;\n const id = window.setInterval(() => setNow(Date.now()), 1000);\n return () => window.clearInterval(id);\n }, [endsAt]);\n if (!endsAt) return null;\n const end = new Date(endsAt).getTime();\n if (Number.isNaN(end)) return null;\n const diff = Math.max(0, end - now);\n const d = Math.floor(diff / 86400000);\n const h = Math.floor((diff % 86400000) / 3600000);\n const m = Math.floor((diff % 3600000) / 60000);\n const s = Math.floor((diff % 60000) / 1000);\n return { d, h, m, s, done: diff === 0 };\n}\n\n/**\n * SeasonalPromo — bold banner for sales, drops, or limited-time offers.\n * Renders eyebrow + headline + optional coupon chip + countdown. Reserve\n * for time-bound campaigns — use CampaignHero or PromoStrip for evergreen.\n */\nexport function SeasonalPromo({\n eyebrow,\n headline,\n body,\n code,\n endsAt,\n cta,\n tone = 'warm',\n dismissible,\n onDismiss,\n className,\n ...rest\n}: SeasonalPromoProps) {\n const cd = useCountdown(endsAt);\n\n return (\n <section\n className={cn(styles.root, styles[`tone-${tone}`], className)}\n {...rest}\n >\n <div className={styles.body}>\n {eyebrow && <p className={styles.eyebrow}>{eyebrow}</p>}\n <h2 className={styles.headline}>{headline}</h2>\n {body && <div className={styles.copy}>{body}</div>}\n\n <div className={styles.meta}>\n {code && (\n <span className={styles.code}>\n <TagIcon width={14} height={14} /> {code}\n </span>\n )}\n {cd && !cd.done && (\n <span className={styles.countdown}>\n <ClockIcon width={14} height={14} />\n Ends in{' '}\n <span className={styles.cdUnit}>{cd.d}d</span>\n <span className={styles.cdUnit}>\n {String(cd.h).padStart(2, '0')}h\n </span>\n <span className={styles.cdUnit}>\n {String(cd.m).padStart(2, '0')}m\n </span>\n <span className={styles.cdUnit}>\n {String(cd.s).padStart(2, '0')}s\n </span>\n </span>\n )}\n {cd?.done && <span className={styles.countdown}>Offer ended</span>}\n </div>\n </div>\n\n {cta && (\n <button type=\"button\" className={styles.cta} onClick={cta.onClick}>\n {cta.label}\n </button>\n )}\n\n {dismissible && (\n <button\n type=\"button\"\n className={styles.close}\n onClick={onDismiss}\n aria-label=\"Dismiss\"\n >\n ×\n </button>\n )}\n </section>\n );\n}\n",".root {\n font-family: var(--bazaar-font-family-sans);\n color: var(--bazaar-color-text-primary);\n display: flex;\n flex-direction: column;\n gap: 48px;\n}\n\n.hero {\n display: grid;\n grid-template-columns: 1fr 1fr;\n gap: 48px;\n align-items: center;\n}\n\n.copy {\n display: flex;\n flex-direction: column;\n gap: 16px;\n max-width: 48ch;\n}\n\n.eyebrow {\n margin: 0;\n font-size: 0.75rem;\n font-weight: 600;\n letter-spacing: 0.14em;\n text-transform: uppercase;\n color: var(--bazaar-color-text-muted);\n}\n\n.headline {\n margin: 0;\n font-family: var(--bazaar-font-family-display, var(--bazaar-font-family-sans));\n font-size: clamp(1.875rem, 3.5vw, 2.75rem);\n font-weight: 500;\n line-height: 1.1;\n letter-spacing: -0.01em;\n}\n\n.body {\n font-size: 1rem;\n line-height: 1.65;\n color: var(--bazaar-color-text-secondary, var(--bazaar-color-text-primary));\n}\n\n.body > * + * {\n margin-top: 1em;\n}\n\n.cta {\n align-self: flex-start;\n margin-top: 6px;\n background: none;\n border: none;\n padding: 0 0 3px;\n font-family: inherit;\n font-size: 0.9375rem;\n font-weight: 600;\n color: var(--bazaar-color-text-primary);\n border-bottom: 1px solid currentColor;\n cursor: pointer;\n display: inline-flex;\n gap: 6px;\n align-items: center;\n}\n\n.cta:hover {\n opacity: 0.7;\n}\n\n.media {\n margin: 0;\n border-radius: var(--bazaar-radius-lg, 12px);\n overflow: hidden;\n background: var(--bazaar-color-surface-subtle, #F4F2EC);\n}\n\n.pull {\n margin: 0;\n padding: 0 24px;\n border-left: 2px solid var(--bazaar-color-text-primary, #1F1C17);\n max-width: 64ch;\n align-self: center;\n}\n\n.pullText {\n margin: 0;\n font-family: var(--bazaar-font-family-display, var(--bazaar-font-family-sans));\n font-size: clamp(1.25rem, 2vw, 1.625rem);\n font-weight: 500;\n font-style: italic;\n line-height: 1.4;\n}\n\n.pullAttr {\n margin-top: 8px;\n font-size: 0.8125rem;\n font-weight: 600;\n letter-spacing: 0.08em;\n text-transform: uppercase;\n color: var(--bazaar-color-text-muted);\n}\n\n.pillars {\n list-style: none;\n margin: 0;\n padding: 0;\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));\n gap: 24px;\n}\n\n.pillar {\n display: flex;\n flex-direction: column;\n gap: 6px;\n padding: 20px;\n border-top: 1px solid var(--bazaar-color-border-default, rgba(0, 0, 0, 0.12));\n}\n\n.pillarIcon {\n display: inline-flex;\n align-items: center;\n margin-bottom: 4px;\n color: var(--bazaar-color-text-primary);\n}\n\n.pillarTitle {\n margin: 0;\n font-size: 1.0625rem;\n font-weight: 600;\n letter-spacing: -0.005em;\n}\n\n.pillarBody {\n font-size: 0.9375rem;\n line-height: 1.5;\n color: var(--bazaar-color-text-muted);\n}\n\n@media (max-width: 820px) {\n .hero {\n grid-template-columns: 1fr;\n gap: 28px;\n }\n}\n","import type { HTMLAttributes, ReactNode } from 'react';\nimport { cn } from '../utils/cn';\nimport { MediaPlaceholder } from './MediaPlaceholder';\nimport styles from './BrandStory.module.css';\n\nexport interface BrandPillar {\n id: string;\n title: string;\n body?: ReactNode;\n /** Optional small icon or glyph (ReactNode). */\n icon?: ReactNode;\n}\n\nexport interface BrandStoryProps extends HTMLAttributes<HTMLElement> {\n eyebrow?: string;\n headline: string;\n /** Paragraphs of body copy. */\n body?: ReactNode;\n image?: { src?: string; alt: string; seed?: string };\n /** 2–4 short pillars summarising what the brand stands for. */\n pillars?: BrandPillar[];\n /** Pull-quote rendered between body and pillars. */\n pullQuote?: { text: string; attribution?: string };\n cta?: { label: string; onClick?: () => void };\n}\n\n/**\n * BrandStory — the \"about\" module. Usually placed on the homepage mid-way\n * or on a dedicated About page. Combines a short manifesto, a hero image,\n * a pull-quote and the brand's core pillars.\n */\nexport function BrandStory({\n eyebrow = 'Our story',\n headline,\n body,\n image,\n pillars = [],\n pullQuote,\n cta,\n className,\n ...rest\n}: BrandStoryProps) {\n return (\n <section className={cn(styles.root, className)} {...rest}>\n <div className={styles.hero}>\n <div className={styles.copy}>\n <p className={styles.eyebrow}>{eyebrow}</p>\n <h2 className={styles.headline}>{headline}</h2>\n {body && <div className={styles.body}>{body}</div>}\n {cta && (\n <button type=\"button\" className={styles.cta} onClick={cta.onClick}>\n {cta.label} <span aria-hidden>→</span>\n </button>\n )}\n </div>\n {image && (\n <figure className={styles.media}>\n <MediaPlaceholder\n src={image.src}\n alt={image.alt}\n seed={image.seed}\n aspectRatio=\"4 / 5\"\n />\n </figure>\n )}\n </div>\n\n {pullQuote && (\n <blockquote className={styles.pull}>\n <p className={styles.pullText}>“{pullQuote.text}”</p>\n {pullQuote.attribution && (\n <footer className={styles.pullAttr}>— {pullQuote.attribution}</footer>\n )}\n </blockquote>\n )}\n\n {pillars.length > 0 && (\n <ul className={styles.pillars}>\n {pillars.map((p) => (\n <li key={p.id} className={styles.pillar}>\n {p.icon && <span className={styles.pillarIcon}>{p.icon}</span>}\n <h3 className={styles.pillarTitle}>{p.title}</h3>\n {p.body && <div className={styles.pillarBody}>{p.body}</div>}\n </li>\n ))}\n </ul>\n )}\n </section>\n );\n}\n",".root {\n font-family: var(--bazaar-font-family-sans);\n display: inline-flex;\n align-items: center;\n gap: 4px;\n padding: 2px;\n border: 1px solid var(--bazaar-color-border-default, rgba(0, 0, 0, 0.14));\n border-radius: 999px;\n background: var(--bazaar-color-surface-default, #fff);\n user-select: none;\n}\n\n.size-sm {\n font-size: 0.8125rem;\n}\n\n.size-md {\n font-size: 0.9375rem;\n}\n\n.size-lg {\n font-size: 1rem;\n}\n\n.btn {\n width: 32px;\n height: 32px;\n border-radius: 999px;\n border: none;\n background: transparent;\n display: flex;\n align-items: center;\n justify-content: center;\n color: var(--bazaar-color-text-primary);\n cursor: pointer;\n transition: background 120ms ease;\n}\n\n.size-sm .btn {\n width: 28px;\n height: 28px;\n}\n\n.size-lg .btn {\n width: 36px;\n height: 36px;\n}\n\n.btn:hover:not(:disabled) {\n background: var(--bazaar-color-surface-subtle, #F4F2EC);\n}\n\n.btn:disabled {\n opacity: 0.4;\n cursor: not-allowed;\n}\n\n.value {\n min-width: 22px;\n text-align: center;\n font-variant-numeric: tabular-nums;\n font-weight: 500;\n}\n\n.disabled {\n opacity: 0.6;\n}\n","import { useState, type HTMLAttributes } from 'react';\nimport { cn } from '../utils/cn';\nimport { MinusIcon, PlusIcon } from './icons';\nimport styles from './QuantityStepper.module.css';\n\nexport interface QuantityStepperProps\n extends Omit<HTMLAttributes<HTMLDivElement>, 'onChange'> {\n value?: number;\n defaultValue?: number;\n min?: number;\n max?: number;\n onChange?: (value: number) => void;\n /** Visual density. */\n size?: 'sm' | 'md' | 'lg';\n disabled?: boolean;\n label?: string;\n}\n\n/**\n * QuantityStepper — minus / value / plus control used in carts and on PDPs.\n * Supports controlled and uncontrolled usage; clamps to `min` / `max`.\n */\nexport function QuantityStepper({\n value,\n defaultValue = 1,\n min = 1,\n max = 99,\n onChange,\n size = 'md',\n disabled,\n label = 'Quantity',\n className,\n ...rest\n}: QuantityStepperProps) {\n const [internal, setInternal] = useState(defaultValue);\n const current = value ?? internal;\n const set = (next: number) => {\n const clamped = Math.min(max, Math.max(min, next));\n setInternal(clamped);\n onChange?.(clamped);\n };\n\n return (\n <div\n className={cn(\n styles.root,\n styles[`size-${size}`],\n disabled && styles.disabled,\n className,\n )}\n role=\"group\"\n aria-label={label}\n {...rest}\n >\n <button\n type=\"button\"\n className={styles.btn}\n onClick={() => set(current - 1)}\n disabled={disabled || current <= min}\n aria-label=\"Decrease quantity\"\n >\n <MinusIcon width={14} height={14} />\n </button>\n <span className={styles.value} aria-live=\"polite\">\n {current}\n </span>\n <button\n type=\"button\"\n className={styles.btn}\n onClick={() => set(current + 1)}\n disabled={disabled || current >= max}\n aria-label=\"Increase quantity\"\n >\n <PlusIcon width={14} height={14} />\n </button>\n </div>\n );\n}\n",".root {\n font-family: var(--bazaar-font-family-sans);\n position: relative;\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 10px 44px;\n font-size: 0.8125rem;\n letter-spacing: 0.03em;\n text-align: center;\n}\n\n.tone-ink {\n background: var(--bazaar-color-text-primary, #1F1C17);\n color: #fff;\n}\n\n.tone-sand {\n background: var(--bazaar-color-surface-subtle, #F4F2EC);\n color: var(--bazaar-color-text-primary);\n}\n\n.tone-warm {\n background: #E8C9A6;\n color: #3A2A1A;\n}\n\n.inner {\n display: inline-flex;\n align-items: center;\n gap: 10px;\n}\n\n.body {\n font-weight: 500;\n}\n\n.cta {\n background: none;\n border: none;\n color: inherit;\n font: inherit;\n text-decoration: underline;\n text-underline-offset: 3px;\n cursor: pointer;\n padding: 0;\n}\n\n.cta:hover {\n opacity: 0.85;\n}\n\n.close {\n position: absolute;\n right: 12px;\n top: 50%;\n transform: translateY(-50%);\n width: 24px;\n height: 24px;\n border-radius: 999px;\n background: transparent;\n color: inherit;\n border: none;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n opacity: 0.7;\n}\n\n.close:hover {\n opacity: 1;\n}\n","import { useEffect, useState, type HTMLAttributes, type ReactNode } from 'react';\nimport { cn } from '../utils/cn';\nimport { XIcon } from './icons';\nimport styles from './AnnouncementBar.module.css';\n\nexport interface AnnouncementMessage {\n id: string;\n body: ReactNode;\n /** Optional inline CTA. */\n cta?: { label: string; onClick?: () => void };\n}\n\nexport interface AnnouncementBarProps extends HTMLAttributes<HTMLElement> {\n /** One or many messages — when multiple, they rotate. */\n messages: AnnouncementMessage[];\n /** Dismissible? */\n dismissible?: boolean;\n onDismiss?: () => void;\n /** Rotation interval (ms). Defaults to 4500. Set 0 to disable. */\n interval?: number;\n /** Visual tone. */\n tone?: 'ink' | 'sand' | 'warm';\n}\n\n/**\n * AnnouncementBar — thin site-wide bar for shipping promises, drops or\n * limited-time promos. Rotates through messages when more than one is\n * supplied.\n */\nexport function AnnouncementBar({\n messages,\n dismissible,\n onDismiss,\n interval = 4500,\n tone = 'ink',\n className,\n ...rest\n}: AnnouncementBarProps) {\n const [idx, setIdx] = useState(0);\n const [dismissed, setDismissed] = useState(false);\n\n useEffect(() => {\n if (messages.length < 2 || !interval) return;\n const id = window.setInterval(() => {\n setIdx((i) => (i + 1) % messages.length);\n }, interval);\n return () => window.clearInterval(id);\n }, [messages.length, interval]);\n\n if (dismissed || messages.length === 0) return null;\n const current = messages[idx];\n\n return (\n <div\n className={cn(styles.root, styles[`tone-${tone}`], className)}\n role=\"region\"\n aria-label=\"Announcements\"\n {...rest}\n >\n <div className={styles.inner}>\n <span className={styles.body}>{current.body}</span>\n {current.cta && (\n <button\n type=\"button\"\n className={styles.cta}\n onClick={current.cta.onClick}\n >\n {current.cta.label} →\n </button>\n )}\n </div>\n {dismissible && (\n <button\n type=\"button\"\n className={styles.close}\n onClick={() => {\n setDismissed(true);\n onDismiss?.();\n }}\n aria-label=\"Dismiss announcement\"\n >\n <XIcon width={14} height={14} />\n </button>\n )}\n </div>\n );\n}\n",".root {\n position: relative;\n font-family: var(--bazaar-font-family-sans);\n color: var(--bazaar-color-text-primary);\n width: 100%;\n}\n\n.form {\n position: relative;\n display: flex;\n align-items: center;\n gap: 10px;\n padding: 0 14px;\n border: 1px solid var(--bazaar-color-border-default, rgba(0, 0, 0, 0.14));\n border-radius: 999px;\n background: var(--bazaar-color-surface-default, #fff);\n transition: border-color 120ms ease, box-shadow 120ms ease;\n}\n\n.form:focus-within {\n border-color: var(--bazaar-color-text-primary, #1F1C17);\n box-shadow: 0 0 0 3px rgba(19, 27, 40, 0.08);\n}\n\n.size-md .form {\n height: 40px;\n}\n\n.size-lg .form {\n height: 48px;\n}\n\n.icon {\n color: var(--bazaar-color-text-muted);\n flex: 0 0 auto;\n}\n\n.input {\n flex: 1 1 auto;\n min-width: 0;\n border: none;\n background: transparent;\n font-family: inherit;\n font-size: 0.9375rem;\n color: inherit;\n outline: none;\n}\n\n.input::-webkit-search-cancel-button {\n display: none;\n}\n\n.clear {\n width: 22px;\n height: 22px;\n border-radius: 999px;\n border: none;\n background: rgba(0, 0, 0, 0.06);\n color: var(--bazaar-color-text-muted);\n display: flex;\n align-items: center;\n justify-content: center;\n cursor: pointer;\n}\n\n.clear:hover {\n background: rgba(0, 0, 0, 0.12);\n color: var(--bazaar-color-text-primary);\n}\n\n.panel {\n position: absolute;\n top: calc(100% + 8px);\n left: 0;\n right: 0;\n z-index: 50;\n padding: 8px 0;\n background: var(--bazaar-color-surface-default, #fff);\n border: 1px solid var(--bazaar-color-border-default, rgba(0, 0, 0, 0.1));\n border-radius: var(--bazaar-radius-md, 8px);\n box-shadow: 0 12px 28px rgba(0, 0, 0, 0.1);\n max-height: 440px;\n overflow: auto;\n}\n\n.section + .section {\n border-top: 1px solid var(--bazaar-color-border-subtle, rgba(0, 0, 0, 0.06));\n margin-top: 6px;\n padding-top: 6px;\n}\n\n.sectionHead {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 6px 14px;\n font-size: 0.6875rem;\n font-weight: 600;\n letter-spacing: 0.1em;\n text-transform: uppercase;\n color: var(--bazaar-color-text-muted);\n}\n\n.clearLink {\n background: none;\n border: none;\n padding: 0;\n font: inherit;\n letter-spacing: 0.04em;\n text-transform: none;\n color: var(--bazaar-color-text-primary);\n text-decoration: underline;\n text-underline-offset: 3px;\n cursor: pointer;\n}\n\n.list {\n list-style: none;\n margin: 0;\n padding: 0;\n}\n\n.row {\n display: flex;\n align-items: center;\n gap: 10px;\n width: 100%;\n padding: 8px 14px;\n border: none;\n background: transparent;\n text-align: left;\n font: inherit;\n color: inherit;\n cursor: pointer;\n}\n\n.row:hover,\n.row:focus-visible {\n background: var(--bazaar-color-surface-subtle, #F4F2EC);\n outline: none;\n}\n\n.productList {\n list-style: none;\n margin: 0;\n padding: 0;\n}\n\n.product {\n display: grid;\n grid-template-columns: 44px 1fr;\n gap: 12px;\n width: 100%;\n padding: 8px 14px;\n border: none;\n background: transparent;\n text-align: left;\n font: inherit;\n color: inherit;\n cursor: pointer;\n align-items: center;\n}\n\n.product:hover,\n.product:focus-visible {\n background: var(--bazaar-color-surface-subtle, #F4F2EC);\n outline: none;\n}\n\n.productThumb {\n width: 44px;\n height: 44px;\n border-radius: var(--bazaar-radius-sm, 6px);\n overflow: hidden;\n background: var(--bazaar-color-surface-subtle, #F4F2EC);\n}\n\n.productCopy {\n display: flex;\n flex-direction: column;\n gap: 1px;\n min-width: 0;\n}\n\n.productBrand {\n font-size: 0.6875rem;\n font-weight: 600;\n letter-spacing: 0.08em;\n text-transform: uppercase;\n color: var(--bazaar-color-text-muted);\n}\n\n.productName {\n font-size: 0.875rem;\n font-weight: 500;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.productPrice {\n font-size: 0.8125rem;\n font-weight: 600;\n font-variant-numeric: tabular-nums;\n}\n\n.empty {\n margin: 0;\n padding: 14px;\n text-align: center;\n font-size: 0.875rem;\n color: var(--bazaar-color-text-muted);\n}\n","import {\n useState,\n type ChangeEvent,\n type FormEvent,\n type HTMLAttributes,\n type KeyboardEvent,\n} from 'react';\nimport { cn } from '../utils/cn';\nimport { MediaPlaceholder } from './MediaPlaceholder';\nimport { SearchIcon, ClockIcon, XIcon } from './icons';\nimport { formatMoney } from './money';\nimport type { Product } from './types';\nimport styles from './SearchBar.module.css';\n\nexport interface SearchSuggestion {\n id: string;\n label: string;\n}\n\nexport interface SearchBarProps\n extends Omit<HTMLAttributes<HTMLDivElement>, 'onChange' | 'onSubmit'> {\n placeholder?: string;\n value?: string;\n onChange?: (value: string) => void;\n onSubmit?: (value: string) => void;\n /** Recent searches shown above suggestions when focused with empty input. */\n recent?: SearchSuggestion[];\n /** Live query suggestions. */\n suggestions?: SearchSuggestion[];\n /** Product hits rendered alongside suggestions. */\n productHits?: Product[];\n onSelectSuggestion?: (s: SearchSuggestion) => void;\n onSelectProduct?: (p: Product) => void;\n onClearRecent?: () => void;\n size?: 'md' | 'lg';\n}\n\n/**\n * SearchBar — input with a dropdown panel containing recent searches,\n * typeahead suggestions and product hits. Uncontrolled by default;\n * pass `value` + `onChange` for controlled usage.\n */\nexport function SearchBar({\n placeholder = 'Search for anything',\n value,\n onChange,\n onSubmit,\n recent = [],\n suggestions = [],\n productHits = [],\n onSelectSuggestion,\n onSelectProduct,\n onClearRecent,\n size = 'md',\n className,\n ...rest\n}: SearchBarProps) {\n const [internal, setInternal] = useState('');\n const [focused, setFocused] = useState(false);\n const q = value ?? internal;\n const hasQuery = q.trim().length > 0;\n\n const change = (next: string) => {\n setInternal(next);\n onChange?.(next);\n };\n\n const submit = (e?: FormEvent) => {\n e?.preventDefault();\n onSubmit?.(q.trim());\n };\n\n const showPanel = focused && (hasQuery || recent.length > 0);\n\n return (\n <div\n className={cn(styles.root, styles[`size-${size}`], className)}\n {...rest}\n >\n <form\n className={styles.form}\n role=\"search\"\n onSubmit={submit}\n onKeyDown={(e: KeyboardEvent) => {\n if (e.key === 'Escape') (e.currentTarget as HTMLFormElement).reset();\n }}\n >\n <SearchIcon width={16} height={16} className={styles.icon} />\n <input\n type=\"search\"\n className={styles.input}\n placeholder={placeholder}\n value={q}\n onChange={(e: ChangeEvent<HTMLInputElement>) => change(e.target.value)}\n onFocus={() => setFocused(true)}\n onBlur={() => window.setTimeout(() => setFocused(false), 150)}\n />\n {hasQuery && (\n <button\n type=\"button\"\n className={styles.clear}\n onClick={() => change('')}\n aria-label=\"Clear search\"\n >\n <XIcon width={12} height={12} />\n </button>\n )}\n </form>\n\n {showPanel && (\n <div className={styles.panel} role=\"listbox\">\n {!hasQuery && recent.length > 0 && (\n <section className={styles.section}>\n <header className={styles.sectionHead}>\n <span>Recent</span>\n {onClearRecent && (\n <button\n type=\"button\"\n className={styles.clearLink}\n onClick={onClearRecent}\n >\n Clear\n </button>\n )}\n </header>\n <ul className={styles.list}>\n {recent.map((r) => (\n <li key={r.id}>\n <button\n type=\"button\"\n className={styles.row}\n onClick={() => onSelectSuggestion?.(r)}\n >\n <ClockIcon width={14} height={14} />\n <span>{r.label}</span>\n </button>\n </li>\n ))}\n </ul>\n </section>\n )}\n\n {hasQuery && suggestions.length > 0 && (\n <section className={styles.section}>\n <header className={styles.sectionHead}>Suggestions</header>\n <ul className={styles.list}>\n {suggestions.map((s) => (\n <li key={s.id}>\n <button\n type=\"button\"\n className={styles.row}\n onClick={() => onSelectSuggestion?.(s)}\n >\n <SearchIcon width={14} height={14} />\n <span>{s.label}</span>\n </button>\n </li>\n ))}\n </ul>\n </section>\n )}\n\n {hasQuery && productHits.length > 0 && (\n <section className={styles.section}>\n <header className={styles.sectionHead}>Products</header>\n <ul className={styles.productList}>\n {productHits.map((p) => (\n <li key={p.id}>\n <button\n type=\"button\"\n className={styles.product}\n onClick={() => onSelectProduct?.(p)}\n >\n <span className={styles.productThumb}>\n <MediaPlaceholder\n src={p.images[0]?.src}\n alt={p.images[0]?.alt ?? p.name}\n seed={p.images[0]?.seed}\n aspectRatio=\"1 / 1\"\n />\n </span>\n <span className={styles.productCopy}>\n {p.brand && (\n <span className={styles.productBrand}>{p.brand}</span>\n )}\n <span className={styles.productName}>{p.name}</span>\n <span className={styles.productPrice}>\n {formatMoney(p.price)}\n </span>\n </span>\n </button>\n </li>\n ))}\n </ul>\n </section>\n )}\n\n {hasQuery &&\n suggestions.length === 0 &&\n productHits.length === 0 && (\n <p className={styles.empty}>No matches for “{q}”.</p>\n )}\n </div>\n )}\n </div>\n );\n}\n",".root {\n font-family: var(--bazaar-font-family-sans);\n color: var(--bazaar-color-text-primary);\n display: grid;\n grid-template-columns: 1fr auto;\n gap: 32px;\n padding: 28px 32px;\n background: var(--bazaar-color-surface-default, #fff);\n border: 1px solid var(--bazaar-color-border-subtle, rgba(0, 0, 0, 0.06));\n border-radius: var(--bazaar-radius-lg, 12px);\n box-shadow: 0 18px 32px rgba(0, 0, 0, 0.08);\n}\n\n.columns {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));\n gap: 24px;\n}\n\n.column {\n display: flex;\n flex-direction: column;\n gap: 10px;\n}\n\n.columnTitle {\n margin: 0;\n font-size: 0.75rem;\n font-weight: 700;\n letter-spacing: 0.1em;\n text-transform: uppercase;\n color: var(--bazaar-color-text-muted);\n}\n\n.links {\n list-style: none;\n margin: 0;\n padding: 0;\n display: flex;\n flex-direction: column;\n gap: 6px;\n}\n\n.link {\n display: inline-flex;\n align-items: center;\n gap: 8px;\n padding: 2px 0;\n background: none;\n border: none;\n color: inherit;\n font: inherit;\n text-align: left;\n text-decoration: none;\n font-size: 0.9375rem;\n cursor: pointer;\n}\n\n.link:hover {\n color: var(--bazaar-color-text-primary);\n text-decoration: underline;\n text-underline-offset: 3px;\n}\n\n.badge {\n font-size: 0.625rem;\n font-weight: 700;\n letter-spacing: 0.1em;\n text-transform: uppercase;\n padding: 2px 7px;\n border-radius: 999px;\n background: rgba(19, 27, 40, 0.08);\n}\n\n.features {\n display: flex;\n gap: 16px;\n width: min(520px, 40vw);\n}\n\n.feature {\n display: flex;\n flex-direction: column;\n gap: 10px;\n flex: 1 1 0;\n min-width: 0;\n}\n\n.featureMedia {\n border-radius: var(--bazaar-radius-md, 8px);\n overflow: hidden;\n background: var(--bazaar-color-surface-subtle, #F4F2EC);\n}\n\n.featureBody {\n display: flex;\n flex-direction: column;\n gap: 4px;\n}\n\n.featureTitle {\n margin: 0;\n font-family: var(--bazaar-font-family-display, var(--bazaar-font-family-sans));\n font-size: 1rem;\n font-weight: 500;\n}\n\n.featureCopy {\n margin: 0;\n font-size: 0.8125rem;\n color: var(--bazaar-color-text-muted);\n line-height: 1.4;\n}\n\n.featureCta {\n background: none;\n border: none;\n padding: 0;\n font: inherit;\n color: var(--bazaar-color-text-primary);\n font-size: 0.8125rem;\n font-weight: 600;\n text-decoration: underline;\n text-underline-offset: 3px;\n cursor: pointer;\n align-self: flex-start;\n}\n\n.featureCta:hover {\n opacity: 0.7;\n}\n\n@media (max-width: 900px) {\n .root {\n grid-template-columns: 1fr;\n }\n .features {\n width: auto;\n }\n}\n","import type { HTMLAttributes, ReactNode } from 'react';\nimport { cn } from '../utils/cn';\nimport { MediaPlaceholder } from './MediaPlaceholder';\nimport styles from './MegaMenu.module.css';\n\nexport interface MegaMenuLink {\n id: string;\n label: string;\n href?: string;\n onClick?: () => void;\n /** Tag rendered next to the label — e.g., \"New\". */\n badge?: string;\n}\n\nexport interface MegaMenuColumn {\n id: string;\n title: string;\n links: MegaMenuLink[];\n}\n\nexport interface MegaMenuFeature {\n id: string;\n title: string;\n body?: ReactNode;\n image: { src?: string; alt: string; seed?: string };\n cta?: { label: string; onClick?: () => void };\n}\n\nexport interface MegaMenuProps extends HTMLAttributes<HTMLDivElement> {\n columns: MegaMenuColumn[];\n /** Featured tile(s) rendered on the right. */\n features?: MegaMenuFeature[];\n}\n\n/**\n * MegaMenu — multi-column navigation panel. Meant to be rendered by\n * SiteHeader inside a dropdown; provides the layout only, not the\n * open/close behaviour.\n */\nexport function MegaMenu({\n columns,\n features = [],\n className,\n ...rest\n}: MegaMenuProps) {\n return (\n <div className={cn(styles.root, className)} {...rest}>\n <div className={styles.columns}>\n {columns.map((c) => (\n <section key={c.id} className={styles.column}>\n <h4 className={styles.columnTitle}>{c.title}</h4>\n <ul className={styles.links}>\n {c.links.map((l) => (\n <li key={l.id}>\n {l.href ? (\n <a href={l.href} className={styles.link}>\n {l.label}\n {l.badge && (\n <span className={styles.badge}>{l.badge}</span>\n )}\n </a>\n ) : (\n <button\n type=\"button\"\n className={styles.link}\n onClick={l.onClick}\n >\n {l.label}\n {l.badge && (\n <span className={styles.badge}>{l.badge}</span>\n )}\n </button>\n )}\n </li>\n ))}\n </ul>\n </section>\n ))}\n </div>\n {features.length > 0 && (\n <aside className={styles.features}>\n {features.map((f) => (\n <article key={f.id} className={styles.feature}>\n <div className={styles.featureMedia}>\n <MediaPlaceholder\n src={f.image.src}\n alt={f.image.alt}\n seed={f.image.seed}\n aspectRatio=\"4 / 5\"\n />\n </div>\n <div className={styles.featureBody}>\n <p className={styles.featureTitle}>{f.title}</p>\n {f.body && <p className={styles.featureCopy}>{f.body}</p>}\n {f.cta && (\n <button\n type=\"button\"\n className={styles.featureCta}\n onClick={f.cta.onClick}\n >\n {f.cta.label} →\n </button>\n )}\n </div>\n </article>\n ))}\n </aside>\n )}\n </div>\n );\n}\n",".root {\n font-family: var(--bazaar-font-family-sans);\n color: var(--bazaar-color-text-primary);\n background: var(--bazaar-color-surface-default, #fff);\n border-bottom: 1px solid var(--bazaar-color-border-subtle, rgba(0, 0, 0, 0.06));\n position: relative;\n z-index: 30;\n}\n\n.bar {\n display: grid;\n grid-template-columns: auto 1fr auto;\n align-items: center;\n gap: 24px;\n padding: 14px 32px;\n max-width: 1400px;\n margin: 0 auto;\n}\n\n.brand {\n font-family: var(--bazaar-font-family-display, var(--bazaar-font-family-sans));\n font-size: 1.25rem;\n font-weight: 500;\n letter-spacing: 0.02em;\n}\n\n.nav {\n min-width: 0;\n}\n\n.navList {\n list-style: none;\n margin: 0;\n padding: 0;\n display: flex;\n justify-content: center;\n gap: 4px;\n}\n\n.navItem {\n position: relative;\n}\n\n.navLink {\n display: inline-flex;\n align-items: center;\n padding: 10px 14px;\n border-radius: 8px;\n background: none;\n border: none;\n color: inherit;\n font: inherit;\n font-size: 0.875rem;\n font-weight: 500;\n letter-spacing: 0.02em;\n text-decoration: none;\n cursor: pointer;\n}\n\n.navLink:hover,\n.navLink:focus-visible {\n background: var(--bazaar-color-surface-subtle, #F4F2EC);\n outline: none;\n}\n\n.mega {\n position: absolute;\n top: calc(100% + 8px);\n left: 50%;\n transform: translateX(-50%);\n min-width: 640px;\n z-index: 10;\n}\n\n.utility {\n display: flex;\n align-items: center;\n gap: 4px;\n}\n\n.searchSlot {\n width: 260px;\n margin-right: 4px;\n}\n\n.iconBtn {\n position: relative;\n width: 40px;\n height: 40px;\n border-radius: 999px;\n background: transparent;\n border: none;\n color: var(--bazaar-color-text-primary);\n display: flex;\n align-items: center;\n justify-content: center;\n cursor: pointer;\n transition: background 120ms ease;\n}\n\n.iconBtn:hover {\n background: var(--bazaar-color-surface-subtle, #F4F2EC);\n}\n\n.count {\n position: absolute;\n top: 4px;\n right: 4px;\n min-width: 18px;\n height: 18px;\n padding: 0 5px;\n border-radius: 999px;\n background: var(--bazaar-color-text-primary, #1F1C17);\n color: var(--bazaar-color-surface-default, #fff);\n font-size: 0.625rem;\n font-weight: 700;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n font-variant-numeric: tabular-nums;\n}\n\n@media (max-width: 960px) {\n .bar {\n grid-template-columns: auto 1fr auto;\n padding: 12px 16px;\n }\n .nav {\n display: none;\n }\n .searchSlot {\n width: 180px;\n }\n}\n","import { useState, type HTMLAttributes, type ReactNode } from 'react';\nimport { cn } from '../utils/cn';\nimport { SearchIcon, UserIcon, BagIcon, HeartIcon } from './icons';\nimport { MegaMenu, type MegaMenuColumn, type MegaMenuFeature } from './MegaMenu';\nimport styles from './SiteHeader.module.css';\n\nexport interface NavItem {\n id: string;\n label: string;\n href?: string;\n onClick?: () => void;\n /** When provided, this item becomes a mega-menu trigger. */\n megaMenu?: {\n columns: MegaMenuColumn[];\n features?: MegaMenuFeature[];\n };\n}\n\nexport interface SiteHeaderProps extends HTMLAttributes<HTMLElement> {\n brand: ReactNode;\n nav: NavItem[];\n /** Slot for a SearchBar — rendered in the utility row. */\n search?: ReactNode;\n cartCount?: number;\n wishlistCount?: number;\n onOpenSearch?: () => void;\n onOpenAccount?: () => void;\n onOpenWishlist?: () => void;\n onOpenCart?: () => void;\n /** Slot above the nav (e.g., AnnouncementBar). */\n topSlot?: ReactNode;\n}\n\n/**\n * SiteHeader — announcement slot + brand + primary nav (with mega-menu\n * support) + utility icons. Open/close state for mega menus is managed\n * internally via hover + focus-within.\n */\nexport function SiteHeader({\n brand,\n nav,\n search,\n cartCount = 0,\n wishlistCount,\n onOpenSearch,\n onOpenAccount,\n onOpenWishlist,\n onOpenCart,\n topSlot,\n className,\n ...rest\n}: SiteHeaderProps) {\n const [openId, setOpenId] = useState<string | null>(null);\n\n return (\n <header className={cn(styles.root, className)} {...rest}>\n {topSlot}\n <div className={styles.bar}>\n <div className={styles.brand}>{brand}</div>\n\n <nav className={styles.nav} aria-label=\"Primary\">\n <ul className={styles.navList}>\n {nav.map((item) => (\n <li\n key={item.id}\n className={styles.navItem}\n onMouseEnter={() => item.megaMenu && setOpenId(item.id)}\n onMouseLeave={() => setOpenId(null)}\n >\n {item.href ? (\n <a\n href={item.href}\n className={styles.navLink}\n onFocus={() => item.megaMenu && setOpenId(item.id)}\n >\n {item.label}\n </a>\n ) : (\n <button\n type=\"button\"\n className={styles.navLink}\n onClick={item.onClick}\n onFocus={() => item.megaMenu && setOpenId(item.id)}\n >\n {item.label}\n </button>\n )}\n {item.megaMenu && openId === item.id && (\n <div className={styles.mega}>\n <MegaMenu {...item.megaMenu} />\n </div>\n )}\n </li>\n ))}\n </ul>\n </nav>\n\n <div className={styles.utility}>\n {search ? (\n <div className={styles.searchSlot}>{search}</div>\n ) : (\n onOpenSearch && (\n <button\n type=\"button\"\n className={styles.iconBtn}\n onClick={onOpenSearch}\n aria-label=\"Search\"\n >\n <SearchIcon width={18} height={18} />\n </button>\n )\n )}\n {onOpenAccount && (\n <button\n type=\"button\"\n className={styles.iconBtn}\n onClick={onOpenAccount}\n aria-label=\"Account\"\n >\n <UserIcon width={18} height={18} />\n </button>\n )}\n {onOpenWishlist && (\n <button\n type=\"button\"\n className={styles.iconBtn}\n onClick={onOpenWishlist}\n aria-label=\"Wishlist\"\n >\n <HeartIcon width={18} height={18} />\n {wishlistCount !== undefined && wishlistCount > 0 && (\n <span className={styles.count}>{wishlistCount}</span>\n )}\n </button>\n )}\n {onOpenCart && (\n <button\n type=\"button\"\n className={styles.iconBtn}\n onClick={onOpenCart}\n aria-label={`Cart — ${cartCount} items`}\n >\n <BagIcon width={18} height={18} />\n {cartCount > 0 && (\n <span className={styles.count}>{cartCount}</span>\n )}\n </button>\n )}\n </div>\n </div>\n </header>\n );\n}\n",".root {\n font-family: var(--bazaar-font-family-sans);\n color: var(--bazaar-color-text-primary);\n background: var(--bazaar-color-surface-subtle, #F4F2EC);\n padding: 56px 32px 24px;\n}\n\n.inner {\n max-width: 1400px;\n margin: 0 auto;\n display: grid;\n grid-template-columns: minmax(260px, 1fr) 2fr;\n gap: 56px;\n}\n\n.lede {\n display: flex;\n flex-direction: column;\n gap: 16px;\n}\n\n.brand {\n font-family: var(--bazaar-font-family-display, var(--bazaar-font-family-sans));\n font-size: 1.5rem;\n font-weight: 500;\n}\n\n.pitch {\n margin: 0;\n color: var(--bazaar-color-text-muted);\n line-height: 1.55;\n font-size: 0.9375rem;\n}\n\n.newsletterSlot {\n margin-top: 8px;\n}\n\n.columns {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));\n gap: 32px;\n}\n\n.column {\n display: flex;\n flex-direction: column;\n gap: 12px;\n}\n\n.columnTitle {\n margin: 0;\n font-size: 0.75rem;\n font-weight: 700;\n letter-spacing: 0.1em;\n text-transform: uppercase;\n color: var(--bazaar-color-text-muted);\n}\n\n.columnList {\n list-style: none;\n margin: 0;\n padding: 0;\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n\n.columnLink {\n background: none;\n border: none;\n padding: 0;\n font: inherit;\n font-size: 0.9375rem;\n color: inherit;\n text-decoration: none;\n text-align: left;\n cursor: pointer;\n}\n\n.columnLink:hover {\n text-decoration: underline;\n text-underline-offset: 3px;\n}\n\n.rail {\n max-width: 1400px;\n margin: 40px auto 0;\n padding-top: 20px;\n border-top: 1px solid var(--bazaar-color-border-subtle, rgba(0, 0, 0, 0.08));\n display: flex;\n flex-wrap: wrap;\n gap: 16px;\n align-items: center;\n justify-content: space-between;\n color: var(--bazaar-color-text-muted);\n font-size: 0.8125rem;\n}\n\n.legalLinks {\n display: flex;\n flex-wrap: wrap;\n gap: 14px;\n}\n\n.legalLink {\n background: none;\n border: none;\n padding: 0;\n font: inherit;\n font-size: 0.8125rem;\n color: inherit;\n text-decoration: none;\n cursor: pointer;\n}\n\n.legalLink:hover {\n text-decoration: underline;\n}\n\n.brands {\n display: flex;\n gap: 6px;\n}\n\n.brandChip {\n padding: 4px 8px;\n border-radius: 4px;\n background: var(--bazaar-color-surface-default, #fff);\n font-size: 0.625rem;\n font-weight: 700;\n letter-spacing: 0.08em;\n text-transform: uppercase;\n color: var(--bazaar-color-text-muted);\n}\n\n.socials {\n display: flex;\n gap: 6px;\n}\n\n.socialBtn {\n width: 36px;\n height: 36px;\n border-radius: 999px;\n border: 1px solid var(--bazaar-color-border-subtle, rgba(0, 0, 0, 0.12));\n background: var(--bazaar-color-surface-default, #fff);\n color: var(--bazaar-color-text-primary);\n display: inline-flex;\n align-items: center;\n justify-content: center;\n font-size: 0.75rem;\n font-weight: 600;\n cursor: pointer;\n}\n\n.socialBtn:hover {\n background: var(--bazaar-color-surface-subtle, #F4F2EC);\n}\n\n@media (max-width: 900px) {\n .inner {\n grid-template-columns: 1fr;\n gap: 32px;\n }\n .root {\n padding: 40px 16px 16px;\n }\n}\n","import type { HTMLAttributes, ReactNode } from 'react';\nimport { cn } from '../utils/cn';\nimport styles from './SiteFooter.module.css';\n\nexport interface FooterLink {\n id: string;\n label: string;\n href?: string;\n onClick?: () => void;\n}\n\nexport interface FooterColumn {\n id: string;\n title: string;\n links: FooterLink[];\n}\n\nexport interface FooterSocial {\n id: string;\n label: string;\n href?: string;\n icon?: ReactNode;\n}\n\nexport interface SiteFooterProps extends HTMLAttributes<HTMLElement> {\n brand: ReactNode;\n /** Lead paragraph below the brand mark. */\n pitch?: ReactNode;\n /** Slot for a NewsletterSignup or custom CTA. */\n newsletterSlot?: ReactNode;\n columns: FooterColumn[];\n legalLinks?: FooterLink[];\n /** Small all-caps chips (payment brands, certifications). */\n brandChips?: string[];\n socials?: FooterSocial[];\n /** e.g., \"© 2026 House\" — rendered verbatim. */\n copyright?: ReactNode;\n}\n\n/**\n * SiteFooter — lede column (brand + pitch + optional newsletter slot) +\n * navigation columns + a bottom rail with legal links, payment/cert chips,\n * social buttons, and copyright.\n */\nexport function SiteFooter({\n brand,\n pitch,\n newsletterSlot,\n columns,\n legalLinks,\n brandChips,\n socials,\n copyright,\n className,\n ...rest\n}: SiteFooterProps) {\n return (\n <footer className={cn(styles.root, className)} {...rest}>\n <div className={styles.inner}>\n <div className={styles.lede}>\n <div className={styles.brand}>{brand}</div>\n {pitch && <p className={styles.pitch}>{pitch}</p>}\n {newsletterSlot && (\n <div className={styles.newsletterSlot}>{newsletterSlot}</div>\n )}\n </div>\n <div className={styles.columns}>\n {columns.map((col) => (\n <div key={col.id} className={styles.column}>\n <h4 className={styles.columnTitle}>{col.title}</h4>\n <ul className={styles.columnList}>\n {col.links.map((link) =>\n link.href ? (\n <li key={link.id}>\n <a className={styles.columnLink} href={link.href}>\n {link.label}\n </a>\n </li>\n ) : (\n <li key={link.id}>\n <button\n type=\"button\"\n className={styles.columnLink}\n onClick={link.onClick}\n >\n {link.label}\n </button>\n </li>\n ),\n )}\n </ul>\n </div>\n ))}\n </div>\n </div>\n <div className={styles.rail}>\n <div className={styles.legalLinks}>\n {copyright && <span>{copyright}</span>}\n {legalLinks?.map((link) =>\n link.href ? (\n <a key={link.id} className={styles.legalLink} href={link.href}>\n {link.label}\n </a>\n ) : (\n <button\n key={link.id}\n type=\"button\"\n className={styles.legalLink}\n onClick={link.onClick}\n >\n {link.label}\n </button>\n ),\n )}\n </div>\n {brandChips && brandChips.length > 0 && (\n <div className={styles.brands}>\n {brandChips.map((chip) => (\n <span key={chip} className={styles.brandChip}>\n {chip}\n </span>\n ))}\n </div>\n )}\n {socials && socials.length > 0 && (\n <div className={styles.socials}>\n {socials.map((s) =>\n s.href ? (\n <a\n key={s.id}\n className={styles.socialBtn}\n href={s.href}\n aria-label={s.label}\n >\n {s.icon ?? s.label.charAt(0)}\n </a>\n ) : (\n <button\n key={s.id}\n type=\"button\"\n className={styles.socialBtn}\n aria-label={s.label}\n >\n {s.icon ?? s.label.charAt(0)}\n </button>\n ),\n )}\n </div>\n )}\n </div>\n </footer>\n );\n}\n",".root {\n font-family: var(--bazaar-font-family-sans);\n color: var(--bazaar-color-text-primary);\n display: flex;\n flex-direction: column;\n gap: 12px;\n}\n\n.header {\n display: flex;\n flex-direction: column;\n gap: 4px;\n}\n\n.title {\n margin: 0;\n font-family: var(--bazaar-font-family-display, var(--bazaar-font-family-sans));\n font-size: 1.125rem;\n font-weight: 500;\n}\n\n.copy {\n margin: 0;\n color: var(--bazaar-color-text-muted);\n font-size: 0.875rem;\n line-height: 1.5;\n}\n\n.form {\n display: flex;\n gap: 8px;\n}\n\n.input {\n flex: 1;\n min-width: 0;\n padding: 12px 14px;\n border-radius: 8px;\n border: 1px solid var(--bazaar-color-border-strong, rgba(0, 0, 0, 0.18));\n background: var(--bazaar-color-surface-default, #fff);\n font: inherit;\n font-size: 0.9375rem;\n color: inherit;\n}\n\n.input:focus-visible {\n outline: 2px solid var(--bazaar-color-accent, #C96C3E);\n outline-offset: 2px;\n}\n\n.submit {\n padding: 12px 18px;\n border-radius: 8px;\n border: none;\n background: var(--bazaar-color-text-primary, #1F1C17);\n color: var(--bazaar-color-surface-default, #fff);\n font: inherit;\n font-size: 0.875rem;\n font-weight: 600;\n cursor: pointer;\n}\n\n.submit:hover {\n opacity: 0.9;\n}\n\n.submit:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n\n.consent {\n font-size: 0.75rem;\n color: var(--bazaar-color-text-muted);\n line-height: 1.5;\n}\n\n.status {\n font-size: 0.8125rem;\n padding: 10px 12px;\n border-radius: 8px;\n}\n\n.statusSuccess {\n background: rgba(74, 124, 89, 0.1);\n color: var(--bazaar-color-status-success, #4A7C59);\n}\n\n.statusError {\n background: rgba(200, 80, 80, 0.1);\n color: var(--bazaar-color-status-danger, #C85050);\n}\n\n.variantInline .form {\n flex-direction: row;\n}\n\n.variantStacked .form {\n flex-direction: column;\n}\n\n.variantStacked .submit {\n width: 100%;\n}\n","import { useState, type FormEvent, type HTMLAttributes, type ReactNode } from 'react';\nimport { cn } from '../utils/cn';\nimport styles from './NewsletterSignup.module.css';\n\nexport type NewsletterStatus = 'idle' | 'submitting' | 'success' | 'error';\n\nexport interface NewsletterSignupProps\n extends Omit<HTMLAttributes<HTMLFormElement>, 'onSubmit' | 'title'> {\n title?: ReactNode;\n copy?: ReactNode;\n placeholder?: string;\n submitLabel?: string;\n consent?: ReactNode;\n /** Controlled status — when provided, overrides internal state. */\n status?: NewsletterStatus;\n successMessage?: ReactNode;\n errorMessage?: ReactNode;\n onSubscribe?: (email: string) => void;\n variant?: 'inline' | 'stacked';\n}\n\n/**\n * NewsletterSignup — email-capture form for footers, promo modals, and\n * checkout thank-you pages. Manages submitting/success/error state internally\n * unless `status` is provided.\n */\nexport function NewsletterSignup({\n title,\n copy,\n placeholder = 'you@example.com',\n submitLabel = 'Subscribe',\n consent,\n status: statusProp,\n successMessage = \"You're in — check your inbox.\",\n errorMessage = \"Hmm, that didn't work. Try again?\",\n onSubscribe,\n variant = 'inline',\n className,\n ...rest\n}: NewsletterSignupProps) {\n const [email, setEmail] = useState('');\n const [internalStatus, setInternalStatus] = useState<NewsletterStatus>('idle');\n const status = statusProp ?? internalStatus;\n\n function handleSubmit(e: FormEvent<HTMLFormElement>) {\n e.preventDefault();\n if (!email) return;\n if (!statusProp) setInternalStatus('success');\n onSubscribe?.(email);\n }\n\n return (\n <form\n className={cn(\n styles.root,\n variant === 'inline' ? styles.variantInline : styles.variantStacked,\n className,\n )}\n onSubmit={handleSubmit}\n {...rest}\n >\n {(title || copy) && (\n <div className={styles.header}>\n {title && <h3 className={styles.title}>{title}</h3>}\n {copy && <p className={styles.copy}>{copy}</p>}\n </div>\n )}\n <div className={styles.form}>\n <input\n className={styles.input}\n type=\"email\"\n required\n placeholder={placeholder}\n value={email}\n onChange={(e) => setEmail(e.target.value)}\n aria-label=\"Email address\"\n />\n <button\n type=\"submit\"\n className={styles.submit}\n disabled={status === 'submitting'}\n >\n {status === 'submitting' ? '…' : submitLabel}\n </button>\n </div>\n {status === 'success' && (\n <div className={cn(styles.status, styles.statusSuccess)}>{successMessage}</div>\n )}\n {status === 'error' && (\n <div className={cn(styles.status, styles.statusError)}>{errorMessage}</div>\n )}\n {consent && <div className={styles.consent}>{consent}</div>}\n </form>\n );\n}\n",".root {\n font-family: var(--bazaar-font-family-sans);\n color: var(--bazaar-color-text-primary);\n display: flex;\n flex-direction: column;\n gap: 16px;\n}\n\n.header {\n display: flex;\n flex-direction: column;\n gap: 2px;\n padding: 0 4px;\n}\n\n.greeting {\n font-size: 0.75rem;\n color: var(--bazaar-color-text-muted);\n text-transform: uppercase;\n letter-spacing: 0.1em;\n font-weight: 600;\n}\n\n.name {\n font-family: var(--bazaar-font-family-display, var(--bazaar-font-family-sans));\n font-size: 1.25rem;\n font-weight: 500;\n}\n\n.list {\n list-style: none;\n margin: 0;\n padding: 0;\n display: flex;\n flex-direction: column;\n gap: 2px;\n}\n\n.item {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 8px;\n padding: 10px 12px;\n border-radius: 8px;\n background: none;\n border: none;\n font: inherit;\n font-size: 0.9375rem;\n color: inherit;\n text-align: left;\n text-decoration: none;\n cursor: pointer;\n width: 100%;\n}\n\n.item:hover {\n background: var(--bazaar-color-surface-subtle, #F4F2EC);\n}\n\n.itemActive {\n background: var(--bazaar-color-surface-subtle, #F4F2EC);\n font-weight: 600;\n}\n\n.count {\n min-width: 22px;\n height: 20px;\n padding: 0 7px;\n border-radius: 999px;\n background: var(--bazaar-color-text-primary, #1F1C17);\n color: var(--bazaar-color-surface-default, #fff);\n font-size: 0.6875rem;\n font-weight: 700;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n}\n\n.divider {\n height: 1px;\n background: var(--bazaar-color-border-subtle, rgba(0, 0, 0, 0.08));\n margin: 8px 0;\n}\n\n.signOut {\n padding: 10px 12px;\n background: none;\n border: none;\n font: inherit;\n font-size: 0.875rem;\n color: var(--bazaar-color-text-muted);\n text-align: left;\n cursor: pointer;\n border-radius: 8px;\n}\n\n.signOut:hover {\n background: var(--bazaar-color-surface-subtle, #F4F2EC);\n color: var(--bazaar-color-text-primary);\n}\n","import type { HTMLAttributes, ReactNode } from 'react';\nimport { cn } from '../utils/cn';\nimport styles from './AccountNav.module.css';\n\nexport interface AccountNavItem {\n id: string;\n label: string;\n href?: string;\n onClick?: () => void;\n /** Small count badge (orders, wishlist size). */\n count?: number;\n /** Optional leading icon. */\n icon?: ReactNode;\n}\n\nexport interface AccountNavProps extends HTMLAttributes<HTMLElement> {\n /** Customer first name or display label shown in the header. */\n name?: ReactNode;\n greeting?: string;\n items: AccountNavItem[];\n /** Id of the currently-active item. */\n activeId?: string;\n signOutLabel?: string;\n onSignOut?: () => void;\n}\n\n/**\n * AccountNav — sidebar navigation for the logged-in account area. Vertical\n * list with optional counts + a subdued sign-out affordance.\n */\nexport function AccountNav({\n name,\n greeting = 'Hello',\n items,\n activeId,\n signOutLabel = 'Sign out',\n onSignOut,\n className,\n ...rest\n}: AccountNavProps) {\n return (\n <nav\n className={cn(styles.root, className)}\n aria-label=\"Account\"\n {...rest}\n >\n {name && (\n <div className={styles.header}>\n <span className={styles.greeting}>{greeting}</span>\n <span className={styles.name}>{name}</span>\n </div>\n )}\n <ul className={styles.list}>\n {items.map((item) => {\n const active = item.id === activeId;\n const content = (\n <>\n <span style={{ display: 'inline-flex', alignItems: 'center', gap: 10 }}>\n {item.icon}\n {item.label}\n </span>\n {item.count !== undefined && item.count > 0 && (\n <span className={styles.count}>{item.count}</span>\n )}\n </>\n );\n return (\n <li key={item.id}>\n {item.href ? (\n <a\n href={item.href}\n className={cn(styles.item, active && styles.itemActive)}\n aria-current={active ? 'page' : undefined}\n >\n {content}\n </a>\n ) : (\n <button\n type=\"button\"\n className={cn(styles.item, active && styles.itemActive)}\n onClick={item.onClick}\n aria-current={active ? 'page' : undefined}\n >\n {content}\n </button>\n )}\n </li>\n );\n })}\n </ul>\n {onSignOut && (\n <>\n <div className={styles.divider} />\n <button type=\"button\" className={styles.signOut} onClick={onSignOut}>\n {signOutLabel}\n </button>\n </>\n )}\n </nav>\n );\n}\n",".root {\n font-family: var(--bazaar-font-family-sans);\n color: var(--bazaar-color-text-primary);\n display: flex;\n flex-direction: column;\n gap: 14px;\n padding: 20px;\n background: var(--bazaar-color-surface-subtle, #F4F2EC);\n border-radius: var(--bazaar-radius-lg, 12px);\n border: 1px solid var(--bazaar-color-border-subtle, rgba(0, 0, 0, 0.06));\n}\n\n.head {\n display: flex;\n flex-direction: column;\n gap: 4px;\n}\n\n.title {\n margin: 0;\n font-family: var(--bazaar-font-family-display, var(--bazaar-font-family-sans));\n font-size: 1.0625rem;\n font-weight: 500;\n}\n\n.productRow {\n display: flex;\n align-items: center;\n gap: 6px;\n color: var(--bazaar-color-text-muted);\n font-size: 0.875rem;\n}\n\n.productName {\n color: var(--bazaar-color-text-primary);\n font-weight: 500;\n}\n\n.variant {\n font-size: 0.8125rem;\n color: var(--bazaar-color-text-muted);\n}\n\n.form {\n display: flex;\n flex-direction: column;\n gap: 10px;\n}\n\n.channel {\n display: flex;\n gap: 6px;\n}\n\n.channelBtn {\n flex: 1;\n padding: 8px 12px;\n border-radius: 8px;\n border: 1px solid var(--bazaar-color-border-subtle, rgba(0, 0, 0, 0.12));\n background: var(--bazaar-color-surface-default, #fff);\n font: inherit;\n font-size: 0.875rem;\n cursor: pointer;\n}\n\n.channelBtnActive {\n background: var(--bazaar-color-text-primary, #1F1C17);\n color: var(--bazaar-color-surface-default, #fff);\n border-color: var(--bazaar-color-text-primary, #1F1C17);\n}\n\n.input {\n width: 100%;\n padding: 12px 14px;\n border-radius: 8px;\n border: 1px solid var(--bazaar-color-border-strong, rgba(0, 0, 0, 0.18));\n background: var(--bazaar-color-surface-default, #fff);\n font: inherit;\n font-size: 0.9375rem;\n color: inherit;\n box-sizing: border-box;\n}\n\n.input:focus-visible {\n outline: 2px solid var(--bazaar-color-accent, #C96C3E);\n outline-offset: 2px;\n}\n\n.submit {\n padding: 12px 18px;\n border-radius: 8px;\n border: none;\n background: var(--bazaar-color-text-primary, #1F1C17);\n color: var(--bazaar-color-surface-default, #fff);\n font: inherit;\n font-size: 0.875rem;\n font-weight: 600;\n cursor: pointer;\n}\n\n.submit:hover {\n opacity: 0.9;\n}\n\n.note {\n font-size: 0.75rem;\n color: var(--bazaar-color-text-muted);\n line-height: 1.5;\n}\n\n.success {\n padding: 12px;\n background: rgba(74, 124, 89, 0.12);\n color: var(--bazaar-color-status-success, #4A7C59);\n border-radius: 8px;\n font-size: 0.875rem;\n}\n","import { useState, type FormEvent, type HTMLAttributes, type ReactNode } from 'react';\nimport { cn } from '../utils/cn';\nimport styles from './BackInStockForm.module.css';\n\nexport type BackInStockChannel = 'email' | 'sms';\n\nexport interface BackInStockFormProps\n extends Omit<HTMLAttributes<HTMLFormElement>, 'onSubmit'> {\n productName: ReactNode;\n /** e.g., \"Size M / Oat\" */\n variantLabel?: ReactNode;\n /** Channels offered. Defaults to email only. */\n channels?: BackInStockChannel[];\n defaultChannel?: BackInStockChannel;\n submitLabel?: string;\n note?: ReactNode;\n submitted?: boolean;\n successMessage?: ReactNode;\n onSubscribe?: (input: { channel: BackInStockChannel; value: string }) => void;\n}\n\n/**\n * BackInStockForm — capture form shown on sold-out variants. Supports email\n * and optional SMS capture with a channel toggle.\n */\nexport function BackInStockForm({\n productName,\n variantLabel,\n channels = ['email'],\n defaultChannel,\n submitLabel = 'Notify me',\n note = \"We'll ping you once — no newsletter signup.\",\n submitted = false,\n successMessage = \"You're on the list. We'll reach out as soon as it's back.\",\n onSubscribe,\n className,\n ...rest\n}: BackInStockFormProps) {\n const [channel, setChannel] = useState<BackInStockChannel>(\n defaultChannel ?? channels[0] ?? 'email',\n );\n const [value, setValue] = useState('');\n\n function handleSubmit(e: FormEvent<HTMLFormElement>) {\n e.preventDefault();\n if (!value) return;\n onSubscribe?.({ channel, value });\n }\n\n return (\n <form\n className={cn(styles.root, className)}\n onSubmit={handleSubmit}\n {...rest}\n >\n <div className={styles.head}>\n <h4 className={styles.title}>Notify me when this is back</h4>\n <div className={styles.productRow}>\n <span className={styles.productName}>{productName}</span>\n {variantLabel && <span className={styles.variant}>· {variantLabel}</span>}\n </div>\n </div>\n\n {submitted ? (\n <div className={styles.success}>{successMessage}</div>\n ) : (\n <div className={styles.form}>\n {channels.length > 1 && (\n <div className={styles.channel} role=\"tablist\">\n {channels.map((c) => (\n <button\n key={c}\n type=\"button\"\n role=\"tab\"\n aria-selected={channel === c}\n className={cn(\n styles.channelBtn,\n channel === c && styles.channelBtnActive,\n )}\n onClick={() => setChannel(c)}\n >\n {c === 'email' ? 'Email' : 'Text'}\n </button>\n ))}\n </div>\n )}\n <input\n className={styles.input}\n type={channel === 'email' ? 'email' : 'tel'}\n required\n value={value}\n onChange={(e) => setValue(e.target.value)}\n placeholder={\n channel === 'email' ? 'you@example.com' : '(555) 555-5555'\n }\n aria-label={channel === 'email' ? 'Email address' : 'Mobile number'}\n />\n <button type=\"submit\" className={styles.submit}>\n {submitLabel}\n </button>\n {note && <div className={styles.note}>{note}</div>}\n </div>\n )}\n </form>\n );\n}\n",".root {\n font-family: var(--bazaar-font-family-sans);\n color: var(--bazaar-color-text-primary);\n background: var(--bazaar-color-surface-default, #fff);\n display: flex;\n flex-direction: column;\n min-height: 100vh;\n}\n\n.main {\n flex: 1;\n display: flex;\n flex-direction: column;\n}\n\n.section {\n padding: 64px 32px;\n max-width: 1400px;\n margin: 0 auto;\n width: 100%;\n box-sizing: border-box;\n display: flex;\n flex-direction: column;\n gap: 24px;\n}\n\n.sectionBleed {\n padding: 0;\n max-width: none;\n}\n\n.sectionMuted {\n background: var(--bazaar-color-surface-subtle, #F4F2EC);\n max-width: none;\n padding: 64px 32px;\n}\n\n.sectionMuted > .sectionInner {\n max-width: 1400px;\n margin: 0 auto;\n width: 100%;\n display: flex;\n flex-direction: column;\n gap: 24px;\n}\n\n@media (max-width: 720px) {\n .section,\n .sectionMuted {\n padding: 40px 16px;\n }\n}\n","import type { HTMLAttributes, ReactNode } from 'react';\nimport { cn } from '../utils/cn';\nimport styles from './HomePageTemplate.module.css';\n\nexport interface HomePageSection {\n id: string;\n content: ReactNode;\n /** Full-bleed section (no padding/max-width). */\n bleed?: boolean;\n /** Muted background wrapper while keeping inner max-width. */\n muted?: boolean;\n}\n\nexport interface HomePageTemplateProps extends HTMLAttributes<HTMLDivElement> {\n header?: ReactNode;\n footer?: ReactNode;\n /** Hero module above the fold — rendered full-bleed by default. */\n hero?: ReactNode;\n sections?: HomePageSection[];\n}\n\n/**\n * HomePageTemplate — marketing home-page shell. Composes a header, a hero\n * slot, an arbitrary list of sections (normal, bleed, or muted), and a\n * footer.\n */\nexport function HomePageTemplate({\n header,\n footer,\n hero,\n sections = [],\n className,\n ...rest\n}: HomePageTemplateProps) {\n return (\n <div className={cn(styles.root, className)} {...rest}>\n {header}\n <main className={styles.main}>\n {hero && <div className={cn(styles.section, styles.sectionBleed)}>{hero}</div>}\n {sections.map((s) => {\n if (s.muted) {\n return (\n <div key={s.id} className={styles.sectionMuted}>\n <div className={styles.sectionInner}>{s.content}</div>\n </div>\n );\n }\n return (\n <div\n key={s.id}\n className={cn(styles.section, s.bleed && styles.sectionBleed)}\n >\n {s.content}\n </div>\n );\n })}\n </main>\n {footer}\n </div>\n );\n}\n",".root {\n font-family: var(--bazaar-font-family-sans);\n color: var(--bazaar-color-text-primary);\n background: var(--bazaar-color-surface-default, #fff);\n display: flex;\n flex-direction: column;\n min-height: 100vh;\n}\n\n.main {\n flex: 1;\n display: flex;\n flex-direction: column;\n}\n\n.breadcrumb {\n max-width: 1400px;\n margin: 0 auto;\n padding: 16px 32px 0;\n width: 100%;\n box-sizing: border-box;\n}\n\n.hero {\n width: 100%;\n}\n\n.toolbar {\n max-width: 1400px;\n margin: 0 auto;\n padding: 12px 32px;\n width: 100%;\n box-sizing: border-box;\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 12px;\n flex-wrap: wrap;\n border-bottom: 1px solid var(--bazaar-color-border-subtle, rgba(0, 0, 0, 0.06));\n}\n\n.body {\n max-width: 1400px;\n margin: 0 auto;\n padding: 24px 32px 64px;\n width: 100%;\n box-sizing: border-box;\n display: grid;\n grid-template-columns: 260px 1fr;\n gap: 32px;\n}\n\n.filters {\n position: sticky;\n top: 24px;\n align-self: start;\n max-height: calc(100vh - 48px);\n overflow-y: auto;\n}\n\n.results {\n display: flex;\n flex-direction: column;\n gap: 24px;\n min-width: 0;\n}\n\n.pagination {\n display: flex;\n justify-content: center;\n margin-top: 16px;\n}\n\n@media (max-width: 900px) {\n .body {\n grid-template-columns: 1fr;\n }\n .filters {\n position: static;\n }\n .breadcrumb,\n .toolbar,\n .body {\n padding-left: 16px;\n padding-right: 16px;\n }\n}\n","import type { HTMLAttributes, ReactNode } from 'react';\nimport { cn } from '../utils/cn';\nimport styles from './CollectionPageTemplate.module.css';\n\nexport interface CollectionPageTemplateProps\n extends Omit<HTMLAttributes<HTMLDivElement>, 'results'> {\n header?: ReactNode;\n footer?: ReactNode;\n breadcrumbs?: ReactNode;\n /** Hero / banner above the listing — CollectionHero is a natural fit. */\n hero?: ReactNode;\n /** Toolbar row — typically SearchResultsHeader on the left + SortMenu on the right. */\n toolbarLeft?: ReactNode;\n toolbarRight?: ReactNode;\n /** Left-rail filters (FilterPanel). */\n filters?: ReactNode;\n /** Main results column — typically a ProductGrid. */\n results: ReactNode;\n /** Optional pagination/load-more row below the grid. */\n pagination?: ReactNode;\n}\n\n/**\n * CollectionPageTemplate — product-listing-page shell. Composes header,\n * breadcrumbs, collection hero, a toolbar (sort + active filter chips),\n * a sticky left-rail FilterPanel, and a results column.\n */\nexport function CollectionPageTemplate({\n header,\n footer,\n breadcrumbs,\n hero,\n toolbarLeft,\n toolbarRight,\n filters,\n results,\n pagination,\n className,\n ...rest\n}: CollectionPageTemplateProps) {\n return (\n <div className={cn(styles.root, className)} {...rest}>\n {header}\n <main className={styles.main}>\n {breadcrumbs && <div className={styles.breadcrumb}>{breadcrumbs}</div>}\n {hero && <div className={styles.hero}>{hero}</div>}\n {(toolbarLeft || toolbarRight) && (\n <div className={styles.toolbar}>\n <div>{toolbarLeft}</div>\n <div>{toolbarRight}</div>\n </div>\n )}\n <div className={styles.body}>\n {filters && <aside className={styles.filters}>{filters}</aside>}\n <div className={styles.results}>\n {results}\n {pagination && <div className={styles.pagination}>{pagination}</div>}\n </div>\n </div>\n </main>\n {footer}\n </div>\n );\n}\n",".root {\n font-family: var(--bazaar-font-family-sans);\n color: var(--bazaar-color-text-primary);\n background: var(--bazaar-color-surface-default, #fff);\n display: flex;\n flex-direction: column;\n min-height: 100vh;\n}\n\n.main {\n flex: 1;\n display: flex;\n flex-direction: column;\n}\n\n.breadcrumb {\n max-width: 1400px;\n margin: 0 auto;\n padding: 16px 32px 0;\n width: 100%;\n box-sizing: border-box;\n}\n\n.hero {\n max-width: 1400px;\n margin: 0 auto;\n padding: 24px 32px;\n width: 100%;\n box-sizing: border-box;\n display: grid;\n grid-template-columns: 1.15fr 1fr;\n gap: 48px;\n align-items: start;\n}\n\n.gallery {\n min-width: 0;\n}\n\n.buyBox {\n position: sticky;\n top: 24px;\n align-self: start;\n display: flex;\n flex-direction: column;\n gap: 16px;\n}\n\n.section {\n max-width: 1400px;\n margin: 0 auto;\n padding: 40px 32px;\n width: 100%;\n box-sizing: border-box;\n display: flex;\n flex-direction: column;\n gap: 20px;\n}\n\n.sectionMuted {\n background: var(--bazaar-color-surface-subtle, #F4F2EC);\n max-width: none;\n padding: 40px 32px;\n}\n\n.sectionMuted > .sectionInner {\n max-width: 1400px;\n margin: 0 auto;\n width: 100%;\n display: flex;\n flex-direction: column;\n gap: 20px;\n}\n\n@media (max-width: 960px) {\n .hero {\n grid-template-columns: 1fr;\n gap: 24px;\n }\n .buyBox {\n position: static;\n }\n .breadcrumb,\n .hero,\n .section,\n .sectionMuted {\n padding-left: 16px;\n padding-right: 16px;\n }\n}\n","import type { HTMLAttributes, ReactNode } from 'react';\nimport { cn } from '../utils/cn';\nimport styles from './ProductDetailPageTemplate.module.css';\n\nexport interface PDPSection {\n id: string;\n content: ReactNode;\n /** Render on a muted background (good for reviews, cross-sell, trust). */\n muted?: boolean;\n}\n\nexport interface ProductDetailPageTemplateProps\n extends HTMLAttributes<HTMLDivElement> {\n header?: ReactNode;\n footer?: ReactNode;\n breadcrumbs?: ReactNode;\n /** Main gallery — typically ProductMediaGallery. */\n gallery: ReactNode;\n /** Sticky right-rail buy box — typically ProductBuyBox. */\n buyBox: ReactNode;\n /** Scrollable sections below the fold — details, reviews, cross-sell. */\n sections?: PDPSection[];\n /** Fixed mobile ATC — typically StickyMobileATC. */\n mobileAtc?: ReactNode;\n}\n\n/**\n * ProductDetailPageTemplate — PDP shell. Gallery on the left, sticky\n * buy box on the right, scrollable sections (details, reviews,\n * recommendations) below, with optional mobile ATC pinned to the bottom.\n */\nexport function ProductDetailPageTemplate({\n header,\n footer,\n breadcrumbs,\n gallery,\n buyBox,\n sections = [],\n mobileAtc,\n className,\n ...rest\n}: ProductDetailPageTemplateProps) {\n return (\n <div className={cn(styles.root, className)} {...rest}>\n {header}\n <main className={styles.main}>\n {breadcrumbs && <div className={styles.breadcrumb}>{breadcrumbs}</div>}\n <div className={styles.hero}>\n <div className={styles.gallery}>{gallery}</div>\n <div className={styles.buyBox}>{buyBox}</div>\n </div>\n {sections.map((s) =>\n s.muted ? (\n <div key={s.id} className={styles.sectionMuted}>\n <div className={styles.sectionInner}>{s.content}</div>\n </div>\n ) : (\n <div key={s.id} className={styles.section}>\n {s.content}\n </div>\n ),\n )}\n </main>\n {footer}\n {mobileAtc}\n </div>\n );\n}\n",".root {\n font-family: var(--bazaar-font-family-sans);\n color: var(--bazaar-color-text-primary);\n background: var(--bazaar-color-surface-default, #fff);\n display: flex;\n flex-direction: column;\n min-height: 100vh;\n}\n\n.main {\n flex: 1;\n display: flex;\n flex-direction: column;\n}\n\n.searchSlot {\n max-width: 1400px;\n margin: 0 auto;\n padding: 20px 32px 0;\n width: 100%;\n box-sizing: border-box;\n}\n\n.suggestions {\n max-width: 1400px;\n margin: 0 auto;\n padding: 20px 32px 0;\n width: 100%;\n box-sizing: border-box;\n}\n\n.body {\n max-width: 1400px;\n margin: 0 auto;\n padding: 24px 32px 64px;\n width: 100%;\n box-sizing: border-box;\n display: grid;\n grid-template-columns: 260px 1fr;\n gap: 32px;\n}\n\n.filters {\n position: sticky;\n top: 24px;\n align-self: start;\n max-height: calc(100vh - 48px);\n overflow-y: auto;\n}\n\n.results {\n display: flex;\n flex-direction: column;\n gap: 24px;\n min-width: 0;\n}\n\n.header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 12px;\n flex-wrap: wrap;\n}\n\n.empty {\n padding: 64px 24px;\n display: flex;\n flex-direction: column;\n align-items: center;\n text-align: center;\n gap: 16px;\n color: var(--bazaar-color-text-muted);\n background: var(--bazaar-color-surface-subtle, #F4F2EC);\n border-radius: var(--bazaar-radius-lg, 12px);\n}\n\n.emptyTitle {\n font-family: var(--bazaar-font-family-display, var(--bazaar-font-family-sans));\n font-size: 1.25rem;\n font-weight: 500;\n color: var(--bazaar-color-text-primary);\n margin: 0;\n}\n\n.emptyBody {\n margin: 0;\n max-width: 420px;\n line-height: 1.5;\n}\n\n@media (max-width: 900px) {\n .body {\n grid-template-columns: 1fr;\n }\n .filters {\n position: static;\n }\n .searchSlot,\n .suggestions,\n .body {\n padding-left: 16px;\n padding-right: 16px;\n }\n}\n","import type { HTMLAttributes, ReactNode } from 'react';\nimport { cn } from '../utils/cn';\nimport styles from './SearchResultsPageTemplate.module.css';\n\nexport interface SearchResultsPageTemplateProps\n extends Omit<HTMLAttributes<HTMLDivElement>, 'results'> {\n header?: ReactNode;\n footer?: ReactNode;\n /** Large top-of-page SearchBar — slot stays rendered above the fold. */\n searchSlot?: ReactNode;\n /** Did-you-mean / spelling suggestion row. */\n suggestionsSlot?: ReactNode;\n /** SearchResultsHeader (title + count + chips). */\n resultsHeader?: ReactNode;\n /** SortMenu or view-toggle. */\n resultsControls?: ReactNode;\n /** FilterPanel on the left. */\n filters?: ReactNode;\n /** Main results — typically a ProductGrid. */\n results?: ReactNode;\n /** Rendered instead of `results` when no matches. */\n empty?: ReactNode;\n /** True when `results` should be replaced by the empty state. */\n isEmpty?: boolean;\n pagination?: ReactNode;\n}\n\n/**\n * SearchResultsPageTemplate — shell for full-page search. Mirrors the\n * collection-page layout but emphasizes the search field and supports an\n * empty-state slot when the query returns no results.\n */\nexport function SearchResultsPageTemplate({\n header,\n footer,\n searchSlot,\n suggestionsSlot,\n resultsHeader,\n resultsControls,\n filters,\n results,\n empty,\n isEmpty = false,\n pagination,\n className,\n ...rest\n}: SearchResultsPageTemplateProps) {\n const defaultEmpty = (\n <div className={styles.empty}>\n <h3 className={styles.emptyTitle}>No results</h3>\n <p className={styles.emptyBody}>\n Try a different term, or browse collections from the top nav.\n </p>\n </div>\n );\n\n return (\n <div className={cn(styles.root, className)} {...rest}>\n {header}\n <main className={styles.main}>\n {searchSlot && <div className={styles.searchSlot}>{searchSlot}</div>}\n {suggestionsSlot && (\n <div className={styles.suggestions}>{suggestionsSlot}</div>\n )}\n <div className={styles.body}>\n {filters && !isEmpty && <aside className={styles.filters}>{filters}</aside>}\n <div className={styles.results} style={isEmpty ? { gridColumn: '1 / -1' } : undefined}>\n {(resultsHeader || resultsControls) && (\n <div className={styles.header}>\n <div>{resultsHeader}</div>\n <div>{resultsControls}</div>\n </div>\n )}\n {isEmpty ? empty ?? defaultEmpty : results}\n {!isEmpty && pagination}\n </div>\n </div>\n </main>\n {footer}\n </div>\n );\n}\n",".root {\n font-family: var(--bazaar-font-family-sans);\n color: var(--bazaar-color-text-primary);\n background: var(--bazaar-color-surface-default, #fff);\n display: flex;\n flex-direction: column;\n min-height: 100vh;\n}\n\n.main {\n flex: 1;\n display: flex;\n flex-direction: column;\n}\n\n.heading {\n max-width: 1400px;\n margin: 0 auto;\n padding: 32px 32px 8px;\n width: 100%;\n box-sizing: border-box;\n}\n\n.title {\n margin: 0;\n font-family: var(--bazaar-font-family-display, var(--bazaar-font-family-sans));\n font-size: 1.75rem;\n font-weight: 500;\n}\n\n.subtitle {\n margin: 4px 0 0;\n color: var(--bazaar-color-text-muted);\n font-size: 0.9375rem;\n}\n\n.body {\n max-width: 1400px;\n margin: 0 auto;\n padding: 16px 32px 64px;\n width: 100%;\n box-sizing: border-box;\n display: grid;\n grid-template-columns: 260px 1fr;\n gap: 40px;\n}\n\n.sidebar {\n position: sticky;\n top: 24px;\n align-self: start;\n}\n\n.content {\n min-width: 0;\n display: flex;\n flex-direction: column;\n gap: 24px;\n}\n\n.summary {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));\n gap: 16px;\n}\n\n.summaryCard {\n background: var(--bazaar-color-surface-subtle, #F4F2EC);\n border-radius: var(--bazaar-radius-lg, 12px);\n padding: 16px 18px;\n display: flex;\n flex-direction: column;\n gap: 4px;\n}\n\n.summaryLabel {\n font-size: 0.75rem;\n letter-spacing: 0.1em;\n text-transform: uppercase;\n font-weight: 600;\n color: var(--bazaar-color-text-muted);\n}\n\n.summaryValue {\n font-family: var(--bazaar-font-family-display, var(--bazaar-font-family-sans));\n font-size: 1.5rem;\n font-weight: 500;\n}\n\n.summaryMeta {\n font-size: 0.8125rem;\n color: var(--bazaar-color-text-muted);\n}\n\n.section {\n display: flex;\n flex-direction: column;\n gap: 12px;\n}\n\n.sectionHead {\n display: flex;\n align-items: baseline;\n justify-content: space-between;\n gap: 12px;\n}\n\n.sectionTitle {\n margin: 0;\n font-family: var(--bazaar-font-family-display, var(--bazaar-font-family-sans));\n font-size: 1.125rem;\n font-weight: 500;\n}\n\n.sectionAction {\n background: none;\n border: none;\n padding: 0;\n font: inherit;\n font-size: 0.875rem;\n font-weight: 600;\n color: var(--bazaar-color-text-primary);\n text-decoration: underline;\n text-underline-offset: 3px;\n cursor: pointer;\n}\n\n@media (max-width: 900px) {\n .body {\n grid-template-columns: 1fr;\n gap: 24px;\n }\n .sidebar {\n position: static;\n }\n .heading,\n .body {\n padding-left: 16px;\n padding-right: 16px;\n }\n}\n","import type { HTMLAttributes, ReactNode } from 'react';\nimport { cn } from '../utils/cn';\nimport styles from './AccountDashboardTemplate.module.css';\n\nexport interface AccountSummaryStat {\n id: string;\n label: string;\n value: ReactNode;\n meta?: ReactNode;\n}\n\nexport interface AccountDashboardSection {\n id: string;\n title: ReactNode;\n actionLabel?: string;\n onAction?: () => void;\n content: ReactNode;\n}\n\nexport interface AccountDashboardTemplateProps\n extends Omit<HTMLAttributes<HTMLDivElement>, 'title'> {\n header?: ReactNode;\n footer?: ReactNode;\n /** Page heading — e.g., \"Hello, Mara\". */\n title: ReactNode;\n subtitle?: ReactNode;\n /** Sidebar nav — typically AccountNav. */\n sidebar: ReactNode;\n /** Summary tiles across the top of the content area. */\n summary?: AccountSummaryStat[];\n /** Stacked content sections (Recent orders, Saved addresses, etc.). */\n sections?: AccountDashboardSection[];\n}\n\n/**\n * AccountDashboardTemplate — logged-in account overview shell. Sidebar nav,\n * summary tiles (orders/points/rewards), and stacked content sections.\n */\nexport function AccountDashboardTemplate({\n header,\n footer,\n title,\n subtitle,\n sidebar,\n summary,\n sections,\n className,\n ...rest\n}: AccountDashboardTemplateProps) {\n return (\n <div className={cn(styles.root, className)} {...rest}>\n {header}\n <main className={styles.main}>\n <div className={styles.heading}>\n <h1 className={styles.title}>{title}</h1>\n {subtitle && <p className={styles.subtitle}>{subtitle}</p>}\n </div>\n <div className={styles.body}>\n <aside className={styles.sidebar}>{sidebar}</aside>\n <div className={styles.content}>\n {summary && summary.length > 0 && (\n <div className={styles.summary}>\n {summary.map((s) => (\n <div key={s.id} className={styles.summaryCard}>\n <span className={styles.summaryLabel}>{s.label}</span>\n <span className={styles.summaryValue}>{s.value}</span>\n {s.meta && (\n <span className={styles.summaryMeta}>{s.meta}</span>\n )}\n </div>\n ))}\n </div>\n )}\n {sections?.map((s) => (\n <section key={s.id} className={styles.section}>\n <div className={styles.sectionHead}>\n <h2 className={styles.sectionTitle}>{s.title}</h2>\n {s.actionLabel && (\n <button\n type=\"button\"\n className={styles.sectionAction}\n onClick={s.onAction}\n >\n {s.actionLabel}\n </button>\n )}\n </div>\n {s.content}\n </section>\n ))}\n </div>\n </div>\n </main>\n {footer}\n </div>\n );\n}\n"],"mappings":"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"}
|