@snowcone-app/canvas 0.36.4 → 0.36.7
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/dist/{ContextualToolbars-GAkUFq2m.js → ContextualToolbars-CG5Gmv_i.js} +3 -3
- package/dist/{ContextualToolbars-GAkUFq2m.js.map → ContextualToolbars-CG5Gmv_i.js.map} +1 -1
- package/dist/{EditorCanvasImpl-B43TaPgW.js → EditorCanvasImpl-BeeY09cA.js} +5 -5
- package/dist/{EditorCanvasImpl-B43TaPgW.js.map → EditorCanvasImpl-BeeY09cA.js.map} +1 -1
- package/dist/{ImagePanel-DK3Zflyc.js → ImagePanel-DLxIDKV-.js} +131 -131
- package/dist/ImagePanel-DLxIDKV-.js.map +1 -0
- package/dist/{SnowconeCanvas-B1lq53my.js → SnowconeCanvas-BaFR8QXs.js} +6 -6
- package/dist/{SnowconeCanvas-B1lq53my.js.map → SnowconeCanvas-BaFR8QXs.js.map} +1 -1
- package/dist/advanced.mjs +7 -7
- package/dist/{custom-icons-wZuopKx7.js → custom-icons-D51KIAfz.js} +2 -2
- package/dist/{custom-icons-wZuopKx7.js.map → custom-icons-D51KIAfz.js.map} +1 -1
- package/dist/{embed-DbCQZ8Q9.js → embed-D9n0deJ3.js} +5 -5
- package/dist/{embed-DbCQZ8Q9.js.map → embed-D9n0deJ3.js.map} +1 -1
- package/dist/embed.mjs +3 -3
- package/dist/index.mjs +5 -5
- package/dist/{template-fields-CMK7aqCw.js → template-fields-D8uOutD4.js} +2 -2
- package/dist/{template-fields-CMK7aqCw.js.map → template-fields-D8uOutD4.js.map} +1 -1
- package/dist/{useCommands-DC6ZPY1n.js → useCommands-CQi4Pyd2.js} +2 -2
- package/dist/{useCommands-DC6ZPY1n.js.map → useCommands-CQi4Pyd2.js.map} +1 -1
- package/dist/{validation-Bm2noYgt.js → validation-THw5W6N_.js} +7 -7
- package/dist/{validation-Bm2noYgt.js.map → validation-THw5W6N_.js.map} +1 -1
- package/example/package.json +1 -1
- package/package.json +4 -4
- package/dist/ImagePanel-DK3Zflyc.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ContextualToolbars-GAkUFq2m.js","sources":["../src/vendor/ui/primitives/checkbox.tsx","../src/vendor/ui/primitives/collapsible.tsx","../src/vendor/ui/primitives/popover.tsx","../src/vendor/ui/primitives/select.tsx","../src/vendor/ui/primitives/separator.tsx","../src/vendor/ui/primitives/slider.tsx","../src/vendor/ui/primitives/switch.tsx","../src/components/ui/collapsed-toolbar-header.tsx","../src/components/ui/SliderRow.tsx","../src/components/ui/PresetCarousel.tsx","../../../node_modules/.pnpm/react-colorful@5.7.0_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/react-colorful/dist/index.mjs","../src/components/ColorPickerDropdown.tsx","../src/components/BackButton.tsx","../src/utils/featureApplied.ts","../src/components/ImageToolbar.tsx","../src/presets/artboard-color-presets.ts","../src/components/ShapeToolbar.tsx","../src/components/PathToolbar.tsx","../src/components/BackgroundPickerDropdown.tsx","../src/components/ArtboardDistressPanel.tsx","../src/components/ArtboardImageMaskPanel.tsx","../src/components/ArtboardPropertiesToolbar.tsx","../src/utils/textUtils.ts","../src/components/FontBrowserDrawer.tsx","../src/components/TransformControlPanel.tsx","../src/components/TextEffectsDropdown.tsx","../src/components/MoreMenu.tsx","../src/components/text-toolbar/FontColorButton.tsx","../src/components/text-toolbar/BoldButton.tsx","../src/components/text-toolbar/ItalicButton.tsx","../src/components/text-toolbar/UnderlineButton.tsx","../src/components/text-toolbar/UppercaseButton.tsx","../src/components/text-toolbar/TextAlignButton.tsx","../src/components/text-toolbar/TextMoreMenu.tsx","../src/components/TextToolbar.tsx","../src/core/TransformConverter.ts","../src/hooks/useTextToolbar.ts","../src/hooks/useLayerPreview.ts","../src/components/LayerLeadingChip.tsx","../src/utils/alignDistribute.ts","../src/hooks/useAlignDistribute.ts","../src/components/toolbars/alignButtons.ts","../src/components/MultiSelectionToolbar.tsx","../src/components/toolbars/GroupElementToolbar.tsx","../src/components/CropPanel.tsx","../src/components/toolbars/SecondaryPanels.tsx","../src/components/toolbars/ExpandedPanelIcon.tsx","../src/components/toolbars/shared/SecondaryPanelWrapper.tsx","../src/components/toolbars/shared/ColorPanelWrapper.tsx","../src/components/toolbars/EmbeddedToolbarLayout.tsx","../src/components/toolbars/FloatingPanels.tsx","../src/utils/documentColors.ts","../src/components/ContextualToolbars.tsx"],"sourcesContent":["'use client';\n\nimport * as React from 'react';\nimport * as CheckboxPrimitive from '@radix-ui/react-checkbox';\nimport { Icon } from '@iconify/react';\nimport { cn } from '../lib/utils';\nimport { useSurface } from './surface';\n\ninterface CheckboxProps extends React.ComponentPropsWithoutRef<typeof CheckboxPrimitive.Root> {\n /** Visual variant - auto-detected from Surface context, or can be set explicitly */\n variant?: 'default' | 'filled';\n}\n\nconst Checkbox = React.forwardRef<React.ElementRef<typeof CheckboxPrimitive.Root>, CheckboxProps>(\n ({ className, checked, variant, ...props }, ref) => {\n // Auto-detect variant from Surface context\n const surface = useSurface();\n const effectiveVariant = variant ?? (surface.variant === 'default' ? 'filled' : 'default');\n\n return (\n <CheckboxPrimitive.Root\n ref={ref}\n className={cn(\n 'sc:peer sc:size-4 sc:shrink-0 sc:rounded sc:transition-colors sc:border-none',\n 'sc:focus-visible:outline-none',\n 'sc:disabled:cursor-not-allowed sc:disabled:opacity-50',\n // Variant styles - semantic: field on page vs field on surface\n effectiveVariant === 'default' && 'sc:bg-field sc:shadow-soft sc:dark:shadow-none',\n effectiveVariant === 'filled' && 'sc:bg-[var(--color-field-on-surface)]',\n 'sc:data-[state=checked]:bg-primary sc:data-[state=checked]:text-primary-foreground sc:data-[state=checked]:shadow-none',\n 'sc:data-[state=indeterminate]:bg-primary sc:data-[state=indeterminate]:text-primary-foreground sc:data-[state=indeterminate]:shadow-none',\n className\n )}\n checked={checked}\n {...props}\n >\n <CheckboxPrimitive.Indicator\n className={cn(\n 'sc:flex sc:items-center sc:justify-center sc:text-current',\n 'sc:data-[state=checked]:animate-in sc:data-[state=checked]:zoom-in-0 sc:data-[state=checked]:duration-300',\n 'sc:data-[state=indeterminate]:animate-in sc:data-[state=indeterminate]:zoom-in-0 sc:data-[state=indeterminate]:duration-150'\n )}\n >\n {checked === 'indeterminate' ? (\n <Icon icon=\"gravity-ui:minus\" className=\"sc:size-3\" />\n ) : (\n <Icon icon=\"gravity-ui:check\" className=\"sc:size-3\" />\n )}\n </CheckboxPrimitive.Indicator>\n </CheckboxPrimitive.Root>\n );\n }\n);\nCheckbox.displayName = CheckboxPrimitive.Root.displayName;\n\nexport { Checkbox };\n","'use client';\n\nimport * as React from 'react';\nimport * as CollapsiblePrimitive from '@radix-ui/react-collapsible';\nimport { cn } from '../lib/utils';\n\nconst CollapsibleRoot = React.forwardRef<\n React.ElementRef<typeof CollapsiblePrimitive.Root>,\n React.ComponentPropsWithoutRef<typeof CollapsiblePrimitive.Root>\n>(({ className, ...props }, ref) => (\n <CollapsiblePrimitive.Root\n ref={ref}\n className={cn(className)}\n {...props}\n />\n));\nCollapsibleRoot.displayName = 'Collapsible';\n\nconst CollapsibleTrigger = CollapsiblePrimitive.Trigger;\n\nconst CollapsibleContent = React.forwardRef<\n React.ElementRef<typeof CollapsiblePrimitive.Content>,\n React.ComponentPropsWithoutRef<typeof CollapsiblePrimitive.Content>\n>(({ className, ...props }, ref) => (\n <CollapsiblePrimitive.Content\n ref={ref}\n className={cn(\n 'sc:overflow-hidden sc:data-[state=closed]:animate-collapsible-up sc:data-[state=open]:animate-collapsible-down',\n className\n )}\n {...props}\n />\n));\nCollapsibleContent.displayName = 'CollapsibleContent';\n\nconst Collapsible = CollapsibleRoot;\n\n// Disclosure aliases (alternative naming)\nconst Disclosure = CollapsibleRoot;\nconst DisclosureTrigger = CollapsibleTrigger;\nconst DisclosureContent = CollapsibleContent;\n\nexport {\n Collapsible,\n CollapsibleTrigger,\n CollapsibleContent,\n CollapsibleRoot,\n Disclosure,\n DisclosureTrigger,\n DisclosureContent,\n};\n","'use client';\n\nimport * as React from 'react';\nimport * as PopoverPrimitive from '@radix-ui/react-popover';\nimport { cn } from '../lib/utils';\nimport { SurfaceContext } from './surface';\n\nconst PopoverRoot = PopoverPrimitive.Root;\n\nconst PopoverTrigger = PopoverPrimitive.Trigger;\n\nconst PopoverAnchor = PopoverPrimitive.Anchor;\n\ninterface PopoverContentProps extends React.ComponentPropsWithoutRef<typeof PopoverPrimitive.Content> {\n /** Preserve text selection when popover opens (useful for canvas/editor contexts) */\n preserveSelection?: boolean;\n /** Use maximum z-index to appear above fullscreen modals (for canvas/editor contexts) */\n maxZIndex?: boolean;\n}\n\nconst PopoverContent = React.forwardRef<\n React.ElementRef<typeof PopoverPrimitive.Content>,\n PopoverContentProps\n>(({ className, align = 'center', sideOffset = 4, preserveSelection, maxZIndex, children, style, ...props }, ref) => (\n <PopoverPrimitive.Portal>\n <SurfaceContext.Provider value={{ variant: 'default' }}>\n <PopoverPrimitive.Content\n ref={ref}\n align={align}\n sideOffset={sideOffset}\n data-preserve-selection={preserveSelection ? '' : undefined}\n className={cn(\n 'sc:z-dropdown sc:w-72 sc:overflow-hidden sc:rounded-tooltip sc:border-none sc:bg-popover sc:p-4 sc:text-popover-foreground sc:shadow-soft sc:outline-none',\n 'sc:data-[state=open]:animate-in sc:data-[state=closed]:animate-out',\n 'sc:data-[state=closed]:fade-out-0 sc:data-[state=open]:fade-in-0',\n 'sc:data-[state=closed]:zoom-out-95 sc:data-[state=open]:zoom-in-95',\n 'sc:data-[side=bottom]:slide-in-from-top-2 sc:data-[side=left]:slide-in-from-right-2',\n 'sc:data-[side=right]:slide-in-from-left-2 sc:data-[side=top]:slide-in-from-bottom-2',\n className\n )}\n style={maxZIndex ? { ...style, zIndex: 2147483647 } : style}\n {...props}\n >\n {children}\n </PopoverPrimitive.Content>\n </SurfaceContext.Provider>\n </PopoverPrimitive.Portal>\n));\nPopoverContent.displayName = PopoverPrimitive.Content.displayName;\n\ninterface PopoverProps {\n children: React.ReactNode;\n open?: boolean;\n onOpenChange?: (open: boolean) => void;\n defaultOpen?: boolean;\n modal?: boolean;\n}\n\nconst PopoverBase = ({ children, open, onOpenChange, ...props }: PopoverProps) => (\n <PopoverRoot open={open} onOpenChange={onOpenChange} {...props}>\n {children}\n </PopoverRoot>\n);\n\n// Compound component with subcomponents\nconst Popover = Object.assign(PopoverBase, {\n Trigger: PopoverTrigger,\n Content: PopoverContent,\n Anchor: PopoverAnchor,\n // HeroUI uses Dialog for the content wrapper - map to Content\n Dialog: React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(\n ({ children, className, ...props }, ref) => (\n <div ref={ref} className={className} {...props}>\n {children}\n </div>\n )\n ),\n});\n\nexport { Popover, PopoverTrigger, PopoverContent, PopoverAnchor, PopoverRoot };\n","'use client';\n\nimport * as React from 'react';\nimport * as SelectPrimitive from '@radix-ui/react-select';\nimport { Icon } from '@iconify/react';\nimport { cn } from '../lib/utils';\nimport { useSurface } from './surface';\n\nconst Select = SelectPrimitive.Root;\n\nconst SelectGroup = SelectPrimitive.Group;\n\nconst SelectValue = SelectPrimitive.Value;\n\ninterface SelectTriggerProps extends React.ComponentPropsWithoutRef<typeof SelectPrimitive.Trigger> {\n /** Visual variant - auto-detected from Surface context, or can be set explicitly */\n variant?: 'default' | 'filled';\n}\n\nconst SelectTrigger = React.forwardRef<React.ElementRef<typeof SelectPrimitive.Trigger>, SelectTriggerProps>(\n ({ className, children, variant, ...props }, ref) => {\n // Auto-detect variant from Surface context\n const surface = useSurface();\n const effectiveVariant = variant ?? (surface.variant === 'default' ? 'filled' : 'default');\n\n return (\n <SelectPrimitive.Trigger\n ref={ref}\n className={cn(\n 'sc:flex sc:h-9 sc:w-full sc:items-center sc:justify-between sc:gap-2 sc:rounded-input sc:px-2.5 sc:py-1.5 sc:text-sm sc:transition-colors',\n 'sc:text-foreground sc:border-none',\n 'sc:focus:ring-focus sc:focus:ring-2 sc:focus:outline-none',\n 'sc:disabled:cursor-not-allowed sc:disabled:opacity-50 sc:[&>span]:line-clamp-1',\n // Placeholder styling (Radix adds data-placeholder attribute to trigger)\n 'sc:data-[placeholder]:text-foreground/50',\n // Variant styles - semantic: field on page vs field on surface\n effectiveVariant === 'default' && 'sc:bg-field sc:shadow-soft sc:dark:shadow-none',\n effectiveVariant === 'filled' && 'sc:bg-[var(--color-field-on-surface)]',\n className\n )}\n {...props}\n >\n {children}\n <SelectPrimitive.Icon asChild>\n <Icon\n icon=\"gravity-ui:chevron-down\"\n className=\"sc:text-foreground/40 sc:size-4 sc:transition-transform sc:duration-200 sc:ease-out sc:[[data-state=open]>&]:rotate-180\"\n />\n </SelectPrimitive.Icon>\n </SelectPrimitive.Trigger>\n );\n }\n);\nSelectTrigger.displayName = SelectPrimitive.Trigger.displayName;\n\nconst SelectScrollUpButton = React.forwardRef<\n React.ElementRef<typeof SelectPrimitive.ScrollUpButton>,\n React.ComponentPropsWithoutRef<typeof SelectPrimitive.ScrollUpButton>\n>(({ className, ...props }, ref) => (\n <SelectPrimitive.ScrollUpButton\n ref={ref}\n className={cn('sc:flex sc:cursor-default sc:items-center sc:justify-center sc:py-1', className)}\n {...props}\n >\n <Icon icon=\"gravity-ui:chevron-up\" className=\"sc:size-4\" />\n </SelectPrimitive.ScrollUpButton>\n));\nSelectScrollUpButton.displayName = SelectPrimitive.ScrollUpButton.displayName;\n\nconst SelectScrollDownButton = React.forwardRef<\n React.ElementRef<typeof SelectPrimitive.ScrollDownButton>,\n React.ComponentPropsWithoutRef<typeof SelectPrimitive.ScrollDownButton>\n>(({ className, ...props }, ref) => (\n <SelectPrimitive.ScrollDownButton\n ref={ref}\n className={cn('sc:flex sc:cursor-default sc:items-center sc:justify-center sc:py-1', className)}\n {...props}\n >\n <Icon icon=\"gravity-ui:chevron-down\" className=\"sc:size-4\" />\n </SelectPrimitive.ScrollDownButton>\n));\nSelectScrollDownButton.displayName = SelectPrimitive.ScrollDownButton.displayName;\n\nconst SelectContent = React.forwardRef<\n React.ElementRef<typeof SelectPrimitive.Content>,\n React.ComponentPropsWithoutRef<typeof SelectPrimitive.Content>\n>(({ className, children, position = 'popper', ...props }, ref) => (\n <SelectPrimitive.Portal>\n <SelectPrimitive.Content\n ref={ref}\n className={cn(\n 'sc:z-dropdown sc:bg-popover sc:text-popover-foreground sc:shadow-soft sc:relative sc:min-w-[8rem] sc:overflow-hidden sc:rounded-tooltip sc:border-none sc:p-1',\n 'sc:data-[state=open]:animate-in sc:data-[state=closed]:animate-out sc:data-[state=closed]:fade-out-0 sc:data-[state=open]:fade-in-0',\n 'sc:data-[state=closed]:zoom-out-95 sc:data-[state=open]:zoom-in-95',\n 'sc:data-[side=bottom]:slide-in-from-top-2 sc:data-[side=left]:slide-in-from-right-2',\n 'sc:data-[side=right]:slide-in-from-left-2 sc:data-[side=top]:slide-in-from-bottom-2',\n position === 'popper' &&\n 'sc:data-[side=bottom]:translate-y-1 sc:data-[side=left]:-translate-x-1 sc:data-[side=right]:translate-x-1 sc:data-[side=top]:-translate-y-1',\n className\n )}\n position={position}\n {...props}\n >\n <SelectScrollUpButton />\n <SelectPrimitive.Viewport\n className={cn(position === 'popper' && 'sc:w-full sc:min-w-[var(--radix-select-trigger-width)]')}\n >\n {children}\n </SelectPrimitive.Viewport>\n <SelectScrollDownButton />\n </SelectPrimitive.Content>\n </SelectPrimitive.Portal>\n));\nSelectContent.displayName = SelectPrimitive.Content.displayName;\n\nconst SelectLabel = React.forwardRef<\n React.ElementRef<typeof SelectPrimitive.Label>,\n React.ComponentPropsWithoutRef<typeof SelectPrimitive.Label>\n>(({ className, ...props }, ref) => (\n <SelectPrimitive.Label\n ref={ref}\n className={cn('sc:text-muted-foreground sc:px-2 sc:py-1.5 sc:text-xs sc:font-label', className)}\n {...props}\n />\n));\nSelectLabel.displayName = SelectPrimitive.Label.displayName;\n\nconst SelectItem = React.forwardRef<\n React.ElementRef<typeof SelectPrimitive.Item>,\n React.ComponentPropsWithoutRef<typeof SelectPrimitive.Item>\n>(({ className, children, ...props }, ref) => (\n <SelectPrimitive.Item\n ref={ref}\n className={cn(\n 'sc:relative sc:flex sc:w-full sc:cursor-default sc:items-center sc:rounded-full sc:py-1 sc:pr-8 sc:pl-2 sc:text-sm sc:text-foreground sc:outline-none sc:select-none sc:font-body',\n 'sc:hover:bg-default/50 sc:focus:bg-default/50 sc:dark:hover:bg-white/5 sc:dark:focus:bg-white/5 sc:data-[disabled]:pointer-events-none sc:data-[disabled]:opacity-50',\n className\n )}\n {...props}\n >\n <span className=\"sc:absolute sc:right-2 sc:flex sc:h-3.5 sc:w-3.5 sc:items-center sc:justify-center\">\n <SelectPrimitive.ItemIndicator>\n <Icon icon=\"gravity-ui:check\" className=\"sc:size-4\" />\n </SelectPrimitive.ItemIndicator>\n </span>\n <SelectPrimitive.ItemText>{children}</SelectPrimitive.ItemText>\n </SelectPrimitive.Item>\n));\nSelectItem.displayName = SelectPrimitive.Item.displayName;\n\nconst SelectSeparator = React.forwardRef<\n React.ElementRef<typeof SelectPrimitive.Separator>,\n React.ComponentPropsWithoutRef<typeof SelectPrimitive.Separator>\n>(({ className, ...props }, ref) => (\n <SelectPrimitive.Separator ref={ref} className={cn('sc:bg-divider sc:mx-2 sc:my-1 sc:h-px', className)} {...props} />\n));\nSelectSeparator.displayName = SelectPrimitive.Separator.displayName;\n\nexport {\n Select,\n SelectGroup,\n SelectValue,\n SelectTrigger,\n SelectContent,\n SelectLabel,\n SelectItem,\n SelectSeparator,\n SelectScrollUpButton,\n SelectScrollDownButton,\n};\n","'use client';\n\nimport * as React from 'react';\nimport * as SeparatorPrimitive from '@radix-ui/react-separator';\nimport { cn } from '../lib/utils';\n\nconst Separator = React.forwardRef<\n React.ElementRef<typeof SeparatorPrimitive.Root>,\n React.ComponentPropsWithoutRef<typeof SeparatorPrimitive.Root>\n>(({ className, orientation = 'horizontal', decorative = true, ...props }, ref) => (\n <SeparatorPrimitive.Root\n ref={ref}\n decorative={decorative}\n orientation={orientation}\n className={cn(\n 'sc:shrink-0 sc:bg-divider',\n orientation === 'horizontal' ? 'sc:h-[1px] sc:w-full' : 'sc:h-full sc:w-[1px]',\n className\n )}\n {...props}\n />\n));\nSeparator.displayName = SeparatorPrimitive.Root.displayName;\n\nexport { Separator };\n","\"use client\";\n\n'use client';\n\nimport * as React from 'react';\nimport * as SliderPrimitive from '@radix-ui/react-slider';\nimport { cn } from '../lib/utils';\n\ninterface SliderProps\n extends Omit<\n React.ComponentPropsWithoutRef<typeof SliderPrimitive.Root>,\n 'value' | 'onValueChange'\n > {\n // Accepts both array and single number for convenience\n value?: number | number[];\n onValueChange?: (value: number[]) => void;\n onChangeEnd?: (value: number[]) => void;\n children?: React.ReactNode;\n}\n\n// Context for passing slider state to compound components\ninterface SliderContextValue {\n values: number[];\n min: number;\n max: number;\n}\nconst SliderContext = React.createContext<SliderContextValue | null>(null);\n\n// HeroUI-compatible compound components\nconst SliderTrack = React.forwardRef<HTMLSpanElement, React.HTMLAttributes<HTMLSpanElement>>(\n ({ className, children, ...props }, ref) => (\n <SliderPrimitive.Track\n ref={ref}\n className={cn('sc:relative sc:h-2 sc:w-full sc:grow sc:overflow-hidden sc:rounded-full sc:bg-muted', className)}\n {...props}\n >\n {children}\n </SliderPrimitive.Track>\n )\n);\nSliderTrack.displayName = 'SliderTrack';\n\nconst SliderThumb = React.forwardRef<HTMLSpanElement, React.HTMLAttributes<HTMLSpanElement>>(\n ({ className, ...props }, ref) => (\n <SliderPrimitive.Thumb\n ref={ref}\n // Base thumb size: h-6 w-6 (24px), touch devices can override via CSS to 32-36px\n className={cn(\n 'sc:relative sc:block sc:h-6 sc:w-6 sc:rounded-full sc:border-2 sc:border-primary sc:bg-background sc:ring-offset-background sc:transition-colors sc:focus-visible:outline-none sc:focus-visible:ring-2 sc:focus-visible:ring-focus sc:focus-visible:ring-offset-2 sc:disabled:pointer-events-none sc:disabled:opacity-50',\n className\n )}\n {...props}\n />\n )\n);\nSliderThumb.displayName = 'SliderThumb';\n\n// HeroUI Fill component - displays the filled range portion\nconst SliderFill = React.forwardRef<HTMLSpanElement, React.HTMLAttributes<HTMLSpanElement>>(\n ({ className, ...props }, ref) => (\n <SliderPrimitive.Range ref={ref} className={cn('sc:absolute sc:h-full sc:bg-primary', className)} {...props} />\n )\n);\nSliderFill.displayName = 'SliderFill';\n\n// HeroUI Output component - renders current value(s)\ninterface SliderOutputProps extends Omit<React.HTMLAttributes<HTMLSpanElement>, 'children'> {\n children?: React.ReactNode | ((props: { state: { values: number[] } }) => React.ReactNode);\n}\n\nconst SliderOutput = React.forwardRef<HTMLSpanElement, SliderOutputProps>(\n ({ className, children, ...props }, ref) => {\n const context = React.useContext(SliderContext);\n const values = context?.values ?? [0];\n\n return (\n <span ref={ref} className={cn('sc:text-sm sc:text-foreground/60', className)} {...props}>\n {typeof children === 'function'\n ? children({ state: { values } })\n : children ?? values.join(' - ')}\n </span>\n );\n }\n);\nSliderOutput.displayName = 'SliderOutput';\n\nconst SliderBase = React.forwardRef<React.ElementRef<typeof SliderPrimitive.Root>, SliderProps>(\n (\n {\n className,\n value,\n onValueChange,\n onChangeEnd,\n min = 0,\n max = 100,\n step = 1,\n children,\n ...props\n },\n ref\n ) => {\n // Normalize value to array (accepts both single number and array for convenience)\n const normalizedValue = value !== undefined ? (Array.isArray(value) ? value : [value]) : undefined;\n\n // Track internal value for context\n const [internalValue, setInternalValue] = React.useState(normalizedValue ?? [min]);\n\n // Track if we're currently dragging (for iOS body scroll prevention)\n const isDraggingRef = React.useRef(false);\n const touchMoveHandlerRef = React.useRef<((e: TouchEvent) => void) | null>(null);\n\n // Prevent scroll during drag - added to document on pointer down, removed on pointer up\n const preventScroll = React.useCallback((e: TouchEvent) => {\n if (isDraggingRef.current) {\n e.preventDefault();\n }\n }, []);\n\n const handleChange = (newValue: number[]) => {\n // Mark as actively dragging once value changes\n isDraggingRef.current = true;\n setInternalValue(newValue);\n onValueChange?.(newValue);\n };\n\n const handleChangeEnd = (newValue: number[]) => {\n isDraggingRef.current = false;\n onChangeEnd?.(newValue);\n };\n\n // Handle pointer down - add document-level touchmove prevention\n const handlePointerDown = React.useCallback(() => {\n // Add touchmove listener to document to intercept scroll during drag\n if (!touchMoveHandlerRef.current) {\n touchMoveHandlerRef.current = preventScroll;\n document.addEventListener('touchmove', preventScroll, { passive: false });\n }\n }, [preventScroll]);\n\n // Handle pointer up/cancel - remove document listener\n const handlePointerUp = React.useCallback(() => {\n isDraggingRef.current = false;\n if (touchMoveHandlerRef.current) {\n document.removeEventListener('touchmove', touchMoveHandlerRef.current);\n touchMoveHandlerRef.current = null;\n }\n }, []);\n\n // Cleanup on unmount\n React.useEffect(() => {\n return () => {\n if (touchMoveHandlerRef.current) {\n document.removeEventListener('touchmove', touchMoveHandlerRef.current);\n }\n };\n }, []);\n\n // Check if children are provided (compound pattern)\n const hasChildren = React.Children.count(children) > 0;\n\n // Determine number of thumbs based on value array length or defaultValue\n const thumbCount = normalizedValue?.length ?? props.defaultValue?.length ?? 1;\n\n // Context value for compound components\n const contextValue = React.useMemo(\n () => ({\n values: normalizedValue ?? internalValue,\n min,\n max,\n }),\n [normalizedValue, internalValue, min, max]\n );\n\n return (\n <SliderContext.Provider value={contextValue}>\n <SliderPrimitive.Root\n ref={ref}\n className={cn('sc:relative sc:flex sc:w-full sc:touch-none sc:select-none sc:items-center', className)}\n value={normalizedValue}\n onValueChange={handleChange}\n onValueCommit={handleChangeEnd}\n onPointerDown={handlePointerDown}\n onPointerUp={handlePointerUp}\n onPointerCancel={handlePointerUp}\n onLostPointerCapture={handlePointerUp}\n min={min}\n max={max}\n step={step}\n {...props}\n >\n {hasChildren ? (\n children\n ) : (\n <>\n <SliderPrimitive.Track className=\"sc:relative sc:h-2 sc:w-full sc:grow sc:overflow-hidden sc:rounded-full sc:bg-muted\">\n <SliderPrimitive.Range className=\"sc:absolute sc:h-full sc:bg-primary\" />\n </SliderPrimitive.Track>\n {Array.from({ length: thumbCount }).map((_, index) => (\n <SliderPrimitive.Thumb\n key={index}\n className=\"sc:relative sc:block sc:h-6 sc:w-6 sc:rounded-full sc:border-2 sc:border-primary sc:bg-background sc:ring-offset-background sc:transition-colors sc:focus-visible:outline-none sc:focus-visible:ring-2 sc:focus-visible:ring-focus sc:focus-visible:ring-offset-2 sc:disabled:pointer-events-none sc:disabled:opacity-50\"\n />\n ))}\n </>\n )}\n </SliderPrimitive.Root>\n </SliderContext.Provider>\n );\n }\n);\nSliderBase.displayName = SliderPrimitive.Root.displayName;\n\n// Compound component with sub-components\nconst Slider = Object.assign(SliderBase, {\n Track: SliderTrack,\n Thumb: SliderThumb,\n Fill: SliderFill,\n Output: SliderOutput,\n});\n\nexport { Slider, SliderTrack, SliderThumb, SliderFill, SliderOutput };\n","'use client';\n\nimport * as React from 'react';\nimport * as SwitchPrimitive from '@radix-ui/react-switch';\nimport { cn } from '../lib/utils';\n\nconst Switch = React.forwardRef<\n React.ElementRef<typeof SwitchPrimitive.Root>,\n React.ComponentPropsWithoutRef<typeof SwitchPrimitive.Root>\n>(({ className, ...props }, ref) => {\n return (\n <SwitchPrimitive.Root\n className={cn(\n 'sc:peer sc:inline-flex sc:h-7 sc:w-12 sc:md:h-5 sc:md:w-9 sc:shrink-0 sc:cursor-pointer sc:items-center sc:rounded-full sc:border-2 sc:border-transparent sc:shadow-sm sc:transition-colors',\n 'sc:focus-visible:outline-none sc:focus-visible:ring-2 sc:focus-visible:ring-focus sc:focus-visible:ring-offset-2 sc:focus-visible:ring-offset-background',\n 'sc:disabled:cursor-not-allowed sc:disabled:opacity-50',\n 'sc:data-[state=checked]:bg-primary sc:data-[state=unchecked]:bg-muted',\n className\n )}\n {...props}\n ref={ref}\n >\n <SwitchPrimitive.Thumb\n className={cn(\n 'sc:pointer-events-none sc:block sc:h-6 sc:w-6 sc:md:h-4 sc:md:w-4 sc:rounded-full sc:bg-background sc:shadow-lg sc:ring-0 sc:transition-transform',\n 'sc:data-[state=checked]:translate-x-5 sc:md:data-[state=checked]:translate-x-4 sc:data-[state=unchecked]:translate-x-0'\n )}\n />\n </SwitchPrimitive.Root>\n );\n }\n);\nSwitch.displayName = SwitchPrimitive.Root.displayName;\n\nexport { Switch };\n","/**\n * CollapsedToolbarHeader - Header shown when a toolbar panel is expanded\n *\n * Displays:\n * - Icon on the left (same as the button that opened the panel)\n * - Label text\n * - Close button on the far right\n *\n * Used for corner radius, effects, and other expandable panels.\n *\n * @example\n * <CollapsedToolbarHeader\n * icon=\"lucide:square-round-corner\"\n * label=\"Corner Radius\"\n * onClose={() => setIsOpen(false)}\n * />\n */\n\nimport React, { useRef, useEffect } from 'react';\nimport { Icon } from '@iconify/react';\nimport { cn } from '../../lib/utils';\nimport { icons } from './icons';\n\nexport interface CollapsedToolbarHeaderProps {\n /** Iconify icon string (e.g., \"lucide:square-round-corner\") or custom React node */\n icon: string | React.ReactNode;\n /** Label text to display */\n label: string;\n /** Callback when close button is clicked */\n onClose: () => void;\n /** Additional CSS classes */\n className?: string;\n /** Close button style: 'icon' shows X, 'done' shows Done button */\n closeButtonStyle?: 'icon' | 'done';\n}\n\nexport const CollapsedToolbarHeader: React.FC<CollapsedToolbarHeaderProps> = ({\n icon,\n label,\n onClose,\n className,\n closeButtonStyle = 'icon',\n}) => {\n // Block horizontal touch movement to prevent drawer/page from being dragged\n const containerRef = useRef<HTMLDivElement>(null);\n const touchStartPos = useRef({ x: 0, y: 0 });\n useEffect(() => {\n const el = containerRef.current;\n if (!el) return;\n\n const handleTouchStart = (e: TouchEvent) => {\n touchStartPos.current = {\n x: e.touches[0].clientX,\n y: e.touches[0].clientY,\n };\n };\n\n const handleTouchMove = (e: TouchEvent) => {\n const deltaX = Math.abs(e.touches[0].clientX - touchStartPos.current.x);\n const deltaY = Math.abs(e.touches[0].clientY - touchStartPos.current.y);\n\n // If horizontal movement is greater than vertical, prevent it\n if (deltaX > 10 && deltaX > deltaY) {\n e.preventDefault();\n }\n };\n\n el.addEventListener('touchstart', handleTouchStart, { passive: true });\n el.addEventListener('touchmove', handleTouchMove, { passive: false });\n\n return () => {\n el.removeEventListener('touchstart', handleTouchStart);\n el.removeEventListener('touchmove', handleTouchMove);\n };\n }, []);\n\n return (\n <div\n ref={containerRef}\n className={cn('sc:flex sc:w-full sc:items-center sc:justify-between', className)}\n style={{ touchAction: 'pan-y' }}\n >\n {/* Left side: Icon + Label */}\n <div className=\"sc:flex sc:items-center sc:gap-3 sc:md:gap-2\">\n {typeof icon === 'string' ? (\n <Icon icon={icon} className=\"sc:text-primary sc:size-7 sc:md:size-5\" />\n ) : (\n icon\n )}\n <span className=\"sc:text-foreground sc:text-lg sc:font-semibold sc:md:text-sm sc:md:font-medium\">{label}</span>\n </div>\n\n {/* Right side: Close button */}\n {closeButtonStyle === 'done' ? (\n <button\n onClick={onClose}\n className=\"sc:bg-primary sc:text-primary-foreground sc:rounded-xl sc:hover:bg-primary/90 sc:shadow-sm sc:px-8 sc:py-3.5 sc:text-xl sc:font-bold sc:transition-colors sc:md:rounded-button sc:md:shadow-none sc:md:px-4 sc:md:py-2 sc:md:text-sm sc:md:font-medium\"\n aria-label=\"Done\"\n >\n Done\n </button>\n ) : (\n <button\n onClick={onClose}\n className=\"sc:hover:bg-muted sc:text-foreground/70 sc:hover:text-foreground sc:flex sc:size-11 sc:items-center sc:justify-center sc:rounded-md sc:transition-colors sc:md:size-7\"\n aria-label=\"Close panel\"\n >\n <Icon icon={icons.close} className=\"sc:size-7 sc:md:size-4\" />\n </button>\n )}\n </div>\n );\n};\n\nCollapsedToolbarHeader.displayName = 'CollapsedToolbarHeader';\n","/**\n * SliderRow - Reusable slider component with label, optional input, and touch guard\n *\n * Used in secondary panels (corner radius, rotation, etc.) for consistent styling\n * and proper touch handling on mobile devices.\n *\n * @example\n * <SliderRow\n * label=\"Radius\"\n * value={50}\n * onChange={setValue}\n * min={0}\n * max={100}\n * unit=\"%\"\n * />\n */\n\nimport React, { useRef, useEffect } from 'react';\nimport { Slider } from '../../vendor/ui';\nimport { cn } from '../../lib/utils';\n\n/**\n * TouchGuard - Wraps interactive elements to prevent parent scroll from capturing touches\n *\n * Uses native event listeners with { passive: false } because:\n * 1. React's synthetic events can't properly preventDefault on touch events\n * 2. CSS touch-action: none is evaluated at gesture start on the ancestor chain,\n * so a parent with pan-y can still capture the gesture before child CSS applies\n * 3. Native listeners with passive: false intercept events before the browser decides to scroll\n */\nfunction TouchGuard({ children, className }: { children: React.ReactNode; className?: string }) {\n const ref = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n const el = ref.current;\n if (!el) return;\n\n const handleTouchStart = (e: TouchEvent) => {\n // Stop the event from reaching parent scroll containers\n e.stopPropagation();\n };\n\n const handleTouchMove = (e: TouchEvent) => {\n // Prevent default scroll behavior and stop propagation\n e.preventDefault();\n e.stopPropagation();\n };\n\n // Must use passive: false to allow preventDefault\n el.addEventListener('touchstart', handleTouchStart, { passive: false });\n el.addEventListener('touchmove', handleTouchMove, { passive: false });\n\n return () => {\n el.removeEventListener('touchstart', handleTouchStart);\n el.removeEventListener('touchmove', handleTouchMove);\n };\n }, []);\n\n return (\n <div ref={ref} className={className} style={{ touchAction: 'none' }}>\n {children}\n </div>\n );\n}\n\nexport interface SliderRowProps {\n /** Label displayed to the left of the slider */\n label: string;\n /** Current value */\n value: number;\n /** Callback when value changes */\n onChange: (value: number) => void;\n /**\n * Callback when a drag/keyboard interaction COMMITS (pointer released /\n * key released). Lets callers coalesce the per-tick onChange stream into\n * one undo step per gesture.\n */\n onChangeEnd?: (value: number) => void;\n /** Minimum value */\n min: number;\n /** Maximum value */\n max: number;\n /** Step increment (default: 1) */\n step?: number;\n /** Unit to display after value (e.g., \"%\", \"°\", \"px\") */\n unit?: string;\n /** Show number input field (default: false) */\n showInput?: boolean;\n /** Width of the number input (default: '56px') */\n inputWidth?: string;\n /** Additional class name for the container */\n className?: string;\n /** Layout variant: 'inline' (default) or 'stacked' */\n variant?: 'inline' | 'stacked';\n}\n\n/**\n * SliderRow - A labeled slider with optional input and value display\n */\nexport const SliderRow: React.FC<SliderRowProps> = ({\n label,\n value,\n onChange,\n onChangeEnd,\n min,\n max,\n step = 1,\n unit = '',\n showInput = false,\n inputWidth = '56px',\n className,\n variant = 'inline',\n}) => {\n const displayValue = Math.round(value);\n\n if (variant === 'stacked') {\n // Stacked layout: label/input on top, slider below\n return (\n <div className={cn('sc:flex sc:flex-col sc:gap-2.5 sc:md:gap-1.5', className)}>\n <div className=\"sc:flex sc:items-center sc:justify-between\">\n <span className=\"sc:text-foreground/60 sc:text-base sc:md:text-xs\">{label}</span>\n {showInput && (\n <input\n type=\"number\"\n value={displayValue}\n onChange={(e) => onChange(Math.max(min, Math.min(max, Number(e.target.value))))}\n min={min}\n max={max}\n aria-label={`${label} value`}\n className=\"sc:bg-transparent sc:text-foreground sc:w-14 sc:rounded-md sc:border-none sc:px-2.5 sc:py-2 sc:text-right sc:text-base sc:md:w-14 sc:md:rounded sc:md:px-1.5 sc:md:py-1 sc:md:text-[13px]\"\n style={{ width: inputWidth }}\n />\n )}\n </div>\n <TouchGuard>\n <Slider\n value={[value]}\n onValueChange={(val) => onChange(val[0])}\n onChangeEnd={onChangeEnd ? (val: number[]) => onChangeEnd(val[0]) : undefined}\n min={min}\n max={max}\n step={step}\n >\n <Slider.Track className=\"sc:bg-foreground/10 sc:h-2.5 sc:md:h-2\">\n <Slider.Fill className=\"sc:bg-primary\" />\n </Slider.Track>\n <Slider.Thumb className=\"sc:size-7 sc:md:size-6\" />\n </Slider>\n </TouchGuard>\n </div>\n );\n }\n\n // Inline layout: label, slider, value all in one row\n return (\n <div className={cn('sc:flex sc:items-center sc:gap-3', className)}>\n <span className=\"sc:text-foreground/70 sc:text-base sc:md:text-[13px] sc:whitespace-nowrap\">{label}</span>\n {showInput ? (\n <input\n type=\"number\"\n value={displayValue}\n onChange={(e) => onChange(Math.max(min, Math.min(max, Number(e.target.value))))}\n min={min}\n max={max}\n aria-label={`${label} value`}\n className=\"sc:bg-transparent sc:text-foreground sc:rounded-md sc:border-none sc:px-2 sc:py-2 sc:text-right sc:text-base sc:md:py-1.5 sc:md:text-[13px]\"\n style={{ width: inputWidth }}\n />\n ) : null}\n <TouchGuard className=\"sc:flex-1\">\n <Slider\n value={[value]}\n onValueChange={(val) => onChange(val[0])}\n onChangeEnd={onChangeEnd ? (val: number[]) => onChangeEnd(val[0]) : undefined}\n min={min}\n max={max}\n step={step}\n >\n <Slider.Track className=\"sc:bg-foreground/10 sc:h-2.5 sc:md:h-2\">\n <Slider.Fill className=\"sc:bg-primary\" />\n </Slider.Track>\n <Slider.Thumb className=\"sc:size-7 sc:md:size-6\" />\n </Slider>\n </TouchGuard>\n <span className=\"sc:text-foreground sc:text-base sc:md:text-[13px] sc:min-w-[44px] sc:md:min-w-[32px] sc:text-right\">\n {displayValue}{unit}\n </span>\n </div>\n );\n};\n\nexport default SliderRow;\n","/**\n * PresetCarousel - Reusable horizontal scrolling preset thumbnail carousel\n *\n * Features:\n * - Visual selection indicator (primary accent border + ring)\n * - Keyboard navigation (left/right arrow keys)\n * - Accessible focus management with roving tabindex\n * - Optional \"Off\" button as first item\n */\n\nimport React, { useRef, useCallback } from 'react';\n\nexport interface PresetItem {\n id: string;\n name: string;\n thumbnailUrl?: string;\n}\n\nexport interface PresetCarouselProps {\n /** Array of preset items to display */\n presets: PresetItem[];\n /** Currently selected preset ID, or empty string for \"Off\" */\n selectedId: string;\n /** Called when a preset is selected. Empty string means \"Off\". */\n onSelect: (id: string) => void;\n /** Show an \"Off\" button as the first item. Default: true */\n showOff?: boolean;\n /** Thumbnail size in pixels. Default: 40 */\n size?: number;\n /** Accessible label for the carousel */\n ariaLabel?: string;\n}\n\nconst SELECTED_CLASSES = 'sc:border-2 sc:border-primary sc:overflow-hidden';\nconst UNSELECTED_CLASSES = 'sc:border-2 sc:border-border-primary sc:hover:border-border-focus sc:overflow-hidden';\n\nexport const PresetCarousel: React.FC<PresetCarouselProps> = ({\n presets,\n selectedId,\n onSelect,\n showOff = true,\n size = 40,\n ariaLabel = 'Preset options',\n}) => {\n const containerRef = useRef<HTMLDivElement>(null);\n\n const scrollToItem = useCallback((button: HTMLButtonElement) => {\n button.scrollIntoView({ behavior: 'smooth', block: 'nearest', inline: 'nearest' });\n }, []);\n\n const handleKeyDown = useCallback(\n (e: React.KeyboardEvent<HTMLDivElement>) => {\n if (e.key !== 'ArrowLeft' && e.key !== 'ArrowRight') return;\n e.preventDefault();\n e.stopPropagation();\n\n const container = containerRef.current;\n if (!container) return;\n\n const buttons = Array.from(container.querySelectorAll<HTMLButtonElement>('button[data-preset-id]'));\n const focused = document.activeElement as HTMLButtonElement;\n let currentIndex = buttons.indexOf(focused);\n\n // If no button is focused, start from selected or first\n if (currentIndex === -1) {\n currentIndex = buttons.findIndex((btn) => btn.getAttribute('aria-selected') === 'true');\n if (currentIndex === -1) currentIndex = 0;\n }\n\n let nextIndex: number;\n if (e.key === 'ArrowRight') {\n nextIndex = currentIndex < buttons.length - 1 ? currentIndex + 1 : 0;\n } else {\n nextIndex = currentIndex > 0 ? currentIndex - 1 : buttons.length - 1;\n }\n\n const nextButton = buttons[nextIndex];\n nextButton.focus();\n scrollToItem(nextButton);\n\n // Also select the item on arrow navigation\n const presetId = nextButton.getAttribute('data-preset-id');\n if (presetId !== null) {\n onSelect(presetId);\n }\n },\n [scrollToItem, onSelect]\n );\n\n const isOffSelected = showOff && !selectedId;\n // Determine which item gets tabIndex 0 for initial Tab entry\n const hasSelection = showOff ? true : presets.some((p) => p.id === selectedId);\n\n return (\n <div\n ref={containerRef}\n className=\"sc:flex sc:gap-1.5 sc:overflow-x-auto sc:p-1 sc:-m-1\"\n style={{ flexWrap: 'nowrap' }}\n role=\"listbox\"\n aria-label={ariaLabel}\n onKeyDown={handleKeyDown}\n >\n {showOff && (\n <button\n data-preset-id=\"\"\n role=\"option\"\n aria-selected={isOffSelected}\n tabIndex={isOffSelected || (!hasSelection) ? 0 : -1}\n onClick={() => onSelect('')}\n className={`sc:shrink-0 sc:rounded-md sc:transition-all sc:flex sc:items-center sc:justify-center ${\n isOffSelected ? SELECTED_CLASSES : UNSELECTED_CLASSES\n }`}\n style={{ width: size, height: size }}\n title=\"None\"\n >\n <span className=\"sc:text-xs sc:text-muted-foreground\">Off</span>\n </button>\n )}\n {presets.map((preset, index) => {\n const isSelected = selectedId === preset.id;\n // First item gets tabIndex 0 if nothing else is selected (and no Off button)\n const isTabbable = isSelected || (!showOff && !hasSelection && index === 0);\n return (\n <button\n key={preset.id}\n data-preset-id={preset.id}\n role=\"option\"\n aria-selected={isSelected}\n tabIndex={isTabbable ? 0 : -1}\n onClick={() => onSelect(preset.id)}\n className={`sc:shrink-0 sc:rounded-md sc:transition-all ${\n isSelected ? SELECTED_CLASSES : UNSELECTED_CLASSES\n }`}\n style={{ width: size, height: size }}\n title={preset.name}\n >\n {preset.thumbnailUrl && (\n <img\n src={preset.thumbnailUrl}\n alt={preset.name}\n className=\"sc:w-full sc:h-full sc:object-cover\"\n loading=\"lazy\"\n />\n )}\n </button>\n );\n })}\n </div>\n );\n};\n","import e,{useRef as r,useMemo as n,useEffect as t,useState as o,useCallback as a,useLayoutEffect as l}from\"react\";function u(){return(u=Object.assign||function(e){for(var r=1;r<arguments.length;r++){var n=arguments[r];for(var t in n)Object.prototype.hasOwnProperty.call(n,t)&&(e[t]=n[t])}return e}).apply(this,arguments)}function c(e,r){if(null==e)return{};var n,t,o={},a=Object.keys(e);for(t=0;t<a.length;t++)r.indexOf(n=a[t])>=0||(o[n]=e[n]);return o}function i(e){var n=r(e),t=r(function(e){n.current&&n.current(e)});return n.current=e,t.current}var s=function(e,r,n){return void 0===r&&(r=0),void 0===n&&(n=1),e>n?n:e<r?r:e},f=function(e){return\"touches\"in e},v=function(e){return e&&e.ownerDocument.defaultView||self},d=function(e,r,n){var t=e.getBoundingClientRect(),o=f(r)?function(e,r){for(var n=0;n<e.length;n++)if(e[n].identifier===r)return e[n];return e[0]}(r.touches,n):r;return{left:s((o.pageX-(t.left+v(e).pageXOffset))/t.width),top:s((o.pageY-(t.top+v(e).pageYOffset))/t.height)}},h=function(e){!f(e)&&e.preventDefault()},g=e.memo(function(o){var a=o.onMove,l=o.onKey,s=o.onEnd,g=c(o,[\"onMove\",\"onKey\",\"onEnd\"]),m=r(null),p=i(a),b=i(l),_=i(s),E=r(null),C=r(!1),x=n(function(){var e=function(e){h(e),(f(e)?e.touches.length>0:e.buttons>0)&&m.current?p(d(m.current,e,E.current)):(n(!1),_())},r=function(){n(!1),_()};function n(n){var t=C.current,o=v(m.current),a=n?o.addEventListener:o.removeEventListener;a(t?\"touchmove\":\"mousemove\",e),a(t?\"touchend\":\"mouseup\",r)}return[function(e){var r=e.nativeEvent,t=m.current;if(t&&(h(r),!function(e,r){return r&&!f(e)}(r,C.current)&&t)){if(f(r)){C.current=!0;var o=r.changedTouches||[];o.length&&(E.current=o[0].identifier)}t.focus(),p(d(t,r,E.current)),n(!0)}},function(e){var r=e.which||e.keyCode;r<37||r>40||(e.preventDefault(),b({left:39===r?.05:37===r?-.05:0,top:40===r?.05:38===r?-.05:0}))},function(e){var r=e.which||e.keyCode;r>=37&&r<=40&&_()},n]},[b,p,_]),H=x[0],M=x[1],N=x[2],w=x[3];return t(function(){return w},[w]),e.createElement(\"div\",u({},g,{onTouchStart:H,onMouseDown:H,className:\"react-colorful__interactive\",ref:m,onKeyDown:M,onKeyUp:N,tabIndex:0,role:\"slider\"}))}),m=function(e){return e.filter(Boolean).join(\" \")},p=function(r){var n=r.color,t=r.left,o=r.top,a=void 0===o?.5:o,l=m([\"react-colorful__pointer\",r.className]);return e.createElement(\"div\",{className:l,style:{top:100*a+\"%\",left:100*t+\"%\"}},e.createElement(\"div\",{className:\"react-colorful__pointer-fill\",style:{backgroundColor:n}}))},b=function(e,r,n){return void 0===r&&(r=0),void 0===n&&(n=Math.pow(10,r)),Math.round(n*e)/n},_={grad:.9,turn:360,rad:360/(2*Math.PI)},E=function(e){return L(C(e))},C=function(e){return\"#\"===e[0]&&(e=e.substring(1)),e.length<6?{r:parseInt(e[0]+e[0],16),g:parseInt(e[1]+e[1],16),b:parseInt(e[2]+e[2],16),a:4===e.length?b(parseInt(e[3]+e[3],16)/255,2):1}:{r:parseInt(e.substring(0,2),16),g:parseInt(e.substring(2,4),16),b:parseInt(e.substring(4,6),16),a:8===e.length?b(parseInt(e.substring(6,8),16)/255,2):1}},x=function(e,r){return void 0===r&&(r=\"deg\"),Number(e)*(_[r]||1)},H=function(e){var r=/hsla?\\(?\\s*(-?\\d*\\.?\\d+)(deg|rad|grad|turn)?[,\\s]+(-?\\d*\\.?\\d+)%?[,\\s]+(-?\\d*\\.?\\d+)%?,?\\s*[/\\s]*(-?\\d*\\.?\\d+)?(%)?\\s*\\)?/i.exec(e);return r?N({h:x(r[1],r[2]),s:Number(r[3]),l:Number(r[4]),a:void 0===r[5]?1:Number(r[5])/(r[6]?100:1)}):{h:0,s:0,v:0,a:1}},M=H,N=function(e){var r=e.s,n=e.l;return{h:e.h,s:(r*=(n<50?n:100-n)/100)>0?2*r/(n+r)*100:0,v:n+r,a:e.a}},w=function(e){return D(I(e))},y=function(e){var r=e.s,n=e.v,t=e.a,o=(200-r)*n/100;return{h:b(e.h),s:b(o>0&&o<200?r*n/100/(o<=100?o:200-o)*100:0),l:b(o/2),a:b(t,2)}},q=function(e){var r=y(e);return\"hsl(\"+r.h+\", \"+r.s+\"%, \"+r.l+\"%)\"},k=function(e){var r=y(e);return\"hsla(\"+r.h+\", \"+r.s+\"%, \"+r.l+\"%, \"+r.a+\")\"},I=function(e){var r=e.h,n=e.s,t=e.v,o=e.a;r=r/360*6,n/=100,t/=100;var a=Math.floor(r),l=t*(1-n),u=t*(1-(r-a)*n),c=t*(1-(1-r+a)*n),i=a%6;return{r:b(255*[t,u,l,l,c,t][i]),g:b(255*[c,t,t,u,l,l][i]),b:b(255*[l,l,c,t,t,u][i]),a:b(o,2)}},O=function(e){var r=/hsva?\\(?\\s*(-?\\d*\\.?\\d+)(deg|rad|grad|turn)?[,\\s]+(-?\\d*\\.?\\d+)%?[,\\s]+(-?\\d*\\.?\\d+)%?,?\\s*[/\\s]*(-?\\d*\\.?\\d+)?(%)?\\s*\\)?/i.exec(e);return r?A({h:x(r[1],r[2]),s:Number(r[3]),v:Number(r[4]),a:void 0===r[5]?1:Number(r[5])/(r[6]?100:1)}):{h:0,s:0,v:0,a:1}},j=O,z=function(e){var r=/rgba?\\(?\\s*(-?\\d*\\.?\\d+)(%)?[,\\s]+(-?\\d*\\.?\\d+)(%)?[,\\s]+(-?\\d*\\.?\\d+)(%)?,?\\s*[/\\s]*(-?\\d*\\.?\\d+)?(%)?\\s*\\)?/i.exec(e);return r?L({r:Number(r[1])/(r[2]?100/255:1),g:Number(r[3])/(r[4]?100/255:1),b:Number(r[5])/(r[6]?100/255:1),a:void 0===r[7]?1:Number(r[7])/(r[8]?100:1)}):{h:0,s:0,v:0,a:1}},K=z,B=function(e){var r=e.toString(16);return r.length<2?\"0\"+r:r},D=function(e){var r=e.r,n=e.g,t=e.b,o=e.a,a=o<1?B(b(255*o)):\"\";return\"#\"+B(r)+B(n)+B(t)+a},L=function(e){var r=e.r,n=e.g,t=e.b,o=e.a,a=Math.max(r,n,t),l=a-Math.min(r,n,t),u=l?a===r?(n-t)/l:a===n?2+(t-r)/l:4+(r-n)/l:0;return{h:b(60*(u<0?u+6:u)),s:b(a?l/a*100:0),v:b(a/255*100),a:o}},A=function(e){return{h:b(e.h),s:b(e.s),v:b(e.v),a:b(e.a,2)}},S=e.memo(function(r){var n=r.hue,t=r.onChange,o=r.onChangeEnd,a=m([\"react-colorful__hue\",r.className]);return e.createElement(\"div\",{className:a},e.createElement(g,{onMove:function(e){t({h:360*e.left})},onKey:function(e){t({h:s(n+360*e.left,0,360)})},onEnd:o,\"aria-label\":\"Hue\",\"aria-valuenow\":b(n),\"aria-valuemax\":\"360\",\"aria-valuemin\":\"0\"},e.createElement(p,{className:\"react-colorful__hue-pointer\",left:n/360,color:q({h:n,s:100,v:100,a:1})})))}),T=e.memo(function(r){var n=r.hsva,t=r.onChange,o=r.onChangeEnd,a={backgroundColor:q({h:n.h,s:100,v:100,a:1})};return e.createElement(\"div\",{className:\"react-colorful__saturation\",style:a},e.createElement(g,{onMove:function(e){t({s:100*e.left,v:100-100*e.top})},onKey:function(e){t({s:s(n.s+100*e.left,0,100),v:s(n.v-100*e.top,0,100)})},onEnd:o,\"aria-label\":\"Color\",\"aria-valuetext\":\"Saturation \"+b(n.s)+\"%, Brightness \"+b(n.v)+\"%\"},e.createElement(p,{className:\"react-colorful__saturation-pointer\",top:1-n.v/100,left:n.s/100,color:q(n)})))}),F=function(e,r){if(e===r)return!0;for(var n in e)if(e[n]!==r[n])return!1;return!0},P=function(e,r){return e.replace(/\\s/g,\"\")===r.replace(/\\s/g,\"\")},X=function(e,r){return e.toLowerCase()===r.toLowerCase()||F(C(e),C(r))};function Y(e,n,l,u){var c=i(l),s=i(u),f=o(function(){return e.toHsva(n)}),v=f[0],d=f[1],h=r({color:n,hsva:v}),g=r(!1);t(function(){if(!e.equal(n,h.current.color)){var r=e.toHsva(n);h.current={hsva:r,color:n},d(r),g.current=!1}},[n,e]),t(function(){var r;F(v,h.current.hsva)||e.equal(r=e.fromHsva(v),h.current.color)||(h.current={hsva:v,color:r},c(r),g.current=!0)},[v,e,c]);var m=a(function(e){d(function(r){return Object.assign({},r,e)})},[]),p=a(function(){g.current&&(g.current=!1,s(h.current.color))},[s]);return[v,m,p]}var R,U=\"undefined\"!=typeof window?l:t,V=function(){return R||(\"undefined\"!=typeof __webpack_nonce__?__webpack_nonce__:void 0)},$=function(e){R=e},G=new Map,J=function(e){U(function(){var r=e.current?e.current.ownerDocument:document;if(void 0!==r&&!G.has(r)){var n=r.createElement(\"style\");n.innerHTML='.react-colorful{position:relative;display:flex;flex-direction:column;width:200px;height:200px;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;cursor:default}.react-colorful__saturation{position:relative;flex-grow:1;border-color:transparent;border-bottom:12px solid #000;border-radius:8px 8px 0 0;background-image:linear-gradient(0deg,#000,transparent),linear-gradient(90deg,#fff,hsla(0,0%,100%,0))}.react-colorful__alpha-gradient,.react-colorful__pointer-fill{content:\"\";position:absolute;left:0;top:0;right:0;bottom:0;pointer-events:none;border-radius:inherit}.react-colorful__alpha-gradient,.react-colorful__saturation{box-shadow:inset 0 0 0 1px rgba(0,0,0,.05)}.react-colorful__alpha,.react-colorful__hue{position:relative;height:24px}.react-colorful__hue{background:linear-gradient(90deg,red 0,#ff0 17%,#0f0 33%,#0ff 50%,#00f 67%,#f0f 83%,red)}.react-colorful__last-control{border-radius:0 0 8px 8px}.react-colorful__interactive{position:absolute;left:0;top:0;right:0;bottom:0;border-radius:inherit;outline:none;touch-action:none}.react-colorful__pointer{position:absolute;z-index:1;box-sizing:border-box;width:28px;height:28px;transform:translate(-50%,-50%);background-color:#fff;border:2px solid #fff;border-radius:50%;box-shadow:0 2px 4px rgba(0,0,0,.2)}.react-colorful__interactive:focus .react-colorful__pointer{transform:translate(-50%,-50%) scale(1.1)}.react-colorful__alpha,.react-colorful__alpha-pointer{background-color:#fff;background-image:url(\\'data:image/svg+xml;charset=utf-8,<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"16\" height=\"16\" fill-opacity=\".05\"><path d=\"M8 0h8v8H8zM0 8h8v8H0z\"/></svg>\\')}.react-colorful__saturation-pointer{z-index:3}.react-colorful__hue-pointer{z-index:2}',G.set(r,n);var t=V();t&&n.setAttribute(\"nonce\",t),r.head.appendChild(n)}},[])},Q=function(n){var t=n.className,o=n.colorModel,a=n.color,l=void 0===a?o.defaultColor:a,i=n.onChange,s=n.onChangeEnd,f=c(n,[\"className\",\"colorModel\",\"color\",\"onChange\",\"onChangeEnd\"]),v=r(null);J(v);var d=Y(o,l,i,s),h=d[0],g=d[1],p=d[2],b=m([\"react-colorful\",t]);return e.createElement(\"div\",u({},f,{ref:v,className:b}),e.createElement(T,{hsva:h,onChange:g,onChangeEnd:p}),e.createElement(S,{hue:h.h,onChange:g,onChangeEnd:p,className:\"react-colorful__last-control\"}))},W={defaultColor:\"000\",toHsva:E,fromHsva:function(e){return w({h:e.h,s:e.s,v:e.v,a:1})},equal:X},Z=function(r){return e.createElement(Q,u({},r,{colorModel:W}))},ee=function(r){var n=r.className,t=r.hsva,o=r.onChange,a=r.onChangeEnd,l={backgroundImage:\"linear-gradient(90deg, \"+k(Object.assign({},t,{a:0}))+\", \"+k(Object.assign({},t,{a:1}))+\")\"},u=m([\"react-colorful__alpha\",n]),c=b(100*t.a);return e.createElement(\"div\",{className:u},e.createElement(\"div\",{className:\"react-colorful__alpha-gradient\",style:l}),e.createElement(g,{onMove:function(e){o({a:e.left})},onKey:function(e){o({a:s(t.a+e.left)})},onEnd:a,\"aria-label\":\"Alpha\",\"aria-valuetext\":c+\"%\",\"aria-valuenow\":c,\"aria-valuemin\":\"0\",\"aria-valuemax\":\"100\"},e.createElement(p,{className:\"react-colorful__alpha-pointer\",left:t.a,color:k(t)})))},re=function(n){var t=n.className,o=n.colorModel,a=n.color,l=void 0===a?o.defaultColor:a,i=n.onChange,s=n.onChangeEnd,f=c(n,[\"className\",\"colorModel\",\"color\",\"onChange\",\"onChangeEnd\"]),v=r(null);J(v);var d=Y(o,l,i,s),h=d[0],g=d[1],p=d[2],b=m([\"react-colorful\",t]);return e.createElement(\"div\",u({},f,{ref:v,className:b}),e.createElement(T,{hsva:h,onChange:g,onChangeEnd:p}),e.createElement(S,{hue:h.h,onChange:g,onChangeEnd:p}),e.createElement(ee,{hsva:h,onChange:g,onChangeEnd:p,className:\"react-colorful__last-control\"}))},ne={defaultColor:\"0001\",toHsva:E,fromHsva:w,equal:X},te=function(r){return e.createElement(re,u({},r,{colorModel:ne}))},oe={defaultColor:{h:0,s:0,l:0,a:1},toHsva:N,fromHsva:y,equal:F},ae=function(r){return e.createElement(re,u({},r,{colorModel:oe}))},le={defaultColor:\"hsla(0, 0%, 0%, 1)\",toHsva:H,fromHsva:k,equal:P},ue=function(r){return e.createElement(re,u({},r,{colorModel:le}))},ce={defaultColor:{h:0,s:0,l:0},toHsva:function(e){return N({h:e.h,s:e.s,l:e.l,a:1})},fromHsva:function(e){return{h:(r=y(e)).h,s:r.s,l:r.l};var r},equal:F},ie=function(r){return e.createElement(Q,u({},r,{colorModel:ce}))},se={defaultColor:\"hsl(0, 0%, 0%)\",toHsva:M,fromHsva:q,equal:P},fe=function(r){return e.createElement(Q,u({},r,{colorModel:se}))},ve={defaultColor:{h:0,s:0,v:0,a:1},toHsva:function(e){return e},fromHsva:A,equal:F},de=function(r){return e.createElement(re,u({},r,{colorModel:ve}))},he={defaultColor:\"hsva(0, 0%, 0%, 1)\",toHsva:O,fromHsva:function(e){var r=A(e);return\"hsva(\"+r.h+\", \"+r.s+\"%, \"+r.v+\"%, \"+r.a+\")\"},equal:P},ge=function(r){return e.createElement(re,u({},r,{colorModel:he}))},me={defaultColor:{h:0,s:0,v:0},toHsva:function(e){return{h:e.h,s:e.s,v:e.v,a:1}},fromHsva:function(e){var r=A(e);return{h:r.h,s:r.s,v:r.v}},equal:F},pe=function(r){return e.createElement(Q,u({},r,{colorModel:me}))},be={defaultColor:\"hsv(0, 0%, 0%)\",toHsva:j,fromHsva:function(e){var r=A(e);return\"hsv(\"+r.h+\", \"+r.s+\"%, \"+r.v+\"%)\"},equal:P},_e=function(r){return e.createElement(Q,u({},r,{colorModel:be}))},Ee={defaultColor:{r:0,g:0,b:0,a:1},toHsva:L,fromHsva:I,equal:F},Ce=function(r){return e.createElement(re,u({},r,{colorModel:Ee}))},xe={defaultColor:\"rgba(0, 0, 0, 1)\",toHsva:z,fromHsva:function(e){var r=I(e);return\"rgba(\"+r.r+\", \"+r.g+\", \"+r.b+\", \"+r.a+\")\"},equal:P},He=function(r){return e.createElement(re,u({},r,{colorModel:xe}))},Me={defaultColor:{r:0,g:0,b:0},toHsva:function(e){return L({r:e.r,g:e.g,b:e.b,a:1})},fromHsva:function(e){return{r:(r=I(e)).r,g:r.g,b:r.b};var r},equal:F},Ne=function(r){return e.createElement(Q,u({},r,{colorModel:Me}))},we={defaultColor:\"rgb(0, 0, 0)\",toHsva:K,fromHsva:function(e){var r=I(e);return\"rgb(\"+r.r+\", \"+r.g+\", \"+r.b+\")\"},equal:P},ye=function(r){return e.createElement(Q,u({},r,{colorModel:we}))},qe=/^#?([0-9A-F]{3,8})$/i,ke=function(r){var n=r.color,l=void 0===n?\"\":n,s=r.onChange,f=r.onBlur,v=r.escape,d=r.validate,h=r.format,g=r.process,m=c(r,[\"color\",\"onChange\",\"onBlur\",\"escape\",\"validate\",\"format\",\"process\"]),p=o(function(){return v(l)}),b=p[0],_=p[1],E=i(s),C=i(f),x=a(function(e){var r=v(e.target.value);_(r),d(r)&&E(g?g(r):r)},[v,g,d,E]),H=a(function(e){d(e.target.value)||_(v(l)),C(e)},[l,v,d,C]);return t(function(){_(v(l))},[l,v]),e.createElement(\"input\",u({},m,{value:h?h(b):b,spellCheck:\"false\",onChange:x,onBlur:H}))},Ie=function(e){return\"#\"+e},Oe=function(r){var n=r.prefixed,t=r.alpha,o=c(r,[\"prefixed\",\"alpha\"]),l=a(function(e){return e.replace(/([^0-9A-F]+)/gi,\"\").substring(0,t?8:6)},[t]),i=a(function(e){return function(e,r){var n=qe.exec(e),t=n?n[1].length:0;return 3===t||6===t||!!r&&4===t||!!r&&8===t}(e,t)},[t]);return e.createElement(ke,u({},o,{escape:l,format:n?Ie:void 0,process:Ie,validate:i}))};export{te as HexAlphaColorPicker,Oe as HexColorInput,Z as HexColorPicker,ie as HslColorPicker,fe as HslStringColorPicker,ae as HslaColorPicker,ue as HslaStringColorPicker,pe as HsvColorPicker,_e as HsvStringColorPicker,de as HsvaColorPicker,ge as HsvaStringColorPicker,Ne as RgbColorPicker,ye as RgbStringColorPicker,Ce as RgbaColorPicker,He as RgbaStringColorPicker,$ as setNonce};\n//# sourceMappingURL=index.module.js.map\n","/**\n * ColorPickerDropdown - Custom color picker with dropdown\n * Uses react-colorful for a better UX than native browser picker\n */\n\nimport { useState, useEffect, memo, useRef } from 'react';\nimport { HexColorPicker } from 'react-colorful';\nimport { Button, Popover, PopoverTrigger, PopoverContent } from './ui';\n\nexport interface ColorPickerDropdownProps {\n value: string;\n onChange: (event: { target: { value: string } }) => void;\n /** Colours already in use elsewhere in the design (text, shapes,\n * paths, strokes, artboard background). Surfaced as the\n * \"Document colors\" row. */\n documentColors?: string[];\n /** Dominant colours sampled from image elements in the design.\n * Surfaced as a separate \"Image colors\" row so users can match\n * a colour from their artwork. Empty / omitted hides the row. */\n imageColors?: string[];\n icon?: React.ReactNode;\n showSquare?: boolean;\n allowTransparent?: boolean;\n isOpen?: boolean;\n onOpenChange?: (isOpen: boolean) => void;\n /** When true, renders the color picker content directly without a popover trigger button */\n embedded?: boolean;\n}\n\nconst ColorPickerDropdown = memo(({\n value,\n onChange,\n documentColors = [],\n imageColors = [],\n icon,\n showSquare = false,\n allowTransparent = false,\n isOpen: controlledIsOpen,\n onOpenChange: controlledOnOpenChange,\n embedded = false,\n}: ColorPickerDropdownProps) => {\n const [internalIsOpen, setInternalIsOpen] = useState(false);\n const [hexInput, setHexInput] = useState(value);\n const [localColor, setLocalColor] = useState(value);\n const lastUpdateTimeRef = useRef<number>(0);\n const pendingUpdateRef = useRef<NodeJS.Timeout | null>(null);\n const isDraggingRef = useRef<boolean>(false);\n\n // CRITICAL: Store onChange in a ref to avoid stale closure bug\n // When throttled updates fire via setTimeout, they need the LATEST onChange,\n // not the one captured when the timeout was created\n const onChangeRef = useRef(onChange);\n onChangeRef.current = onChange;\n\n // Use controlled state if provided, otherwise use internal state\n const isOpen = controlledIsOpen !== undefined ? controlledIsOpen : internalIsOpen;\n const setIsOpen = controlledOnOpenChange || setInternalIsOpen;\n\n // Sync local state with value prop - but ONLY when not actively dragging\n // This prevents jank from prop updates conflicting with local drag state\n useEffect(() => {\n if (!isDraggingRef.current && value !== 'transparent') {\n setHexInput(value);\n setLocalColor(value);\n }\n }, [value]);\n\n // Throttled color change - updates at max 60fps for smooth real-time feedback\n const handleColorChange = (color: string) => {\n // Mark as dragging to prevent prop sync from causing jank\n isDraggingRef.current = true;\n\n // Update local state immediately for smooth UI\n setLocalColor(color);\n setHexInput(color);\n\n const now = Date.now();\n const timeSinceLastUpdate = now - lastUpdateTimeRef.current;\n\n // Throttle: update max once every 16ms (~60fps) for smooth real-time updates\n if (timeSinceLastUpdate >= 16) {\n // Call immediately if enough time has passed\n // Use ref to always get latest onChange (avoids stale closure on mobile)\n onChangeRef.current({ target: { value: color } });\n lastUpdateTimeRef.current = now;\n\n // Clear any pending update\n if (pendingUpdateRef.current) {\n clearTimeout(pendingUpdateRef.current);\n pendingUpdateRef.current = null;\n }\n } else {\n // Schedule an update for the remaining throttle time\n if (pendingUpdateRef.current) {\n clearTimeout(pendingUpdateRef.current);\n }\n\n pendingUpdateRef.current = setTimeout(() => {\n // CRITICAL: Use ref to get latest onChange, not captured closure value\n // This fixes intermittent color update failures on mobile\n onChangeRef.current({ target: { value: color } });\n lastUpdateTimeRef.current = Date.now();\n pendingUpdateRef.current = null;\n // Clear dragging state after final update\n isDraggingRef.current = false;\n }, 16 - timeSinceLastUpdate);\n }\n };\n\n // Store localColor in a ref for the pointerup handler to access\n const localColorRef = useRef(localColor);\n localColorRef.current = localColor;\n\n // Clear dragging state when mouse/touch is released and flush any pending update\n useEffect(() => {\n const handlePointerUp = () => {\n // If there's a pending throttled update, cancel it and send immediately\n // This ensures the final color is always applied even if component re-renders\n if (pendingUpdateRef.current) {\n clearTimeout(pendingUpdateRef.current);\n pendingUpdateRef.current = null;\n // Send the final color using the latest refs\n onChangeRef.current({ target: { value: localColorRef.current } });\n }\n // Clear dragging state after a small delay\n setTimeout(() => {\n isDraggingRef.current = false;\n }, 50);\n };\n\n window.addEventListener('pointerup', handlePointerUp);\n window.addEventListener('pointercancel', handlePointerUp);\n\n return () => {\n window.removeEventListener('pointerup', handlePointerUp);\n window.removeEventListener('pointercancel', handlePointerUp);\n };\n }, []);\n\n // Cleanup timeout on unmount\n useEffect(() => {\n return () => {\n if (pendingUpdateRef.current) {\n clearTimeout(pendingUpdateRef.current);\n }\n };\n }, []);\n\n const handleHexInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {\n const input = e.target.value;\n setHexInput(input);\n\n // Validate hex color (with or without #)\n const hexPattern = /^#?([0-9A-Fa-f]{6}|[0-9A-Fa-f]{3})$/;\n const withHash = input.startsWith('#') ? input : `#${input}`;\n\n if (hexPattern.test(withHash)) {\n // Use ref to ensure we always call the latest onChange\n onChangeRef.current({ target: { value: withHash } });\n }\n };\n\n const handlePresetClick = (color: string) => {\n handleColorChange(color);\n };\n\n const handleTransparentClick = () => {\n // Use ref to ensure we always call the latest onChange\n onChangeRef.current({ target: { value: 'transparent' } });\n };\n\n const isTransparent = value === 'transparent';\n\n const buttonContent = showSquare ? (\n <div\n className={`sc:size-8 sc:md:size-6 sc:rounded-md sc:border sc:border-border-primary ${isTransparent ? 'transparent-pattern-small' : ''}`}\n style={isTransparent ? {} : { backgroundColor: value }}\n />\n ) : (\n <div className=\"sc:relative sc:flex sc:items-center sc:justify-center sc:h-5 sc:w-5\">\n {icon ? <span className=\"sc:flex sc:items-center sc:-translate-y-0.5\">{icon}</span> : <span className=\"sc:font-bold sc:text-lg sc:leading-none sc:-translate-y-0.5\">A</span>}\n <div\n className={`sc:absolute sc:bottom-0 sc:left-1/2 sc:-translate-x-1/2 sc:h-[3px] sc:w-4 sc:rounded-sm ${isTransparent ? 'transparent-pattern-small' : ''}`}\n style={isTransparent ? {} : { backgroundColor: value }}\n />\n </div>\n );\n\n const pickerContent = (\n <div className=\"sc:space-y-4 sc:min-w-[232px]\">\n {allowTransparent && (\n <Button\n variant=\"ghost\"\n className={`sc:flex sc:w-full sc:cursor-pointer sc:items-center sc:justify-start sc:gap-2 sc:rounded-lg ${isTransparent ? 'sc:bg-primary/10' : ''}`}\n onClick={handleTransparentClick}\n >\n <div className=\"transparent-pattern-small sc:h-6 sc:w-6 sc:rounded\" />\n <span className=\"sc:text-sm sc:font-medium\">Transparent</span>\n </Button>\n )}\n\n <div className=\"sc:w-[200px]\">\n <HexColorPicker color={isTransparent ? '#ffffff' : localColor} onChange={handleColorChange} />\n </div>\n\n <div className=\"sc:flex sc:items-center sc:gap-2\">\n <label htmlFor=\"hex-input\" className=\"sc:text-sm sc:font-medium sc:uppercase sc:text-foreground/60\">\n HEX\n </label>\n <input\n id=\"hex-input\"\n type=\"text\"\n className=\"sc:w-24 sc:rounded-lg sc:border sc:border-divider sc:bg-field sc:px-2 sc:py-1.5 sc:text-sm sc:text-foreground sc:focus:border-primary sc:focus:outline-none\"\n value={hexInput}\n onChange={handleHexInputChange}\n placeholder=\"#000000\"\n maxLength={7}\n />\n </div>\n\n {documentColors.length > 0 && (\n <div className=\"sc:flex sc:flex-col sc:gap-1.5\">\n <div className=\"sc:text-sm sc:font-medium sc:text-foreground/60\">Document colors</div>\n <div className=\"sc:grid sc:grid-cols-8 sc:gap-1\">\n {documentColors.map((color, index) => (\n <button\n key={index}\n className={`sc:h-6 sc:w-6 sc:cursor-pointer sc:rounded sc:border-2 sc:transition-all sc:duration-150 sc:hover:scale-110 ${color === value ? 'sc:border-primary' : 'sc:border-transparent'}`}\n style={{ backgroundColor: color }}\n onClick={() => handlePresetClick(color)}\n aria-label={color}\n />\n ))}\n </div>\n </div>\n )}\n\n {imageColors.length > 0 && (\n <div className=\"sc:flex sc:flex-col sc:gap-1.5\">\n <div className=\"sc:text-sm sc:font-medium sc:text-foreground/60\">Image colors</div>\n <div className=\"sc:grid sc:grid-cols-8 sc:gap-1\">\n {imageColors.map((color, index) => (\n <button\n key={`img-${index}`}\n className={`sc:h-6 sc:w-6 sc:cursor-pointer sc:rounded sc:border-2 sc:transition-all sc:duration-150 sc:hover:scale-110 ${color === value ? 'sc:border-primary' : 'sc:border-transparent'}`}\n style={{ backgroundColor: color }}\n onClick={() => handlePresetClick(color)}\n aria-label={color}\n />\n ))}\n </div>\n </div>\n )}\n </div>\n );\n\n // Embedded mode: render just the picker content without popover wrapper\n if (embedded) {\n return pickerContent;\n }\n\n return (\n <Popover open={isOpen} onOpenChange={setIsOpen}>\n <PopoverTrigger asChild>\n <button\n className={\n showSquare\n ? 'sc:flex sc:items-center sc:justify-center sc:bg-transparent sc:border-0 sc:p-0 sc:cursor-pointer sc:rounded-md sc:hover:opacity-80 sc:transition-opacity'\n : 'sc-toolbar-btn'\n }\n aria-label=\"Color Picker\"\n >\n {buttonContent}\n </button>\n </PopoverTrigger>\n <PopoverContent className=\"sc:w-auto\" maxZIndex>\n {pickerContent}\n </PopoverContent>\n </Popover>\n );\n});\n\nColorPickerDropdown.displayName = 'ColorPickerDropdown';\n\nexport default ColorPickerDropdown;\n","/**\n * BackButton - Reusable back button for toolbar menus\n */\n\nimport { Button, Tooltip, TooltipTrigger, TooltipContent, TooltipProvider } from './ui';\n\nconst BackIcon = () => (\n <svg\n width=\"20\"\n height=\"20\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n className=\"sc:shrink-0\"\n >\n <path d=\"M19 12H5M12 19l-7-7 7-7\" />\n </svg>\n);\n\nexport function BackButton({ onClick }: { onClick: () => void }) {\n return (\n <TooltipProvider delayDuration={300}>\n <Tooltip>\n <TooltipTrigger asChild>\n <Button\n variant=\"outline\"\n onClick={onClick}\n className=\"sc:mr-sm sc:border-r-border-primary sc:pr-md\"\n aria-label=\"Back\"\n >\n <BackIcon />\n </Button>\n </TooltipTrigger>\n <TooltipContent>Back</TooltipContent>\n </Tooltip>\n </TooltipProvider>\n );\n}\n\nexport default BackButton;\n","/**\n * featureApplied — derive boolean flags from a canvas element saying\n * \"this feature has a non-default value.\" Used by toolbar buttons to\n * paint the active/selected style not just when the panel is open\n * but also when the property has actually been applied to the\n * element. Lets users tell at a glance whether a layer is rotated /\n * has a stroke / has a knockout / etc.\n *\n * Default values match the element constructors: rotation=0,\n * opacity=1, borderRadius=0, fillOpacity=1, blendMode unset, no\n * masks, no stroke, no distress, no shadow.\n */\n\nimport type { BaseElement } from '../core/BaseElement.js';\nimport type { ImageAdjustments } from '../types/index.js';\nimport { isStandardBlendMode } from '../types/index.js';\nimport { isNeutralAdjustments } from '../core/image-adjustments.js';\n\nconst EPSILON = 0.001;\n\nexport interface FeatureAppliedFlags {\n rotation: boolean;\n opacity: boolean;\n stroke: boolean;\n knockout: boolean;\n distress: boolean;\n imageMask: boolean;\n /** Drop shadow enabled */\n shadow: boolean;\n /** Standard blend mode applied (multiply/screen/overlay/darken/lighten — NOT knockout/clip) */\n blendMode: boolean;\n /** Image: `transformData.borderRadius`. */\n cornerRadius: boolean;\n /** Image: `transformData.adjustments` (brightness/contrast/saturation non-neutral). */\n adjustments: boolean;\n /** Shape: `transformData.fillOpacity`. */\n shapeTransparency: boolean;\n /**\n * Text: non-default `letterSpacing` (≠ 0) or `lineHeight` (≠ 1.2 default).\n * Drives the font-size toolbar button's applied highlight, since both\n * controls live inside the Font Size panel.\n */\n typography: boolean;\n}\n\nexport function getFeatureApplied(element: BaseElement | null | undefined): FeatureAppliedFlags {\n if (!element) {\n return {\n rotation: false,\n opacity: false,\n stroke: false,\n knockout: false,\n distress: false,\n imageMask: false,\n shadow: false,\n blendMode: false,\n cornerRadius: false,\n adjustments: false,\n shapeTransparency: false,\n typography: false,\n };\n }\n\n const td = element.transformData as\n | { borderRadius?: number; fillOpacity?: number; adjustments?: ImageAdjustments }\n | undefined;\n\n // Text typography knobs (TextElement only; undefined elsewhere)\n const { letterSpacing, lineHeight } = element as unknown as {\n letterSpacing?: number;\n lineHeight?: number;\n };\n\n return {\n rotation: Math.abs(element.rotation ?? 0) > EPSILON,\n opacity: (element.opacity ?? 1) < 1 - EPSILON,\n stroke: element.stroke?.enabled === true,\n knockout: element.blendMode === 'knockout' || element.blendMode === 'clip',\n distress: element.distressEffect?.enabled === true,\n imageMask: !!element.masks && element.masks.length > 0,\n shadow: element.shadow?.enabled === true,\n blendMode: isStandardBlendMode(element.blendMode),\n cornerRadius: (td?.borderRadius ?? 0) > 0,\n adjustments: !isNeutralAdjustments(td?.adjustments),\n shapeTransparency: (td?.fillOpacity ?? 1) < 1 - EPSILON,\n typography:\n Math.abs(letterSpacing ?? 0) > EPSILON ||\n (lineHeight !== undefined && Math.abs(lineHeight - 1.2) > EPSILON),\n };\n}\n","/**\n * ImageToolbar - Toolbar for image-specific controls\n * Handles crop, flip, and border radius controls\n */\n\nimport React, { useState } from 'react';\nimport { Tooltip, TooltipTrigger, TooltipContent, ToolbarButton, Button, Popover, PopoverTrigger, PopoverContent } from './ui';\nimport { Icon } from '@iconify/react';\nimport { ImageElement } from '../core/ImageElement';\nimport { RotateLeftIcon } from './ui/custom-icons';\nimport { icons } from './ui/icons';\nimport { getFeatureApplied } from '../utils/featureApplied.js';\n\ninterface ImageToolbarProps {\n element: ImageElement;\n onElementUpdate: (element: ImageElement) => void;\n showUngroupButton?: boolean;\n onUngroup?: () => void;\n onMoveForward?: () => void;\n onMoveBackward?: () => void;\n onChangeImage?: () => void;\n /**\n * Remove-background action. Provided only when the host configured\n * `services.removeBackground` — unconfigured = no button (consistent with\n * the services contract used by the Image Browser tabs).\n */\n onRemoveBackground?: () => void;\n /** Background removal in flight — disables the button + shows a spinner */\n removingBackground?: boolean;\n /** Inline error from the last background-removal attempt */\n removeBackgroundError?: string | null;\n /** Callback when element should be deleted */\n onDelete?: () => void;\n /** Whether the corner radius panel is expanded */\n cornerRadiusExpanded?: boolean;\n /** Callback when corner radius panel should be toggled */\n onCornerRadiusToggle?: () => void;\n /** Whether the crop panel is expanded */\n cropExpanded?: boolean;\n /** Callback when crop panel should be toggled */\n onCropToggle?: () => void;\n /** Whether the adjust panel (brightness/contrast/saturation) is expanded */\n adjustExpanded?: boolean;\n /** Callback when adjust panel should be toggled */\n onAdjustToggle?: () => void;\n /** Whether the rotation panel is expanded */\n rotationExpanded?: boolean;\n /** Callback when rotation panel should be toggled */\n onRotationToggle?: () => void;\n /** Whether the opacity panel is expanded */\n opacityExpanded?: boolean;\n /** Callback when opacity panel should be toggled */\n onOpacityToggle?: () => void;\n /** Whether the stroke panel is expanded */\n strokeExpanded?: boolean;\n /** Callback when stroke panel should be toggled */\n onStrokeToggle?: () => void;\n /** Whether the shadow panel is expanded */\n shadowExpanded?: boolean;\n /** Callback when shadow panel should be toggled */\n onShadowToggle?: () => void;\n /** Whether the blend mode panel is expanded */\n blendModeExpanded?: boolean;\n /** Callback when blend mode panel should be toggled */\n onBlendModeToggle?: () => void;\n /** Whether the knockout panel is expanded */\n knockoutExpanded?: boolean;\n /** Callback when knockout panel should be toggled */\n onKnockoutToggle?: () => void;\n /** Whether the distress texture panel is expanded */\n distressTextureExpanded?: boolean;\n /** Callback when distress texture panel should be toggled */\n onDistressTextureToggle?: () => void;\n /** Whether the image mask panel is expanded */\n imageMaskExpanded?: boolean;\n /** Callback when image mask panel should be toggled */\n onImageMaskToggle?: () => void;\n}\n\nconst ImageToolbar: React.FC<ImageToolbarProps> = ({\n element,\n onElementUpdate,\n showUngroupButton = false,\n onUngroup,\n onMoveForward,\n onMoveBackward,\n onChangeImage,\n onRemoveBackground,\n removingBackground = false,\n removeBackgroundError = null,\n onDelete,\n cornerRadiusExpanded = false,\n onCornerRadiusToggle,\n cropExpanded = false,\n onCropToggle,\n adjustExpanded = false,\n onAdjustToggle,\n rotationExpanded = false,\n onRotationToggle,\n opacityExpanded = false,\n onOpacityToggle,\n strokeExpanded = false,\n onStrokeToggle,\n shadowExpanded = false,\n onShadowToggle,\n blendModeExpanded = false,\n onBlendModeToggle,\n knockoutExpanded = false,\n onKnockoutToggle,\n distressTextureExpanded = false,\n onDistressTextureToggle,\n imageMaskExpanded = false,\n onImageMaskToggle,\n}) => {\n const [moreMenuOpen, setMoreMenuOpen] = useState<boolean>(false);\n const [changeImageTooltipDisabled, setChangeImageTooltipDisabled] = useState(false);\n const [removeBgTooltipDisabled, setRemoveBgTooltipDisabled] = useState(false);\n const [cornerRadiusTooltipDisabled, setCornerRadiusTooltipDisabled] = useState(false);\n const [cropTooltipDisabled, setCropTooltipDisabled] = useState(false);\n const [adjustTooltipDisabled, setAdjustTooltipDisabled] = useState(false);\n const [rotationTooltipDisabled, setRotationTooltipDisabled] = useState(false);\n const [opacityTooltipDisabled, setOpacityTooltipDisabled] = useState(false);\n const [strokeTooltipDisabled, setStrokeTooltipDisabled] = useState(false);\n const [shadowTooltipDisabled, setShadowTooltipDisabled] = useState(false);\n const [blendModeTooltipDisabled, setBlendModeTooltipDisabled] = useState(false);\n const [knockoutTooltipDisabled, setKnockoutTooltipDisabled] = useState(false);\n const [distressTooltipDisabled, setDistressTooltipDisabled] = useState(false);\n const [imageMaskTooltipDisabled, setImageMaskTooltipDisabled] = useState(false);\n\n // Check if element is in crop mode\n const isCropping = element.isCropping;\n\n // Feature-applied flags — drive the \"selected\" highlight on the\n // toolbar buttons whose underlying property is set to a non-default\n // value. Combined with the panel-open flag below.\n const applied = getFeatureApplied(element);\n\n const handleCropToggle = () => {\n setCropTooltipDisabled(true);\n if (isCropping) {\n // Exit crop mode\n const updatedElement = element.clone();\n updatedElement.exitCropMode();\n onElementUpdate(updatedElement);\n } else {\n // Enter crop mode\n const updatedElement = element.clone();\n updatedElement.enterCropMode();\n onElementUpdate(updatedElement);\n }\n onCropToggle?.();\n };\n\n const handleFlipHorizontal = () => {\n const updatedElement = element.clone();\n updatedElement.transformData.flipHorizontal = !updatedElement.transformData.flipHorizontal;\n onElementUpdate(updatedElement);\n };\n\n const handleFlipVertical = () => {\n const updatedElement = element.clone();\n updatedElement.transformData.flipVertical = !updatedElement.transformData.flipVertical;\n onElementUpdate(updatedElement);\n };\n\n return (\n <div className=\"sc-toolbar-items\">\n {/* Change Image button */}\n {onChangeImage && (\n <ToolbarButton\n icon=\"lucide:image\"\n onClick={() => {\n setChangeImageTooltipDisabled(true);\n onChangeImage();\n }}\n onMouseLeave={() => setChangeImageTooltipDisabled(false)}\n tooltip=\"Change Image\"\n tooltipDisabled={changeImageTooltipDisabled}\n />\n )}\n\n {/* Remove Background button — one-shot service action, NOT a toggle\n (deliberately absent from getFeatureApplied). Rendered only when the\n host configured `services.removeBackground` (unconfigured = hidden);\n disabled with no crash when the element has no imageUrl yet. */}\n {onRemoveBackground && (\n <ToolbarButton\n icon={\n removingBackground ? (\n <Icon icon=\"eos-icons:loading\" className=\"sc:size-6 sc:md:size-5 sc:animate-spin\" />\n ) : (\n 'gravity-ui:magic-wand'\n )\n }\n onClick={() => {\n setRemoveBgTooltipDisabled(true);\n onRemoveBackground();\n }}\n onMouseLeave={() => setRemoveBgTooltipDisabled(false)}\n tooltip={removingBackground ? 'Removing…' : 'Remove Background'}\n tooltipDisabled={removeBgTooltipDisabled}\n disabled={removingBackground || !element.imageUrl}\n aria-label=\"Remove Background\"\n />\n )}\n\n {/* Inline error from the last background-removal attempt. Lives inside\n .toolbar-items so it wraps with the rest of the row (embed mode uses\n `display: contents` — all items wrap together). */}\n {onRemoveBackground && removeBackgroundError && (\n <span\n role=\"alert\"\n data-testid=\"toolbar-remove-bg-error\"\n className=\"sc:self-center sc:whitespace-nowrap sc:rounded-lg sc:border sc:border-danger sc:bg-danger/10 sc:px-2 sc:py-1 sc:text-xs sc:text-danger\"\n >\n {removeBackgroundError}\n </span>\n )}\n\n {/* Crop button */}\n <ToolbarButton\n icon=\"lucide:crop\"\n onClick={handleCropToggle}\n onMouseLeave={() => setCropTooltipDisabled(false)}\n tooltip={isCropping ? 'Exit Crop Mode' : 'Crop'}\n tooltipDisabled={cropTooltipDisabled || cropExpanded}\n active={isCropping || cropExpanded}\n />\n\n {/* Flip Horizontal button */}\n <ToolbarButton icon=\"lucide:flip-horizontal-2\" onClick={handleFlipHorizontal} tooltip=\"Flip Horizontal\" />\n\n {/* Flip Vertical button */}\n <ToolbarButton icon=\"lucide:flip-vertical-2\" onClick={handleFlipVertical} tooltip=\"Flip Vertical\" />\n\n {/* Adjust button — brightness/contrast/saturation panel. Tinted while\n the panel is open OR while non-neutral adjustments are applied\n (getFeatureApplied affordance, gotcha #21). */}\n {onAdjustToggle && (\n <ToolbarButton\n icon=\"gravity-ui:sliders\"\n onClick={() => {\n setAdjustTooltipDisabled(true);\n onAdjustToggle();\n }}\n onMouseLeave={() => setAdjustTooltipDisabled(false)}\n tooltip=\"Adjust\"\n tooltipDisabled={adjustTooltipDisabled || adjustExpanded}\n active={adjustExpanded || applied.adjustments}\n data-testid=\"toolbar-adjust\"\n aria-label=\"Adjust\"\n />\n )}\n\n {/* Rotate button - toggles rotation panel */}\n <ToolbarButton\n icon={<RotateLeftIcon size={20} className=\"sc:md:size-5\" />}\n onClick={() => {\n setRotationTooltipDisabled(true);\n onRotationToggle?.();\n }}\n onMouseLeave={() => setRotationTooltipDisabled(false)}\n tooltip=\"Rotate\"\n tooltipDisabled={rotationTooltipDisabled || rotationExpanded}\n active={rotationExpanded || applied.rotation}\n />\n\n {/* Transparency button - toggles transparency panel */}\n <ToolbarButton\n icon=\"lucide:blend\"\n onClick={() => {\n setOpacityTooltipDisabled(true);\n onOpacityToggle?.();\n }}\n onMouseLeave={() => setOpacityTooltipDisabled(false)}\n tooltip=\"Transparency\"\n tooltipDisabled={opacityTooltipDisabled || opacityExpanded}\n active={opacityExpanded || applied.opacity}\n />\n\n {/* Border radius control - toggle button for embedded panel */}\n <ToolbarButton\n icon=\"lucide:square-round-corner\"\n onClick={() => {\n setCornerRadiusTooltipDisabled(true);\n onCornerRadiusToggle?.();\n }}\n onMouseLeave={() => setCornerRadiusTooltipDisabled(false)}\n tooltip=\"Corner Radius\"\n tooltipDisabled={cornerRadiusTooltipDisabled || cornerRadiusExpanded}\n active={cornerRadiusExpanded || applied.cornerRadius}\n />\n\n {/* Knockout */}\n {onKnockoutToggle && (\n <ToolbarButton\n icon=\"lucide:scissors\"\n onClick={() => {\n setKnockoutTooltipDisabled(true);\n onKnockoutToggle();\n }}\n onMouseLeave={() => setKnockoutTooltipDisabled(false)}\n tooltip=\"Clip / Knockout\"\n tooltipDisabled={knockoutTooltipDisabled || knockoutExpanded}\n active={knockoutExpanded || applied.knockout}\n />\n )}\n\n {/* Distress Texture */}\n {onDistressTextureToggle && (\n <ToolbarButton\n icon=\"lucide:stamp\"\n onClick={() => {\n setDistressTooltipDisabled(true);\n onDistressTextureToggle();\n }}\n onMouseLeave={() => setDistressTooltipDisabled(false)}\n tooltip=\"Distress Texture\"\n tooltipDisabled={distressTooltipDisabled || distressTextureExpanded}\n active={distressTextureExpanded || applied.distress}\n />\n )}\n\n {/* Image Mask */}\n {onImageMaskToggle && (\n <ToolbarButton\n icon=\"lucide:venetian-mask\"\n onClick={() => {\n setImageMaskTooltipDisabled(true);\n onImageMaskToggle();\n }}\n onMouseLeave={() => setImageMaskTooltipDisabled(false)}\n tooltip=\"Image Mask\"\n tooltipDisabled={imageMaskTooltipDisabled || imageMaskExpanded}\n active={imageMaskExpanded || applied.imageMask}\n />\n )}\n\n {/* Stroke */}\n {onStrokeToggle && (\n <ToolbarButton\n icon=\"lucide:pen-line\"\n onClick={() => {\n setStrokeTooltipDisabled(true);\n onStrokeToggle();\n }}\n onMouseLeave={() => setStrokeTooltipDisabled(false)}\n tooltip=\"Stroke\"\n tooltipDisabled={strokeTooltipDisabled || strokeExpanded}\n active={strokeExpanded || applied.stroke}\n />\n )}\n\n {/* Shadow */}\n {onShadowToggle && (\n <ToolbarButton\n icon=\"gravity-ui:square-dashed-circle\"\n onClick={() => {\n setShadowTooltipDisabled(true);\n onShadowToggle();\n }}\n onMouseLeave={() => setShadowTooltipDisabled(false)}\n tooltip=\"Shadow\"\n tooltipDisabled={shadowTooltipDisabled || shadowExpanded}\n active={shadowExpanded || applied.shadow}\n />\n )}\n\n {/* Blend Mode */}\n {onBlendModeToggle && (\n <ToolbarButton\n icon=\"gravity-ui:circles-intersection\"\n onClick={() => {\n setBlendModeTooltipDisabled(true);\n onBlendModeToggle();\n }}\n onMouseLeave={() => setBlendModeTooltipDisabled(false)}\n tooltip=\"Blend Mode\"\n tooltipDisabled={blendModeTooltipDisabled || blendModeExpanded}\n active={blendModeExpanded || applied.blendMode}\n />\n )}\n\n {/* More Menu - overflow menu for additional options */}\n {(onMoveForward || onMoveBackward || onDelete) && (\n <Popover open={moreMenuOpen} onOpenChange={setMoreMenuOpen}>\n <PopoverTrigger asChild>\n <button className=\"sc-toolbar-btn\" aria-label=\"More options\">\n <Icon icon=\"lucide:ellipsis-vertical\" className=\"sc:size-6\" />\n </button>\n </PopoverTrigger>\n <PopoverContent align=\"end\" className=\"sc:w-auto sc:p-1\" maxZIndex>\n <div className=\"sc:flex sc:items-center sc:gap-1\">\n {onMoveForward && (\n <Tooltip delayDuration={300}>\n <TooltipTrigger asChild>\n <Button\n variant=\"ghost\"\n size=\"icon\"\n onClick={() => {\n onMoveForward();\n setMoreMenuOpen(false);\n }}\n aria-label=\"Move Forward\"\n >\n <Icon icon=\"hugeicons:layer-bring-forward\" className=\"sc:size-5\" />\n </Button>\n </TooltipTrigger>\n <TooltipContent>Move Forward</TooltipContent>\n </Tooltip>\n )}\n {onMoveBackward && (\n <Tooltip delayDuration={300}>\n <TooltipTrigger asChild>\n <Button\n variant=\"ghost\"\n size=\"icon\"\n onClick={() => {\n onMoveBackward();\n setMoreMenuOpen(false);\n }}\n aria-label=\"Move Backward\"\n >\n <Icon icon=\"hugeicons:layer-send-backward\" className=\"sc:size-5\" />\n </Button>\n </TooltipTrigger>\n <TooltipContent>Move Backward</TooltipContent>\n </Tooltip>\n )}\n {onDelete && (\n <Tooltip delayDuration={300}>\n <TooltipTrigger asChild>\n <Button\n variant=\"ghost\"\n size=\"icon\"\n onClick={() => {\n setMoreMenuOpen(false);\n onDelete();\n }}\n aria-label=\"Delete\"\n >\n <Icon icon={icons.trash} className=\"sc:size-5\" />\n </Button>\n </TooltipTrigger>\n <TooltipContent>Delete</TooltipContent>\n </Tooltip>\n )}\n </div>\n </PopoverContent>\n </Popover>\n )}\n\n {/* Ungroup button - shown when editing a child in a group */}\n {showUngroupButton && onUngroup && (\n <Tooltip delay={300}>\n <TooltipTrigger asChild>\n <Button variant=\"ghost\" size=\"sm\" onClick={onUngroup}>\n Ungroup\n </Button>\n </TooltipTrigger>\n <TooltipContent>Ungroup this group</TooltipContent>\n </Tooltip>\n )}\n </div>\n );\n};\n\nexport default ImageToolbar;\n","/**\n * Artboard Color Presets\n * A curated set of 10 background colors for artboards\n */\n\nexport interface ArtboardColor {\n id: string;\n name: string;\n color: string; // Hex color\n}\n\n/**\n * Artboard color presets\n * Includes a variety of colors for different design needs\n */\nexport const ARTBOARD_COLORS: ArtboardColor[] = [\n { id: 'white', name: 'White', color: '#FFFFFF' },\n { id: 'light-gray', name: 'Light Gray', color: '#E5E5E5' },\n { id: 'medium-gray', name: 'Medium Gray', color: '#999999' },\n { id: 'dark-gray', name: 'Dark Gray', color: '#333333' },\n { id: 'black', name: 'Black', color: '#000000' },\n { id: 'orange', name: 'Orange', color: '#FF8800' },\n { id: 'blue', name: 'Blue', color: '#0074D9' },\n { id: 'indigo', name: 'Indigo', color: '#4B0082' },\n { id: 'teal', name: 'Teal', color: '#39CCCC' },\n { id: 'coral', name: 'Coral', color: '#FF6B6B' },\n];\n\n/**\n * Get a random artboard color\n */\nexport function getRandomArtboardColor(): string {\n const randomIndex = Math.floor(Math.random() * ARTBOARD_COLORS.length);\n return ARTBOARD_COLORS[randomIndex].color;\n}\n\n/**\n * Find artboard color by hex value\n */\nexport function findArtboardColor(hexColor: string): ArtboardColor | undefined {\n return ARTBOARD_COLORS.find((c) => c.color.toLowerCase() === hexColor.toLowerCase());\n}\n","/**\n * ShapeToolbar - Toolbar for shape-specific controls\n * Handles shape type, fill color, opacity, and shape-specific parameters\n *\n * Uses callback props for secondary panels (like ImageToolbar) for better mobile UX\n */\n\nimport React, { useState, useMemo } from 'react';\nimport { Icon } from '@iconify/react';\nimport { Button, Popover, PopoverTrigger, PopoverContent, Tooltip, TooltipTrigger, TooltipContent, ToolbarButton, icons, RotateLeftIcon } from './ui';\nimport { ShapeElement } from '../core/ShapeElement';\nimport { getFeatureApplied } from '../utils/featureApplied.js';\n\nimport type { ShapeType } from '../types/index.js';\nimport { ARTBOARD_COLORS } from '../presets/artboard-color-presets.js';\nimport { shapeFillToCss } from '../core/shape-fill.js';\nimport ColorPickerDropdown from './ColorPickerDropdown.jsx';\n\ninterface ShapeToolbarProps {\n element: ShapeElement;\n onElementUpdate: (element: ShapeElement) => void;\n /**\n * Colours actually in use elsewhere in the design (text colours,\n * shape fills, strokes, paths, artboard background). Surfaced in\n * the colour picker so users can match an existing colour. Pass\n * `[]` (or omit) to fall back to the artboard-preset palette.\n */\n documentColors?: string[];\n /**\n * Dominant colours sampled from image elements in the design.\n * Surfaced as a separate \"Image colors\" row in the colour picker.\n */\n imageColors?: string[];\n showUngroupButton?: boolean;\n onUngroup?: () => void;\n onMoveForward?: () => void;\n onMoveBackward?: () => void;\n onOpenShapeTypeDrawer?: () => void;\n /** Callback when element should be deleted */\n onDelete?: () => void;\n /** Whether the rotation panel is expanded */\n rotationExpanded?: boolean;\n /** Callback when rotation panel should be toggled */\n onRotationToggle?: () => void;\n /** Whether the corner radius panel is expanded */\n cornerRadiusExpanded?: boolean;\n /** Callback when corner radius panel should be toggled */\n onCornerRadiusToggle?: () => void;\n /** Whether the transparency/opacity panel is expanded */\n transparencyExpanded?: boolean;\n /** Callback when transparency panel should be toggled */\n onTransparencyToggle?: () => void;\n /** Whether the sides panel is expanded (polygon) */\n sidesExpanded?: boolean;\n /** Callback when sides panel should be toggled */\n onSidesToggle?: () => void;\n /** Whether the points panel is expanded (star) */\n pointsExpanded?: boolean;\n /** Callback when points panel should be toggled */\n onPointsToggle?: () => void;\n /** Whether the inner radius panel is expanded (star) */\n innerRadiusExpanded?: boolean;\n /** Callback when inner radius panel should be toggled */\n onInnerRadiusToggle?: () => void;\n /** Whether the fill color panel is expanded */\n colorExpanded?: boolean;\n /** Callback when fill color panel should be toggled */\n onColorToggle?: () => void;\n /** Whether the stroke panel is expanded */\n strokeExpanded?: boolean;\n /** Callback when stroke panel should be toggled */\n onStrokeToggle?: () => void;\n /** Whether the shadow panel is expanded */\n shadowExpanded?: boolean;\n /** Callback when shadow panel should be toggled */\n onShadowToggle?: () => void;\n /** Whether the blend mode panel is expanded */\n blendModeExpanded?: boolean;\n /** Callback when blend mode panel should be toggled */\n onBlendModeToggle?: () => void;\n /** Whether the knockout panel is expanded */\n knockoutExpanded?: boolean;\n /** Callback when knockout panel should be toggled */\n onKnockoutToggle?: () => void;\n /** Whether the distress texture panel is expanded */\n distressTextureExpanded?: boolean;\n /** Callback when distress texture panel should be toggled */\n onDistressTextureToggle?: () => void;\n /** Whether the image mask panel is expanded */\n imageMaskExpanded?: boolean;\n /** Callback when image mask panel should be toggled */\n onImageMaskToggle?: () => void;\n}\n\nconst ShapeToolbar: React.FC<ShapeToolbarProps> = ({\n element,\n onElementUpdate,\n documentColors,\n imageColors,\n showUngroupButton = false,\n onUngroup,\n onMoveForward,\n onMoveBackward,\n onOpenShapeTypeDrawer,\n onDelete,\n rotationExpanded = false,\n onRotationToggle,\n cornerRadiusExpanded = false,\n onCornerRadiusToggle,\n transparencyExpanded = false,\n onTransparencyToggle,\n sidesExpanded = false,\n onSidesToggle,\n pointsExpanded = false,\n onPointsToggle,\n innerRadiusExpanded = false,\n onInnerRadiusToggle,\n colorExpanded = false,\n onColorToggle,\n strokeExpanded = false,\n onStrokeToggle,\n shadowExpanded = false,\n onShadowToggle,\n blendModeExpanded = false,\n onBlendModeToggle,\n knockoutExpanded = false,\n onKnockoutToggle,\n distressTextureExpanded = false,\n onDistressTextureToggle,\n imageMaskExpanded = false,\n onImageMaskToggle,\n}) => {\n const [moreMenuOpen, setMoreMenuOpen] = useState<boolean>(false);\n const [shapeTypeTooltipDisabled, setShapeTypeTooltipDisabled] = useState<boolean>(false);\n const [rotationTooltipDisabled, setRotationTooltipDisabled] = useState<boolean>(false);\n const [cornerRadiusTooltipDisabled, setCornerRadiusTooltipDisabled] = useState<boolean>(false);\n const [transparencyTooltipDisabled, setTransparencyTooltipDisabled] = useState<boolean>(false);\n const [sidesTooltipDisabled, setSidesTooltipDisabled] = useState<boolean>(false);\n const [pointsTooltipDisabled, setPointsTooltipDisabled] = useState<boolean>(false);\n const [innerRadiusTooltipDisabled, setInnerRadiusTooltipDisabled] = useState<boolean>(false);\n const [colorTooltipDisabled, setColorTooltipDisabled] = useState<boolean>(false);\n const [strokeTooltipDisabled, setStrokeTooltipDisabled] = useState<boolean>(false);\n const [shadowTooltipDisabled, setShadowTooltipDisabled] = useState<boolean>(false);\n const [blendModeTooltipDisabled, setBlendModeTooltipDisabled] = useState<boolean>(false);\n const [knockoutTooltipDisabled, setKnockoutTooltipDisabled] = useState<boolean>(false);\n const [distressTooltipDisabled, setDistressTooltipDisabled] = useState<boolean>(false);\n const [imageMaskTooltipDisabled, setImageMaskTooltipDisabled] = useState<boolean>(false);\n\n // Prefer colours from the active design (passed in by\n // ContextualToolbars) so users can match a colour they're already\n // using. Fall back to the artboard-preset palette only when the\n // design has no colours yet.\n const presetDocumentColors = useMemo(() => ARTBOARD_COLORS.map((c) => c.color), []);\n const effectiveDocumentColors = useMemo(() => {\n if (documentColors && documentColors.length > 0) return documentColors;\n return presetDocumentColors;\n }, [documentColors, presetDocumentColors]);\n\n // Feature-applied flags — drive the \"selected\" highlight on the\n // toolbar buttons whose underlying property has been set to a\n // non-default value.\n const applied = getFeatureApplied(element);\n\n const handleFillColorChange = (e: { target: { value: string } }) => {\n const updatedElement = element.clone();\n updatedElement.transformData.fillColor = e.target.value;\n // A rich `fill` wins over `fillColor` at render time — clear it so the\n // picked solid color is what actually renders.\n delete updatedElement.transformData.fill;\n onElementUpdate(updatedElement);\n };\n\n // Shape labels for the tooltip — the toolbar button itself uses\n // a generic \"shapes picker\" icon (icons.shapes) rather than the\n // current shape's outline. Showing the current shape made it look\n // like a static label, so users couldn't discover that tapping it\n // opens a picker. The label still names the current shape so the\n // hover tooltip (\"Change Shape (Star)\") gives context.\n const shapeTypeLabels: Record<ShapeType, string> = {\n rectangle: 'Rectangle',\n circle: 'Circle',\n ellipse: 'Ellipse',\n triangle: 'Triangle',\n polygon: 'Polygon',\n star: 'Star',\n line: 'Line',\n };\n\n const currentShapeType = element.transformData.shapeType;\n const currentLabel = shapeTypeLabels[currentShapeType] || 'Shape';\n\n return (\n <div className=\"sc-toolbar-items\">\n {/* Shape Type Button - Opens Drawer (picker affordance) */}\n {onOpenShapeTypeDrawer && (\n <ToolbarButton\n icon={icons.shapes}\n onClick={() => {\n setShapeTypeTooltipDisabled(true);\n onOpenShapeTypeDrawer();\n }}\n onMouseLeave={() => setShapeTypeTooltipDisabled(false)}\n tooltip={`Change Shape (${currentLabel})`}\n tooltipDisabled={shapeTypeTooltipDisabled}\n />\n )}\n\n {/* Fill Color Button - toggles secondary panel */}\n {onColorToggle ? (\n <Tooltip delay={300}>\n <TooltipTrigger asChild>\n <button\n className=\"sc-toolbar-btn\"\n onClick={() => {\n setColorTooltipDisabled(true);\n onColorToggle();\n }}\n onMouseLeave={() => setColorTooltipDisabled(false)}\n aria-label=\"Fill Color\"\n data-active={colorExpanded}\n >\n <div\n className=\"sc:h-6 sc:w-6 sc:rounded-md sc:border sc:border-border-primary\"\n style={{ background: shapeFillToCss(element.transformData.fill, element.transformData.fillColor) }}\n />\n </button>\n </TooltipTrigger>\n {!colorTooltipDisabled && !colorExpanded && <TooltipContent>Fill Color</TooltipContent>}\n </Tooltip>\n ) : (\n <Tooltip delay={300}>\n <TooltipTrigger asChild>\n <div>\n <ColorPickerDropdown\n value={element.transformData.fillColor || '#3b82f6'}\n onChange={handleFillColorChange}\n documentColors={effectiveDocumentColors}\n imageColors={imageColors}\n showSquare={true}\n />\n </div>\n </TooltipTrigger>\n <TooltipContent>Fill Color</TooltipContent>\n </Tooltip>\n )}\n\n {/* Border Radius (Rectangle only) - toggles secondary panel */}\n {element.transformData.shapeType === 'rectangle' && onCornerRadiusToggle && (\n <ToolbarButton\n icon=\"lucide:square-round-corner\"\n onClick={() => {\n setCornerRadiusTooltipDisabled(true);\n onCornerRadiusToggle();\n }}\n onMouseLeave={() => setCornerRadiusTooltipDisabled(false)}\n tooltip=\"Corner Radius\"\n tooltipDisabled={cornerRadiusTooltipDisabled || cornerRadiusExpanded}\n active={cornerRadiusExpanded || applied.cornerRadius}\n />\n )}\n\n {/* Sides (Polygon only) - toggles secondary panel */}\n {element.transformData.shapeType === 'polygon' && onSidesToggle && (\n <ToolbarButton\n icon=\"healthicons:polygon\"\n onClick={() => {\n setSidesTooltipDisabled(true);\n onSidesToggle();\n }}\n onMouseLeave={() => setSidesTooltipDisabled(false)}\n tooltip=\"Sides\"\n tooltipDisabled={sidesTooltipDisabled || sidesExpanded}\n active={sidesExpanded}\n />\n )}\n\n {/* Points (Star only) - toggles secondary panel */}\n {element.transformData.shapeType === 'star' && onPointsToggle && (\n <ToolbarButton\n icon=\"material-symbols:award-star-outline\"\n onClick={() => {\n setPointsTooltipDisabled(true);\n onPointsToggle();\n }}\n onMouseLeave={() => setPointsTooltipDisabled(false)}\n tooltip=\"Points\"\n tooltipDisabled={pointsTooltipDisabled || pointsExpanded}\n active={pointsExpanded}\n />\n )}\n\n {/* Inner Radius (Star only) - toggles secondary panel */}\n {element.transformData.shapeType === 'star' && onInnerRadiusToggle && (\n <ToolbarButton\n icon=\"lucide:circle-dashed\"\n onClick={() => {\n setInnerRadiusTooltipDisabled(true);\n onInnerRadiusToggle();\n }}\n onMouseLeave={() => setInnerRadiusTooltipDisabled(false)}\n tooltip=\"Inner Radius\"\n tooltipDisabled={innerRadiusTooltipDisabled || innerRadiusExpanded}\n active={innerRadiusExpanded}\n />\n )}\n\n {/* Transparency - toggles secondary panel */}\n {onTransparencyToggle && (\n <ToolbarButton\n icon=\"lucide:blend\"\n onClick={() => {\n setTransparencyTooltipDisabled(true);\n onTransparencyToggle();\n }}\n onMouseLeave={() => setTransparencyTooltipDisabled(false)}\n tooltip=\"Transparency\"\n tooltipDisabled={transparencyTooltipDisabled || transparencyExpanded}\n active={transparencyExpanded || applied.shapeTransparency}\n />\n )}\n\n {/* Rotate - toggles rotation panel */}\n {onRotationToggle && (\n <ToolbarButton\n icon={<RotateLeftIcon size={20} className=\"sc:md:size-5\" />}\n onClick={() => {\n setRotationTooltipDisabled(true);\n onRotationToggle();\n }}\n onMouseLeave={() => setRotationTooltipDisabled(false)}\n tooltip=\"Rotate\"\n tooltipDisabled={rotationTooltipDisabled || rotationExpanded}\n active={rotationExpanded || applied.rotation}\n />\n )}\n\n {/* Knockout */}\n {onKnockoutToggle && (\n <ToolbarButton\n icon=\"lucide:scissors\"\n onClick={() => {\n setKnockoutTooltipDisabled(true);\n onKnockoutToggle();\n }}\n onMouseLeave={() => setKnockoutTooltipDisabled(false)}\n tooltip=\"Clip / Knockout\"\n tooltipDisabled={knockoutTooltipDisabled || knockoutExpanded}\n active={knockoutExpanded || applied.knockout}\n />\n )}\n\n {/* Distress Texture */}\n {onDistressTextureToggle && (\n <ToolbarButton\n icon=\"lucide:stamp\"\n onClick={() => {\n setDistressTooltipDisabled(true);\n onDistressTextureToggle();\n }}\n onMouseLeave={() => setDistressTooltipDisabled(false)}\n tooltip=\"Distress Texture\"\n tooltipDisabled={distressTooltipDisabled || distressTextureExpanded}\n active={distressTextureExpanded || applied.distress}\n />\n )}\n\n {/* Image Mask */}\n {onImageMaskToggle && (\n <ToolbarButton\n icon=\"lucide:venetian-mask\"\n onClick={() => {\n setImageMaskTooltipDisabled(true);\n onImageMaskToggle();\n }}\n onMouseLeave={() => setImageMaskTooltipDisabled(false)}\n tooltip=\"Image Mask\"\n tooltipDisabled={imageMaskTooltipDisabled || imageMaskExpanded}\n active={imageMaskExpanded || applied.imageMask}\n />\n )}\n\n {/* Stroke */}\n {onStrokeToggle && (\n <ToolbarButton\n icon=\"lucide:pen-line\"\n onClick={() => {\n setStrokeTooltipDisabled(true);\n onStrokeToggle();\n }}\n onMouseLeave={() => setStrokeTooltipDisabled(false)}\n tooltip=\"Stroke\"\n tooltipDisabled={strokeTooltipDisabled || strokeExpanded}\n active={strokeExpanded || applied.stroke}\n />\n )}\n\n {/* Shadow */}\n {onShadowToggle && (\n <ToolbarButton\n icon=\"gravity-ui:square-dashed-circle\"\n onClick={() => {\n setShadowTooltipDisabled(true);\n onShadowToggle();\n }}\n onMouseLeave={() => setShadowTooltipDisabled(false)}\n tooltip=\"Shadow\"\n tooltipDisabled={shadowTooltipDisabled || shadowExpanded}\n active={shadowExpanded || applied.shadow}\n />\n )}\n\n {/* Blend Mode */}\n {onBlendModeToggle && (\n <ToolbarButton\n icon=\"gravity-ui:circles-intersection\"\n onClick={() => {\n setBlendModeTooltipDisabled(true);\n onBlendModeToggle();\n }}\n onMouseLeave={() => setBlendModeTooltipDisabled(false)}\n tooltip=\"Blend Mode\"\n tooltipDisabled={blendModeTooltipDisabled || blendModeExpanded}\n active={blendModeExpanded || applied.blendMode}\n />\n )}\n\n {/* More Menu - overflow menu for additional options */}\n {(onMoveForward || onMoveBackward || onDelete) && (\n <Popover open={moreMenuOpen} onOpenChange={setMoreMenuOpen}>\n <PopoverTrigger asChild>\n <button className=\"sc-toolbar-btn\" aria-label=\"More options\">\n <Icon icon=\"lucide:ellipsis-vertical\" className=\"sc:size-6\" />\n </button>\n </PopoverTrigger>\n <PopoverContent align=\"end\" className=\"sc:w-auto sc:p-1\" maxZIndex>\n <div className=\"sc:flex sc:items-center sc:gap-1\">\n {onMoveForward && (\n <Tooltip delayDuration={300}>\n <TooltipTrigger asChild>\n <Button\n variant=\"ghost\"\n size=\"icon\"\n onClick={() => {\n onMoveForward();\n setMoreMenuOpen(false);\n }}\n aria-label=\"Move Forward\"\n >\n <Icon icon=\"hugeicons:layer-bring-forward\" className=\"sc:size-5\" />\n </Button>\n </TooltipTrigger>\n <TooltipContent>Move Forward</TooltipContent>\n </Tooltip>\n )}\n {onMoveBackward && (\n <Tooltip delayDuration={300}>\n <TooltipTrigger asChild>\n <Button\n variant=\"ghost\"\n size=\"icon\"\n onClick={() => {\n onMoveBackward();\n setMoreMenuOpen(false);\n }}\n aria-label=\"Move Backward\"\n >\n <Icon icon=\"hugeicons:layer-send-backward\" className=\"sc:size-5\" />\n </Button>\n </TooltipTrigger>\n <TooltipContent>Move Backward</TooltipContent>\n </Tooltip>\n )}\n {onDelete && (\n <Tooltip delayDuration={300}>\n <TooltipTrigger asChild>\n <Button\n variant=\"ghost\"\n size=\"icon\"\n onClick={() => {\n setMoreMenuOpen(false);\n onDelete();\n }}\n aria-label=\"Delete\"\n >\n <Icon icon={icons.trash} className=\"sc:size-5\" />\n </Button>\n </TooltipTrigger>\n <TooltipContent>Delete</TooltipContent>\n </Tooltip>\n )}\n </div>\n </PopoverContent>\n </Popover>\n )}\n\n {/* Ungroup button - shown when editing a child in a group */}\n {showUngroupButton && onUngroup && (\n <Tooltip delay={300}>\n <TooltipTrigger asChild>\n <Button variant=\"ghost\" size=\"sm\" onClick={onUngroup}>\n Ungroup\n </Button>\n </TooltipTrigger>\n <TooltipContent>Ungroup this group</TooltipContent>\n </Tooltip>\n )}\n </div>\n );\n};\n\nexport default ShapeToolbar;\n","/**\n * PathToolbar - Toolbar for path-specific controls\n * Handles stroke color, width, fill properties, and path editing\n */\n\nimport React, { useState } from 'react';\nimport { Icon } from '@iconify/react';\nimport { Button, Popover, PopoverTrigger, PopoverContent, Slider, Tooltip, TooltipTrigger, TooltipContent, Label } from './ui';\nimport { PathElement } from '../core/PathElement';\nimport { ARTBOARD_COLORS } from '../presets/artboard-color-presets.js';\n\ninterface PathToolbarProps {\n element: PathElement;\n onElementUpdate: (element: PathElement) => void;\n onMoveForward?: () => void;\n onMoveBackward?: () => void;\n}\n\nconst PathToolbar: React.FC<PathToolbarProps> = ({ element, onElementUpdate, onMoveForward, onMoveBackward }) => {\n const [strokeColorOpen, setStrokeColorOpen] = useState<boolean>(false);\n const [fillColorOpen, setFillColorOpen] = useState<boolean>(false);\n const [strokeWidthOpen, setStrokeWidthOpen] = useState<boolean>(false);\n\n const handleStrokeColorChange = (color: string) => {\n const updatedElement = element.clone();\n updatedElement.transformData.strokeColor = color;\n onElementUpdate(updatedElement);\n setStrokeColorOpen(false);\n };\n\n const handleFillColorChange = (color: string) => {\n const updatedElement = element.clone();\n updatedElement.transformData.fillColor = color;\n onElementUpdate(updatedElement);\n setFillColorOpen(false);\n };\n\n const handleStrokeEnabledToggle = () => {\n const updatedElement = element.clone();\n updatedElement.transformData.strokeEnabled = !updatedElement.transformData.strokeEnabled;\n onElementUpdate(updatedElement);\n };\n\n const handleFillEnabledToggle = () => {\n const updatedElement = element.clone();\n updatedElement.transformData.fillEnabled = !updatedElement.transformData.fillEnabled;\n onElementUpdate(updatedElement);\n };\n\n const handleStrokeWidthChange = (value: number) => {\n const updatedElement = element.clone();\n updatedElement.transformData.strokeWidth = value;\n onElementUpdate(updatedElement);\n };\n\n const strokeColor = element.transformData.strokeColor || '#000000';\n const fillColor = element.transformData.fillColor || '#3b82f6';\n const strokeEnabled = element.transformData.strokeEnabled ?? true;\n const fillEnabled = element.transformData.fillEnabled ?? false;\n const strokeWidth = element.transformData.strokeWidth ?? 2;\n const isClosed = element.transformData.closed;\n const pointCount = element.transformData.points.length;\n\n return (\n <div className=\"sc:fixed sc:top-3xl sc:left-1/2 sc:-translate-x-1/2 sc:flex sc:items-center sc:gap-md sc:px-xl sc:py-md sc:bg-bg-primary sc:rounded-xl sc:shadow-md\" style={{ zIndex: 'var(--sc-z-dropdown)' }}>\n {/* Path Info */}\n <div className=\"sc:px-xl sc:text-base sc:text-text-muted sc:border-r sc:border-border-primary\">\n <span className=\"sc:font-semibold\">Path</span>\n <span className=\"sc:ml-md sc:text-text-placeholder\">\n {pointCount} {pointCount === 1 ? 'point' : 'points'}\n {isClosed && ' • Closed'}\n </span>\n </div>\n\n {/* Stroke Enabled Toggle */}\n <Tooltip delay={300}>\n <TooltipTrigger asChild>\n <Button\n variant={strokeEnabled ? 'default' : 'ghost'}\n onClick={handleStrokeEnabledToggle}\n className=\"sc:px-xl sc:text-base\"\n >\n Stroke\n </Button>\n </TooltipTrigger>\n <TooltipContent>{strokeEnabled ? 'Disable Stroke' : 'Enable Stroke'}</TooltipContent>\n </Tooltip>\n\n {/* Stroke Color Picker */}\n {strokeEnabled && (\n <Popover open={strokeColorOpen} onOpenChange={setStrokeColorOpen}>\n <PopoverTrigger asChild>\n <button\n className=\"sc:w-8 sc:h-8 sc:p-xs sc:rounded-md sc:border-2 sc:border-border-primary sc:cursor-pointer sc:transition-transform sc:hover:scale-105\"\n style={{ background: strokeColor }}\n title=\"Stroke Color\"\n />\n </PopoverTrigger>\n <PopoverContent align=\"start\" className=\"sc:p-0\">\n <div className=\"sc:bg-bg-primary sc:rounded-xl sc:shadow-lg sc:p-6 sc:min-w-[240px]\">\n <div className=\"sc:grid sc:grid-cols-6 sc:gap-sm sc:mb-md\">\n {ARTBOARD_COLORS.map((color) => (\n <Button\n key={color.color}\n onClick={() => handleStrokeColorChange(color.color)}\n aria-label={color.name}\n className={`sc:w-8 sc:h-8 sc:rounded-md sc:cursor-pointer sc:transition-all sc:min-h-0 sc:min-w-0 sc:p-0 ${\n strokeColor === color.color\n ? 'sc:border-2 sc:border-accent-primary sc:scale-110'\n : 'sc:border sc:border-border-primary sc:hover:scale-105'\n }`}\n style={{ background: color.color }}\n />\n ))}\n </div>\n <input\n type=\"color\"\n value={strokeColor}\n onChange={(e) => handleStrokeColorChange(e.target.value)}\n className=\"sc:w-full sc:h-8 sc:cursor-pointer sc:rounded-md sc:border sc:border-border-primary\"\n />\n </div>\n </PopoverContent>\n </Popover>\n )}\n\n {/* Stroke Width */}\n {strokeEnabled && (\n <Popover open={strokeWidthOpen} onOpenChange={setStrokeWidthOpen}>\n <PopoverTrigger asChild>\n <Button variant=\"ghost\" className=\"sc:px-xl sc:text-base\">\n {strokeWidth}px\n </Button>\n </PopoverTrigger>\n <PopoverContent align=\"start\" className=\"sc:p-0\">\n <div className=\"sc:bg-bg-primary sc:rounded-xl sc:shadow-lg sc:p-6 sc:min-w-[200px]\">\n <Slider\n value={[strokeWidth]}\n onValueChange={(val) => handleStrokeWidthChange(val[0])}\n min={1}\n max={20}\n step={0.5}\n className=\"slider-no-fill sc:w-full\"\n >\n <Label>Width (px)</Label>\n <Slider.Output />\n <Slider.Track />\n <Slider.Thumb />\n </Slider>\n </div>\n </PopoverContent>\n </Popover>\n )}\n\n <div className=\"sc:w-px sc:h-6 sc:bg-border-primary sc:mx-xs\" />\n\n {/* Fill Enabled Toggle */}\n <Tooltip delay={300}>\n <TooltipTrigger asChild>\n <Button\n variant={fillEnabled ? 'default' : 'ghost'}\n onClick={handleFillEnabledToggle}\n className=\"sc:px-xl sc:text-base\"\n >\n Fill\n </Button>\n </TooltipTrigger>\n <TooltipContent>{fillEnabled ? 'Disable Fill' : 'Enable Fill'}</TooltipContent>\n </Tooltip>\n\n {/* Fill Color Picker */}\n {fillEnabled && (\n <Popover open={fillColorOpen} onOpenChange={setFillColorOpen}>\n <PopoverTrigger asChild>\n <button\n className=\"sc:w-8 sc:h-8 sc:p-xs sc:rounded-md sc:border-2 sc:border-border-primary sc:cursor-pointer sc:transition-transform sc:hover:scale-105\"\n style={{ background: fillColor }}\n title=\"Fill Color\"\n />\n </PopoverTrigger>\n <PopoverContent align=\"start\" className=\"sc:p-0\">\n <div className=\"sc:bg-bg-primary sc:rounded-xl sc:shadow-lg sc:p-6 sc:min-w-[240px]\">\n <div className=\"sc:grid sc:grid-cols-6 sc:gap-sm sc:mb-md\">\n {ARTBOARD_COLORS.map((color) => (\n <Button\n key={color.color}\n onClick={() => handleFillColorChange(color.color)}\n aria-label={color.name}\n className={`sc:w-8 sc:h-8 sc:rounded-md sc:cursor-pointer sc:transition-all sc:min-h-0 sc:min-w-0 sc:p-0 ${\n fillColor === color.color\n ? 'sc:border-2 sc:border-accent-primary sc:scale-110'\n : 'sc:border sc:border-border-primary sc:hover:scale-105'\n }`}\n style={{ background: color.color }}\n />\n ))}\n </div>\n <input\n type=\"color\"\n value={fillColor}\n onChange={(e) => handleFillColorChange(e.target.value)}\n className=\"sc:w-full sc:h-8 sc:cursor-pointer sc:rounded-md sc:border sc:border-border-primary\"\n />\n </div>\n </PopoverContent>\n </Popover>\n )}\n\n <div className=\"sc:w-px sc:h-6 sc:bg-border-primary sc:mx-xs\" />\n\n {/* Layer Order Controls */}\n {onMoveForward && (\n <Tooltip delay={300}>\n <TooltipTrigger asChild>\n <Button variant=\"ghost\" onClick={onMoveForward}>\n <Icon icon=\"hugeicons:layer-bring-forward\" className=\"sc:size-[18px]\" />\n </Button>\n </TooltipTrigger>\n <TooltipContent>Move Forward</TooltipContent>\n </Tooltip>\n )}\n\n {onMoveBackward && (\n <Tooltip delay={300}>\n <TooltipTrigger asChild>\n <Button variant=\"ghost\" onClick={onMoveBackward}>\n <Icon icon=\"hugeicons:layer-send-backward\" className=\"sc:size-[18px]\" />\n </Button>\n </TooltipTrigger>\n <TooltipContent>Move Backward</TooltipContent>\n </Tooltip>\n )}\n </div>\n );\n};\n\nexport default PathToolbar;\n","/**\n * BackgroundPickerDropdown - Unified picker for artboard backgrounds\n * Supports color, texture, and gradient (future) backgrounds\n */\n\nimport { useState, useEffect, memo } from 'react';\nimport { HexColorPicker } from 'react-colorful';\nimport { Button, Popover, PopoverTrigger, PopoverContent, icons } from './ui';\nimport { Icon } from '@iconify/react';\nimport { TextureManager } from '../utils/TextureManager';\nimport type { ArtboardBackgroundType } from '../types/index';\n\nexport interface BackgroundPickerDropdownProps {\n backgroundType: ArtboardBackgroundType;\n backgroundColor: string;\n backgroundTexture?: string;\n onBackgroundTypeChange: (type: ArtboardBackgroundType) => void;\n onColorChange: (color: string) => void;\n onTextureChange: (textureId: string) => void;\n}\n\ntype BackgroundTab = 'color' | 'texture' | 'gradient';\n\nconst BackgroundPickerDropdown = memo(({\n backgroundType,\n backgroundColor,\n backgroundTexture,\n onBackgroundTypeChange,\n onColorChange,\n onTextureChange,\n}: BackgroundPickerDropdownProps) => {\n const [isOpen, setIsOpen] = useState(false);\n const [activeTab, setActiveTab] = useState<BackgroundTab>('color');\n const [hexInput, setHexInput] = useState(backgroundColor);\n\n // Sync active tab with background type\n useEffect(() => {\n if (backgroundType === 'texture') {\n setActiveTab('texture');\n } else {\n setActiveTab('color');\n }\n }, [backgroundType]);\n\n // Sync hex input with color prop\n useEffect(() => {\n if (backgroundColor !== 'transparent') {\n setHexInput(backgroundColor);\n }\n }, [backgroundColor]);\n\n const handleColorChange = (color: string) => {\n setHexInput(color);\n onColorChange(color);\n onBackgroundTypeChange('color');\n };\n\n const handleHexInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {\n const input = e.target.value;\n setHexInput(input);\n\n // Validate hex color (with or without #)\n const hexPattern = /^#?([0-9A-Fa-f]{6}|[0-9A-Fa-f]{3})$/;\n const withHash = input.startsWith('#') ? input : `#${input}`;\n\n if (hexPattern.test(withHash)) {\n onColorChange(withHash);\n onBackgroundTypeChange('color');\n }\n };\n\n const handleTransparentClick = () => {\n onColorChange('transparent');\n onBackgroundTypeChange('transparent');\n };\n\n const handleTextureClick = (textureId: string) => {\n onTextureChange(textureId);\n onBackgroundTypeChange('texture');\n };\n\n const handleTabChange = (tab: BackgroundTab) => {\n setActiveTab(tab);\n if (tab === 'color') {\n onBackgroundTypeChange(backgroundColor === 'transparent' ? 'transparent' : 'color');\n } else if (tab === 'texture') {\n if (!backgroundTexture) {\n // Set default texture if none is set\n const defaultTexture = TextureManager.getAllTextures()[0];\n if (defaultTexture) {\n onTextureChange(defaultTexture.id);\n }\n }\n onBackgroundTypeChange('texture');\n }\n };\n\n const isTransparent = backgroundColor === 'transparent';\n\n return (\n <Popover open={isOpen} onOpenChange={setIsOpen}>\n <PopoverTrigger asChild>\n <Button variant={isOpen ? 'default' : 'ghost'} aria-label=\"Background\">\n <Icon icon={icons.palette} className=\"sc:size-[18px]\" />\n </Button>\n </PopoverTrigger>\n <PopoverContent className=\"sc:w-auto sc:p-3\">\n <div className=\"sc:flex sc:min-w-[220px] sc:flex-col sc:gap-3\">\n {/* Tab selector */}\n <div className=\"sc:flex sc:gap-1 sc:border-b sc:border-divider sc:pb-3\">\n <Button\n variant=\"ghost\"\n size=\"sm\"\n className={`sc:flex-1 ${activeTab === 'color' ? 'sc:bg-primary sc:text-primary-foreground' : ''}`}\n onClick={() => handleTabChange('color')}\n >\n Color\n </Button>\n <Button\n variant=\"ghost\"\n size=\"sm\"\n className={`sc:flex-1 ${activeTab === 'texture' ? 'sc:bg-primary sc:text-primary-foreground' : ''}`}\n onClick={() => handleTabChange('texture')}\n >\n Texture\n </Button>\n <Button\n variant=\"ghost\"\n size=\"sm\"\n className=\"sc:flex-1 sc:cursor-not-allowed sc:opacity-50\"\n disabled\n aria-label=\"Gradient (Coming soon)\"\n >\n Gradient\n </Button>\n </div>\n\n {/* Color picker panel */}\n {activeTab === 'color' && (\n <div className=\"sc:flex sc:flex-col sc:gap-3\">\n <Button\n variant=\"ghost\"\n className={`sc:flex sc:w-full sc:cursor-pointer sc:items-center sc:justify-start sc:gap-2 sc:rounded-lg ${isTransparent ? 'sc:bg-primary/10' : ''}`}\n onClick={handleTransparentClick}\n >\n <div className=\"transparent-pattern-small sc:h-6 sc:w-6 sc:rounded\" />\n <span className=\"sc:text-sm sc:font-medium\">Transparent</span>\n </Button>\n\n <HexColorPicker color={isTransparent ? '#ffffff' : backgroundColor} onChange={handleColorChange} />\n\n <div className=\"sc:flex sc:items-center sc:gap-2\">\n <label htmlFor=\"bg-hex-input\" className=\"sc:text-sm sc:font-medium sc:uppercase sc:text-foreground/60\">\n HEX\n </label>\n <input\n id=\"bg-hex-input\"\n type=\"text\"\n className=\"sc:flex-1 sc:rounded-lg sc:border sc:border-divider sc:bg-field sc:px-2 sc:py-1.5 sc:text-sm sc:text-foreground sc:focus:border-primary sc:focus:outline-none\"\n value={hexInput}\n onChange={handleHexInputChange}\n placeholder=\"#000000\"\n maxLength={7}\n />\n </div>\n </div>\n )}\n\n {/* Texture picker panel */}\n {activeTab === 'texture' && (\n <div className=\"sc:flex sc:flex-col sc:gap-3\">\n <div className=\"sc:text-sm sc:font-medium sc:text-foreground/60\">Select a texture</div>\n <div className=\"sc:grid sc:grid-cols-4 sc:gap-1.5\">\n {TextureManager.getAllTextures().map((texture) => (\n <button\n key={texture.id}\n className={`sc:flex sc:items-center sc:justify-center sc:p-1 sc:rounded-lg sc:cursor-pointer sc:transition-all sc:border-2 ${\n backgroundTexture === texture.id\n ? 'sc:border-primary'\n : 'sc:border-transparent sc:hover:border-primary/50'\n }`}\n onClick={() => handleTextureClick(texture.id)}\n aria-label={texture.name}\n >\n <img src={texture.url} alt={texture.name} className=\"sc:w-full sc:h-full sc:rounded\" />\n </button>\n ))}\n </div>\n </div>\n )}\n\n {/* Gradient picker panel (future) */}\n {activeTab === 'gradient' && (\n <div className=\"sc:flex sc:flex-col sc:items-center sc:justify-center sc:gap-3 sc:py-8 sc:text-foreground/60\">\n <div className=\"sc:text-sm\">Gradient backgrounds</div>\n <div className=\"sc:text-xs\">Coming soon</div>\n </div>\n )}\n </div>\n </PopoverContent>\n </Popover>\n );\n});\n\nBackgroundPickerDropdown.displayName = 'BackgroundPickerDropdown';\n\nexport default BackgroundPickerDropdown;\n","/**\n * ArtboardDistressPanel - UI panel for artboard-level distress texture\n *\n * Allows applying a grayscale texture as an alpha mask over all elements\n * on the artboard. Dark areas knock out pixels, light areas preserve them.\n */\n\nimport React, { useCallback } from 'react';\nimport type { ArtboardDistressTexture } from '../types/index.js';\nimport { DISTRESS_TEXTURE_PRESETS, ensureBuiltinTexturesReady } from '../effects/distress-textures.js';\nimport { preloadTexture } from '../effects/DistressTextureCache.js';\nimport {\n Disclosure,\n DisclosureTrigger,\n DisclosureContent,\n Switch,\n Label,\n SliderRow,\n PresetCarousel,\n} from './ui';\nimport type { PresetItem } from './ui';\n\ninterface ArtboardDistressPanelProps {\n distressTexture?: ArtboardDistressTexture;\n onChange: (distressTexture: ArtboardDistressTexture | undefined) => void;\n}\n\nconst ArtboardDistressPanel = ({ distressTexture, onChange }: ArtboardDistressPanelProps) => {\n ensureBuiltinTexturesReady();\n\n const enabled = distressTexture?.enabled || false;\n const textureUrl = distressTexture?.textureUrl || '';\n const intensity = distressTexture?.intensity ?? 50;\n\n const presetItems: PresetItem[] = DISTRESS_TEXTURE_PRESETS.map((p) => ({ id: p.textureUrl, name: p.name, thumbnailUrl: p.thumbnailUrl }));\n\n const handleEnabledChange = (newEnabled: boolean) => {\n if (newEnabled) {\n const url = textureUrl || DISTRESS_TEXTURE_PRESETS[0].textureUrl;\n preloadTexture(url);\n onChange({\n enabled: true,\n textureUrl: url,\n intensity,\n });\n } else {\n onChange(undefined);\n }\n };\n\n const handleTextureSelect = useCallback(\n (id: string) => {\n preloadTexture(id);\n onChange({\n enabled: true,\n textureUrl: id,\n intensity,\n });\n },\n [onChange, intensity]\n );\n\n const handleIntensityChange = (value: number[]) => {\n if (!distressTexture) return;\n onChange({\n ...distressTexture,\n intensity: value[0],\n });\n };\n\n return (\n <Disclosure open={enabled} onOpenChange={handleEnabledChange} className=\"sc:mb-xl\">\n <DisclosureTrigger className=\"sc:w-full\">\n <div className=\"sc:flex sc:items-center sc:justify-between sc:w-full\">\n <Label>Distress Texture</Label>\n <Switch\n checked={enabled}\n onCheckedChange={handleEnabledChange}\n onClick={(e: React.MouseEvent) => e.stopPropagation()}\n />\n </div>\n </DisclosureTrigger>\n <DisclosureContent className=\"sc:flex sc:flex-col sc:gap-lg sc:py-lg\">\n <PresetCarousel\n presets={presetItems}\n selectedId={textureUrl}\n onSelect={handleTextureSelect}\n showOff={false}\n ariaLabel=\"Distress texture presets\"\n />\n\n {/* Intensity slider */}\n <SliderRow\n label=\"Intensity\"\n value={intensity}\n onChange={(v) => handleIntensityChange([v])}\n min={0}\n max={100}\n step={1}\n unit=\"%\"\n />\n </DisclosureContent>\n </Disclosure>\n );\n};\n\nexport default ArtboardDistressPanel;\n","/**\n * ArtboardImageMaskPanel - UI panel for artboard-level image mask\n *\n * Allows applying an image mask over all elements on the artboard.\n * Supports clip, alpha, and luma mask types with inversion and opacity.\n */\n\nimport React, { useCallback } from 'react';\nimport type { ArtboardImageMask } from '../types/index.js';\nimport { MASK_IMAGE_PRESETS, ensureMaskPresetsReady } from '../effects/mask-presets.js';\nimport {\n Disclosure,\n DisclosureTrigger,\n DisclosureContent,\n Switch,\n Label,\n SliderRow,\n Checkbox,\n PresetCarousel,\n} from './ui';\nimport type { PresetItem } from './ui';\n\ninterface ArtboardImageMaskPanelProps {\n imageMask?: ArtboardImageMask;\n onChange: (imageMask: ArtboardImageMask | undefined) => void;\n}\n\nconst ArtboardImageMaskPanel = ({ imageMask, onChange }: ArtboardImageMaskPanelProps) => {\n ensureMaskPresetsReady();\n\n const enabled = imageMask?.enabled || false;\n const imageUrl = imageMask?.imageUrl || '';\n const maskType = imageMask?.maskType || 'clip';\n const opacity = imageMask?.opacity ?? 100;\n const inverted = imageMask?.inverted ?? false;\n\n const presetItems: PresetItem[] = MASK_IMAGE_PRESETS.map((p) => ({ id: p.imageUrl, name: p.name, thumbnailUrl: p.thumbnailUrl }));\n\n const handleEnabledChange = (newEnabled: boolean) => {\n if (newEnabled) {\n const url = imageUrl || MASK_IMAGE_PRESETS[0].imageUrl;\n onChange({\n enabled: true,\n imageUrl: url,\n maskType,\n opacity,\n inverted,\n });\n } else {\n onChange(undefined);\n }\n };\n\n const handleImageSelect = useCallback(\n (id: string) => {\n onChange({\n enabled: true,\n imageUrl: id,\n maskType,\n opacity,\n inverted,\n });\n },\n [onChange, maskType, opacity, inverted]\n );\n\n const handleMaskTypeChange = (type: 'clip' | 'alpha' | 'luma') => {\n if (!imageMask) return;\n onChange({ ...imageMask, maskType: type });\n };\n\n const handleOpacityChange = (value: number[]) => {\n if (!imageMask) return;\n onChange({ ...imageMask, opacity: value[0] });\n };\n\n const handleInvertedChange = (checked: boolean) => {\n if (!imageMask) return;\n onChange({ ...imageMask, inverted: checked });\n };\n\n return (\n <Disclosure open={enabled} onOpenChange={handleEnabledChange} className=\"sc:mb-xl\">\n <DisclosureTrigger className=\"sc:w-full\">\n <div className=\"sc:flex sc:items-center sc:justify-between sc:w-full\">\n <Label>Image Mask</Label>\n <Switch\n checked={enabled}\n onCheckedChange={handleEnabledChange}\n onClick={(e: React.MouseEvent) => e.stopPropagation()}\n />\n </div>\n </DisclosureTrigger>\n <DisclosureContent className=\"sc:flex sc:flex-col sc:gap-lg sc:py-lg\">\n <PresetCarousel\n presets={presetItems}\n selectedId={imageUrl}\n onSelect={handleImageSelect}\n showOff={false}\n ariaLabel=\"Image mask presets\"\n />\n\n {/* Mask type selector */}\n <div className=\"sc:flex sc:items-center sc:gap-2\">\n <Label className=\"sc:text-sm\">Type</Label>\n <div className=\"sc:flex sc:rounded-md sc:border sc:border-divider sc:overflow-hidden\">\n {(['clip', 'alpha', 'luma'] as const).map((type) => (\n <button\n key={type}\n className={`sc:px-3 sc:py-1 sc:text-xs sc:capitalize sc:transition-colors ${\n maskType === type\n ? 'sc:bg-primary sc:text-primary-foreground'\n : 'sc:text-foreground sc:hover:bg-muted'\n }`}\n onClick={() => handleMaskTypeChange(type)}\n >\n {type}\n </button>\n ))}\n </div>\n </div>\n\n {/* Opacity slider */}\n <SliderRow\n label=\"Opacity\"\n value={opacity}\n onChange={(v) => handleOpacityChange([v])}\n min={0}\n max={100}\n step={1}\n unit=\"%\"\n />\n\n {/* Inverted checkbox */}\n <label className=\"sc:flex sc:items-center sc:gap-2 sc:text-sm sc:text-foreground\">\n <Checkbox checked={inverted} onCheckedChange={(v) => handleInvertedChange(v === true)} />\n Invert Mask\n </label>\n </DisclosureContent>\n </Disclosure>\n );\n};\n\nexport default ArtboardImageMaskPanel;\n","/**\n * ArtboardPropertiesToolbar - Contextual toolbar for editing artboard properties\n * Shows when an artboard is selected (instead of an element)\n */\n\nimport React, { useState, useRef, useEffect } from 'react';\nimport { Icon } from '@iconify/react';\nimport { Button, Switch, Popover, PopoverTrigger, PopoverContent, Label, Tooltip, TooltipTrigger, TooltipContent, Surface, Separator, icons } from './ui';\nimport { ArtboardElement } from '../core/ArtboardElement';\nimport BackgroundPickerDropdown from './BackgroundPickerDropdown';\nimport ArtboardDistressPanel from './ArtboardDistressPanel';\nimport ArtboardImageMaskPanel from './ArtboardImageMaskPanel';\nimport type { ArtboardBackgroundType, ArtboardDistressTexture, ArtboardImageMask } from '../types/index';\n\ninterface ArtboardPropertiesToolbarProps {\n artboard: ArtboardElement;\n artboards: ArtboardElement[];\n onArtboardUpdate: (artboard: ArtboardElement) => void;\n onRenameArtboard: (artboardId: string, newName: string) => void;\n onDeleteArtboard: (artboardId: string) => void;\n artboardScreenBounds?: {\n left: number;\n top: number;\n width: number;\n height: number;\n bottom: number;\n centerX: number;\n };\n}\n\nconst ArtboardPropertiesToolbar: React.FC<ArtboardPropertiesToolbarProps> = ({\n artboard,\n artboards,\n onArtboardUpdate,\n onRenameArtboard,\n onDeleteArtboard,\n artboardScreenBounds,\n}) => {\n const [isEditing, setIsEditing] = useState(false);\n const [editingName, setEditingName] = useState('');\n const [moreMenuOpen, setMoreMenuOpen] = useState(false);\n const inputRef = useRef<HTMLInputElement>(null);\n\n const handleBackgroundTypeChange = (type: ArtboardBackgroundType) => {\n const updatedArtboard = artboard.clone();\n updatedArtboard.backgroundType = type;\n onArtboardUpdate(updatedArtboard);\n };\n\n const handleColorChange = (color: string) => {\n const updatedArtboard = artboard.clone();\n updatedArtboard.backgroundColor = color;\n onArtboardUpdate(updatedArtboard);\n };\n\n const handleTextureChange = (textureId: string) => {\n const updatedArtboard = artboard.clone();\n updatedArtboard.backgroundTexture = textureId;\n onArtboardUpdate(updatedArtboard);\n };\n\n const handleExportBackgroundToggle = (checked: boolean) => {\n const updatedArtboard = artboard.clone();\n updatedArtboard.exportBackground = checked;\n onArtboardUpdate(updatedArtboard);\n };\n\n const handleDistressTextureChange = (distressTexture: ArtboardDistressTexture | undefined) => {\n const updatedArtboard = artboard.clone();\n updatedArtboard.distressTexture = distressTexture;\n onArtboardUpdate(updatedArtboard);\n };\n\n const handleImageMaskChange = (imageMask: ArtboardImageMask | undefined) => {\n const updatedArtboard = artboard.clone();\n updatedArtboard.imageMask = imageMask;\n onArtboardUpdate(updatedArtboard);\n };\n\n const handleStartEdit = () => {\n setIsEditing(true);\n setEditingName(artboard.name);\n };\n\n const handleSaveEdit = () => {\n if (editingName.trim()) {\n onRenameArtboard(artboard.id, editingName.trim());\n }\n setIsEditing(false);\n setEditingName('');\n };\n\n const handleCancelEdit = () => {\n setIsEditing(false);\n setEditingName('');\n };\n\n const handleKeyDown = (e: React.KeyboardEvent) => {\n if (e.key === 'Enter') {\n handleSaveEdit();\n } else if (e.key === 'Escape') {\n handleCancelEdit();\n }\n };\n\n const handleDelete = () => {\n if (artboards.length <= 1) {\n alert('Cannot delete the last artboard');\n return;\n }\n\n if (artboard.getElementCount() > 0) {\n if (!confirm(`Delete \"${artboard.name}\" with ${artboard.getElementCount()} element(s)?`)) {\n return;\n }\n }\n\n onDeleteArtboard(artboard.id);\n };\n\n // Focus input when editing starts\n useEffect(() => {\n if (isEditing && inputRef.current) {\n inputRef.current.focus();\n inputRef.current.select();\n }\n }, [isEditing]);\n\n return (\n <Surface\n className=\"sc:absolute sc:px-4 sc:py-2 sc:flex sc:items-center sc:gap-2 sc:shadow-lg sc:z-50 sc:rounded-full sc:bg-bg-primary sc:border sc:border-border-primary\"\n style={{\n left: '50%',\n top: artboardScreenBounds ? `${artboardScreenBounds.top - 68}px` : '32px',\n transform: 'translateX(-50%)',\n }}\n >\n {/* Artboard name with edit/delete controls */}\n {isEditing ? (\n <div className=\"sc:flex sc:items-center sc:gap-2\">\n <input\n ref={inputRef}\n type=\"text\"\n value={editingName}\n onChange={(e) => setEditingName(e.target.value)}\n onKeyDown={handleKeyDown}\n className=\"sc:px-3 sc:py-1 sc:border sc:border-border-primary sc:rounded-lg sc:text-base sc:text-text-primary sc:bg-bg-primary sc:outline-none sc:min-w-[120px] sc:transition-colors sc:focus:border-border-focus\"\n />\n <Tooltip delay={300}>\n <TooltipTrigger asChild>\n <Button variant=\"ghost\" onClick={handleSaveEdit} aria-label=\"Save\">\n <Icon icon={icons.check} className=\"sc:size-4\" />\n </Button>\n </TooltipTrigger>\n <TooltipContent>Save</TooltipContent>\n </Tooltip>\n <Tooltip delay={300}>\n <TooltipTrigger asChild>\n <Button variant=\"ghost\" onClick={handleCancelEdit} aria-label=\"Cancel\">\n <Icon icon={icons.close} className=\"sc:size-4\" />\n </Button>\n </TooltipTrigger>\n <TooltipContent>Cancel</TooltipContent>\n </Tooltip>\n </div>\n ) : (\n <div className=\"sc:flex sc:items-center sc:gap-2\">\n <span className=\"sc:text-xl sc:font-semibold sc:text-text-primary\">{artboard.name}</span>\n <Tooltip delay={300}>\n <TooltipTrigger asChild>\n <Button variant=\"ghost\" onClick={handleStartEdit} aria-label=\"Rename\">\n <Icon icon={icons.pencil} className=\"sc:size-4\" />\n </Button>\n </TooltipTrigger>\n <TooltipContent>Rename</TooltipContent>\n </Tooltip>\n <Tooltip delay={300}>\n <TooltipTrigger asChild>\n <Button variant=\"ghost\" onClick={handleDelete} disabled={artboards.length <= 1} aria-label=\"Delete\">\n <Icon icon={icons.trash} className=\"sc:size-4\" />\n </Button>\n </TooltipTrigger>\n <TooltipContent>Delete</TooltipContent>\n </Tooltip>\n </div>\n )}\n\n <Separator orientation=\"vertical\" className=\"sc:h-6\" />\n\n {/* Background picker */}\n <BackgroundPickerDropdown\n backgroundType={artboard.backgroundType}\n backgroundColor={artboard.backgroundColor}\n backgroundTexture={artboard.backgroundTexture}\n onBackgroundTypeChange={handleBackgroundTypeChange}\n onColorChange={handleColorChange}\n onTextureChange={handleTextureChange}\n />\n\n <Separator orientation=\"vertical\" className=\"sc:h-6\" />\n\n {/* Dimensions display */}\n <div className=\"sc:text-base sc:font-mono sc:text-text-muted sc:uppercase\">\n {Math.round(artboard.width)} × {Math.round(artboard.height)}\n </div>\n\n <Separator orientation=\"vertical\" className=\"sc:h-6\" />\n\n {/* More Menu - overflow menu for additional options */}\n <Popover open={moreMenuOpen} onOpenChange={setMoreMenuOpen}>\n <PopoverTrigger asChild>\n <Button variant={moreMenuOpen ? 'default' : 'ghost'} aria-label=\"More options\">\n <Icon icon={icons.menu} className=\"sc:size-6\" />\n </Button>\n </PopoverTrigger>\n <PopoverContent align=\"end\">\n <div className=\"sc:flex sc:flex-col sc:gap-2 sc:min-w-[240px]\">\n <div className=\"sc:flex sc:items-center sc:gap-3\">\n <Switch\n checked={artboard.exportBackground}\n onCheckedChange={handleExportBackgroundToggle}\n />\n <Label>Export Background</Label>\n </div>\n <Separator />\n <ArtboardDistressPanel\n distressTexture={artboard.distressTexture}\n onChange={handleDistressTextureChange}\n />\n <ArtboardImageMaskPanel\n imageMask={artboard.imageMask}\n onChange={handleImageMaskChange}\n />\n </div>\n </PopoverContent>\n </Popover>\n </Surface>\n );\n};\n\nexport default ArtboardPropertiesToolbar;\n","/**\n * Text utility functions\n */\n\n/**\n * Strip glyph characters from text for display purposes\n * Removes PUA (Private Use Area) characters used for alternate glyphs\n *\n * @param text - Text that may contain glyph characters\n * @returns Text with glyph characters removed\n */\nexport function stripGlyphs(text: string): string {\n // Remove PUA (Private Use Area) characters used for glyphs\n // PUA range: U+E000 to U+F8FF (standard), U+F0000 to U+FFFFD (supplementary)\n return Array.from(text)\n .filter((char) => {\n const cp = char.codePointAt(0);\n return !cp || cp < 0xf0000 || cp > 0xffffd;\n })\n .join('');\n}\n","/**\n * FontBrowserDrawer - Drawer for selecting font family with search and category filters\n * Refactored to use HeroUI design system\n */\n\nimport React, { useRef, useEffect, useState, useMemo, useSyncExternalStore } from 'react';\nimport { Icon } from '@iconify/react';\nimport { Input, Button, Tabs, Surface, Tooltip, TooltipTrigger, TooltipContent, TextField } from './ui';\nimport { Drawer } from './Drawer';\nimport { TSHIRT_FONTS, CATEGORY_LABELS, FontCategory, FontDefinition } from '../fonts/google-fonts.js';\nimport { UnifiedFontService } from '../utils/UnifiedFontService.js';\nimport {\n customFontRegistry,\n ensureCustomFontsLoaded,\n loadCustomFont,\n registerCustomFonts,\n type CustomFont,\n} from '../utils/custom-fonts.js';\nimport { useCanvasServices } from '../contexts/CanvasServicesContext.js';\nimport { isEditorError } from '../errors/editorError.js';\nimport { stripGlyphs } from '../utils/textUtils.js';\nimport { createLogger } from '../utils/logger.js';\n\nconst logger = createLogger('FontBrowserDrawer');\n\nexport interface FontBrowserDrawerProps {\n value: string;\n onChange: (event: { target: { value: string } }) => void;\n fontFamilies?: string[]; // Optional - uses TSHIRT_FONTS by default\n isOpen: boolean;\n onToggle: (open: boolean) => void;\n showLabel?: boolean;\n previewText?: string; // Text to preview in each font\n elements?: Array<Record<string, unknown>>; // Elements to extract fonts used in document\n}\n\nconst FontBrowserDrawer = ({\n value,\n onChange,\n fontFamilies: _fontFamilies,\n isOpen,\n onToggle,\n showLabel: _,\n previewText,\n elements,\n}: FontBrowserDrawerProps) => {\n const selectedFontRef = useRef<HTMLDivElement>(null);\n const [searchQuery, setSearchQuery] = useState('');\n const [selectedCategory, setSelectedCategory] = useState<FontCategory | 'all'>('all');\n const [fontsLoadedTrigger, setFontsLoadedTrigger] = useState(0); // Used to trigger re-render when fonts load\n const [displayMode, setDisplayMode] = useState<'both' | 'name' | 'preview'>('name'); // Three-way toggle: preview+name, name only, preview only\n const [cardSize, setCardSize] = useState<'small' | 'medium' | 'large'>('medium'); // Card size: small (1.0), medium (1.8), large (3.0)\n const [viewMode, setViewMode] = useState<'grid' | 'masonry'>('masonry'); // Toggle between grid and masonry layout\n const [loadedFonts, setLoadedFonts] = useState<Set<string>>(new Set()); // Track which fonts have been loaded\n const loadQueueRef = useRef<string[]>([]); // Queue of fonts to load\n const loadingRef = useRef(false); // Flag to prevent concurrent loading\n\n // === Custom (brand) fonts — \"Your fonts\" ===\n // The host-owned upload seam: `services.onFontUpload` receives the File,\n // stores it (the canvas never owns storage), and resolves { family, url }.\n // No callback → the upload affordance is NOT rendered (capability opt-in).\n const { onFontUpload } = useCanvasServices();\n const customFonts = useSyncExternalStore(\n customFontRegistry.subscribe,\n customFontRegistry.list,\n customFontRegistry.list\n );\n const fontFileInputRef = useRef<HTMLInputElement>(null);\n const [fontUploadBusy, setFontUploadBusy] = useState(false);\n const [fontUploadError, setFontUploadError] = useState<{ code?: string; message: string } | null>(\n null\n );\n\n // One picker entry per custom family (a family may register several\n // weight/style faces).\n const customFamilies = useMemo(() => {\n const seen = new Set<string>();\n const families: string[] = [];\n for (const font of customFonts) {\n const key = font.family.trim().toLowerCase();\n if (seen.has(key)) continue;\n seen.add(key);\n families.push(font.family);\n }\n return families;\n }, [customFonts]);\n\n // Families a custom font deterministically shadows out of the Google\n // sections below (see utils/custom-fonts.ts for the contract).\n const customFamilyKeys = useMemo(\n () => new Set(customFamilies.map((f) => f.trim().toLowerCase())),\n [customFamilies]\n );\n\n // Ensure registered custom fonts are activated while the drawer is open so\n // \"Your fonts\" previews render in their own face. Per-font failures stay\n // typed (E_FONT_LOAD_FAILED) and surface on the upload-error strip.\n useEffect(() => {\n if (!isOpen || customFonts.length === 0) return;\n void ensureCustomFontsLoaded(customFonts, {\n onLoadError: (error) => {\n logger.error('Custom font failed to load:', error);\n setFontUploadError({ code: error.code, message: error.message });\n },\n });\n }, [isOpen, customFonts]);\n\n const handleFontFileChange = async (e: React.ChangeEvent<HTMLInputElement>) => {\n const file = e.target.files?.[0];\n e.target.value = ''; // allow re-selecting the same file\n if (!file || !onFontUpload) return;\n\n setFontUploadBusy(true);\n setFontUploadError(null);\n try {\n const uploaded = await onFontUpload(file);\n const font: CustomFont = {\n family: uploaded.family,\n url: uploaded.url,\n ...(uploaded.weight !== undefined && { weight: uploaded.weight }),\n ...(uploaded.style !== undefined && { style: uploaded.style }),\n };\n // Load BEFORE registering: a font that can't load never enters the\n // design state (the wrong state stays unrepresentable). Throws the\n // typed E_FONT_LOAD_FAILED on a bad URL — no silent serif fallback.\n await loadCustomFont(font);\n registerCustomFonts([font]);\n // Immediately usable + selected.\n onChange({ target: { value: font.family } });\n setTimeout(() => onToggle(false), 0);\n } catch (error) {\n logger.error('Font upload failed:', error);\n setFontUploadError({\n code: isEditorError(error) ? error.code : undefined,\n message: error instanceof Error ? error.message : String(error),\n });\n } finally {\n setFontUploadBusy(false);\n }\n };\n\n const handleSelectCustom = (family: string) => {\n // Custom fonts never touch UnifiedFontService (no Google source may be\n // injected for a custom family) — the face is already activated by the\n // ensure effect above / the upload flow.\n onChange({ target: { value: family } });\n setTimeout(() => onToggle(false), 0);\n };\n\n // Convert size name to numeric scale value\n const getCardSizeScale = (size: 'small' | 'medium' | 'large'): number => {\n switch (size) {\n case 'small':\n return 1.0;\n case 'medium':\n return 1.8;\n case 'large':\n return 3.0;\n }\n };\n\n const cardSizeScale = getCardSizeScale(cardSize);\n\n // Inject font-preview CSS rule to ensure it overrides body font-family\n useEffect(() => {\n const styleId = 'font-preview-style';\n if (!document.getElementById(styleId)) {\n const style = document.createElement('style');\n style.id = styleId;\n style.textContent = '.font-preview { font-family: var(--font-preview) !important; }';\n document.head.appendChild(style);\n }\n }, []);\n\n // Fetch all fonts on mount\n useEffect(() => {\n if (!UnifiedFontService.isFontsLoaded()) {\n UnifiedFontService.initialize()\n .then(() => {\n setFontsLoadedTrigger((prev) => prev + 1); // Trigger re-render\n })\n .catch((error) => {\n logger.error('Failed to load fonts:', error);\n });\n }\n }, []);\n\n // Function to dynamically load a font for preview\n // Uses text= parameter to load only required glyphs (~99.9% smaller than full font)\n const loadFont = async (font: FontDefinition, forSelection: boolean = false) => {\n try {\n if (forSelection) {\n // Loading for actual selection - load full font\n await UnifiedFontService.loadFont(font);\n } else if (font.googleFont) {\n // Google Font preview - load only characters needed for preview text AND font name\n // This prevents iOS Safari memory crashes from loading full fonts\n // We need both: the preview text to display, and the font name for the label\n const textToLoad = previewText ? `${previewText}${font.name}` : font.name;\n UnifiedFontService.loadGoogleFontForPreview(font.name, textToLoad);\n } else {\n // System font - use regular loading\n await UnifiedFontService.loadFont(font);\n }\n // Update state immediately (no batching) to prevent accumulating 50+ fonts in one render\n setLoadedFonts((prev) => new Set(prev).add(font.name));\n } catch (error) {\n logger.error(`Failed to load font ${font.name}:`, error);\n }\n };\n\n // Load all queued fonts concurrently (no delays)\n useEffect(() => {\n const processQueue = async () => {\n if (loadingRef.current || loadQueueRef.current.length === 0) return;\n\n loadingRef.current = true;\n\n // Take all queued fonts and load them concurrently\n const fontsToLoad = [...loadQueueRef.current];\n loadQueueRef.current = [];\n\n const allFonts = UnifiedFontService.getAllFonts();\n\n // Load all fonts at once\n await Promise.all(\n fontsToLoad.map(async (fontName) => {\n const font = allFonts.find((f) => f.name === fontName);\n if (font && !loadedFonts.has(fontName)) {\n await loadFont(font);\n }\n })\n );\n\n loadingRef.current = false;\n };\n\n processQueue();\n }, [loadedFonts]);\n\n // Add font to load queue (called when font comes into view)\n const queueFontLoad = (fontName: string) => {\n // Check if already loaded or queued to avoid duplicates\n const alreadyLoaded = loadedFonts.has(fontName);\n const alreadyQueued = loadQueueRef.current.includes(fontName);\n\n if (!alreadyLoaded && !alreadyQueued) {\n loadQueueRef.current.push(fontName);\n // Trigger queue processing immediately if not already running\n if (!loadingRef.current && loadQueueRef.current.length === 1) {\n setLoadedFonts((prev) => new Set(prev)); // Trigger useEffect\n }\n }\n };\n\n // Focus search input when drawer opens\n useEffect(() => {\n if (isOpen) {\n // Scroll to selected font\n setTimeout(() => {\n if (selectedFontRef.current) {\n selectedFontRef.current.scrollIntoView({ behavior: 'smooth', block: 'center' });\n }\n }, 150);\n }\n // Reset filters and clear preview fonts when closing\n if (!isOpen) {\n setSearchQuery('');\n setSelectedCategory('all');\n // Clear preview font links from DOM to free memory (prevents iOS Safari crashes)\n UnifiedFontService.clearPreviewFonts();\n // Reset loaded fonts set so previews will load fresh next time\n setLoadedFonts(new Set());\n }\n }, [isOpen, value]);\n\n // Load the currently selected font so it displays correctly in the toolbar button\n // This needs to be the full font since it's actively being used\n useEffect(() => {\n if (value && !loadedFonts.has(value)) {\n const allFonts = UnifiedFontService.getAllFonts();\n const font = allFonts.find((f) => f.name === value);\n if (font) {\n loadFont(font, true); // forSelection=true to load full font\n }\n }\n }, [value, loadedFonts, fontsLoadedTrigger]);\n\n // When user starts searching, reset category to all\n useEffect(() => {\n if (searchQuery.trim()) {\n setSelectedCategory('all');\n }\n }, [searchQuery]);\n\n const handleSelect = async (family: string) => {\n // Load full font on selection (preview only loaded subset characters)\n const allFonts = UnifiedFontService.getAllFonts();\n const selectedFont = allFonts.find((f) => f.name === family);\n if (selectedFont) {\n try {\n // Load full font for actual use (forSelection=true)\n await loadFont(selectedFont, true);\n } catch (error) {\n logger.warn(`Failed to load font ${family}, will use fallback`);\n }\n }\n\n onChange({ target: { value: family } });\n // Small delay to allow tooltip to close properly before drawer closes\n setTimeout(() => onToggle(false), 0);\n };\n\n // Font Item Component - Memoized to prevent unnecessary re-renders\n const FontItem = React.memo(\n ({ font, isUsedInDocument = false }: { font: FontDefinition; isUsedInDocument?: boolean }) => {\n const fontItemRef = useRef<HTMLDivElement>(null);\n const isSelected = value === font.name;\n const isLoaded = loadedFonts.has(font.name);\n\n // Lazy load fonts when they come into view\n useEffect(() => {\n if (!fontItemRef.current) return;\n\n const observer = new IntersectionObserver(\n (entries) => {\n entries.forEach((entry) => {\n if (entry.isIntersecting && !isLoaded) {\n queueFontLoad(font.name);\n }\n });\n },\n { rootMargin: '600px' } // Load fonts before they come into view for smoother scrolling\n );\n\n observer.observe(fontItemRef.current);\n\n return () => observer.disconnect();\n }, [font.name, isLoaded]);\n\n // Determine what text to display based on mode\n let mainText = '';\n let showSecondaryLabel = false;\n\n if (displayMode === 'name') {\n mainText = font.name;\n showSecondaryLabel = false;\n } else if (displayMode === 'preview') {\n mainText = previewText || font.name;\n // Only show font name underneath in \"Used in Document\" section\n showSecondaryLabel = isUsedInDocument;\n } else {\n // displayMode === 'both'\n mainText = previewText || font.name;\n showSecondaryLabel = true;\n }\n\n // Check if we should show a tooltip (when displaying user text and not showing secondary label)\n const shouldShowTooltip = displayMode === 'preview' && !showSecondaryLabel;\n\n const surfaceContent = (\n <Surface\n ref={(el) => {\n // Assign to both refs: selectedFontRef for scrolling, fontItemRef for intersection observer\n if (isSelected && selectedFontRef) {\n selectedFontRef.current = el;\n }\n fontItemRef.current = el;\n }}\n className={`sc:relative sc:flex sc:cursor-pointer sc:flex-col sc:justify-center sc:rounded-lg sc:border-2 sc:text-left ${viewMode === 'masonry' ? 'sc:w-fit' : 'sc:min-w-0'} ${isSelected ? 'sc:border-accent' : 'sc:hover:border-muted sc:border-transparent'}`}\n onClick={shouldShowTooltip ? undefined : () => handleSelect(font.name)}\n role={shouldShowTooltip ? undefined : 'button'}\n aria-label={shouldShowTooltip ? undefined : `Select ${font.name} font`}\n tabIndex={shouldShowTooltip ? undefined : 0}\n onKeyDown={\n shouldShowTooltip\n ? undefined\n : (e) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n handleSelect(font.name);\n }\n }\n }\n style={{\n minHeight: `${showSecondaryLabel ? 48 * cardSizeScale : 36 * cardSizeScale}px`,\n padding: `${6 * cardSizeScale}px ${10 * cardSizeScale}px`,\n gap: `${2 * cardSizeScale}px`,\n }}\n >\n {/* Simple loading background - no animation for performance */}\n {!isLoaded && (\n <div\n className=\"sc:absolute sc:inset-0 sc:rounded-lg sc:bg-gray-100\"\n style={{\n opacity: 0.5,\n }}\n />\n )}\n\n <div\n className=\"sc-font-preview sc:text-foreground sc:overflow-hidden sc:leading-[1.1] sc:font-medium sc:text-ellipsis sc:whitespace-nowrap\"\n style={{\n '--font-preview': isLoaded ? `\"${font.name}\", sans-serif` : 'sans-serif',\n fontSize: `${15 * cardSizeScale}px`,\n opacity: isLoaded ? 1 : 0.4,\n } as React.CSSProperties}\n >\n {mainText}\n </div>\n {showSecondaryLabel && (\n <div\n className=\"sc:text-muted sc:overflow-hidden sc:font-sans sc:leading-[1.1] sc:font-normal sc:text-ellipsis sc:whitespace-nowrap\"\n style={{\n fontSize: `${7 * cardSizeScale}px`,\n opacity: isLoaded ? 1 : 0.4,\n }}\n >\n {font.name}\n </div>\n )}\n </Surface>\n );\n\n // Wrap with Tooltip if needed\n if (shouldShowTooltip) {\n return (\n <Tooltip key={font.name} delayDuration={200}>\n <TooltipTrigger asChild>\n <Button\n className=\"sc:m-0 sc:inline-block sc:h-auto sc:min-h-0 sc:border-0 sc:bg-transparent sc:p-0 sc:hover:bg-transparent\"\n style={{ width: viewMode === 'masonry' ? 'auto' : '100%' }}\n onClick={() => handleSelect(font.name)}\n aria-label={`Select ${font.name} font`}\n >\n <Surface\n ref={(el) => {\n // Assign to both refs: selectedFontRef for scrolling, fontItemRef for intersection observer\n if (isSelected && selectedFontRef) {\n selectedFontRef.current = el;\n }\n fontItemRef.current = el;\n }}\n className={`sc:relative sc:flex sc:cursor-pointer sc:flex-col sc:justify-center sc:rounded-lg sc:border-2 sc:text-left ${viewMode === 'masonry' ? 'sc:w-fit' : 'sc:min-w-0'} ${isSelected ? 'sc:border-accent' : 'sc:hover:border-muted sc:border-transparent'}`}\n style={{\n minHeight: `${showSecondaryLabel ? 48 * cardSizeScale : 36 * cardSizeScale}px`,\n padding: `${6 * cardSizeScale}px ${10 * cardSizeScale}px`,\n gap: `${2 * cardSizeScale}px`,\n }}\n >\n {/* Simple loading background - no animation for performance */}\n {!isLoaded && (\n <div\n className=\"sc:absolute sc:inset-0 sc:rounded-lg sc:bg-gray-100\"\n style={{\n opacity: 0.5,\n }}\n />\n )}\n\n <div\n className=\"sc-font-preview sc:text-foreground sc:overflow-hidden sc:leading-[1.1] sc:font-medium sc:text-ellipsis sc:whitespace-nowrap\"\n style={{\n '--font-preview': isLoaded ? `\"${font.name}\", sans-serif` : 'sans-serif',\n fontSize: `${15 * cardSizeScale}px`,\n opacity: isLoaded ? 1 : 0.4,\n } as React.CSSProperties}\n >\n {mainText}\n </div>\n {showSecondaryLabel && (\n <div\n className=\"sc:text-muted sc:overflow-hidden sc:font-sans sc:leading-[1.1] sc:font-normal sc:text-ellipsis sc:whitespace-nowrap\"\n style={{\n fontSize: `${7 * cardSizeScale}px`,\n opacity: isLoaded ? 1 : 0.4,\n }}\n >\n {font.name}\n </div>\n )}\n </Surface>\n </Button>\n </TooltipTrigger>\n <TooltipContent side=\"top\">\n <p>{font.name}</p>\n </TooltipContent>\n </Tooltip>\n );\n }\n\n return <React.Fragment key={font.name}>{surfaceContent}</React.Fragment>;\n },\n (prevProps, nextProps) => {\n // Custom comparison for memoization\n return prevProps.font.name === nextProps.font.name && prevProps.isUsedInDocument === nextProps.isUsedInDocument;\n }\n );\n\n // Extract fonts used in the document (excluding glyph-only elements)\n const fontsUsedInDocument = useMemo(() => {\n if (!elements) return new Set<string>();\n\n const usedFonts = new Set<string>();\n\n const addFontIfValid = (el: Record<string, unknown>) => {\n // Only add font if element has a fontFamily and non-glyph text\n const fontFamily = el.fontFamily as string | undefined;\n const text = el.text as string | undefined;\n if (fontFamily && text) {\n const cleanText = stripGlyphs(text);\n // Only add if there's actual text left after stripping glyphs\n if (cleanText.trim().length > 0) {\n usedFonts.add(fontFamily);\n }\n }\n };\n\n elements.forEach((el) => {\n addFontIfValid(el);\n\n // Check children for groups\n if (el.children && Array.isArray(el.children)) {\n (el.children as Record<string, unknown>[]).forEach((child) => {\n addFontIfValid(child);\n });\n }\n });\n\n return usedFonts;\n }, [elements]);\n\n // Organize fonts into sections\n const fontSections = useMemo(() => {\n // Get all fonts from UnifiedFontService (system + Google). A family\n // registered as a custom font deterministically SHADOWS its Google\n // namesake: the Google entry is hidden here and the custom one renders\n // under \"Your fonts\" instead (utils/custom-fonts.ts contract).\n const allFonts = (\n UnifiedFontService.isFontsLoaded() ? UnifiedFontService.getAllFonts() : TSHIRT_FONTS\n ) // Fallback to recommended fonts only if not loaded\n .filter((font) => !customFamilyKeys.has(font.name.trim().toLowerCase()));\n\n const recommendedNames = new Set(TSHIRT_FONTS.map((f) => f.name));\n\n // Extract \"Used in Document\" fonts first (only filter by search, not category)\n const usedFonts: FontDefinition[] = [];\n allFonts.forEach((font) => {\n if (fontsUsedInDocument.has(font.name)) {\n // Only apply search filter, not category filter\n if (searchQuery) {\n const query = searchQuery.toLowerCase();\n if (font.name.toLowerCase().includes(query)) {\n usedFonts.push(font);\n }\n } else {\n usedFonts.push(font);\n }\n }\n });\n\n // For remaining fonts, apply both category and search filters\n let remainingFonts = allFonts.filter((font) => !fontsUsedInDocument.has(font.name));\n\n // Filter by category\n if (selectedCategory !== 'all') {\n remainingFonts = remainingFonts.filter((font) => font.category === selectedCategory);\n }\n\n // Filter by search query\n if (searchQuery) {\n const query = searchQuery.toLowerCase();\n remainingFonts = remainingFonts.filter((font) => font.name.toLowerCase().includes(query));\n }\n\n // Separate remaining into recommended and other\n const recommendedFonts: FontDefinition[] = [];\n const otherFonts: FontDefinition[] = [];\n\n remainingFonts.forEach((font) => {\n if (recommendedNames.has(font.name)) {\n recommendedFonts.push(font);\n } else {\n otherFonts.push(font);\n }\n });\n\n // Sort each section alphabetically\n usedFonts.sort((a, b) => a.name.localeCompare(b.name));\n recommendedFonts.sort((a, b) => a.name.localeCompare(b.name));\n otherFonts.sort((a, b) => a.name.localeCompare(b.name));\n\n return { usedFonts, recommendedFonts, otherFonts };\n }, [searchQuery, selectedCategory, fontsLoadedTrigger, fontsUsedInDocument, customFamilyKeys]);\n\n // Render a font section - simple grid layout (all fonts same height, no masonry needed)\n const renderFontSection = (fonts: FontDefinition[], isUsedInDocument = false) => {\n if (viewMode === 'masonry') {\n // Flex wrap layout - simpler than true masonry since all items same height\n return (\n <div className=\"sc:flex sc:flex-wrap sc:content-start sc:items-start sc:gap-2 sc:px-4 sc:pb-4\">\n {fonts.map((font) => (\n <FontItem key={font.name} font={font} isUsedInDocument={isUsedInDocument} />\n ))}\n </div>\n );\n } else {\n // Grid layout - optimized for uniform height items\n return (\n <div\n className=\"sc:px-4 sc:pb-4\"\n style={{\n display: 'grid',\n gridTemplateColumns: `repeat(auto-fill, minmax(${140 * cardSizeScale}px, 1fr))`,\n gap: '8px',\n }}\n >\n {fonts.map((font) => (\n <FontItem key={font.name} font={font} isUsedInDocument={isUsedInDocument} />\n ))}\n </div>\n );\n }\n };\n\n // Get unique categories in order\n const categories: Array<FontCategory | 'all'> = [\n 'all',\n 'system',\n 'display',\n 'sans-serif',\n 'script',\n 'serif',\n 'slab-serif',\n 'vintage',\n 'decorative',\n 'monospace',\n ];\n\n return (\n <>\n {/*\n Fixed at 3× the standard toolbar button width so the contextual\n toolbar's button grid stays aligned regardless of font name\n length. Long names (e.g. \"Permanent Marker\", \"Architects\n Daughter\") truncate with ellipsis. The full name is still\n visible in the drawer once opened, and the tooltip shows it.\n */}\n <button\n onClick={() => onToggle(!isOpen)}\n className={`sc:h-11 sc:md:h-9 sc:w-[132px] sc:md:w-[108px] sc:flex sc:items-center sc:justify-center sc:px-2 sc:text-foreground sc:cursor-pointer sc:rounded-lg sc:border sc:border-transparent sc:text-base sc:font-medium sc:transition-all sc:hover:bg-black/5 sc:dark:hover:bg-white/5 ${isOpen ? 'sc:bg-black/10 sc:dark:bg-white/10' : 'sc:bg-transparent'}`}\n aria-label={isOpen ? 'Close font browser' : 'Open font browser'}\n title={value}\n >\n <span\n className=\"sc-font-preview sc:overflow-hidden sc:text-ellipsis sc:whitespace-nowrap sc:min-w-0\"\n style={{ '--font-preview': `\"${value}\", sans-serif`, fontWeight: 400 } as React.CSSProperties}\n >\n {value}\n </span>\n </button>\n\n <Drawer\n isOpen={isOpen}\n onClose={() => onToggle(false)}\n title=\"Fonts\"\n description=\"\"\n height=\"85vh\"\n placement=\"bottom\"\n showCloseButton={false}\n hideVisibleTitle={true}\n hideHandle={true}\n disableScrollWrapper={true}\n >\n {/* IMPORTANT: Wrapper pattern to avoid backdrop-filter compositing bugs */}\n {/* Outer wrapper: defines border-radius + overflow clipping */}\n {/* Inner element: no border-radius, just backdrop-filter */}\n {/* See docs/BACKDROP_FILTER_GOTCHAS.md for details */}\n <div className=\"sc:relative sc:flex-1 sc:overflow-hidden\">\n <div className=\"sc:h-full sc:bg-white\">\n {/* Inner scrollable container */}\n <div className=\"sc:h-full sc:overflow-y-auto\">\n {/* Search Input & Controls - Scrolls away */}\n <div className=\"sc:px-4 sc:pt-5\">\n <Surface className=\"sc:flex sc:gap-2\">\n <TextField className=\"sc:flex-1\" aria-label=\"Search fonts\">\n <Input\n type=\"text\"\n className=\"sc:rounded-2xl sc:pt-[10px] sc:pb-[9px]\"\n placeholder=\"Search fonts...\"\n value={searchQuery}\n onChange={(e) => setSearchQuery(e.target.value)}\n autoFocus\n aria-label=\"Search fonts\"\n />\n </TextField>\n\n <Tabs\n value={cardSize}\n onValueChange={(value) => setCardSize(value as 'small' | 'medium' | 'large')}\n >\n <Tabs.ListContainer>\n <Tabs.List aria-label=\"Card size\">\n <Tabs.Tab id=\"small\" className=\"sc:text-xs sc:font-semibold\" aria-label=\"Small card size\">\n A\n <Tabs.Indicator />\n </Tabs.Tab>\n <Tabs.Tab id=\"medium\" className=\"sc:text-base sc:font-semibold\" aria-label=\"Medium card size\">\n A\n <Tabs.Indicator />\n </Tabs.Tab>\n <Tabs.Tab id=\"large\" className=\"sc:text-xl sc:font-semibold\" aria-label=\"Large card size\">\n A\n <Tabs.Indicator />\n </Tabs.Tab>\n </Tabs.List>\n </Tabs.ListContainer>\n </Tabs>\n\n <Button\n variant=\"secondary\"\n onClick={() => {\n setDisplayMode((prev) => {\n if (prev === 'both') return 'name';\n if (prev === 'name') return 'preview';\n return 'both';\n });\n }}\n aria-label={\n displayMode === 'both'\n ? 'Show font name only'\n : displayMode === 'name'\n ? 'Show preview only'\n : 'Show preview with font name'\n }\n className=\"sc:h-10 sc:w-10 sc:p-0\"\n >\n {displayMode === 'both' ? (\n <Icon icon=\"lucide:credit-card\" className=\"sc:size-[22px]\" />\n ) : displayMode === 'name' ? (\n <Icon icon=\"lucide:type\" className=\"sc:size-[22px]\" />\n ) : (\n <Icon icon=\"lucide:text-cursor\" className=\"sc:size-[22px]\" />\n )}\n </Button>\n\n <Button\n variant=\"secondary\"\n onClick={() => setViewMode(viewMode === 'grid' ? 'masonry' : 'grid')}\n aria-label={viewMode === 'grid' ? 'Switch to masonry view' : 'Switch to grid view'}\n className=\"sc:h-10 sc:w-10 sc:p-0\"\n >\n {viewMode === 'grid' ? (\n <Icon icon=\"lucide:grid-2x2\" className=\"sc:size-[22px]\" />\n ) : (\n <Icon icon=\"lucide:grid-3x3\" className=\"sc:size-[22px]\" />\n )}\n </Button>\n </Surface>\n </div>\n\n {/* Category Filters - Sticky at top with blur and gradient */}\n <div className=\"sc:sticky sc:top-0 sc:z-20 sc:shrink-0\">\n {/* Gradient overlay - sticky with pills */}\n <div\n className=\"sc:pointer-events-none sc:absolute sc:top-0 sc:right-0 sc:left-0\"\n style={{\n height: '64px',\n background:\n 'linear-gradient(to bottom, var(--background) 0%, color-mix(in srgb, var(--background) 80%, transparent) 40%, transparent 100%)',\n zIndex: 16,\n }}\n />\n\n {/* Pills content */}\n <div className=\"sc:relative sc:z-20 sc:px-4 sc:py-4 sc:pt-3\">\n <div className=\"sc:flex sc:gap-2 sc:overflow-x-auto\">\n {categories.map((category) => {\n const label = category === 'all' ? 'All' : CATEGORY_LABELS[category as FontCategory];\n\n return (\n <Button\n key={category}\n size=\"sm\"\n variant={selectedCategory === category ? 'default' : 'secondary'}\n onClick={() => setSelectedCategory(category)}\n className={`sc:shrink-0 ${selectedCategory === category ? '' : 'sc:hover:brightness-95'}`}\n >\n {label}\n </Button>\n );\n })}\n </div>\n </div>\n </div>\n\n {/* Font List with Sections */}\n <div className=\"sc:flex-1\">\n {/* Your Fonts Section — custom (brand) fonts + the host-owned\n upload affordance. The whole section disappears when there\n are no custom fonts AND no `services.onFontUpload`. */}\n {(customFamilies.length > 0 || onFontUpload) && !searchQuery && (\n <div className=\"sc:shrink-0 sc:p-0\" data-sc-part=\"font-picker-your-fonts\">\n <div className=\"sc:text-muted sc:bg-white sc:px-4 sc:pt-2 sc:pb-2 sc:text-xs sc:font-bold sc:tracking-wider sc:uppercase\">\n Your Fonts\n </div>\n <div className=\"sc:flex sc:flex-wrap sc:content-start sc:items-center sc:gap-2 sc:px-4 sc:pb-4\">\n {customFamilies.map((family) => {\n const isSelected = value === family;\n return (\n <Surface\n key={family}\n data-sc-part=\"font-picker-custom-font\"\n data-family={family}\n className={`sc:relative sc:flex sc:w-fit sc:cursor-pointer sc:flex-col sc:justify-center sc:rounded-lg sc:border-2 sc:text-left ${isSelected ? 'sc:border-accent' : 'sc:hover:border-muted sc:border-transparent'}`}\n onClick={() => handleSelectCustom(family)}\n role=\"button\"\n aria-label={`Select ${family} font`}\n tabIndex={0}\n onKeyDown={(e) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n handleSelectCustom(family);\n }\n }}\n style={{\n minHeight: `${36 * cardSizeScale}px`,\n padding: `${6 * cardSizeScale}px ${10 * cardSizeScale}px`,\n }}\n >\n <div\n className=\"sc-font-preview sc:text-foreground sc:overflow-hidden sc:leading-[1.1] sc:font-medium sc:text-ellipsis sc:whitespace-nowrap\"\n style={{\n '--font-preview': `\"${family}\", sans-serif`,\n fontSize: `${15 * cardSizeScale}px`,\n } as React.CSSProperties}\n >\n {displayMode === 'name' ? family : previewText || family}\n </div>\n </Surface>\n );\n })}\n {onFontUpload && (\n <>\n <input\n ref={fontFileInputRef}\n type=\"file\"\n accept=\".woff2,.woff,.ttf,.otf,font/woff2,font/woff,font/ttf,font/otf\"\n className=\"sc:hidden\"\n data-sc-part=\"font-picker-upload-input\"\n data-testid=\"font-upload-input\"\n aria-label=\"Upload font file\"\n onChange={handleFontFileChange}\n />\n <Button\n variant=\"secondary\"\n data-sc-part=\"font-picker-upload\"\n data-testid=\"font-upload-button\"\n onClick={() => fontFileInputRef.current?.click()}\n disabled={fontUploadBusy}\n aria-label=\"Upload a font\"\n >\n <Icon icon=\"lucide:upload\" className=\"sc:size-4\" />\n {fontUploadBusy ? 'Uploading…' : 'Upload font'}\n </Button>\n </>\n )}\n </div>\n {fontUploadError && (\n <div\n className=\"sc:text-danger sc:px-4 sc:pb-3 sc:text-xs\"\n data-sc-part=\"font-picker-upload-error\"\n {...(fontUploadError.code && { 'data-sc-error-code': fontUploadError.code })}\n role=\"alert\"\n >\n {fontUploadError.message}\n </div>\n )}\n </div>\n )}\n\n {/* Used in Document Section */}\n {fontSections.usedFonts.length > 0 && (\n <div className=\"sc:shrink-0 sc:p-0\">\n <div className=\"sc:text-muted sc:bg-white sc:px-4 sc:pt-2 sc:pb-2 sc:text-xs sc:font-bold sc:tracking-wider sc:uppercase\">\n Used in Document\n </div>\n {renderFontSection(fontSections.usedFonts, true)}\n </div>\n )}\n\n {fontSections.recommendedFonts.length === 0 && fontSections.otherFonts.length === 0 ? (\n <div className=\"sc:text-muted sc:col-span-full sc:px-4 sc:py-8 sc:text-center sc:text-sm\">No fonts found</div>\n ) : (\n <>\n {/* Recommended Section */}\n {fontSections.recommendedFonts.length > 0 && (\n <div className=\"sc:p-0\">\n <div className=\"sc:text-muted sc:bg-white sc:px-4 sc:pt-2 sc:pb-2 sc:text-xs sc:font-bold sc:tracking-wider sc:uppercase\">\n Recommended\n </div>\n {renderFontSection(fontSections.recommendedFonts)}\n </div>\n )}\n\n {/* All Fonts Section */}\n {fontSections.otherFonts.length > 0 && (\n <div className=\"sc:p-0\">\n <div className=\"sc:text-muted sc:bg-white sc:px-4 sc:pt-4 sc:pb-2 sc:text-xs sc:font-bold sc:tracking-wider sc:uppercase\">\n All Fonts\n </div>\n {renderFontSection(fontSections.otherFonts)}\n </div>\n )}\n </>\n )}\n </div>\n </div>\n </div>\n </div>\n </Drawer>\n </>\n );\n};\n\nexport default FontBrowserDrawer;\n","/**\n * TransformControlPanel - Reusable component for transform-specific sliders\n * Eliminates duplication of slider control code across transforms\n *\n * Migrated to Shadcn/Radix:\n * - Switch\n * - Slider\n * - Label\n */\n\nimport React, { useState } from 'react';\nimport { TextElement } from '../core/TextElement';\nimport { ImageElement } from '../core/ImageElement';\nimport { ShapeElement } from '../core/ShapeElement';\nimport type { TransformControl } from '../types/index.js';\nimport { Switch, Slider, Label } from './ui';\nimport { createLogger } from '../utils/logger.js';\n\nconst logger = createLogger('TransformControlPanel');\n\ninterface TransformControlPanelProps {\n element: TextElement | ImageElement | ShapeElement;\n controls: TransformControl[];\n onUpdate: (element: TextElement | ImageElement | ShapeElement) => void;\n}\n\nexport const TransformControlPanel: React.FC<TransformControlPanelProps> = ({ element, controls, onUpdate }) => {\n // Track which slider is being dragged to show preview value\n const [draggingValues, setDraggingValues] = useState<Record<string, number>>({});\n\n return (\n <div className=\"sc:w-full sc:space-y-4\">\n {controls.map((control) => {\n // Get the stored value (internal representation)\n const storedValue =\n (element.transformData as Record<string, unknown>)[control.key] ?? control.defaultInternalValue ?? control.defaultValue;\n\n // Handle checkbox controls\n if (control.type === 'checkbox') {\n return (\n <div key={control.key} className=\"sc:flex sc:items-center sc:space-x-2\">\n <Switch\n id={`control-${control.key}`}\n checked={storedValue as boolean}\n onCheckedChange={(checked: boolean) => {\n const newElement = element.clone();\n (newElement.transformData as Record<string, unknown>)[control.key] = checked;\n onUpdate(newElement);\n }}\n />\n <Label htmlFor={`control-${control.key}`}>{control.label}</Label>\n </div>\n );\n }\n\n // Handle slider controls (default)\n // Safety check: ensure storedValue is a valid number\n const safeStoredValue = typeof storedValue === 'number' && !isNaN(storedValue)\n ? storedValue\n : (control.defaultInternalValue ?? 0);\n\n // Use preview value while dragging, otherwise use stored value\n const currentInternalValue = draggingValues[control.key] !== undefined\n ? draggingValues[control.key]\n : safeStoredValue;\n\n // Convert to slider position (0-100 scale for simplicity)\n const sliderValue = control.toSlider ? control.toSlider(currentInternalValue) : currentInternalValue;\n\n // Convert to display string\n const formatValue = (value: number): string => {\n // Note: value is the slider position, we need to convert back to stored value for display\n const internalValue = control.fromSlider ? control.fromSlider(value) : value;\n\n // Safety check: ensure internalValue is a number\n if (typeof internalValue !== 'number' || isNaN(internalValue)) {\n logger.warn('Invalid internalValue:', internalValue, 'for control:', control.key);\n return '0';\n }\n\n return control.toDisplay\n ? control.toDisplay(internalValue)\n : 'isPercentage' in control && control.isPercentage\n ? `${(internalValue * 100).toFixed(0)}%`\n : internalValue.toFixed(1);\n };\n\n return (\n <div key={control.key} className=\"sc:flex sc:flex-col sc:gap-sm\">\n <div className=\"sc:flex sc:justify-between\">\n <Label>{control.label}</Label>\n <span className=\"sc:text-sm sc:text-foreground/60\">{formatValue(sliderValue)}</span>\n </div>\n <Slider\n value={[sliderValue]}\n onValueChange={(val) => {\n // Update preview value while dragging\n const newSliderValue = val[0];\n const newInternalValue = control.fromSlider\n ? control.fromSlider(newSliderValue)\n : newSliderValue;\n setDraggingValues(prev => ({ ...prev, [control.key]: newInternalValue }));\n }}\n onChangeEnd={(val) => {\n // Only update element when drag ends\n const newSliderValue = val[0];\n const newElement = element.clone();\n (newElement.transformData as Record<string, unknown>)[control.key] = control.fromSlider\n ? control.fromSlider(newSliderValue)\n : newSliderValue;\n onUpdate(newElement);\n // Clear preview value\n setDraggingValues(prev => {\n const updated = { ...prev };\n delete updated[control.key];\n return updated;\n });\n }}\n min={0}\n max={100}\n step={control.step ?? 1}\n className=\"slider-no-fill\"\n />\n </div>\n );\n })}\n </div>\n );\n};\n\nexport default TransformControlPanel;\n","/**\n * TextEffectsDropdown - Dropdown for selecting and configuring text transforms\n * Shows currently selected transform and configuration controls\n */\n\nimport React, { useState } from 'react';\nimport { Popover, PopoverTrigger, PopoverContent, Select, SelectTrigger, SelectValue, SelectContent, SelectItem, Label, icons } from './ui';\nimport { Icon } from '@iconify/react';\nimport { TRANSFORM_TYPES, getTransformControls } from '../transforms/registry.js';\nimport { TransformControlPanel } from './TransformControlPanel.js';\nimport type { TransformType } from '../types/index.js';\nimport type { TextElement } from '../core/TextElement.js';\nimport type { ImageElement } from '../core/ImageElement.js';\nimport type { ShapeElement } from '../core/ShapeElement.js';\n\nexport interface TextEffectsDropdownProps {\n element: TextElement;\n onTransformTypeChange: (newType: TransformType) => void;\n onElementUpdate: (updatedElement: TextElement | ImageElement | ShapeElement) => void;\n isOpen?: boolean;\n onOpenChange?: (isOpen: boolean) => void;\n}\n\nexport const TextEffectsDropdown: React.FC<TextEffectsDropdownProps> = ({\n element,\n onTransformTypeChange,\n onElementUpdate,\n isOpen: controlledIsOpen,\n onOpenChange: controlledOnOpenChange,\n}) => {\n const [internalIsOpen, setInternalIsOpen] = useState(false);\n\n // Use controlled state if provided, otherwise use internal state\n const isOpen = controlledIsOpen !== undefined ? controlledIsOpen : internalIsOpen;\n const setIsOpen = controlledOnOpenChange || setInternalIsOpen;\n\n const currentTransformType = element.transformType;\n const controls = getTransformControls(currentTransformType);\n\n // Filter to only text transform types (exclude image, group, shape, path)\n const textTransformTypes = TRANSFORM_TYPES.filter(\n (t) => t.Component && t.id !== 'image' && t.id !== 'group' && t.id !== 'shape' && t.id !== 'path'\n );\n\n const handleTransformChange = (newType: string) => {\n if (newType !== currentTransformType) {\n onTransformTypeChange(newType as TransformType);\n }\n };\n\n return (\n <Popover open={isOpen} onOpenChange={setIsOpen}>\n <PopoverTrigger asChild>\n <button className=\"sc-toolbar-btn\" aria-label=\"Text Effects\">\n <Icon icon={icons.wand} className=\"sc:size-6\" />\n </button>\n </PopoverTrigger>\n <PopoverContent align=\"start\" className=\"sc:w-[280px] sc:p-0\" maxZIndex>\n <div className=\"sc:space-y-4 sc:p-6\">\n {/* Transform Type Select */}\n <div className=\"sc:space-y-2\">\n <Label>Text Effect</Label>\n <Select value={currentTransformType} onValueChange={handleTransformChange}>\n <SelectTrigger>\n <SelectValue placeholder=\"Select effect\" />\n </SelectTrigger>\n <SelectContent style={{ zIndex: 2147483647 }}>\n {textTransformTypes.map((transform) => (\n <SelectItem key={transform.id} value={transform.id}>\n {transform.label}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n\n {/* Transform Configuration Controls */}\n {controls.length > 0 && (\n <TransformControlPanel element={element} controls={controls} onUpdate={onElementUpdate} />\n )}\n </div>\n </PopoverContent>\n </Popover>\n );\n};\n\nexport default TextEffectsDropdown;\n","/**\n * MoreMenu - Overflow menu for toolbar items\n * Shows a \"...\" menu with items that don't fit or are always hidden\n */\n\nimport { useState } from 'react';\nimport { Button, Popover, PopoverTrigger, PopoverContent, Tooltip, TooltipTrigger, TooltipContent, icons } from './ui';\nimport { Icon } from '@iconify/react';\n\ninterface MoreMenuItem {\n label: string;\n icon: React.ReactNode;\n onClick: () => void;\n active?: boolean;\n}\n\ninterface MoreMenuProps {\n items: MoreMenuItem[];\n}\n\nconst MoreMenu = ({ items }: MoreMenuProps) => {\n const [showMenu, setShowMenu] = useState(false);\n\n return (\n <Popover open={showMenu} onOpenChange={setShowMenu}>\n <PopoverTrigger asChild>\n <button className=\"sc-toolbar-btn\" aria-label=\"More options\">\n <Icon icon={icons.moreHorizontal} className=\"sc:size-6\" />\n </button>\n </PopoverTrigger>\n <PopoverContent align=\"start\" className=\"sc:w-auto sc:p-1\" maxZIndex>\n <div className=\"sc:flex sc:items-center sc:gap-1\">\n {items.map((item, index) => (\n <Tooltip key={index} delay={300}>\n <TooltipTrigger asChild>\n <Button\n variant={item.active ? 'default' : 'ghost'}\n size=\"icon\"\n onClick={() => {\n item.onClick();\n setShowMenu(false);\n }}\n aria-label={item.label}\n >\n {item.icon}\n </Button>\n </TooltipTrigger>\n <TooltipContent>{item.label}</TooltipContent>\n </Tooltip>\n ))}\n </div>\n </PopoverContent>\n </Popover>\n );\n};\n\nexport default MoreMenu;\n","import { Tooltip, TooltipTrigger, TooltipContent } from '../ui';\n\nexport interface FontColorButtonProps {\n colorPickerValue: string;\n isActive: boolean;\n onClick: () => void;\n}\n\nexport function FontColorButton({ colorPickerValue, isActive, onClick }: FontColorButtonProps) {\n return (\n <Tooltip delay={300}>\n <TooltipTrigger asChild>\n <button\n className=\"sc-toolbar-btn\"\n onClick={onClick}\n aria-label=\"Font Color\"\n data-active={isActive}\n >\n <div className=\"sc:relative sc:flex sc:h-5 sc:w-5 sc:items-center sc:justify-center\">\n <span className=\"sc:-translate-y-0.5 sc:text-lg sc:leading-none sc:font-bold\">A</span>\n <div\n className=\"sc:absolute sc:bottom-0 sc:left-1/2 sc:h-[3px] sc:w-4 sc:-translate-x-1/2 sc:rounded-sm\"\n style={{ backgroundColor: colorPickerValue }}\n />\n </div>\n </button>\n </TooltipTrigger>\n {!isActive && <TooltipContent>Font Color</TooltipContent>}\n </Tooltip>\n );\n}\n","import { ToolbarButton, icons } from '../ui';\nimport type { UseTextToolbarReturn } from '../../hooks/useTextToolbar.js';\n\nexport interface BoldButtonProps {\n toolbar: UseTextToolbarReturn;\n}\n\nexport function BoldButton({ toolbar }: BoldButtonProps) {\n return (\n <ToolbarButton\n icon={icons.bold}\n onClick={toolbar.handleBoldToggle}\n active={toolbar.getEffectiveStyle().bold}\n tooltip=\"Bold\"\n />\n );\n}\n","import { ToolbarButton, icons } from '../ui';\nimport type { UseTextToolbarReturn } from '../../hooks/useTextToolbar.js';\n\nexport interface ItalicButtonProps {\n toolbar: UseTextToolbarReturn;\n}\n\nexport function ItalicButton({ toolbar }: ItalicButtonProps) {\n return (\n <ToolbarButton\n icon={icons.italic}\n onClick={toolbar.handleItalicToggle}\n active={toolbar.getEffectiveStyle().italic}\n tooltip=\"Italic\"\n />\n );\n}\n","import { ToolbarButton, icons } from '../ui';\nimport type { UseTextToolbarReturn } from '../../hooks/useTextToolbar.js';\n\nexport interface UnderlineButtonProps {\n toolbar: UseTextToolbarReturn;\n}\n\nexport function UnderlineButton({ toolbar }: UnderlineButtonProps) {\n return (\n <ToolbarButton\n icon={icons.underline}\n onClick={toolbar.handleUnderlineToggle}\n active={toolbar.getEffectiveStyle().underline}\n tooltip=\"Underline\"\n />\n );\n}\n","import { ToolbarButton } from '../ui';\nimport type { UseTextToolbarReturn } from '../../hooks/useTextToolbar.js';\n\nexport interface UppercaseButtonProps {\n toolbar: UseTextToolbarReturn;\n}\n\nexport function UppercaseButton({ toolbar }: UppercaseButtonProps) {\n return (\n <ToolbarButton\n icon=\"lucide:case-upper\"\n onClick={toolbar.handleLetterCaseToggle}\n active={toolbar.isLetterCaseActive()}\n tooltip=\"Uppercase\"\n />\n );\n}\n","import { ToolbarButton, icons } from '../ui';\nimport type { UseTextToolbarReturn } from '../../hooks/useTextToolbar.js';\n\nexport interface TextAlignButtonProps {\n toolbar: UseTextToolbarReturn;\n}\n\nexport function TextAlignButton({ toolbar }: TextAlignButtonProps) {\n const { textAlign, handleTextAlignToggle } = toolbar;\n const icon =\n textAlign === 'left' ? icons.alignLeft : textAlign === 'center' ? icons.alignCenter : icons.alignRight;\n\n return (\n <ToolbarButton\n icon={icon}\n onClick={handleTextAlignToggle}\n tooltip={`Align ${textAlign.charAt(0).toUpperCase() + textAlign.slice(1)}`}\n />\n );\n}\n","import { useState } from 'react';\nimport { Icon } from '@iconify/react';\nimport {\n Tooltip,\n TooltipTrigger,\n TooltipContent,\n Button,\n Popover,\n PopoverTrigger,\n PopoverContent,\n icons,\n} from '../ui';\n\nexport interface TextMoreMenuProps {\n onMoveForward: () => void;\n onMoveBackward: () => void;\n onDelete: () => void;\n onOpenChange?: (open: boolean) => void;\n}\n\nexport function TextMoreMenu({ onMoveForward, onMoveBackward, onDelete, onOpenChange }: TextMoreMenuProps) {\n const [isOpen, setIsOpen] = useState(false);\n\n const handleOpenChange = (open: boolean) => {\n setIsOpen(open);\n onOpenChange?.(open);\n };\n\n return (\n <Popover open={isOpen} onOpenChange={handleOpenChange}>\n <PopoverTrigger asChild>\n <button className=\"sc-toolbar-btn\" aria-label=\"More options\">\n <Icon icon=\"lucide:ellipsis-vertical\" className=\"sc:size-6\" />\n </button>\n </PopoverTrigger>\n <PopoverContent align=\"end\" className=\"sc:w-auto sc:p-1\" maxZIndex>\n <div className=\"sc:flex sc:items-center sc:gap-1\">\n <Tooltip delayDuration={300}>\n <TooltipTrigger asChild>\n <Button\n variant=\"ghost\"\n size=\"icon\"\n onClick={() => {\n onMoveForward();\n handleOpenChange(false);\n }}\n aria-label=\"Move Forward\"\n >\n <Icon icon=\"hugeicons:layer-bring-forward\" className=\"sc:size-5\" />\n </Button>\n </TooltipTrigger>\n <TooltipContent>Move Forward</TooltipContent>\n </Tooltip>\n <Tooltip delayDuration={300}>\n <TooltipTrigger asChild>\n <Button\n variant=\"ghost\"\n size=\"icon\"\n onClick={() => {\n onMoveBackward();\n handleOpenChange(false);\n }}\n aria-label=\"Move Backward\"\n >\n <Icon icon=\"hugeicons:layer-send-backward\" className=\"sc:size-5\" />\n </Button>\n </TooltipTrigger>\n <TooltipContent>Move Backward</TooltipContent>\n </Tooltip>\n <Tooltip delayDuration={300}>\n <TooltipTrigger asChild>\n <Button\n variant=\"ghost\"\n size=\"icon\"\n onClick={() => {\n handleOpenChange(false);\n onDelete();\n }}\n aria-label=\"Delete\"\n >\n <Icon icon={icons.trash} className=\"sc:size-5\" />\n </Button>\n </TooltipTrigger>\n <TooltipContent>Delete</TooltipContent>\n </Tooltip>\n </div>\n </PopoverContent>\n </Popover>\n );\n}\n","/**\n * TextToolbar - Composed text formatting toolbar using primitives.\n *\n * Replaces the inline text toolbar JSX from ContextualToolbars.\n * Accepts a `toolbar` prop (from useTextToolbar) so the parent can\n * share the same state with other panels (e.g. text color picker).\n *\n * For standalone usage, call useTextToolbar() in your component and\n * pass the result as the `toolbar` prop.\n */\n\nimport React, { useState } from 'react';\nimport FontBrowserDrawer from './FontBrowserDrawer.jsx';\nimport TextEffectsDropdown from './TextEffectsDropdown.jsx';\nimport MoreMenu from './MoreMenu.jsx';\nimport { FontColorButton } from './text-toolbar/FontColorButton.js';\nimport { BoldButton } from './text-toolbar/BoldButton.js';\nimport { ItalicButton } from './text-toolbar/ItalicButton.js';\nimport { UnderlineButton } from './text-toolbar/UnderlineButton.js';\nimport { UppercaseButton } from './text-toolbar/UppercaseButton.js';\nimport { TextAlignButton } from './text-toolbar/TextAlignButton.js';\nimport { TextMoreMenu } from './text-toolbar/TextMoreMenu.js';\nimport { ToolbarButton, RotateLeftIcon } from './ui';\nimport { FONT_FAMILIES } from '../constants.js';\nimport { getFeatureApplied } from '../utils/featureApplied.js';\nimport type { UseTextToolbarReturn } from '../hooks/useTextToolbar.js';\nimport type { EditorElement } from '../contexts/EditorContext.js';\nimport type { TextElement } from '../core/TextElement.js';\n\nexport interface TextToolbarProps {\n toolbar: UseTextToolbarReturn;\n stableElementId?: string;\n viewportWidth?: number;\n colorPickerValue: string;\n isColorActive: boolean;\n onColorToggle: () => void;\n onOpenGlyphBrowser?: () => void;\n hasGlyphs?: boolean;\n expandedPanel: { type: string } | null;\n onRotationToggle: () => void;\n onOpacityToggle: () => void;\n onFontSizeToggle: () => void;\n getMoreMenuItems?: () => Array<{ label: string; onClick: () => void; icon: React.ReactNode; active?: boolean }>;\n strokeExpanded?: boolean;\n onStrokeToggle?: () => void;\n shadowExpanded?: boolean;\n onShadowToggle?: () => void;\n blendModeExpanded?: boolean;\n onBlendModeToggle?: () => void;\n knockoutExpanded?: boolean;\n onKnockoutToggle?: () => void;\n distressTextureExpanded?: boolean;\n onDistressTextureToggle?: () => void;\n imageMaskExpanded?: boolean;\n onImageMaskToggle?: () => void;\n onMoveForward: () => void;\n onMoveBackward: () => void;\n onDelete: () => void;\n elementForProperties: EditorElement;\n elements: EditorElement[];\n isTransformMenuOpen: boolean;\n onTransformMenuOpenChange: (open: boolean) => void;\n elementUpdateHandler: (updatedElement: EditorElement) => void;\n showUngroupButton?: boolean;\n onUngroup?: () => void;\n isFontBrowserOpen?: boolean;\n onFontBrowserToggle: (isOpen: boolean) => void;\n onTextMoreMenuOpenChange?: (open: boolean) => void;\n}\n\nexport function TextToolbar({\n toolbar,\n stableElementId,\n viewportWidth = window.innerWidth,\n colorPickerValue,\n isColorActive,\n onColorToggle,\n onOpenGlyphBrowser,\n hasGlyphs = false,\n expandedPanel,\n onRotationToggle,\n onOpacityToggle,\n onFontSizeToggle,\n strokeExpanded = false,\n onStrokeToggle,\n shadowExpanded = false,\n onShadowToggle,\n blendModeExpanded = false,\n onBlendModeToggle,\n knockoutExpanded = false,\n onKnockoutToggle,\n distressTextureExpanded = false,\n onDistressTextureToggle,\n imageMaskExpanded = false,\n onImageMaskToggle,\n getMoreMenuItems,\n onMoveForward,\n onMoveBackward,\n onDelete,\n elementForProperties,\n elements,\n isTransformMenuOpen,\n onTransformMenuOpenChange,\n elementUpdateHandler,\n showUngroupButton = false,\n onUngroup,\n isFontBrowserOpen = false,\n onFontBrowserToggle,\n onTextMoreMenuOpenChange,\n}: TextToolbarProps) {\n // Tooltip disabled states (prevent flicker after click)\n const [strokeTooltipDisabled, setStrokeTooltipDisabled] = useState(false);\n const [glyphTooltipDisabled, setGlyphTooltipDisabled] = useState(false);\n const [rotationTooltipDisabled, setRotationTooltipDisabled] = useState(false);\n const [fontSizeTooltipDisabled, setFontSizeTooltipDisabled] = useState(false);\n\n // Feature-applied flags — drive the \"selected\" highlight on the\n // toolbar buttons whose underlying property has been set to a\n // non-default value.\n const applied = getFeatureApplied(elementForProperties);\n const [opacityTooltipDisabled, setOpacityTooltipDisabled] = useState(false);\n const [shadowTooltipDisabled, setShadowTooltipDisabled] = useState(false);\n const [blendModeTooltipDisabled, setBlendModeTooltipDisabled] = useState(false);\n const [knockoutTooltipDisabled, setKnockoutTooltipDisabled] = useState(false);\n const [distressTooltipDisabled, setDistressTooltipDisabled] = useState(false);\n const [imageMaskTooltipDisabled, setImageMaskTooltipDisabled] = useState(false);\n\n return (\n <div key={`text-toolbar-${stableElementId}`} className=\"sc-toolbar-items\">\n {/* Font Browser Drawer */}\n <FontBrowserDrawer\n value={toolbar.getEffectiveStyle().fontFamily || toolbar.fontFamily}\n onChange={(e: { target: { value: string } }) => toolbar.handleFontFamilyChange(e.target.value)}\n fontFamilies={FONT_FAMILIES}\n isOpen={isFontBrowserOpen}\n onToggle={onFontBrowserToggle}\n showLabel={viewportWidth > 700}\n previewText={'text' in elementForProperties ? (elementForProperties as { text: string }).text : undefined}\n elements={elements as unknown as Array<Record<string, unknown>>}\n />\n\n {/* Font Size — toolbar button using the standard \"Aa\" font-size\n icon. Tapping opens the secondary panel (slider + number\n input). Earlier this button rendered the current size as\n its label — but at 3 digits (\"148\") that broke the toolbar's\n uniform button-width grid. The current size still shows in\n the tooltip and inside the panel; the icon keeps the\n toolbar visually aligned with the rest of its buttons. */}\n <ToolbarButton\n icon=\"lucide:a-large-small\"\n onClick={() => {\n setFontSizeTooltipDisabled(true);\n onFontSizeToggle();\n }}\n onMouseLeave={() => setFontSizeTooltipDisabled(false)}\n tooltip={`Font Size · ${Math.round(toolbar.fontSize)}`}\n tooltipDisabled={fontSizeTooltipDisabled || expandedPanel?.type === 'fontSize'}\n active={expandedPanel?.type === 'fontSize' || applied.typography}\n />\n\n {/* Font Color */}\n <FontColorButton\n colorPickerValue={colorPickerValue}\n isActive={isColorActive}\n onClick={onColorToggle}\n />\n\n {/* Text formatting buttons */}\n <BoldButton toolbar={toolbar} />\n <ItalicButton toolbar={toolbar} />\n <UnderlineButton toolbar={toolbar} />\n <UppercaseButton toolbar={toolbar} />\n\n {/* Text Alignment */}\n <TextAlignButton toolbar={toolbar} />\n\n {/* Text Effects Dropdown */}\n <TextEffectsDropdown\n element={elementForProperties as TextElement}\n onTransformTypeChange={toolbar.handleTransformTypeChange}\n onElementUpdate={elementUpdateHandler}\n isOpen={isTransformMenuOpen}\n onOpenChange={onTransformMenuOpenChange}\n />\n\n {/* Stroke */}\n {onStrokeToggle && (\n <ToolbarButton\n icon=\"lucide:pen-line\"\n onClick={() => {\n setStrokeTooltipDisabled(true);\n onStrokeToggle();\n }}\n onMouseLeave={() => setStrokeTooltipDisabled(false)}\n tooltip=\"Stroke\"\n tooltipDisabled={strokeTooltipDisabled || strokeExpanded}\n active={strokeExpanded || applied.stroke}\n />\n )}\n\n {/* Rotation */}\n <ToolbarButton\n icon={<RotateLeftIcon size={20} className=\"sc:md:size-5\" />}\n onClick={() => {\n setRotationTooltipDisabled(true);\n onRotationToggle();\n }}\n onMouseLeave={() => setRotationTooltipDisabled(false)}\n tooltip=\"Rotate\"\n tooltipDisabled={rotationTooltipDisabled || expandedPanel?.type === 'rotation'}\n active={expandedPanel?.type === 'rotation' || applied.rotation}\n />\n\n {/* Transparency */}\n <ToolbarButton\n icon=\"lucide:blend\"\n onClick={() => {\n setOpacityTooltipDisabled(true);\n onOpacityToggle();\n }}\n onMouseLeave={() => setOpacityTooltipDisabled(false)}\n tooltip=\"Transparency\"\n tooltipDisabled={opacityTooltipDisabled || expandedPanel?.type === 'opacity'}\n active={expandedPanel?.type === 'opacity' || applied.opacity}\n />\n\n {/* Shadow */}\n {onShadowToggle && (\n <ToolbarButton\n icon=\"gravity-ui:square-dashed-circle\"\n onClick={() => {\n setShadowTooltipDisabled(true);\n onShadowToggle();\n }}\n onMouseLeave={() => setShadowTooltipDisabled(false)}\n tooltip=\"Shadow\"\n tooltipDisabled={shadowTooltipDisabled || shadowExpanded}\n active={shadowExpanded || applied.shadow}\n />\n )}\n\n {/* Blend Mode */}\n {onBlendModeToggle && (\n <ToolbarButton\n icon=\"gravity-ui:circles-intersection\"\n onClick={() => {\n setBlendModeTooltipDisabled(true);\n onBlendModeToggle();\n }}\n onMouseLeave={() => setBlendModeTooltipDisabled(false)}\n tooltip=\"Blend Mode\"\n tooltipDisabled={blendModeTooltipDisabled || blendModeExpanded}\n active={blendModeExpanded || applied.blendMode}\n />\n )}\n\n {/* Knockout */}\n {onKnockoutToggle && (\n <ToolbarButton\n icon=\"lucide:scissors\"\n onClick={() => {\n setKnockoutTooltipDisabled(true);\n onKnockoutToggle();\n }}\n onMouseLeave={() => setKnockoutTooltipDisabled(false)}\n tooltip=\"Clip / Knockout\"\n tooltipDisabled={knockoutTooltipDisabled || knockoutExpanded}\n active={knockoutExpanded || applied.knockout}\n />\n )}\n\n {/* Distress Texture */}\n {onDistressTextureToggle && (\n <ToolbarButton\n icon=\"lucide:stamp\"\n onClick={() => {\n setDistressTooltipDisabled(true);\n onDistressTextureToggle();\n }}\n onMouseLeave={() => setDistressTooltipDisabled(false)}\n tooltip=\"Distress Texture\"\n tooltipDisabled={distressTooltipDisabled || distressTextureExpanded}\n active={distressTextureExpanded || applied.distress}\n />\n )}\n\n {/* Image Mask */}\n {onImageMaskToggle && (\n <ToolbarButton\n icon=\"lucide:venetian-mask\"\n onClick={() => {\n setImageMaskTooltipDisabled(true);\n onImageMaskToggle();\n }}\n onMouseLeave={() => setImageMaskTooltipDisabled(false)}\n tooltip=\"Image Mask\"\n tooltipDisabled={imageMaskTooltipDisabled || imageMaskExpanded}\n active={imageMaskExpanded || applied.imageMask}\n />\n )}\n\n {/* Glyph Browser */}\n <ToolbarButton\n icon=\"lucide:flag\"\n onClick={() => {\n setGlyphTooltipDisabled(true);\n onOpenGlyphBrowser?.();\n }}\n onMouseLeave={() => setGlyphTooltipDisabled(false)}\n tooltip={hasGlyphs ? 'Browse All Glyphs' : 'No alternate glyphs available'}\n tooltipDisabled={glyphTooltipDisabled}\n disabled={!hasGlyphs}\n className={!hasGlyphs ? 'sc:opacity-50' : ''}\n />\n\n {/* More Menu - custom items passed via prop */}\n {getMoreMenuItems && <MoreMenu items={getMoreMenuItems()} />}\n\n {/* More Menu - layer order and delete */}\n <TextMoreMenu\n onMoveForward={onMoveForward}\n onMoveBackward={onMoveBackward}\n onDelete={onDelete}\n onOpenChange={onTextMoreMenuOpenChange}\n />\n\n {/* Ungroup button - shown when editing a child in a group */}\n {showUngroupButton && (\n <button className=\"sc-toolbar-btn\" onClick={onUngroup}>\n Ungroup\n </button>\n )}\n </div>\n );\n}\n","/**\n * TransformConverter - Utility for converting between transform types\n * Handles position and dimension adjustments when switching transforms\n */\n\nimport { WAVE_DEFAULTS, FLAG_DEFAULTS, ARCH_DEFAULTS, LEAN_DEFAULTS } from '../transforms/defaults.js';\nimport type { TextElement } from './TextElement.js';\nimport type { TransformType, Point } from '../types/index.js';\n\n/** Configuration result for a transform conversion */\ninterface TransformConfig {\n x: number;\n y: number;\n fontSize: number;\n transformData: Record<string, unknown>;\n}\n\n/**\n * Convert an element from one transform type to another\n * Maintains visual size and position during conversion\n *\n * @param sourceElement - Element to convert from\n * @param targetType - Target transform type id\n * @param TargetClass - Target transform class constructor\n * @returns New element with target transform type\n */\nexport function convertTransform(\n sourceElement: TextElement,\n targetType: TransformType,\n TargetClass: new (config: Record<string, unknown>) => TextElement\n): TextElement {\n // Get the current element's rotation anchor as the consistent reference point\n const rotationAnchor = sourceElement.getRotationAnchor();\n\n // Get the current effective fontSize to maintain visual size\n let currentEffectiveFontSize: number;\n if (sourceElement.transformType === 'circle' && 'getEffectiveFontSize' in sourceElement) {\n // Circle mode uses scale, so get effective font size\n currentEffectiveFontSize = (sourceElement as unknown as { getEffectiveFontSize: () => number }).getEffectiveFontSize();\n } else {\n currentEffectiveFontSize = sourceElement.fontSize;\n }\n\n // Calculate appropriate transformData based on target type\n const config = calculateTransformConfig(sourceElement, targetType, currentEffectiveFontSize, rotationAnchor);\n\n // Create new element with converted properties\n return new TargetClass({\n id: sourceElement.id,\n text: sourceElement.text,\n x: config.x,\n y: config.y,\n rotation: sourceElement.rotation,\n fontSize: config.fontSize,\n fontFamily: sourceElement.fontFamily,\n color: sourceElement.color,\n textAlign: sourceElement.textAlign,\n transformData: config.transformData,\n });\n}\n\n/**\n * Calculate configuration for target transform type\n * @private\n */\nfunction calculateTransformConfig(\n sourceElement: TextElement,\n targetType: TransformType,\n effectiveFontSize: number,\n rotationAnchor: Point\n): TransformConfig {\n let transformData: Record<string, unknown>;\n let x: number, y: number;\n const fontSize = effectiveFontSize;\n\n switch (targetType) {\n case 'circle':\n // For circle, maintain the visual size by calculating radius from current dimensions\n // Use the height as the primary dimension since it's consistent across transforms\n const textHeight = effectiveFontSize * 1.2;\n // Use text height as basis for circle radius\n const radius = textHeight * 2; // Reasonable default circle size\n transformData = { radius, scale: 1 };\n // Circle's (x, y) is its center, which matches rotation anchor\n x = rotationAnchor.x;\n y = rotationAnchor.y;\n break;\n\n case 'custom':\n // For custom, preserve the fontSize and calculate appropriate width\n // Measure the actual text to determine minimum required width\n const minWidth = 200;\n const estimatedTextWidth = effectiveFontSize * sourceElement.text.length * 0.6;\n const targetWidth = Math.max(estimatedTextWidth, minWidth);\n\n transformData = { width: targetWidth };\n // CustomTransform's (x, y) is top-left, but rotation anchor is center\n // So we need to calculate top-left from the center\n const targetHeight = effectiveFontSize * 1.2;\n x = rotationAnchor.x - targetWidth / 2;\n y = rotationAnchor.y - targetHeight / 2;\n break;\n\n case 'arch':\n // For arch, use reasonable width based on text size\n const archMinWidth = 200;\n const archEstimatedWidth = effectiveFontSize * sourceElement.text.length * 0.6;\n transformData = {\n width: Math.max(archEstimatedWidth, archMinWidth),\n archHeight: ARCH_DEFAULTS.archHeight,\n };\n // Arch's (x, y) is center, which matches rotation anchor\n x = rotationAnchor.x;\n y = rotationAnchor.y;\n break;\n\n case 'wave':\n // Wave transform config\n const waveMinWidth = 200;\n const waveEstimatedWidth = effectiveFontSize * sourceElement.text.length * 0.6;\n transformData = {\n width: Math.max(waveEstimatedWidth, waveMinWidth),\n amplitude: WAVE_DEFAULTS.amplitude,\n frequency: WAVE_DEFAULTS.frequency,\n };\n x = rotationAnchor.x;\n y = rotationAnchor.y;\n break;\n\n case 'flag':\n // Flag transform config\n const flagMinWidth = 200;\n const flagEstimatedWidth = effectiveFontSize * sourceElement.text.length * 0.6;\n transformData = {\n width: Math.max(flagEstimatedWidth, flagMinWidth),\n amplitude: FLAG_DEFAULTS.amplitude,\n frequency: FLAG_DEFAULTS.frequency,\n };\n x = rotationAnchor.x;\n y = rotationAnchor.y;\n break;\n\n case 'lean':\n // Lean transform config\n const leanMinWidth = 200;\n const leanEstimatedWidth = effectiveFontSize * sourceElement.text.length * 0.6;\n transformData = {\n width: Math.max(leanEstimatedWidth, leanMinWidth),\n leanAmount: LEAN_DEFAULTS.leanAmount,\n };\n x = rotationAnchor.x;\n y = rotationAnchor.y;\n break;\n\n default:\n // Fallback for unknown transform types\n transformData = { width: 200 };\n x = rotationAnchor.x;\n y = rotationAnchor.y;\n }\n\n return { x, y, fontSize, transformData };\n}\n\nexport default { convertTransform };\n","/**\n * useTextToolbar - Hook for text element formatting state and handlers.\n *\n * Extracts all text-specific toolbar logic (font size, color, family,\n * bold/italic/underline, letter case, text align, transform type) from\n * ContextualToolbars so it can be reused in composed toolbar layouts.\n *\n * Uses `useEditor()` internally — no need to pass element/elements as props.\n * The only external dependency is `canvasEditorRef` for character-level formatting.\n */\n\nimport { useState, useCallback, useEffect, useRef } from 'react';\nimport { useEditor } from '../contexts/EditorContext.js';\nimport type { EditorElement } from '../contexts/EditorContext.js';\nimport { TextElement } from '../core/TextElement.js';\nimport { GroupElement } from '../core/GroupElement.js';\nimport { getTransformById } from '../transforms/registry.js';\nimport { convertTransform } from '../core/TransformConverter.js';\nimport type { TransformType, TextAlign, CharacterStyle } from '../types/index.js';\nimport type { CanvasEditorHandle } from '../components/CanvasEditor.js';\nimport type { CircleTransform } from '../transforms/CircleTransform.js';\n\nexport interface UseTextToolbarOptions {\n canvasEditorRef?: React.RefObject<CanvasEditorHandle | null>;\n}\n\nexport interface UseTextToolbarReturn {\n // State\n fontSize: number;\n fontColor: string;\n fontFamily: string;\n textAlign: TextAlign;\n bold: boolean;\n italic: boolean;\n underline: boolean;\n letterCase: string;\n /** Letter-spacing in px per character (element-level default; 0 = none). */\n letterSpacing: number;\n /** Line-height multiplier (1.2 = the layout default). */\n lineHeight: number;\n\n // Handlers\n handleFontSizeChange: (size: number) => void;\n handleFontSizeIncrement: (delta: number) => void;\n /** Per-character aware (applies to the selection while editing text). */\n handleLetterSpacingChange: (spacing: number) => void;\n /** Element-level only (line layout is an element concern, not a span one). */\n handleLineHeightChange: (lineHeight: number) => void;\n handleFontFamilyChange: (family: string) => void;\n handleFontColorChange: (e: React.ChangeEvent<HTMLInputElement>) => void;\n handleBoldToggle: () => void;\n handleItalicToggle: () => void;\n handleUnderlineToggle: () => void;\n handleLetterCaseToggle: () => void;\n isLetterCaseActive: () => boolean;\n handleTextAlignToggle: () => void;\n\n // Rich text support\n getEffectiveStyle: () => CharacterStyle;\n\n // Transform type\n handleTransformTypeChange: (type: TransformType) => void;\n}\n\n/**\n * Hook for text element formatting state and handlers.\n *\n * Extracts all text-specific toolbar logic (font size, color, family,\n * bold/italic/underline, letter case, text align, transform type) so it\n * can be reused across different toolbar layouts.\n *\n * Uses `useEditor()` internally. Pass a `canvasEditorRef` to enable\n * character-level rich text formatting during text editing mode.\n *\n * @param options - Configuration options\n * @returns Text toolbar state and handler functions\n *\n * @example\n * ```tsx\n * function MyTextToolbar() {\n * const toolbar = useTextToolbar({ canvasEditorRef });\n *\n * return (\n * <div>\n * <button onClick={toolbar.handleBoldToggle}>\n * Bold: {toolbar.bold ? 'ON' : 'OFF'}\n * </button>\n * <input\n * type=\"number\"\n * value={toolbar.fontSize}\n * onChange={(e) => toolbar.handleFontSizeChange(Number(e.target.value))}\n * />\n * </div>\n * );\n * }\n * ```\n */\nexport function useTextToolbar(options: UseTextToolbarOptions = {}): UseTextToolbarReturn {\n const { canvasEditorRef } = options;\n\n const {\n selectedElement,\n activeChildElement,\n handleElementUpdate,\n } = useEditor();\n\n // Determine which element to show properties for\n const elementForProperties = activeChildElement || selectedElement;\n\n // Element update handler (handles group children)\n const elementUpdateHandler = useCallback(\n (updatedElement: EditorElement) => {\n if (!selectedElement) return;\n\n if (activeChildElement) {\n // Update child within group\n if (!(selectedElement instanceof GroupElement)) return;\n const updatedGroup = selectedElement.clone();\n const childIndex = updatedGroup.children.findIndex((c) => c.id === activeChildElement.id);\n if (childIndex !== -1) {\n updatedGroup.children[childIndex] = updatedElement as typeof updatedGroup.children[number];\n handleElementUpdate(updatedGroup);\n }\n } else {\n handleElementUpdate(updatedElement);\n }\n },\n [selectedElement, activeChildElement, handleElementUpdate]\n );\n\n // Track element ID to detect real selection changes\n const currentElementId = elementForProperties?.id;\n const prevElementIdRef = useRef<string | undefined>(undefined);\n\n // Local state for toolbar\n const [localFontSize, setLocalFontSize] = useState<number>(32);\n const [localFontColor, setLocalFontColor] = useState<string>('#333333');\n const [localFontFamily, setLocalFontFamily] = useState<string>('Arial');\n const [localTextAlign, setLocalTextAlign] = useState<TextAlign>('center');\n\n // Sync local state ONLY when element ID changes (selection change)\n useEffect(() => {\n if (currentElementId !== prevElementIdRef.current) {\n prevElementIdRef.current = currentElementId;\n\n if (elementForProperties && elementForProperties instanceof TextElement) {\n if (elementForProperties.transformType === 'circle' && 'getEffectiveFontSize' in elementForProperties) {\n setLocalFontSize(Math.round((elementForProperties as CircleTransform).getEffectiveFontSize()));\n } else if (elementForProperties.fontSize !== undefined) {\n setLocalFontSize(Math.round(elementForProperties.fontSize));\n }\n if (elementForProperties.color !== undefined) {\n setLocalFontColor(elementForProperties.color);\n }\n if (elementForProperties.fontFamily !== undefined) {\n setLocalFontFamily(elementForProperties.fontFamily);\n }\n setLocalTextAlign(elementForProperties.textAlign || 'center');\n }\n }\n }, [currentElementId, elementForProperties]);\n\n // Derived display values\n const fontSize = localFontSize;\n const fontColor = localFontColor;\n const fontFamily = localFontFamily;\n const textAlign = localTextAlign;\n\n // Element-level text style properties\n const textElement = elementForProperties instanceof TextElement ? elementForProperties : null;\n const letterSpacing = textElement?.letterSpacing ?? 0;\n const lineHeight = textElement?.lineHeight ?? 1.2;\n const bold = textElement?.bold ?? false;\n const italic = textElement?.italic ?? false;\n const underline = textElement?.underline ?? false;\n // letterCase is not declared in TextElement's type but is stored as a dynamic property at runtime\n const letterCase = (textElement as Record<string, unknown> | null)?.letterCase as string ?? 'none';\n\n // Commit handlers\n const setFontSizeValue = useCallback(\n (newSize: number) => {\n setLocalFontSize(newSize);\n if (!elementForProperties || !(elementForProperties instanceof TextElement)) return;\n\n const updatedElement = elementForProperties.clone();\n if (updatedElement.transformType === 'circle' && 'setEffectiveFontSize' in updatedElement) {\n (updatedElement as CircleTransform).setEffectiveFontSize(newSize);\n } else {\n updatedElement.setFontSize(newSize);\n }\n\n if (updatedElement.richText) {\n updatedElement.richText.clearStyleProperty('fontSize');\n }\n\n elementUpdateHandler(updatedElement);\n },\n [elementForProperties, elementUpdateHandler]\n );\n\n const updateFontFamily = useCallback(\n (newFamily: string) => {\n setLocalFontFamily(newFamily);\n if (!elementForProperties || !(elementForProperties instanceof TextElement)) return;\n\n const updatedElement = elementForProperties.clone();\n updatedElement.fontFamily = newFamily;\n\n if (updatedElement.richText) {\n updatedElement.richText.clearStyleProperty('fontFamily');\n }\n\n elementUpdateHandler(updatedElement);\n },\n [elementForProperties, elementUpdateHandler]\n );\n\n const updateFontColor = useCallback(\n (newColor: string) => {\n setLocalFontColor(newColor);\n if (!elementForProperties || !(elementForProperties instanceof TextElement)) return;\n\n const updatedElement = elementForProperties.clone();\n updatedElement.color = newColor;\n if (updatedElement.richText) {\n updatedElement.richText.clearStyleProperty('color');\n }\n elementUpdateHandler(updatedElement);\n },\n [elementForProperties, elementUpdateHandler]\n );\n\n const updateTextAlign = useCallback(\n (alignment: TextAlign) => {\n setLocalTextAlign(alignment);\n if (!elementForProperties || !(elementForProperties instanceof TextElement)) return;\n\n const updatedElement = elementForProperties.clone();\n updatedElement.textAlign = alignment;\n elementUpdateHandler(updatedElement);\n },\n [elementForProperties, elementUpdateHandler]\n );\n\n // Character-level aware handlers\n const handleFontSizeChange = useCallback(\n (newSize: number) => {\n if (canvasEditorRef?.current?.isEditingText()) {\n canvasEditorRef.current.applyTextFormatting({ fontSize: newSize });\n } else {\n setFontSizeValue(newSize);\n }\n },\n [setFontSizeValue, canvasEditorRef]\n );\n\n const handleFontSizeIncrement = useCallback(\n (delta: number) => {\n const newSize = fontSize + delta;\n if (newSize >= 8 && newSize <= 500) {\n handleFontSizeChange(newSize);\n }\n },\n [fontSize, handleFontSizeChange]\n );\n\n // Letter-spacing: per-character aware (mirror handleFontSizeChange).\n // Element-level set clears span-level overrides so the slider acts on the\n // whole element, same contract as font size.\n const handleLetterSpacingChange = useCallback(\n (newSpacing: number) => {\n if (canvasEditorRef?.current?.isEditingText()) {\n canvasEditorRef.current.applyTextFormatting({ letterSpacing: newSpacing });\n return;\n }\n if (!elementForProperties || !(elementForProperties instanceof TextElement)) return;\n\n const updatedElement = elementForProperties.clone();\n updatedElement.letterSpacing = newSpacing;\n if (updatedElement.richText) {\n updatedElement.richText.clearStyleProperty('letterSpacing');\n }\n elementUpdateHandler(updatedElement);\n },\n [elementForProperties, elementUpdateHandler, canvasEditorRef]\n );\n\n // Line-height: element-level only — a line's height is a property of the\n // line box, not of individual characters.\n const handleLineHeightChange = useCallback(\n (newLineHeight: number) => {\n if (!elementForProperties || !(elementForProperties instanceof TextElement)) return;\n\n const updatedElement = elementForProperties.clone();\n updatedElement.lineHeight = newLineHeight;\n elementUpdateHandler(updatedElement);\n },\n [elementForProperties, elementUpdateHandler]\n );\n\n const handleFontFamilyChange = useCallback(\n (newFamily: string) => {\n if (canvasEditorRef?.current?.isEditingText()) {\n canvasEditorRef.current.applyTextFormatting({ fontFamily: newFamily });\n } else {\n updateFontFamily(newFamily);\n }\n },\n [updateFontFamily, canvasEditorRef]\n );\n\n const handleFontColorChange = useCallback(\n (e: React.ChangeEvent<HTMLInputElement>) => {\n const newColor = e.target.value;\n const isEditing = canvasEditorRef?.current?.isEditingText();\n if (isEditing && canvasEditorRef?.current) {\n canvasEditorRef.current.applyTextFormatting({ color: newColor });\n } else {\n updateFontColor(newColor);\n }\n },\n [updateFontColor, canvasEditorRef]\n );\n\n const handleBoldToggle = useCallback(() => {\n if (canvasEditorRef?.current?.isEditingText()) {\n canvasEditorRef.current.toggleFormattingProperty('bold');\n } else {\n if (!elementForProperties || !(elementForProperties instanceof TextElement)) return;\n const updated = elementForProperties.clone();\n updated.bold = !bold;\n if (updated.richText) {\n updated.richText.clearStyleProperty('bold');\n }\n elementUpdateHandler(updated);\n }\n }, [bold, elementForProperties, elementUpdateHandler, canvasEditorRef]);\n\n const handleItalicToggle = useCallback(() => {\n if (canvasEditorRef?.current?.isEditingText()) {\n canvasEditorRef.current.toggleFormattingProperty('italic');\n } else {\n if (!elementForProperties || !(elementForProperties instanceof TextElement)) return;\n const updated = elementForProperties.clone();\n updated.italic = !italic;\n if (updated.richText) {\n updated.richText.clearStyleProperty('italic');\n }\n elementUpdateHandler(updated);\n }\n }, [italic, elementForProperties, elementUpdateHandler, canvasEditorRef]);\n\n const handleUnderlineToggle = useCallback(() => {\n if (canvasEditorRef?.current?.isEditingText()) {\n canvasEditorRef.current.toggleFormattingProperty('underline');\n } else {\n if (!elementForProperties || !(elementForProperties instanceof TextElement)) return;\n const updated = elementForProperties.clone();\n updated.underline = !underline;\n if (updated.richText) {\n updated.richText.clearStyleProperty('underline');\n }\n elementUpdateHandler(updated);\n }\n }, [underline, elementForProperties, elementUpdateHandler, canvasEditorRef]);\n\n const handleLetterCaseToggle = useCallback(() => {\n if (!elementForProperties) return;\n const newCase = letterCase === 'uppercase' ? 'none' : 'uppercase';\n const updated = elementForProperties.clone();\n // letterCase is not declared in TextElement's type but is stored as a dynamic property at runtime\n (updated as unknown as Record<string, unknown>).letterCase = newCase;\n elementUpdateHandler(updated);\n }, [letterCase, elementForProperties, elementUpdateHandler]);\n\n const isLetterCaseActive = useCallback(() => {\n return letterCase === 'uppercase';\n }, [letterCase]);\n\n const handleTextAlignToggle = useCallback(() => {\n const alignments: TextAlign[] = ['left', 'center', 'right'];\n const currentIndex = alignments.indexOf(textAlign);\n const nextAlign = alignments[(currentIndex + 1) % alignments.length];\n updateTextAlign(nextAlign);\n }, [textAlign, updateTextAlign]);\n\n // Get effective style (for rich text support)\n const getEffectiveStyle = useCallback((): CharacterStyle => {\n if (canvasEditorRef?.current?.isEditingText?.()) {\n const selectionStyle = canvasEditorRef.current.getSelectionStyle?.();\n if (selectionStyle) {\n return {\n fontFamily: selectionStyle.fontFamily ?? fontFamily,\n fontSize: selectionStyle.fontSize ?? fontSize,\n color: selectionStyle.color ?? fontColor,\n bold: selectionStyle.bold ?? bold,\n italic: selectionStyle.italic ?? italic,\n underline: selectionStyle.underline ?? underline,\n };\n }\n }\n return {\n fontFamily,\n fontSize,\n color: fontColor,\n bold,\n italic,\n underline,\n };\n }, [canvasEditorRef, fontFamily, fontSize, fontColor, bold, italic, underline]);\n\n // Transform type change handler\n const handleTransformTypeChange = useCallback(\n (newType: TransformType) => {\n if (!elementForProperties) return;\n\n const transformDef = getTransformById(newType);\n if (!transformDef?.Component) return;\n\n const updated = convertTransform(elementForProperties as TextElement, newType, transformDef.Component as unknown as new (config: Record<string, unknown>) => TextElement);\n elementUpdateHandler(updated);\n },\n [elementForProperties, elementUpdateHandler]\n );\n\n return {\n fontSize,\n fontColor,\n fontFamily,\n textAlign,\n bold,\n italic,\n underline,\n letterCase,\n letterSpacing,\n lineHeight,\n handleFontSizeChange,\n handleFontSizeIncrement,\n handleLetterSpacingChange,\n handleLineHeightChange,\n handleFontFamilyChange,\n handleFontColorChange,\n handleBoldToggle,\n handleItalicToggle,\n handleUnderlineToggle,\n handleLetterCaseToggle,\n isLetterCaseActive,\n handleTextAlignToggle,\n getEffectiveStyle,\n handleTransformTypeChange,\n };\n}\n","/**\n * useLayerPreview - Hook for generating element preview thumbnails\n *\n * Extracts the preview/thumbnail generation logic from LayersPanel's\n * LayerPreview component into a reusable hook. Handles async image loading\n * for ImageElements and synchronous preview generation for other element types.\n *\n * @example\n * ```tsx\n * function LayerThumbnail({ element }: { element: EditorElement }) {\n * const { previewUrl, isLoading } = useLayerPreview({\n * element,\n * size: 148,\n * backgroundColor: 'transparent',\n * });\n *\n * if (isLoading || !previewUrl) return <Spinner />;\n * return <img src={previewUrl} alt=\"\" />;\n * }\n * ```\n */\n\nimport { useState, useEffect, useRef } from 'react';\nimport { ImageElement } from '../core/ImageElement.js';\nimport { TextElement } from '../core/TextElement.js';\nimport { ShapeElement } from '../core/ShapeElement.js';\nimport { PathElement } from '../core/PathElement.js';\nimport { GroupElement } from '../core/GroupElement.js';\nimport { generateElementPreview } from '../utils/ElementPreviewRenderer.js';\nimport { createLogger } from '../utils/logger.js';\nimport type { EditorElement } from '../contexts/EditorContext.js';\n\nconst logger = createLogger('useLayerPreview');\n\nexport interface UseLayerPreviewOptions {\n /** The element to generate a preview for */\n element: EditorElement;\n /** Preview size in pixels (width and height). Default: 148 */\n size?: number;\n /** Background color for the preview. Default: 'transparent' */\n backgroundColor?: string;\n /** Whether preview generation is enabled. Default: true */\n enabled?: boolean;\n}\n\nexport interface UseLayerPreviewReturn {\n /** Data URL of the preview image, or null if not yet generated */\n previewUrl: string | null;\n /** Whether the preview is currently being generated */\n isLoading: boolean;\n}\n\n/**\n * Hook for generating element preview thumbnails.\n *\n * Handles image elements by waiting for the image to load before\n * generating the preview. For text, shape, path, and group elements,\n * the preview is generated synchronously.\n *\n * Automatically regenerates when visual properties change (position,\n * rotation, transform data, text content, image URL, etc.).\n *\n * Debounces regeneration with a 50ms delay to avoid excessive\n * canvas operations during rapid property changes.\n */\nexport function useLayerPreview(options: UseLayerPreviewOptions): UseLayerPreviewReturn {\n const { element, size = 148, backgroundColor = 'transparent', enabled = true } = options;\n\n const [previewUrl, setPreviewUrl] = useState<string | null>(null);\n const [isLoading, setIsLoading] = useState(false);\n const debounceRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n\n useEffect(() => {\n if (!enabled) {\n setPreviewUrl(null);\n setIsLoading(false);\n return;\n }\n\n let mounted = true;\n setIsLoading(true);\n\n // Clear any pending debounce\n if (debounceRef.current) {\n clearTimeout(debounceRef.current);\n }\n\n debounceRef.current = setTimeout(() => {\n const generatePreview = async () => {\n try {\n // For image elements, wait for the image to load first\n if (element instanceof ImageElement && element.imageUrl) {\n const img = new Image();\n img.crossOrigin = 'anonymous';\n\n await new Promise<void>((resolve, reject) => {\n img.onload = () => resolve();\n img.onerror = () => reject(new Error('Failed to load image'));\n img.src = element.imageUrl;\n });\n\n if (!mounted) return;\n }\n\n // Generate the preview\n const url = generateElementPreview(element, {\n width: size,\n height: size,\n padding: 8,\n backgroundColor,\n });\n\n if (mounted) {\n setPreviewUrl(url);\n setIsLoading(false);\n }\n } catch (error) {\n logger.warn('Failed to generate preview:', error);\n // Generate a fallback preview without the loaded image\n if (mounted) {\n const url = generateElementPreview(element, {\n width: size,\n height: size,\n padding: 8,\n backgroundColor,\n });\n setPreviewUrl(url);\n setIsLoading(false);\n }\n }\n };\n\n generatePreview();\n }, 50); // 50ms debounce\n\n return () => {\n mounted = false;\n if (debounceRef.current) {\n clearTimeout(debounceRef.current);\n }\n };\n }, [\n element.id,\n backgroundColor,\n size,\n enabled,\n // Re-generate preview when visual properties change\n element.x,\n element.y,\n element.rotation,\n // Reference comparison is sufficient — elements are cloned before modification\n element.transformData,\n element instanceof TextElement ? element.text : null,\n element instanceof TextElement ? element.fontSize : null,\n element instanceof TextElement ? element.fontFamily : null,\n element instanceof TextElement ? element.color : null,\n element instanceof ImageElement ? element.imageUrl : null,\n element instanceof ImageElement ? element.imageLoaded : null,\n element instanceof ImageElement ? element.isCropping : null,\n element instanceof ShapeElement ? element.transformData?.fillColor : null,\n element instanceof ShapeElement ? element.transformData?.fill : null,\n element instanceof PathElement ? element.transformData?.points?.length : null,\n element instanceof GroupElement ? element.children?.length : null,\n ]);\n\n return { previewUrl, isLoading };\n}\n","/**\n * LayerLeadingChip — leading slot for the contextual toolbar.\n *\n * Shows the selected element's thumbnail and a lock toggle, inline\n * with the rest of the toolbar buttons.\n *\n * The thumbnail uses `useLayerPreview` — the same hook the LayersPanel\n * uses to render real per-element previews via the canvas pipeline.\n * That way a star shape looks like a star, a rotated layer looks\n * rotated, and a masked / distressed layer reads accordingly. Earlier\n * versions used a hand-coded element-type-specific glyph (a square\n * for any shape, a single character for any text), which lied to the\n * user about what they had selected.\n *\n * The toolbar wrapper carries `data-preserve-selection` already, so\n * tapping the lock toggle won't trigger the document-level deselect\n * listener.\n *\n * The lock button uses `ToolbarButton` so it inherits the standard\n * toolbar sizing, the standard 20px icon, and the standard\n * `data-active='true'` \"selected\" styling.\n */\n\nimport { BaseElement } from '../core/BaseElement.js';\nimport { ToolbarButton } from './ui/toolbar-button.js';\nimport { useLayerPreview } from '../hooks/useLayerPreview.js';\nimport type { EditorElement } from '../contexts/EditorContext.js';\n\nexport function LayerLeadingChip({\n element,\n onToggleLock,\n onThumbnailClick,\n}: {\n element: BaseElement | null;\n onToggleLock: () => void;\n /** Optional click handler for the thumbnail. When provided, the\n * thumbnail becomes a button — typical use is to open the\n * \"Manage Layers\" drawer with the current layer focused. */\n onThumbnailClick?: () => void;\n}) {\n if (!element) return null;\n const locked = element.locked === true;\n return (\n <>\n <SelectionThumbnail\n element={element as EditorElement}\n onClick={onThumbnailClick}\n />\n <ToolbarButton\n icon={<LockIcon locked={locked} />}\n onClick={onToggleLock}\n active={locked}\n tooltip={locked ? 'Unlock layer' : 'Lock layer'}\n aria-label={locked ? 'Unlock layer' : 'Lock layer'}\n />\n </>\n );\n}\n\n// Outer cell is a button-sized slot for layout alignment with the\n// toolbar buttons. Inner thumbnail is icon-sized so it carries the\n// same visual weight as an icon. We render the actual preview from\n// `useLayerPreview` (already used by the LayersPanel) — for shapes\n// that means a star renders as a star, polygon as polygon, etc.\nfunction SelectionThumbnail({\n element,\n onClick,\n}: {\n element: EditorElement;\n onClick?: () => void;\n}) {\n // 64px source — small enough to be cheap to regenerate, big enough\n // that browser downscale to 20–24px stays sharp. Transparent bg\n // so the muted backdrop shows through the layer's empty space.\n const { previewUrl } = useLayerPreview({\n element,\n size: 64,\n backgroundColor: 'transparent',\n });\n\n const inner = (\n <span\n className=\"sc:size-6 sc:md:size-5 sc:rounded-md sc:shrink-0 sc:flex sc:items-center sc:justify-center sc:overflow-hidden\"\n style={{ background: 'var(--color-muted, rgba(120,120,120,0.18))' }}\n >\n {previewUrl ? (\n <img\n src={previewUrl}\n alt=\"\"\n style={{ width: '100%', height: '100%', objectFit: 'contain' }}\n />\n ) : null}\n </span>\n );\n\n // When a click handler is wired (e.g. open layers drawer), render\n // the cell as a button so it gets the standard hover affordance and\n // keyboard focus. Otherwise keep it as a plain decorative span.\n if (onClick) {\n return (\n <button\n type=\"button\"\n onClick={onClick}\n onPointerDown={(e) => e.stopPropagation()}\n onPointerUp={(e) => e.stopPropagation()}\n aria-label=\"Manage layers\"\n title=\"Manage layers\"\n className=\"sc:size-11 sc:md:size-9 sc:shrink-0 sc:flex sc:items-center sc:justify-center\"\n >\n {inner}\n </button>\n );\n }\n return (\n <span\n aria-hidden\n className=\"sc:size-11 sc:md:size-9 sc:shrink-0 sc:flex sc:items-center sc:justify-center\"\n >\n {inner}\n </span>\n );\n}\n\n// 20px lock icon (size-5) matches the other toolbar icons. Closed\n// shackle when locked, open shackle when unlocked. `currentColor`\n// so the data-active=true styling tints the icon too.\nfunction LockIcon({ locked }: { locked: boolean }) {\n return (\n <svg width=\"20\" height=\"20\" viewBox=\"0 0 20 20\" fill=\"none\" aria-hidden>\n <rect\n x=\"4\"\n y=\"9\"\n width=\"12\"\n height=\"8.5\"\n rx=\"1.6\"\n stroke=\"currentColor\"\n strokeWidth=\"1.6\"\n fill={locked ? 'currentColor' : 'none'}\n fillOpacity={locked ? 0.18 : 0}\n />\n {locked ? (\n <path\n d=\"M6.5 9V6.25a3.5 3.5 0 0 1 7 0V9\"\n stroke=\"currentColor\"\n strokeWidth=\"1.6\"\n strokeLinecap=\"round\"\n />\n ) : (\n <path\n d=\"M6.5 9V6.25a3.5 3.5 0 0 1 7 0\"\n stroke=\"currentColor\"\n strokeWidth=\"1.6\"\n strokeLinecap=\"round\"\n />\n )}\n </svg>\n );\n}\n","/**\n * alignDistribute - Pure geometry for explicit align / distribute commands.\n *\n * The snap system (`AlignmentSnapSystem`) draws guides WHILE dragging; this\n * module is the other half: explicit \"align left / center / distribute\"\n * commands applied to a selection in one shot.\n *\n * Everything here is pure — element bboxes in, new positions out. The caller\n * (see `useAlignDistribute`) owns selection semantics, locked-element\n * filtering, and applying the result through the command history so one undo\n * reverts the whole operation.\n *\n * Coordinate model (gotcha #19 in packages/canvas/CLAUDE.md): `bbox` is the\n * CONCEPTUAL `getBoundingBox()` rect (x/y = top-left of the rect transform\n * handles act on), while an element's own `x`/`y` is its position field —\n * for most elements the CENTER point, NOT the bbox top-left. To stay correct\n * for every element type we never assume where `x` sits inside the bbox:\n * we compute the delta that moves the bbox where it should go and shift the\n * position field by the same delta.\n */\n\nimport { EditorError } from '../errors/editorError.js';\nimport type { BoundingBox } from '../types/index.js';\n\n/** Minimum number of movable elements for a distribute operation. */\nexport const DISTRIBUTE_MIN_COUNT = 3;\n\n/** Minimum number of elements for aligning relative to the selection itself\n * (below this the caller should align relative to the artboard). */\nexport const ALIGN_SELECTION_MIN_COUNT = 2;\n\nexport type AlignMode = 'left' | 'center-h' | 'right' | 'top' | 'center-v' | 'bottom';\nexport type DistributeMode = 'horizontal' | 'vertical';\n\n/** Geometry of one alignable element. `x`/`y` is the element's position\n * field (center point for canvas elements); `bbox` its conceptual\n * `getBoundingBox()` rect in the same world coordinates. */\nexport interface AlignableItem {\n id: string;\n x: number;\n y: number;\n bbox: BoundingBox;\n}\n\n/** New value for an element's position field. */\nexport interface PositionUpdate {\n id: string;\n x: number;\n y: number;\n}\n\n/** Union of the items' bboxes. Returns null for an empty list. */\nexport function combinedBounds(items: readonly AlignableItem[]): BoundingBox | null {\n if (items.length === 0) return null;\n let minX = Infinity;\n let minY = Infinity;\n let maxX = -Infinity;\n let maxY = -Infinity;\n for (const item of items) {\n minX = Math.min(minX, item.bbox.x);\n minY = Math.min(minY, item.bbox.y);\n maxX = Math.max(maxX, item.bbox.x + item.bbox.width);\n maxY = Math.max(maxY, item.bbox.y + item.bbox.height);\n }\n return { x: minX, y: minY, width: maxX - minX, height: maxY - minY };\n}\n\n/**\n * Align every item's bbox to `frame` (the selection's combined bounds, or the\n * artboard rect for a single element). Returns position updates ONLY for\n * items that actually move, so callers can batch exactly the real changes.\n */\nexport function computeAlign(\n items: readonly AlignableItem[],\n mode: AlignMode,\n frame: BoundingBox\n): PositionUpdate[] {\n const updates: PositionUpdate[] = [];\n for (const item of items) {\n let dx = 0;\n let dy = 0;\n switch (mode) {\n case 'left':\n dx = frame.x - item.bbox.x;\n break;\n case 'center-h':\n dx = frame.x + frame.width / 2 - (item.bbox.x + item.bbox.width / 2);\n break;\n case 'right':\n dx = frame.x + frame.width - (item.bbox.x + item.bbox.width);\n break;\n case 'top':\n dy = frame.y - item.bbox.y;\n break;\n case 'center-v':\n dy = frame.y + frame.height / 2 - (item.bbox.y + item.bbox.height / 2);\n break;\n case 'bottom':\n dy = frame.y + frame.height - (item.bbox.y + item.bbox.height);\n break;\n }\n if (dx !== 0 || dy !== 0) {\n updates.push({ id: item.id, x: item.x + dx, y: item.y + dy });\n }\n }\n return updates;\n}\n\n/**\n * Distribute items along one axis with EQUAL GAPS between bbox edges. The\n * outermost items (first/last along the axis) stay put; everything between\n * is repositioned. Requires at least {@link DISTRIBUTE_MIN_COUNT} items —\n * with fewer there is nothing between the ends to distribute, so calling\n * this is a contradiction and throws (`E_DISTRIBUTE_MIN_THREE`), never a\n * silent no-op. UI callers must not render distribute affordances below the\n * threshold (see `useAlignDistribute().canDistribute`).\n */\nexport function computeDistribute(\n items: readonly AlignableItem[],\n mode: DistributeMode\n): PositionUpdate[] {\n if (items.length < DISTRIBUTE_MIN_COUNT) {\n throw new EditorError(\n 'E_DISTRIBUTE_MIN_THREE',\n `distribute ${mode} needs at least ${DISTRIBUTE_MIN_COUNT} movable elements, got ${items.length}. ` +\n `Gate the action on useAlignDistribute().canDistribute (or items.length >= DISTRIBUTE_MIN_COUNT) ` +\n `instead of calling computeDistribute below the threshold.`,\n { mode, count: items.length, min: DISTRIBUTE_MIN_COUNT }\n );\n }\n\n const horizontal = mode === 'horizontal';\n const sorted = [...items].sort((a, b) =>\n horizontal\n ? a.bbox.x + a.bbox.width / 2 - (b.bbox.x + b.bbox.width / 2)\n : a.bbox.y + a.bbox.height / 2 - (b.bbox.y + b.bbox.height / 2)\n );\n\n const first = sorted[0];\n const last = sorted[sorted.length - 1];\n const span = horizontal\n ? last.bbox.x + last.bbox.width - first.bbox.x\n : last.bbox.y + last.bbox.height - first.bbox.y;\n const totalSize = sorted.reduce(\n (sum, item) => sum + (horizontal ? item.bbox.width : item.bbox.height),\n 0\n );\n const gap = (span - totalSize) / (sorted.length - 1);\n\n const updates: PositionUpdate[] = [];\n let cursor = horizontal ? first.bbox.x : first.bbox.y;\n for (const item of sorted) {\n const current = horizontal ? item.bbox.x : item.bbox.y;\n const delta = cursor - current;\n if (delta !== 0) {\n updates.push({\n id: item.id,\n x: item.x + (horizontal ? delta : 0),\n y: item.y + (horizontal ? 0 : delta),\n });\n }\n cursor += (horizontal ? item.bbox.width : item.bbox.height) + gap;\n }\n return updates;\n}\n","/**\n * useAlignDistribute - Explicit align / distribute commands for the current\n * selection, applied as ONE undo step.\n *\n * Semantics:\n * - Targets are the multi-selection if active, otherwise the single selected\n * element.\n * - `locked` elements are excluded entirely — they neither move nor serve as\n * an alignment reference (lock gates manipulation, gotcha #20; align IS\n * manipulation, unlike select/delete).\n * - With ≥2 movable elements, align is relative to the selection's combined\n * bbox; with exactly 1, align is relative to the active artboard (\"center\n * on artboard\").\n * - Distribute needs ≥3 movable elements. Below the threshold the action is\n * unavailable (`canDistribute` is false — UI must not render the buttons);\n * calling `distribute()` anyway throws `E_DISTRIBUTE_MIN_THREE` from the\n * pure layer, never a silent no-op.\n * - All moves go through `executeCommandBatch` (clone-before-modify), so a\n * single undo reverts the whole align/distribute.\n */\n\nimport { useCallback, useMemo } from 'react';\nimport { useEditor } from '../contexts/EditorContext.js';\nimport type { EditorElement } from '../contexts/EditorContext.js';\nimport {\n combinedBounds,\n computeAlign,\n computeDistribute,\n ALIGN_SELECTION_MIN_COUNT,\n DISTRIBUTE_MIN_COUNT,\n type AlignMode,\n type AlignableItem,\n type DistributeMode,\n type PositionUpdate,\n} from '../utils/alignDistribute.js';\n\nexport type { AlignMode, DistributeMode } from '../utils/alignDistribute.js';\n\nexport interface UseAlignDistributeResult {\n /** Number of movable (selected, unlocked) elements. */\n movableCount: number;\n /** True when align commands have something to act on. */\n canAlign: boolean;\n /** True when distribute commands are available (≥3 movable elements).\n * UI must gate rendering of distribute affordances on this. */\n canDistribute: boolean;\n /** Align the movable selection. ≥2 elements: relative to the selection's\n * combined bbox; exactly 1: relative to the active artboard. */\n align: (mode: AlignMode) => void;\n /** Distribute the movable selection with equal gaps between bbox edges.\n * Throws `E_DISTRIBUTE_MIN_THREE` when `canDistribute` is false. */\n distribute: (mode: DistributeMode) => void;\n}\n\nexport function useAlignDistribute(): UseAlignDistributeResult {\n const { elements, multiSelection, selectedElement, artboardManager, executeCommandBatch, setElements } =\n useEditor();\n\n // Movable targets: the multi-selection (or single selection), minus locked\n // elements — lock gates manipulation (gotcha #20), and align moves things.\n const movableElements = useMemo(() => {\n const selected =\n multiSelection.length > 0\n ? elements.filter((el) => multiSelection.includes(el.id))\n : selectedElement\n ? [selectedElement]\n : [];\n return selected.filter((el) => !el.locked);\n }, [elements, multiSelection, selectedElement]);\n\n const applyUpdates = useCallback(\n (updates: PositionUpdate[]) => {\n if (updates.length === 0) return;\n const byId = new Map(movableElements.map((el) => [el.id, el]));\n const commands = updates.flatMap((update) => {\n const oldElement = byId.get(update.id);\n if (!oldElement) return [];\n // Clone-before-modify: the old reference stays untouched for undo.\n const newElement = oldElement.clone() as EditorElement;\n newElement.x = update.x;\n newElement.y = update.y;\n const replaceWith = (el: EditorElement) => {\n setElements((prev) => prev.map((s) => (s.id === el.id ? el : s)));\n };\n return [{ execute: () => replaceWith(newElement), undo: () => replaceWith(oldElement) }];\n });\n // One CompoundCommand on the active artboard → one undo step.\n executeCommandBatch(commands);\n },\n [movableElements, executeCommandBatch, setElements]\n );\n\n const align = useCallback(\n (mode: AlignMode) => {\n const items: AlignableItem[] = movableElements.map((el) => ({\n id: el.id,\n x: el.x,\n y: el.y,\n bbox: el.getBoundingBox(),\n }));\n let frame = items.length >= ALIGN_SELECTION_MIN_COUNT ? combinedBounds(items) : null;\n if (!frame) {\n // Single element (or selection bbox unavailable): align to artboard.\n const artboard = artboardManager.getActiveArtboard();\n if (!artboard) return;\n frame = { x: artboard.x, y: artboard.y, width: artboard.width, height: artboard.height };\n }\n applyUpdates(computeAlign(items, mode, frame));\n },\n [movableElements, artboardManager, applyUpdates]\n );\n\n const distribute = useCallback(\n (mode: DistributeMode) => {\n const items: AlignableItem[] = movableElements.map((el) => ({\n id: el.id,\n x: el.x,\n y: el.y,\n bbox: el.getBoundingBox(),\n }));\n // Below DISTRIBUTE_MIN_COUNT the pure layer throws E_DISTRIBUTE_MIN_THREE.\n applyUpdates(computeDistribute(items, mode));\n },\n [movableElements, applyUpdates]\n );\n\n return {\n movableCount: movableElements.length,\n canAlign: movableElements.length >= 1,\n canDistribute: movableElements.length >= DISTRIBUTE_MIN_COUNT,\n align,\n distribute,\n };\n}\n\nexport default useAlignDistribute;\n","/**\n * Shared align / distribute button definitions.\n *\n * One source of truth for the icon + label + mode of each alignment command,\n * consumed by BOTH alignment surfaces:\n * - `MultiSelectionToolbar` (≥2 selected: align relative to the selection)\n * - `AlignPanel` (single selection: align relative to the artboard)\n *\n * Keeping the defs in one module guarantees the two surfaces can't drift —\n * same icons, same labels, same `data-testid` vocabulary (`align-<mode>`).\n */\n\nimport type { AlignMode, DistributeMode } from '../../utils/alignDistribute.js';\n\nexport interface AlignButtonDef {\n mode: AlignMode;\n icon: string;\n label: string;\n}\n\nexport interface DistributeButtonDef {\n mode: DistributeMode;\n icon: string;\n label: string;\n}\n\nexport const ALIGN_BUTTONS: readonly AlignButtonDef[] = [\n { mode: 'left', icon: 'gravity-ui:objects-align-left', label: 'Align left' },\n { mode: 'center-h', icon: 'gravity-ui:objects-align-center-horizontal', label: 'Align horizontal centers' },\n { mode: 'right', icon: 'gravity-ui:objects-align-right', label: 'Align right' },\n { mode: 'top', icon: 'gravity-ui:objects-align-top', label: 'Align top' },\n { mode: 'center-v', icon: 'gravity-ui:objects-align-center-vertical', label: 'Align vertical centers' },\n { mode: 'bottom', icon: 'gravity-ui:objects-align-bottom', label: 'Align bottom' },\n] as const;\n\nexport const DISTRIBUTE_BUTTONS: readonly DistributeButtonDef[] = [\n { mode: 'horizontal', icon: 'gravity-ui:objects-align-justify-horizontal', label: 'Distribute horizontally' },\n { mode: 'vertical', icon: 'gravity-ui:objects-align-justify-vertical', label: 'Distribute vertically' },\n] as const;\n","/**\n * MultiSelectionToolbar - Contextual toolbar for multi-element selections.\n *\n * Rendered by `ContextualToolbars` whenever a multi-selection is active (the\n * per-element toolbars only handle single selections). Provides the explicit\n * align / distribute commands (`useAlignDistribute`):\n *\n * - Align buttons act relative to the selection's combined bbox (or the\n * artboard when only one movable element remains after locked filtering).\n * - Distribute buttons are NOT RENDERED below 3 movable elements — the wrong\n * state is unrepresentable in the UI (the pure layer additionally throws\n * `E_DISTRIBUTE_MIN_THREE` for programmatic misuse).\n * - Locked elements neither move nor act as a reference.\n *\n * Each command lands as ONE undo step (CompoundCommand batch).\n *\n * Floating mode portals to `document.body` and anchors above the selection's\n * combined bbox using the same screen mapping + resize/scroll listeners as\n * the single-selection toolbar (class-3 anchoring contract, ADR-0085 §5).\n */\n\nimport React, { useEffect, useMemo, useRef, useState } from 'react';\nimport { createPortal } from 'react-dom';\nimport { useEditor } from '../contexts/EditorContext.js';\nimport { useViewportContext } from '../contexts/ViewportContext.js';\nimport { useAlignDistribute } from '../hooks/useAlignDistribute.js';\nimport { combinedBounds, type AlignableItem } from '../utils/alignDistribute.js';\nimport { ALIGN_BUTTONS, DISTRIBUTE_BUTTONS } from './toolbars/alignButtons.js';\nimport { ToolbarButton } from './ui/index.js';\n\nexport interface MultiSelectionToolbarProps {\n /** Positioning mode — mirrors `ContextualToolbars`. */\n mode?: 'floating' | 'embedded';\n /** Artboard screen bounds fallback when no canvas ref is available. */\n artboardScreenBounds?: {\n left: number;\n top: number;\n width: number;\n height: number;\n bottom: number;\n centerX: number;\n };\n /** `data-sc-part` value for the toolbar root (Editor.* parts contract). */\n partAttr?: string;\n}\n\nexport const MultiSelectionToolbar: React.FC<MultiSelectionToolbarProps> = ({\n mode = 'floating',\n artboardScreenBounds,\n partAttr,\n}) => {\n const { elements, multiSelection, artboardManager, canvasRef, canvasEditorRef } = useEditor();\n const { panOffset } = useViewportContext();\n const { canAlign, canDistribute, align, distribute } = useAlignDistribute();\n\n const toolbarRef = useRef<HTMLDivElement>(null);\n const [position, setPosition] = useState<{ top: number; left: number } | null>(null);\n\n // Combined world-space bounds of the multi-selection (all selected\n // elements, locked included — the toolbar anchors to what the user sees).\n const selectionBounds = useMemo(() => {\n const items: AlignableItem[] = elements\n .filter((el) => multiSelection.includes(el.id))\n .map((el) => ({ id: el.id, x: el.x, y: el.y, bbox: el.getBoundingBox() }));\n return combinedBounds(items);\n }, [elements, multiSelection]);\n\n // ── Floating position: anchor above the selection bbox ─────────────────\n // Same screen mapping + resize/scroll listeners as the single-selection\n // toolbar in ContextualToolbars (capture-phase scroll for nested scrollers).\n useEffect(() => {\n if (mode !== 'floating') return;\n if (!selectionBounds) {\n setPosition(null);\n return;\n }\n\n const updatePosition = () => {\n const toolbarWidth = toolbarRef.current?.offsetWidth || 0;\n const toolbarHeight = toolbarRef.current?.offsetHeight || 48;\n const activeArtboard = artboardManager.getActiveArtboard();\n const artboardX = activeArtboard?.x || 0;\n const artboardY = activeArtboard?.y || 0;\n const currentZoom = canvasEditorRef?.current?.getZoom?.() || 1;\n const canvas = canvasRef?.current;\n\n let screenX: number;\n let screenY: number;\n if (canvas) {\n const canvasRect = canvas.getBoundingClientRect();\n screenX = canvasRect.left + (selectionBounds.x - artboardX) * currentZoom;\n screenY = canvasRect.top + (selectionBounds.y - artboardY) * currentZoom;\n } else if (artboardScreenBounds) {\n screenX = artboardScreenBounds.left + (selectionBounds.x - artboardX) * currentZoom;\n screenY = artboardScreenBounds.top + (selectionBounds.y - artboardY) * currentZoom;\n } else {\n screenX = window.innerWidth / 2 - (selectionBounds.width * currentZoom) / 2;\n screenY = window.innerHeight / 2 - (selectionBounds.height * currentZoom) / 2;\n }\n const screenWidth = selectionBounds.width * currentZoom;\n const screenHeight = selectionBounds.height * currentZoom;\n\n const gap = 12;\n let top = screenY - toolbarHeight - gap;\n let left = screenX + screenWidth / 2;\n\n if (toolbarWidth > 0) {\n const padding = 20;\n const minLeft = toolbarWidth / 2 + padding;\n const maxLeft = window.innerWidth - toolbarWidth / 2 - padding;\n left = Math.max(minLeft, Math.min(maxLeft, left));\n }\n if (top < 10) {\n top = screenY + screenHeight + gap;\n }\n top = Math.min(top, window.innerHeight - toolbarHeight - 10);\n top = Math.max(10, top);\n\n setPosition({ top, left });\n };\n\n updatePosition();\n window.addEventListener('resize', updatePosition);\n window.addEventListener('scroll', updatePosition, { passive: true, capture: true });\n return () => {\n window.removeEventListener('resize', updatePosition);\n window.removeEventListener('scroll', updatePosition, { capture: true });\n };\n }, [mode, selectionBounds, artboardManager, canvasRef, canvasEditorRef, artboardScreenBounds, panOffset]);\n\n if (!canAlign || multiSelection.length === 0) return null;\n\n const style: React.CSSProperties =\n mode === 'embedded'\n ? { borderRadius: '9999px', position: 'static', display: 'flex', justifyContent: 'flex-start' }\n : position\n ? {\n top: `${position.top}px`,\n left: `${position.left}px`,\n position: 'fixed',\n transform: 'translateX(-50%)',\n borderRadius: '9999px',\n zIndex: 'var(--sc-z-tooltip)' as React.CSSProperties['zIndex'],\n }\n : {\n borderRadius: '9999px',\n visibility: 'hidden',\n position: 'fixed',\n top: '-9999px',\n left: '-9999px',\n zIndex: 'var(--sc-z-tooltip)' as React.CSSProperties['zIndex'],\n };\n\n const content = (\n <div\n ref={toolbarRef}\n className=\"sc-toolbar\"\n data-sc-part={partAttr ?? 'multi-selection-toolbar'}\n data-testid=\"multi-selection-toolbar\"\n data-mode={mode}\n data-preserve-selection\n style={style}\n >\n <div className=\"sc-toolbar-items\">\n {ALIGN_BUTTONS.map(({ mode: alignMode, icon, label }) => (\n <ToolbarButton\n key={alignMode}\n icon={icon}\n onClick={() => align(alignMode)}\n tooltip={label}\n data-testid={`align-${alignMode}`}\n />\n ))}\n {/* Distribute needs ≥3 movable elements — below the threshold the\n buttons do not exist (no disabled state to mis-click), matching\n the E_DISTRIBUTE_MIN_THREE contract in the pure layer. */}\n {canDistribute &&\n DISTRIBUTE_BUTTONS.map(({ mode: distMode, icon, label }) => (\n <ToolbarButton\n key={distMode}\n icon={icon}\n onClick={() => distribute(distMode)}\n tooltip={label}\n data-testid={`distribute-${distMode}`}\n />\n ))}\n </div>\n </div>\n );\n\n return mode === 'floating' ? createPortal(content, document.body) : content;\n};\n\nexport default MultiSelectionToolbar;\n","/**\n * GroupElementToolbar - Toolbar for group element controls.\n *\n * Shows when a group element is selected (not when editing a child within it).\n * Provides stroke, rotation, transparency, and ungroup controls.\n */\n\nimport React, { useState } from 'react';\nimport {\n Tooltip,\n TooltipTrigger,\n TooltipContent,\n ToolbarButton,\n Button,\n RotateLeftIcon,\n} from '../ui/index.js';\nimport { getFeatureApplied } from '../../utils/featureApplied.js';\nimport type { GroupElement } from '../../core/GroupElement.js';\n\nexport interface GroupElementToolbarProps {\n /** The group element being edited — used to derive feature-applied\n * flags so the toolbar buttons highlight when a property is set. */\n element?: GroupElement;\n /** Whether the rotation panel is expanded */\n rotationExpanded?: boolean;\n /** Callback when rotation panel should be toggled */\n onRotationToggle: () => void;\n /** Whether the opacity panel is expanded */\n opacityExpanded?: boolean;\n /** Callback when opacity panel should be toggled */\n onOpacityToggle: () => void;\n /** Whether the stroke panel is expanded */\n strokeExpanded?: boolean;\n /** Callback when stroke panel should be toggled */\n onStrokeToggle?: () => void;\n /** Whether the shadow panel is expanded */\n shadowExpanded?: boolean;\n /** Callback when shadow panel should be toggled */\n onShadowToggle?: () => void;\n /** Whether the blend mode panel is expanded */\n blendModeExpanded?: boolean;\n /** Callback when blend mode panel should be toggled */\n onBlendModeToggle?: () => void;\n /** Whether the knockout panel is expanded */\n knockoutExpanded?: boolean;\n /** Callback when knockout panel should be toggled */\n onKnockoutToggle?: () => void;\n /** Whether the distress texture panel is expanded */\n distressTextureExpanded?: boolean;\n /** Callback when distress texture panel should be toggled */\n onDistressTextureToggle?: () => void;\n /** Whether the image mask panel is expanded */\n imageMaskExpanded?: boolean;\n /** Callback when image mask panel should be toggled */\n onImageMaskToggle?: () => void;\n /** Callback when the group should be ungrouped */\n onUngroup: () => void;\n}\n\nexport const GroupElementToolbar: React.FC<GroupElementToolbarProps> = ({\n element,\n rotationExpanded = false,\n onRotationToggle,\n opacityExpanded = false,\n onOpacityToggle,\n strokeExpanded = false,\n onStrokeToggle,\n shadowExpanded = false,\n onShadowToggle,\n blendModeExpanded = false,\n onBlendModeToggle,\n knockoutExpanded = false,\n onKnockoutToggle,\n distressTextureExpanded = false,\n onDistressTextureToggle,\n imageMaskExpanded = false,\n onImageMaskToggle,\n onUngroup,\n}) => {\n const [rotationTooltipDisabled, setRotationTooltipDisabled] = useState(false);\n const [opacityTooltipDisabled, setOpacityTooltipDisabled] = useState(false);\n const [strokeTooltipDisabled, setStrokeTooltipDisabled] = useState(false);\n const [shadowTooltipDisabled, setShadowTooltipDisabled] = useState(false);\n const [blendModeTooltipDisabled, setBlendModeTooltipDisabled] = useState(false);\n const [knockoutTooltipDisabled, setKnockoutTooltipDisabled] = useState(false);\n const [distressTooltipDisabled, setDistressTooltipDisabled] = useState(false);\n const [imageMaskTooltipDisabled, setImageMaskTooltipDisabled] = useState(false);\n\n // Feature-applied flags — drive the \"selected\" highlight on the\n // toolbar buttons whose underlying property has been set to a\n // non-default value on the group element.\n const applied = getFeatureApplied(element ?? null);\n\n return (\n <div className=\"sc-toolbar-items\">\n {/* Rotation */}\n <ToolbarButton\n icon={<RotateLeftIcon size={20} className=\"sc:md:size-5\" />}\n onClick={() => {\n setRotationTooltipDisabled(true);\n onRotationToggle();\n }}\n onMouseLeave={() => setRotationTooltipDisabled(false)}\n tooltip=\"Rotate\"\n tooltipDisabled={rotationTooltipDisabled || rotationExpanded}\n active={rotationExpanded || applied.rotation}\n />\n\n {/* Transparency */}\n <ToolbarButton\n icon=\"lucide:blend\"\n onClick={() => {\n setOpacityTooltipDisabled(true);\n onOpacityToggle();\n }}\n onMouseLeave={() => setOpacityTooltipDisabled(false)}\n tooltip=\"Transparency\"\n tooltipDisabled={opacityTooltipDisabled || opacityExpanded}\n active={opacityExpanded || applied.opacity}\n />\n\n {/* Stroke */}\n {onStrokeToggle && (\n <ToolbarButton\n icon=\"lucide:pen-line\"\n onClick={() => {\n setStrokeTooltipDisabled(true);\n onStrokeToggle();\n }}\n onMouseLeave={() => setStrokeTooltipDisabled(false)}\n tooltip=\"Stroke\"\n tooltipDisabled={strokeTooltipDisabled || strokeExpanded}\n active={strokeExpanded || applied.stroke}\n />\n )}\n\n {/* Shadow */}\n {onShadowToggle && (\n <ToolbarButton\n icon=\"gravity-ui:square-dashed-circle\"\n onClick={() => {\n setShadowTooltipDisabled(true);\n onShadowToggle();\n }}\n onMouseLeave={() => setShadowTooltipDisabled(false)}\n tooltip=\"Shadow\"\n tooltipDisabled={shadowTooltipDisabled || shadowExpanded}\n active={shadowExpanded || applied.shadow}\n />\n )}\n\n {/* Blend Mode */}\n {onBlendModeToggle && (\n <ToolbarButton\n icon=\"gravity-ui:circles-intersection\"\n onClick={() => {\n setBlendModeTooltipDisabled(true);\n onBlendModeToggle();\n }}\n onMouseLeave={() => setBlendModeTooltipDisabled(false)}\n tooltip=\"Blend Mode\"\n tooltipDisabled={blendModeTooltipDisabled || blendModeExpanded}\n active={blendModeExpanded || applied.blendMode}\n />\n )}\n\n {/* Knockout */}\n {onKnockoutToggle && (\n <ToolbarButton\n icon=\"lucide:scissors\"\n onClick={() => {\n setKnockoutTooltipDisabled(true);\n onKnockoutToggle();\n }}\n onMouseLeave={() => setKnockoutTooltipDisabled(false)}\n tooltip=\"Knockout\"\n tooltipDisabled={knockoutTooltipDisabled || knockoutExpanded}\n active={knockoutExpanded || applied.knockout}\n />\n )}\n\n {/* Distress Texture */}\n {onDistressTextureToggle && (\n <ToolbarButton\n icon=\"lucide:stamp\"\n onClick={() => {\n setDistressTooltipDisabled(true);\n onDistressTextureToggle();\n }}\n onMouseLeave={() => setDistressTooltipDisabled(false)}\n tooltip=\"Distress Texture\"\n tooltipDisabled={distressTooltipDisabled || distressTextureExpanded}\n active={distressTextureExpanded || applied.distress}\n />\n )}\n\n {/* Image Mask */}\n {onImageMaskToggle && (\n <ToolbarButton\n icon=\"lucide:venetian-mask\"\n onClick={() => {\n setImageMaskTooltipDisabled(true);\n onImageMaskToggle();\n }}\n onMouseLeave={() => setImageMaskTooltipDisabled(false)}\n tooltip=\"Image Mask\"\n tooltipDisabled={imageMaskTooltipDisabled || imageMaskExpanded}\n active={imageMaskExpanded || applied.imageMask}\n />\n )}\n\n <Tooltip delayDuration={300}>\n <TooltipTrigger asChild>\n <Button variant=\"ghost\" size=\"sm\" onClick={onUngroup}>\n Ungroup\n </Button>\n </TooltipTrigger>\n <TooltipContent>Ungroup this group</TooltipContent>\n </Tooltip>\n </div>\n );\n};\n\nexport default GroupElementToolbar;\n","/**\n * CropPanel - Reusable crop controls for image elements\n *\n * Can be used standalone in a drawer or embedded in the contextual toolbar.\n * Provides anchor point selection and width/height sliders.\n *\n * @example\n * // In a drawer\n * <Drawer open={cropDrawerOpen} onOpenChange={setCropDrawerOpen}>\n * <DrawerContent>\n * <CropPanel\n * element={selectedImageElement}\n * onElementUpdate={handleElementUpdate}\n * />\n * </DrawerContent>\n * </Drawer>\n */\n\nimport React, { useState, useCallback, useRef, useEffect } from 'react';\nimport { Slider } from './ui';\nimport { ImageElement } from '../core/ImageElement.js';\nimport { cn } from '../lib/utils.js';\n\n/**\n * TouchGuard - Wraps interactive elements to prevent parent scroll from capturing touches\n *\n * Uses native event listeners with { passive: false } because:\n * 1. React's synthetic events can't properly preventDefault on touch events\n * 2. CSS touch-action: none is evaluated at gesture start on the ancestor chain,\n * so a parent with pan-y can still capture the gesture before child CSS applies\n * 3. Native listeners with passive: false intercept events before the browser decides to scroll\n */\nfunction TouchGuard({ children, className }: { children: React.ReactNode; className?: string }) {\n const ref = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n const el = ref.current;\n if (!el) return;\n\n const handleTouchStart = (e: TouchEvent) => {\n // Stop the event from reaching parent scroll containers\n e.stopPropagation();\n };\n\n const handleTouchMove = (e: TouchEvent) => {\n // Prevent default scroll behavior and stop propagation\n e.preventDefault();\n e.stopPropagation();\n };\n\n // Must use passive: false to allow preventDefault\n el.addEventListener('touchstart', handleTouchStart, { passive: false });\n el.addEventListener('touchmove', handleTouchMove, { passive: false });\n\n return () => {\n el.removeEventListener('touchstart', handleTouchStart);\n el.removeEventListener('touchmove', handleTouchMove);\n };\n }, []);\n\n return (\n <div ref={ref} className={className} style={{ touchAction: 'none' }}>\n {children}\n </div>\n );\n}\n\ntype CropAnchor =\n | 'top-left'\n | 'top-center'\n | 'top-right'\n | 'middle-left'\n | 'center'\n | 'middle-right'\n | 'bottom-left'\n | 'bottom-center'\n | 'bottom-right';\n\nexport interface CropPanelProps {\n /** The image element to crop */\n element: ImageElement;\n /** Callback when element is updated */\n onElementUpdate: (element: ImageElement) => void;\n /** Optional class name for the container */\n className?: string;\n}\n\n/**\n * CropPanel - Controls for cropping image elements\n *\n * Provides:\n * - 3x3 anchor grid for selecting resize origin\n * - Width slider (10-100%)\n * - Height slider (10-100%)\n */\nexport const CropPanel: React.FC<CropPanelProps> = ({ element, onElementUpdate, className }) => {\n // Crop anchor point - determines where the crop resizes from\n const [cropAnchor, setCropAnchor] = useState<CropAnchor>('center');\n\n // Block horizontal touch movement to prevent drawer/page from being dragged\n const containerRef = useRef<HTMLDivElement>(null);\n const touchStartPos = useRef({ x: 0, y: 0 });\n useEffect(() => {\n const el = containerRef.current;\n if (!el) return;\n\n const handleTouchStart = (e: TouchEvent) => {\n touchStartPos.current = {\n x: e.touches[0].clientX,\n y: e.touches[0].clientY,\n };\n };\n\n const handleTouchMove = (e: TouchEvent) => {\n const deltaX = Math.abs(e.touches[0].clientX - touchStartPos.current.x);\n const deltaY = Math.abs(e.touches[0].clientY - touchStartPos.current.y);\n\n // If horizontal movement is greater than vertical, prevent it\n if (deltaX > 10 && deltaX > deltaY) {\n e.preventDefault();\n }\n };\n\n el.addEventListener('touchstart', handleTouchStart, { passive: true });\n el.addEventListener('touchmove', handleTouchMove, { passive: false });\n\n return () => {\n el.removeEventListener('touchstart', handleTouchStart);\n el.removeEventListener('touchmove', handleTouchMove);\n };\n }, []);\n\n // Get current crop values\n const currentCropWidth = element.transformData?.cropWidth || 1;\n const currentCropHeight = element.transformData?.cropHeight || 1;\n\n // Handle crop changes\n const handleCropChange = useCallback(\n (cropX: number, cropY: number, cropWidth: number, cropHeight: number) => {\n const updatedElement = element.clone();\n updatedElement.updateCrop(cropX, cropY, cropWidth, cropHeight, true);\n onElementUpdate(updatedElement);\n },\n [element, onElementUpdate]\n );\n\n const handleCropWidthChange = useCallback(\n (value: number, anchor: CropAnchor = cropAnchor) => {\n const oldWidth = element.transformData.cropWidth;\n const oldX = element.transformData.cropX;\n const widthDiff = value - oldWidth;\n\n let newX = oldX;\n // Adjust X based on horizontal anchor position\n if (anchor.includes('center')) {\n newX = oldX - widthDiff / 2;\n } else if (anchor.includes('right')) {\n newX = oldX - widthDiff;\n }\n\n // Clamp X to valid range\n newX = Math.max(0, Math.min(1 - value, newX));\n\n handleCropChange(newX, element.transformData.cropY, value, element.transformData.cropHeight);\n },\n [element, handleCropChange, cropAnchor]\n );\n\n const handleCropHeightChange = useCallback(\n (value: number, anchor: CropAnchor = cropAnchor) => {\n const oldHeight = element.transformData.cropHeight;\n const oldY = element.transformData.cropY;\n const heightDiff = value - oldHeight;\n\n let newY = oldY;\n // Adjust Y based on vertical anchor position\n if (anchor.includes('middle') || anchor === 'center') {\n newY = oldY - heightDiff / 2;\n } else if (anchor.includes('bottom')) {\n newY = oldY - heightDiff;\n }\n\n // Clamp Y to valid range\n newY = Math.max(0, Math.min(1 - value, newY));\n\n handleCropChange(element.transformData.cropX, newY, element.transformData.cropWidth, value);\n },\n [element, handleCropChange, cropAnchor]\n );\n\n // Anchor grid positions\n const anchorPositions: CropAnchor[] = [\n 'top-left',\n 'top-center',\n 'top-right',\n 'middle-left',\n 'center',\n 'middle-right',\n 'bottom-left',\n 'bottom-center',\n 'bottom-right',\n ];\n\n return (\n <div\n ref={containerRef}\n data-preserve-selection\n className={cn('sc:flex sc:min-h-0 sc:flex-1 sc:flex-col', className)}\n style={{ touchAction: 'pan-y' }}\n >\n <div className=\"sc:flex sc:flex-col sc:gap-5 sc:px-5 sc:pt-1 sc:pb-[calc(env(safe-area-inset-bottom,0px)+20px)] sc:md:gap-4 sc:md:px-4 sc:md:pt-0 sc:md:pb-[calc(env(safe-area-inset-bottom,0px)+16px)]\">\n {/* Main content: Anchor Grid + Sliders */}\n <div className=\"sc:flex sc:items-start sc:gap-6 sc:md:gap-5\">\n {/* Anchor Grid */}\n <div className=\"sc:flex sc:flex-col sc:gap-2\">\n <span className=\"sc:text-foreground/60 sc:text-sm sc:md:text-xs\">Anchor</span>\n <div className=\"sc:grid sc:grid-cols-3 sc:gap-0.5 sc:rounded-md sc:p-1\">\n {anchorPositions.map((pos) => (\n <button\n key={pos}\n onClick={() => setCropAnchor(pos)}\n className={cn(\n 'sc-crop-anchor-btn sc:size-8 sc:rounded-md sc:md:size-6 sc:md:rounded',\n cropAnchor === pos && 'sc-active'\n )}\n title={pos.replace('-', ' ')}\n >\n <div\n className={cn(\n 'sc-crop-anchor-dot sc:size-2 sc:md:size-1.5',\n cropAnchor === pos && 'sc-active sc:size-2.5 sc:md:size-2'\n )}\n />\n </button>\n ))}\n </div>\n </div>\n\n {/* Size Sliders */}\n <div className=\"sc:flex sc:flex-1 sc:flex-col sc:gap-4 sc:md:gap-3\">\n {/* Width Slider */}\n <div className=\"sc:flex sc:flex-col sc:gap-2.5 sc:md:gap-1.5\">\n <div className=\"sc:flex sc:items-center sc:justify-between\">\n <span className=\"sc:text-foreground/60 sc:text-sm sc:md:text-xs\">Width</span>\n <input\n type=\"number\"\n value={Math.round(currentCropWidth * 100)}\n onChange={(e) => handleCropWidthChange(Math.max(10, Math.min(100, Number(e.target.value))) / 100)}\n min={10}\n max={100}\n className=\"sc:bg-transparent sc:text-foreground sc:w-14 sc:rounded-md sc:border-none sc:px-2.5 sc:py-2 sc:text-right sc:text-base sc:md:w-14 sc:md:rounded sc:md:px-1.5 sc:md:py-1 sc:md:text-[13px]\"\n />\n </div>\n {/* TouchGuard prevents parent scroll from capturing slider touches */}\n <TouchGuard>\n <Slider\n value={[currentCropWidth * 100]}\n onValueChange={(val) => handleCropWidthChange(val[0] / 100)}\n min={10}\n max={100}\n step={1}\n >\n <Slider.Track className=\"sc:bg-foreground/10 sc:h-2\">\n <Slider.Fill className=\"sc:bg-primary\" />\n </Slider.Track>\n <Slider.Thumb />\n </Slider>\n </TouchGuard>\n </div>\n\n {/* Height Slider */}\n <div className=\"sc:flex sc:flex-col sc:gap-2.5 sc:md:gap-1.5\">\n <div className=\"sc:flex sc:items-center sc:justify-between\">\n <span className=\"sc:text-foreground/60 sc:text-sm sc:md:text-xs\">Height</span>\n <input\n type=\"number\"\n value={Math.round(currentCropHeight * 100)}\n onChange={(e) => handleCropHeightChange(Math.max(10, Math.min(100, Number(e.target.value))) / 100)}\n min={10}\n max={100}\n className=\"sc:bg-transparent sc:text-foreground sc:w-14 sc:rounded-md sc:border-none sc:px-2.5 sc:py-2 sc:text-right sc:text-base sc:md:w-14 sc:md:rounded sc:md:px-1.5 sc:md:py-1 sc:md:text-[13px]\"\n />\n </div>\n {/* TouchGuard prevents parent scroll from capturing slider touches */}\n <TouchGuard>\n <Slider\n value={[currentCropHeight * 100]}\n onValueChange={(val) => handleCropHeightChange(val[0] / 100)}\n min={10}\n max={100}\n step={1}\n >\n <Slider.Track className=\"sc:bg-foreground/10 sc:h-2\">\n <Slider.Fill className=\"sc:bg-primary\" />\n </Slider.Track>\n <Slider.Thumb />\n </Slider>\n </TouchGuard>\n </div>\n </div>\n </div>\n </div>\n </div>\n );\n};\n\nexport default CropPanel;\n","/**\n * SecondaryPanels - Panel content components for expanded toolbar panels.\n *\n * These are the content areas rendered below the collapsed toolbar header\n * when a secondary panel (corner radius, rotation, opacity, etc.) is expanded.\n */\n\nimport React, { useCallback, useState } from 'react';\nimport { SliderRow, ToolbarButton, Button, Checkbox, Label, icons, PresetCarousel, Switch } from '../ui/index.js';\nimport type { PresetItem } from '../ui/index.js';\nimport ColorPickerDropdown from '../ColorPickerDropdown.jsx';\nimport CropPanel from '../CropPanel.jsx';\nimport type { ImageElement } from '../../core/ImageElement.js';\nimport type { StrokeConfig, CompositingScope, ImageAdjustments, ShapeFill, ShadowConfig, StandardBlendMode } from '../../types/index.js';\nimport { STANDARD_BLEND_MODES } from '../../types/index.js';\nimport { NEUTRAL_ADJUSTMENTS, isNeutralAdjustments } from '../../core/image-adjustments.js';\nimport { DISTRESS_TEXTURE_PRESETS, ensureBuiltinTexturesReady } from '../../effects/distress-textures.js';\nimport { preloadTexture } from '../../effects/DistressTextureCache.js';\nimport { MASK_IMAGE_PRESETS, ensureMaskPresetsReady } from '../../effects/mask-presets.js';\nimport type { AlignMode } from '../../utils/alignDistribute.js';\nimport { ALIGN_BUTTONS } from './alignButtons.js';\n\n// ── Shared panel body styling ───────────────────────────────────────────────\nconst PANEL_BODY_CLASSES =\n 'sc:flex sc:flex-col sc:gap-5 sc:px-5 sc:pt-4 sc:pb-4 sc:md:gap-4 sc:md:px-4 sc:md:pt-3 sc:md:pb-3';\n\nconst COLOR_PANEL_BODY_CLASSES =\n 'sc:flex sc:flex-col sc:gap-5 sc:px-5 sc:pt-4 sc:pb-[calc(env(safe-area-inset-bottom,0px)+20px)] sc:md:gap-4 sc:md:px-4 sc:md:pt-2 sc:md:pb-[calc(env(safe-area-inset-bottom,0px)+16px)]';\n\n// ── Corner Radius Panel (Image) ─────────────────────────────────────────────\n\nexport interface CornerRadiusPanelProps {\n value: number;\n onChange: (value: number) => void;\n}\n\nexport const CornerRadiusPanel: React.FC<CornerRadiusPanelProps> = ({ value, onChange }) => (\n <div\n className=\"corner-radius-panel sc:flex sc:flex-col\"\n data-preserve-selection\n style={{ touchAction: 'pan-y' }}\n >\n <div className={PANEL_BODY_CLASSES}>\n <SliderRow label=\"Radius\" value={value} onChange={onChange} min={0} max={50} unit=\"%\" />\n </div>\n </div>\n);\n\n// ── Align Panel (single selection → artboard) ───────────────────────────────\n\nexport interface AlignPanelProps {\n /** Apply one alignment command. For a single selection\n * `useAlignDistribute` aligns relative to the active artboard. */\n onAlign: (mode: AlignMode) => void;\n}\n\n/**\n * Position panel for a SINGLE selected element — the six align commands,\n * relative to the artboard (\"center on artboard\"). Multi-selections get the\n * same buttons inline in `MultiSelectionToolbar`, relative to the selection\n * bbox; both surfaces share `ALIGN_BUTTONS` so they cannot drift.\n */\nexport const AlignPanel: React.FC<AlignPanelProps> = ({ onAlign }) => (\n <div className=\"align-panel sc:flex sc:flex-col\" data-preserve-selection style={{ touchAction: 'pan-y' }}>\n <div className={PANEL_BODY_CLASSES}>\n <div className=\"sc:flex sc:items-center sc:justify-center sc:gap-1\">\n {ALIGN_BUTTONS.map(({ mode, icon, label }) => (\n <ToolbarButton\n key={mode}\n icon={icon}\n onClick={() => onAlign(mode)}\n tooltip={label}\n data-testid={`align-${mode}`}\n />\n ))}\n </div>\n </div>\n </div>\n);\n\n// ── Rotation Panel ──────────────────────────────────────────────────────────\n\nexport interface RotationPanelProps {\n value: number;\n onChange: (value: number) => void;\n onRotate90: () => void;\n}\n\nexport const RotationPanel: React.FC<RotationPanelProps> = ({ value, onChange, onRotate90 }) => (\n <div\n className=\"rotation-panel sc:flex sc:flex-col\"\n data-preserve-selection\n style={{ touchAction: 'pan-y' }}\n >\n <div className={PANEL_BODY_CLASSES}>\n <div className=\"sc:flex sc:items-end sc:gap-3\">\n <SliderRow\n label=\"Rotation\"\n value={value}\n onChange={onChange}\n min={-180}\n max={180}\n unit=\"°\"\n showInput\n inputWidth=\"56px\"\n variant=\"stacked\"\n className=\"sc:flex-1\"\n />\n {/* 90 Degree Button */}\n <div className=\"sc:pb-0.5\">\n <ToolbarButton icon={icons.rotateCcwSquare} onClick={onRotate90} tooltip=\"Rotate 90° CCW\" />\n </div>\n </div>\n </div>\n </div>\n);\n\n// ── Font Size Panel ─────────────────────────────────────────────────────────\n\nexport interface FontSizePanelProps {\n value: number;\n onChange: (value: number) => void;\n /** Current text-box width. When null/undefined the width slider is\n * hidden (e.g. element type doesn't expose a width on transformData). */\n widthValue?: number | null;\n /** Called when the width slider moves. */\n onWidthChange?: (value: number) => void;\n /** Letter-spacing in px (extra advance per character). When\n * null/undefined the slider is hidden (curved transforms — they lay\n * glyphs along a path and intentionally ignore letter-spacing). */\n letterSpacingValue?: number | null;\n /** Called when the letter-spacing slider moves. */\n onLetterSpacingChange?: (value: number) => void;\n /** Line-height multiplier (lineSpacing = fontSize × value). When\n * null/undefined the slider is hidden (curved transforms). */\n lineHeightValue?: number | null;\n /** Called when the line-height slider moves. */\n onLineHeightChange?: (value: number) => void;\n}\n\n// Font size panel — slider + number input. Replaces the older +/-\n// stepper which moved in 1px steps (too small to be useful) and\n// stretched the toolbar to fit a long number. Min/max give plenty\n// of headroom: 8 (smallest legible) → 256 (very large display\n// type). Step 1 because the input lets users dial precisely; the\n// slider handles coarse motion.\n//\n// Width slider sits directly under the font size slider — same\n// section because both control the layout of the text element. The\n// width slider operates on the text-box width (`transformData.width`)\n// which drives line-wrapping for custom text and the bounding box\n// for transformed text (wave, arch, etc.).\n// Letter-spacing and line-height sit in the same panel, directly under the\n// font size slider — they're the other two \"every editor has these\" type\n// knobs. Letter-spacing is in world-space px per character (CSS model);\n// line-height is a multiplier of fontSize (1.2 = the layout default).\n// Both apply to straight ('custom') text only — pass null to hide them for\n// curved transforms, which intentionally ignore these properties.\nexport const FontSizePanel: React.FC<FontSizePanelProps> = ({\n value,\n onChange,\n widthValue,\n onWidthChange,\n letterSpacingValue,\n onLetterSpacingChange,\n lineHeightValue,\n onLineHeightChange,\n}) => (\n <div\n className=\"font-size-panel sc:flex sc:flex-col\"\n data-preserve-selection\n data-sc-part=\"font-size-panel\"\n style={{ touchAction: 'pan-y' }}\n >\n <div className={PANEL_BODY_CLASSES}>\n <SliderRow\n label=\"Font Size\"\n value={Math.round(value)}\n onChange={onChange}\n min={8}\n max={256}\n step={1}\n unit=\"px\"\n showInput\n inputWidth=\"64px\"\n />\n {letterSpacingValue != null && onLetterSpacingChange && (\n <div data-sc-part=\"letter-spacing-control\">\n <SliderRow\n label=\"Letter Spacing\"\n value={letterSpacingValue}\n onChange={onLetterSpacingChange}\n min={-20}\n max={100}\n step={1}\n unit=\"px\"\n showInput\n inputWidth=\"64px\"\n />\n </div>\n )}\n {lineHeightValue != null && onLineHeightChange && (\n <div data-sc-part=\"line-height-control\">\n <SliderRow\n label=\"Line Height\"\n value={lineHeightValue}\n onChange={onLineHeightChange}\n min={0.5}\n max={3}\n step={0.1}\n unit=\"×\"\n showInput\n inputWidth=\"64px\"\n />\n </div>\n )}\n {widthValue != null && onWidthChange && (\n <SliderRow\n label=\"Width\"\n value={Math.round(widthValue)}\n onChange={onWidthChange}\n min={50}\n max={4000}\n step={1}\n unit=\"px\"\n showInput\n inputWidth=\"64px\"\n />\n )}\n </div>\n </div>\n);\n\n// ── Opacity Panel ───────────────────────────────────────────────────────────\n\nexport interface OpacityPanelProps {\n /** Opacity value 0-1 */\n value: number;\n /** Called with 0-1 range */\n onChange: (value: number) => void;\n}\n\nexport const OpacityPanel: React.FC<OpacityPanelProps> = ({ value, onChange }) => (\n <div\n className=\"opacity-panel sc:flex sc:flex-col\"\n data-preserve-selection\n style={{ touchAction: 'pan-y' }}\n >\n <div className={PANEL_BODY_CLASSES}>\n <SliderRow\n label=\"Opacity\"\n value={Math.round(value * 100)}\n onChange={(v) => onChange(v / 100)}\n min={0}\n max={100}\n unit=\"%\"\n />\n </div>\n </div>\n);\n\n// ── Adjust Panel (Image brightness / contrast / saturation) ─────────────────\n\nexport interface AdjustPanelProps {\n /** Current adjustments — undefined means neutral (all 1). */\n adjustments: ImageAdjustments | undefined;\n /** Called with the FULL next adjustments value on every slider tick. */\n onChange: (adjustments: ImageAdjustments) => void;\n /** Called when a slider gesture commits (pointer release) — breaks the undo-coalescing run. */\n onChangeEnd?: () => void;\n /** Reset all three channels to neutral (one undo step). */\n onReset: () => void;\n}\n\n/**\n * Brightness / contrast / saturation sliders for image elements.\n * Values are multipliers (1 = neutral) shown as 0–200%; the neutral detent is\n * 100%. Reset clears the adjustments back to neutral in a single undo step.\n */\nexport const AdjustPanel: React.FC<AdjustPanelProps> = ({ adjustments, onChange, onChangeEnd, onReset }) => {\n const current: ImageAdjustments = adjustments ?? { ...NEUTRAL_ADJUSTMENTS };\n const isNeutral = isNeutralAdjustments(adjustments);\n\n const channelRow = (label: string, channel: keyof ImageAdjustments) => (\n <div data-testid={`adjust-${channel}`}>\n <SliderRow\n label={label}\n value={Math.round(current[channel] * 100)}\n onChange={(v) => onChange({ ...current, [channel]: v / 100 })}\n onChangeEnd={onChangeEnd ? () => onChangeEnd() : undefined}\n min={0}\n max={200}\n unit=\"%\"\n />\n </div>\n );\n\n return (\n <div\n className=\"adjust-panel sc:flex sc:flex-col\"\n data-preserve-selection\n data-testid=\"adjust-panel\"\n style={{ touchAction: 'pan-y' }}\n >\n <div className={PANEL_BODY_CLASSES}>\n {channelRow('Brightness', 'brightness')}\n {channelRow('Contrast', 'contrast')}\n {channelRow('Saturation', 'saturation')}\n <div className=\"sc:flex sc:justify-end\">\n <Button\n variant=\"ghost\"\n size=\"sm\"\n onClick={onReset}\n disabled={isNeutral}\n data-testid=\"adjust-reset\"\n aria-label=\"Reset adjustments\"\n >\n Reset\n </Button>\n </div>\n </div>\n </div>\n );\n};\n\n// ── Shape Corner Radius Panel ───────────────────────────────────────────────\n\nexport interface ShapeCornerRadiusPanelProps {\n value: number;\n onChange: (value: number) => void;\n}\n\nexport const ShapeCornerRadiusPanel: React.FC<ShapeCornerRadiusPanelProps> = ({ value, onChange }) => (\n <div\n className=\"shape-corner-radius-panel sc:flex sc:flex-col\"\n data-preserve-selection\n style={{ touchAction: 'pan-y' }}\n >\n <div className={PANEL_BODY_CLASSES}>\n <SliderRow label=\"Radius\" value={value} onChange={onChange} min={0} max={50} unit=\"%\" />\n </div>\n </div>\n);\n\n// ── Shape Transparency Panel ────────────────────────────────────────────────\n\nexport interface ShapeTransparencyPanelProps {\n /** Fill opacity 0-1 */\n value: number;\n /** Called with 0-1 range */\n onChange: (value: number) => void;\n}\n\nexport const ShapeTransparencyPanel: React.FC<ShapeTransparencyPanelProps> = ({ value, onChange }) => (\n <div\n className=\"shape-transparency-panel sc:flex sc:flex-col\"\n data-preserve-selection\n style={{ touchAction: 'pan-y' }}\n >\n <div className={PANEL_BODY_CLASSES}>\n <SliderRow\n label=\"Opacity\"\n value={Math.round(value * 100)}\n onChange={(val) => onChange(val / 100)}\n min={0}\n max={100}\n unit=\"%\"\n />\n </div>\n </div>\n);\n\n// ── Shape Sides Panel (Polygon) ─────────────────────────────────────────────\n\nexport interface ShapeSidesPanelProps {\n value: number;\n onChange: (value: number) => void;\n}\n\nexport const ShapeSidesPanel: React.FC<ShapeSidesPanelProps> = ({ value, onChange }) => (\n <div\n className=\"shape-sides-panel sc:flex sc:flex-col\"\n data-preserve-selection\n style={{ touchAction: 'pan-y' }}\n >\n <div className={PANEL_BODY_CLASSES}>\n <SliderRow label=\"Sides\" value={value} onChange={onChange} min={3} max={20} />\n </div>\n </div>\n);\n\n// ── Shape Points Panel (Star) ───────────────────────────────────────────────\n\nexport interface ShapePointsPanelProps {\n value: number;\n onChange: (value: number) => void;\n}\n\nexport const ShapePointsPanel: React.FC<ShapePointsPanelProps> = ({ value, onChange }) => (\n <div\n className=\"shape-points-panel sc:flex sc:flex-col\"\n data-preserve-selection\n style={{ touchAction: 'pan-y' }}\n >\n <div className={PANEL_BODY_CLASSES}>\n <SliderRow label=\"Points\" value={value} onChange={onChange} min={3} max={20} />\n </div>\n </div>\n);\n\n// ── Shape Inner Radius Panel (Star) ─────────────────────────────────────────\n\nexport interface ShapeInnerRadiusPanelProps {\n /** Inner radius 0-1 */\n value: number;\n /** Called with 0-1 range */\n onChange: (value: number) => void;\n}\n\nexport const ShapeInnerRadiusPanel: React.FC<ShapeInnerRadiusPanelProps> = ({ value, onChange }) => (\n <div\n className=\"shape-inner-radius-panel sc:flex sc:flex-col\"\n data-preserve-selection\n style={{ touchAction: 'pan-y' }}\n >\n <div className={PANEL_BODY_CLASSES}>\n <SliderRow\n label=\"Inner Radius\"\n value={Math.round(value * 100)}\n onChange={(val) => onChange(val / 100)}\n min={10}\n max={90}\n unit=\"%\"\n />\n </div>\n </div>\n);\n\n// ── Shape Fill Color Panel ──────────────────────────────────────────────────\n\ntype ShapeFillMode = 'solid' | 'linear' | 'radial';\n\nexport interface ShapeColorPanelProps {\n /** Current solid fill color (legacy `fillColor`). */\n value: string;\n /** Solid color change — the host also clears any gradient `fill` (fill wins at render time). */\n onChange: (color: string) => void;\n /** Current rich fill (solid or gradient), if any. */\n fill?: ShapeFill;\n /** Rich fill change; `null` switches back to the solid `fillColor` path. */\n onFillChange?: (fill: ShapeFill | null) => void;\n documentColors: string[];\n imageColors?: string[];\n}\n\nconst FILL_MODE_LABELS: Record<ShapeFillMode, string> = {\n solid: 'Solid',\n linear: 'Linear',\n radial: 'Radial',\n};\n\nexport const ShapeColorPanel: React.FC<ShapeColorPanelProps> = ({\n value,\n onChange,\n fill,\n onFillChange,\n documentColors,\n imageColors,\n}) => {\n const mode: ShapeFillMode = fill?.type === 'linear' || fill?.type === 'radial' ? fill.type : 'solid';\n const gradient = fill?.type === 'linear' || fill?.type === 'radial' ? fill : null;\n const [activeStop, setActiveStop] = useState(0);\n\n const handleModeChange = useCallback(\n (next: ShapeFillMode) => {\n if (next === mode || !onFillChange) return;\n if (next === 'solid') {\n // Collapse to the first stop's color via the solid path (the host\n // clears `fill` on solid color writes).\n onChange(gradient?.stops[0]?.color ?? value);\n return;\n }\n // Keep stops when toggling linear <-> radial; otherwise seed a simple\n // two-stop ramp from the current solid color.\n const stops = gradient\n ? gradient.stops.map((s) => ({ ...s }))\n : [\n { offset: 0, color: value },\n { offset: 1, color: '#ffffff' },\n ];\n onFillChange(\n next === 'linear'\n ? { type: 'linear', angle: gradient?.type === 'linear' ? gradient.angle : 180, stops }\n : { type: 'radial', stops },\n );\n setActiveStop(0);\n },\n [mode, gradient, value, onChange, onFillChange],\n );\n\n const handleStopColorChange = useCallback(\n (color: string) => {\n if (!gradient || !onFillChange) return;\n const stops = gradient.stops.map((s, i) => (i === activeStop ? { ...s, color } : { ...s }));\n onFillChange(\n gradient.type === 'linear' ? { type: 'linear', angle: gradient.angle, stops } : { type: 'radial', stops },\n );\n },\n [gradient, activeStop, onFillChange],\n );\n\n const handleAngleChange = useCallback(\n (angle: number) => {\n if (gradient?.type !== 'linear' || !onFillChange) return;\n onFillChange({ type: 'linear', angle, stops: gradient.stops.map((s) => ({ ...s })) });\n },\n [gradient, onFillChange],\n );\n\n const activeColor = gradient ? (gradient.stops[activeStop]?.color ?? value) : value;\n\n return (\n <div\n className=\"shape-color-panel sc:flex sc:flex-col\"\n data-preserve-selection\n style={{ touchAction: 'pan-y' }}\n >\n <div className={COLOR_PANEL_BODY_CLASSES}>\n {/* Fill mode: Solid / Linear / Radial */}\n {onFillChange && (\n <div className=\"sc:flex sc:items-center sc:gap-3\">\n <Label className=\"sc:text-base sc:md:text-sm sc:font-medium\">Fill</Label>\n <div className=\"sc:flex sc:rounded-md sc:border sc:border-divider sc:overflow-hidden\">\n {(['solid', 'linear', 'radial'] as const).map((m) => (\n <button\n key={m}\n className={`sc:px-4 sc:py-2.5 sc:text-base sc:md:px-3 sc:md:py-1.5 sc:md:text-sm sc:transition-colors ${mode === m ? 'sc:bg-primary sc:text-primary-foreground' : 'sc:text-foreground sc:hover:bg-muted'}`}\n onClick={() => handleModeChange(m)}\n aria-pressed={mode === m}\n >\n {FILL_MODE_LABELS[m]}\n </button>\n ))}\n </div>\n </div>\n )}\n\n {/* Gradient controls: stop swatches + angle (linear only) */}\n {gradient && (\n <>\n <div className=\"sc:flex sc:items-center sc:gap-3\">\n <Label className=\"sc:text-base sc:md:text-sm sc:font-medium\">Stops</Label>\n <div className=\"sc:flex sc:items-center sc:gap-2\">\n {gradient.stops.map((stop, i) => (\n <button\n key={i}\n className={`sc:h-8 sc:w-8 sc:rounded-md sc:border-2 sc:transition-colors ${i === activeStop ? 'sc:border-primary' : 'sc:border-divider'}`}\n style={{ backgroundColor: stop.color }}\n onClick={() => setActiveStop(i)}\n aria-label={`Edit gradient stop ${i + 1}`}\n aria-pressed={i === activeStop}\n />\n ))}\n </div>\n </div>\n {gradient.type === 'linear' && (\n <SliderRow\n label=\"Angle\"\n value={Math.round(gradient.angle)}\n onChange={handleAngleChange}\n min={0}\n max={360}\n unit=\"°\"\n />\n )}\n </>\n )}\n\n <ColorPickerDropdown\n value={activeColor}\n onChange={(e: { target: { value: string } }) =>\n gradient ? handleStopColorChange(e.target.value) : onChange(e.target.value)\n }\n documentColors={documentColors}\n imageColors={imageColors}\n showSquare={true}\n embedded={true}\n />\n </div>\n </div>\n );\n};\n\n// ── Text Color Panel ────────────────────────────────────────────────────────\n\nexport interface TextColorPanelProps {\n value: string;\n onChange: (e: { target: { value: string } }) => void;\n documentColors: string[];\n imageColors?: string[];\n}\n\nexport const TextColorPanel: React.FC<TextColorPanelProps> = ({ value, onChange, documentColors, imageColors }) => (\n <div\n className=\"sc-text-color-panel sc:flex sc:flex-col\"\n data-preserve-selection\n style={{ touchAction: 'pan-y' }}\n >\n <div className={COLOR_PANEL_BODY_CLASSES}>\n <ColorPickerDropdown value={value} onChange={onChange} documentColors={documentColors} imageColors={imageColors} embedded={true} />\n </div>\n </div>\n);\n\n// ── Compositing Panel (Clip / Knockout) ─────────────────────────────────────\n\nexport type CompositingMode = 'clip' | 'knockout';\n\nexport interface CompositingPanelProps {\n mode: CompositingMode;\n fill: boolean;\n stroke: boolean;\n scope: CompositingScope;\n onModeChange: (mode: CompositingMode) => void;\n onFillChange: (fill: boolean) => void;\n onStrokeChange: (stroke: boolean) => void;\n onScopeChange: (scope: CompositingScope) => void;\n}\n\nexport const CompositingPanel: React.FC<CompositingPanelProps> = ({\n mode,\n fill,\n stroke,\n scope,\n onModeChange,\n onFillChange,\n onStrokeChange,\n onScopeChange,\n}) => (\n <div\n className=\"knockout-panel sc:flex sc:flex-col\"\n data-preserve-selection\n style={{ touchAction: 'pan-y' }}\n >\n <div className={PANEL_BODY_CLASSES}>\n {/* Mode selector: Clip / Knockout */}\n <div className=\"sc:flex sc:items-center sc:gap-3\">\n <Label className=\"sc:text-base sc:md:text-sm sc:font-medium\">Mode</Label>\n <div className=\"sc:flex sc:rounded-md sc:border sc:border-divider sc:overflow-hidden\">\n <button\n className={`sc:px-4 sc:py-2.5 sc:text-base sc:md:px-3 sc:md:py-1.5 sc:md:text-sm sc:transition-colors ${mode === 'clip' ? 'sc:bg-primary sc:text-primary-foreground' : 'sc:text-foreground sc:hover:bg-muted'}`}\n onClick={() => onModeChange('clip')}\n >\n Clip\n </button>\n <button\n className={`sc:px-4 sc:py-2.5 sc:text-base sc:md:px-3 sc:md:py-1.5 sc:md:text-sm sc:transition-colors ${mode === 'knockout' ? 'sc:bg-primary sc:text-primary-foreground' : 'sc:text-foreground sc:hover:bg-muted'}`}\n onClick={() => onModeChange('knockout')}\n >\n Knockout\n </button>\n </div>\n </div>\n\n {/* Fill / Stroke checkboxes */}\n <div className=\"sc:flex sc:items-center sc:gap-5\">\n <label className=\"sc:flex sc:items-center sc:gap-2 sc:text-base sc:md:text-sm sc:text-foreground\">\n <Checkbox checked={fill} onCheckedChange={(v) => onFillChange(v === true)} />\n Fill\n </label>\n <label className=\"sc:flex sc:items-center sc:gap-2 sc:text-base sc:md:text-sm sc:text-foreground\">\n <Checkbox checked={stroke} onCheckedChange={(v) => onStrokeChange(v === true)} />\n Stroke\n </label>\n </div>\n\n {/* Scope selector */}\n <div className=\"sc:flex sc:items-center sc:gap-3\">\n <Label className=\"sc:text-base sc:md:text-sm sc:font-medium\">Scope</Label>\n <div className=\"sc:flex sc:rounded-md sc:border sc:border-divider sc:overflow-hidden\">\n <button\n className={`sc:px-4 sc:py-2.5 sc:text-base sc:md:px-3 sc:md:py-1.5 sc:md:text-sm sc:transition-colors ${scope === 'group' ? 'sc:bg-primary sc:text-primary-foreground' : 'sc:text-foreground sc:hover:bg-muted'}`}\n onClick={() => onScopeChange('group')}\n >\n Group\n </button>\n <button\n className={`sc:px-4 sc:py-2.5 sc:text-base sc:md:px-3 sc:md:py-1.5 sc:md:text-sm sc:transition-colors ${scope === 'artboard' ? 'sc:bg-primary sc:text-primary-foreground' : 'sc:text-foreground sc:hover:bg-muted'}`}\n onClick={() => onScopeChange('artboard')}\n >\n Artboard\n </button>\n </div>\n </div>\n </div>\n </div>\n);\n\n/** @deprecated Use CompositingPanel instead */\nexport type KnockoutPanelProps = CompositingPanelProps;\n/** @deprecated Use CompositingPanel instead */\nexport const KnockoutPanel = CompositingPanel;\n\n// ── Distress Texture Panel ──────────────────────────────────────────────────\n\nexport interface DistressTexturePanelProps {\n textureUrl: string;\n /** Opacity 0-100 (percentage) */\n opacity: number;\n onTextureChange: (url: string) => void;\n onOpacityChange: (pct: number) => void;\n}\n\nexport const DistressTexturePanel: React.FC<DistressTexturePanelProps> = ({\n textureUrl,\n opacity,\n onTextureChange,\n onOpacityChange,\n}) => {\n // Call synchronously so thumbnailUrls are populated before we read them\n ensureBuiltinTexturesReady();\n\n const presetItems: PresetItem[] = DISTRESS_TEXTURE_PRESETS.map((p) => ({ id: p.textureUrl, name: p.name, thumbnailUrl: p.thumbnailUrl }));\n\n const handleSelect = useCallback(\n (id: string) => {\n if (id) preloadTexture(id);\n onTextureChange(id);\n },\n [onTextureChange]\n );\n\n return (\n <div\n className=\"distress-texture-panel sc:flex sc:flex-col\"\n data-preserve-selection\n style={{ touchAction: 'pan-y' }}\n >\n <div className={PANEL_BODY_CLASSES}>\n <PresetCarousel\n presets={presetItems}\n selectedId={textureUrl}\n onSelect={handleSelect}\n ariaLabel=\"Distress texture presets\"\n />\n\n {/* Opacity slider */}\n <SliderRow\n label=\"Opacity\"\n value={opacity}\n onChange={onOpacityChange}\n min={0}\n max={100}\n unit=\"%\"\n />\n </div>\n </div>\n );\n};\n\n// ── Image Mask Panel ────────────────────────────────────────────────────\n\nexport interface ImageMaskPanelProps {\n imageUrl: string;\n maskType: 'clip' | 'alpha' | 'luma';\n opacity: number; // 0-100\n inverted: boolean;\n onImageChange: (url: string) => void;\n onMaskTypeChange: (type: 'clip' | 'alpha' | 'luma') => void;\n onOpacityChange: (pct: number) => void;\n onInvertedChange: (inverted: boolean) => void;\n}\n\nexport const ImageMaskPanel: React.FC<ImageMaskPanelProps> = ({\n imageUrl,\n maskType,\n opacity,\n inverted,\n onImageChange,\n onMaskTypeChange,\n onOpacityChange,\n onInvertedChange,\n}) => {\n // Call synchronously so thumbnailUrls are populated before we read them\n ensureMaskPresetsReady();\n\n const presetItems: PresetItem[] = MASK_IMAGE_PRESETS.map((p) => ({ id: p.imageUrl, name: p.name, thumbnailUrl: p.thumbnailUrl }));\n\n return (\n <div\n className=\"image-mask-panel sc:flex sc:flex-col\"\n data-preserve-selection\n style={{ touchAction: 'pan-y' }}\n >\n <div className={PANEL_BODY_CLASSES}>\n <PresetCarousel\n presets={presetItems}\n selectedId={imageUrl}\n onSelect={onImageChange}\n ariaLabel=\"Image mask presets\"\n />\n\n {/* Mask type row */}\n <div className=\"sc:flex sc:items-center sc:gap-2\">\n <Label className=\"sc:text-base sc:md:text-sm sc:font-medium\">Type</Label>\n <div className=\"sc:flex sc:rounded-md sc:border sc:border-divider sc:overflow-hidden\">\n {(['clip', 'alpha', 'luma'] as const).map((type) => (\n <button\n key={type}\n className={`sc:px-4 sc:py-2.5 sc:text-base sc:md:px-3 sc:md:py-1.5 sc:md:text-sm sc:capitalize sc:transition-colors ${\n maskType === type\n ? 'sc:bg-primary sc:text-primary-foreground'\n : 'sc:text-foreground sc:hover:bg-muted'\n }`}\n onClick={() => onMaskTypeChange(type)}\n >\n {type}\n </button>\n ))}\n </div>\n </div>\n\n {/* Opacity slider */}\n <SliderRow\n label=\"Opacity\"\n value={opacity}\n onChange={onOpacityChange}\n min={0}\n max={100}\n unit=\"%\"\n />\n\n {/* Inverted checkbox */}\n <label className=\"sc:flex sc:items-center sc:gap-2 sc:text-base sc:md:text-sm sc:text-foreground\">\n <Checkbox checked={inverted} onCheckedChange={(v) => onInvertedChange(v === true)} />\n Invert Mask\n </label>\n </div>\n </div>\n );\n};\n\n// ── Stroke Panel ────────────────────────────────────────────────────────────\n\nexport interface StrokePanelProps {\n stroke?: StrokeConfig;\n onChange: (stroke: StrokeConfig | undefined) => void;\n documentColors?: string[];\n imageColors?: string[];\n}\n\nexport const StrokePanel: React.FC<StrokePanelProps> = ({ stroke, onChange, documentColors, imageColors }) => {\n const [showAdvanced, setShowAdvanced] = useState(false);\n\n const enabled = stroke?.enabled ?? false;\n const color = stroke?.color ?? '#000000';\n const width = stroke?.width ?? 5;\n const opacity = stroke?.opacity ?? 1;\n const lineCap = stroke?.lineCap ?? 'butt';\n const lineJoin = stroke?.lineJoin ?? 'miter';\n\n const handleEnabledChange = useCallback(\n (newEnabled: boolean) => {\n if (newEnabled) {\n onChange({ enabled: true, color, width, lineCap, lineJoin, opacity });\n } else {\n onChange(undefined);\n }\n },\n [onChange, color, width, lineCap, lineJoin, opacity]\n );\n\n const update = useCallback(\n (patch: Partial<StrokeConfig>) => {\n if (!stroke) return;\n onChange({ ...stroke, ...patch });\n },\n [stroke, onChange]\n );\n\n return (\n <div\n className=\"stroke-panel sc:flex sc:flex-col\"\n data-preserve-selection\n style={{ touchAction: 'pan-y' }}\n >\n <div className={PANEL_BODY_CLASSES}>\n {/* Enable/disable toggle */}\n <div className=\"sc:flex sc:items-center sc:justify-between\">\n <Label className=\"sc:text-foreground/70 sc:text-base sc:md:text-[13px]\">Stroke</Label>\n <Switch checked={enabled} onCheckedChange={handleEnabledChange} />\n </div>\n\n {enabled && (\n <>\n {/* Color picker */}\n <div className=\"sc:flex sc:items-center sc:justify-between\">\n <Label className=\"sc:text-foreground/70 sc:text-base sc:md:text-[13px]\">Color</Label>\n <ColorPickerDropdown\n value={color}\n onChange={(e: { target: { value: string } }) => update({ color: e.target.value })}\n documentColors={documentColors}\n imageColors={imageColors}\n showSquare={true}\n />\n </div>\n\n {/* Width slider */}\n <SliderRow\n label=\"Width\"\n value={width}\n onChange={(v) => update({ width: v })}\n min={1}\n max={50}\n unit=\"px\"\n />\n\n {/* Opacity slider */}\n <SliderRow\n label=\"Opacity\"\n value={Math.round(opacity * 100)}\n onChange={(v) => update({ opacity: v / 100 })}\n min={0}\n max={100}\n unit=\"%\"\n />\n\n {/* Advanced toggle */}\n <button\n className=\"sc:flex sc:items-center sc:gap-1 sc:text-base sc:md:text-sm sc:text-muted-foreground sc:hover:text-foreground sc:transition-colors sc:py-1.5 sc:md:py-0\"\n onClick={() => setShowAdvanced((prev) => !prev)}\n >\n {showAdvanced ? 'Hide' : 'Show'} Advanced\n </button>\n\n {showAdvanced && (\n <>\n {/* Line Cap */}\n <div className=\"sc:flex sc:items-center sc:gap-3\">\n <Label className=\"sc:text-foreground/70 sc:text-base sc:md:text-[13px]\">Line Cap</Label>\n <div className=\"sc:flex sc:rounded-md sc:border sc:border-divider sc:overflow-hidden\">\n {(['butt', 'round', 'square'] as const).map((cap) => (\n <button\n key={cap}\n className={`sc:px-4 sc:py-2.5 sc:text-base sc:md:px-3 sc:md:py-1.5 sc:md:text-sm sc:capitalize sc:transition-colors ${\n lineCap === cap\n ? 'sc:bg-primary sc:text-primary-foreground'\n : 'sc:text-foreground sc:hover:bg-muted'\n }`}\n onClick={() => update({ lineCap: cap })}\n >\n {cap}\n </button>\n ))}\n </div>\n </div>\n\n {/* Line Join */}\n <div className=\"sc:flex sc:items-center sc:gap-3\">\n <Label className=\"sc:text-foreground/70 sc:text-base sc:md:text-[13px]\">Line Join</Label>\n <div className=\"sc:flex sc:rounded-md sc:border sc:border-divider sc:overflow-hidden\">\n {(['miter', 'round', 'bevel'] as const).map((join) => (\n <button\n key={join}\n className={`sc:px-4 sc:py-2.5 sc:text-base sc:md:px-3 sc:md:py-1.5 sc:md:text-sm sc:capitalize sc:transition-colors ${\n lineJoin === join\n ? 'sc:bg-primary sc:text-primary-foreground'\n : 'sc:text-foreground sc:hover:bg-muted'\n }`}\n onClick={() => update({ lineJoin: join })}\n >\n {join}\n </button>\n ))}\n </div>\n </div>\n </>\n )}\n </>\n )}\n </div>\n </div>\n );\n};\n\n// ── Shadow Panel ────────────────────────────────────────────────────────────\n\n/** Defaults used when the shadow is first enabled (world-space px). */\nconst SHADOW_DEFAULTS = {\n color: '#000000',\n blur: 8,\n offsetX: 4,\n offsetY: 4,\n opacity: 0.5,\n} as const;\n\nexport interface ShadowPanelProps {\n shadow?: ShadowConfig;\n onChange: (shadow: ShadowConfig | undefined) => void;\n documentColors?: string[];\n imageColors?: string[];\n}\n\nexport const ShadowPanel: React.FC<ShadowPanelProps> = ({ shadow, onChange, documentColors, imageColors }) => {\n const enabled = shadow?.enabled ?? false;\n const color = shadow?.color ?? SHADOW_DEFAULTS.color;\n const blur = shadow?.blur ?? SHADOW_DEFAULTS.blur;\n const offsetX = shadow?.offsetX ?? SHADOW_DEFAULTS.offsetX;\n const offsetY = shadow?.offsetY ?? SHADOW_DEFAULTS.offsetY;\n const opacity = shadow?.opacity ?? SHADOW_DEFAULTS.opacity;\n\n const handleEnabledChange = useCallback(\n (newEnabled: boolean) => {\n if (newEnabled) {\n onChange({ enabled: true, color, blur, offsetX, offsetY, opacity });\n } else {\n onChange(undefined);\n }\n },\n [onChange, color, blur, offsetX, offsetY, opacity]\n );\n\n const update = useCallback(\n (patch: Partial<ShadowConfig>) => {\n if (!shadow) return;\n onChange({ ...shadow, ...patch });\n },\n [shadow, onChange]\n );\n\n return (\n <div\n className=\"shadow-panel sc:flex sc:flex-col\"\n data-sc-part=\"shadow-panel\"\n data-preserve-selection\n style={{ touchAction: 'pan-y' }}\n >\n <div className={PANEL_BODY_CLASSES}>\n {/* Enable/disable toggle */}\n <div className=\"sc:flex sc:items-center sc:justify-between\">\n <Label className=\"sc:text-foreground/70 sc:text-base sc:md:text-[13px]\">Shadow</Label>\n <Switch checked={enabled} onCheckedChange={handleEnabledChange} data-testid=\"shadow-enabled-switch\" />\n </div>\n\n {enabled && (\n <>\n {/* Color picker */}\n <div className=\"sc:flex sc:items-center sc:justify-between\">\n <Label className=\"sc:text-foreground/70 sc:text-base sc:md:text-[13px]\">Color</Label>\n <ColorPickerDropdown\n value={color}\n onChange={(e: { target: { value: string } }) => update({ color: e.target.value })}\n documentColors={documentColors}\n imageColors={imageColors}\n showSquare={true}\n />\n </div>\n\n {/* Blur slider */}\n <SliderRow\n label=\"Blur\"\n value={blur}\n onChange={(v) => update({ blur: v })}\n min={0}\n max={100}\n unit=\"px\"\n />\n\n {/* Offset sliders */}\n <SliderRow\n label=\"Offset X\"\n value={offsetX}\n onChange={(v) => update({ offsetX: v })}\n min={-100}\n max={100}\n unit=\"px\"\n />\n <SliderRow\n label=\"Offset Y\"\n value={offsetY}\n onChange={(v) => update({ offsetY: v })}\n min={-100}\n max={100}\n unit=\"px\"\n />\n\n {/* Opacity slider */}\n <SliderRow\n label=\"Opacity\"\n value={Math.round(opacity * 100)}\n onChange={(v) => update({ opacity: v / 100 })}\n min={0}\n max={100}\n unit=\"%\"\n />\n </>\n )}\n </div>\n </div>\n );\n};\n\n// ── Blend Mode Panel ────────────────────────────────────────────────────────\n\n/** 'normal' plus the standard blend modes, in display order. */\nconst BLEND_MODE_OPTIONS: ReadonlyArray<'normal' | StandardBlendMode> = ['normal', ...STANDARD_BLEND_MODES];\n\nexport interface BlendModePanelProps {\n /**\n * Current standard blend mode. 'normal' covers unset, 'normal', and the\n * knockout/clip compositing modes (which are controlled by the Clip /\n * Knockout panel, not here — picking a mode here replaces them).\n */\n blendMode: 'normal' | StandardBlendMode;\n onChange: (blendMode: 'normal' | StandardBlendMode) => void;\n}\n\nexport const BlendModePanel: React.FC<BlendModePanelProps> = ({ blendMode, onChange }) => (\n <div\n className=\"blend-mode-panel sc:flex sc:flex-col\"\n data-sc-part=\"blend-mode-panel\"\n data-preserve-selection\n style={{ touchAction: 'pan-y' }}\n >\n <div className={PANEL_BODY_CLASSES}>\n <div className=\"sc:flex sc:items-center sc:gap-3\">\n <Label className=\"sc:text-foreground/70 sc:text-base sc:md:text-[13px]\">Blend</Label>\n <div className=\"sc:flex sc:flex-wrap sc:rounded-md sc:border sc:border-divider sc:overflow-hidden\">\n {BLEND_MODE_OPTIONS.map((mode) => (\n <button\n key={mode}\n data-blend-mode={mode}\n aria-pressed={blendMode === mode}\n className={`sc:px-4 sc:py-2.5 sc:text-base sc:md:px-3 sc:md:py-1.5 sc:md:text-sm sc:capitalize sc:transition-colors ${\n blendMode === mode\n ? 'sc:bg-primary sc:text-primary-foreground'\n : 'sc:text-foreground sc:hover:bg-muted'\n }`}\n onClick={() => onChange(mode)}\n >\n {mode}\n </button>\n ))}\n </div>\n </div>\n </div>\n </div>\n);\n\n// ── Crop Panel Content ──────────────────────────────────────────────────────\n\nexport interface CropPanelContentProps {\n element: ImageElement;\n onElementUpdate: (element: ImageElement) => void;\n}\n\nexport const CropPanelContent: React.FC<CropPanelContentProps> = ({ element, onElementUpdate }) => (\n <CropPanel element={element} onElementUpdate={onElementUpdate} />\n);\n","/**\n * ExpandedPanelIcon - Renders the icon for the collapsed toolbar header\n * when a secondary panel is expanded.\n *\n * Special rendering for text color (shows \"A\" with color underline)\n * and shape color (shows fill icon with color underline).\n */\n\nimport React from 'react';\nimport { Icon } from '@iconify/react';\n\nexport interface ExpandedPanelIconProps {\n /** The type of expanded panel */\n panelType: string;\n /** The default icon from the panel config (used for non-special types) */\n defaultIcon: string | React.ReactNode;\n /** Current text color value (for textColor type) */\n textColorValue?: string;\n /** Current shape fill color value (for shapeColor type) */\n shapeFillColor?: string;\n}\n\nexport const ExpandedPanelIcon: React.FC<ExpandedPanelIconProps> = ({\n panelType,\n defaultIcon,\n textColorValue,\n shapeFillColor,\n}) => {\n if (panelType === 'textColor') {\n return (\n <div className=\"sc:relative sc:flex sc:size-6 sc:items-center sc:justify-center sc:md:size-5\">\n <span className=\"sc:text-primary sc:text-xl sc:leading-none sc:font-bold sc:md:text-lg\">A</span>\n <div\n className=\"sc:absolute sc:bottom-0 sc:left-1/2 sc:h-[3px] sc:w-4 sc:-translate-x-1/2 sc:rounded-sm\"\n style={{ backgroundColor: textColorValue }}\n />\n </div>\n );\n }\n\n if (panelType === 'shapeColor') {\n return (\n <div className=\"sc:relative sc:flex sc:size-6 sc:items-center sc:justify-center sc:md:size-5\">\n <Icon icon=\"mdi:format-color-fill\" className=\"sc:text-primary sc:size-5 sc:md:size-4\" />\n <div\n className=\"sc:absolute sc:-bottom-0.5 sc:left-1/2 sc:h-[3px] sc:w-4 sc:-translate-x-1/2 sc:rounded-sm\"\n style={{ background: shapeFillColor || '#3b82f6' }}\n />\n </div>\n );\n }\n\n if (typeof defaultIcon === 'string') {\n return <Icon icon={defaultIcon} className=\"sc:text-primary sc:size-6 sc:md:size-5\" />;\n }\n\n return <>{defaultIcon}</>;\n};\n\nexport default ExpandedPanelIcon;\n","/**\n * SecondaryPanelWrapper - Animated wrapper for secondary toolbar panels.\n *\n * Provides consistent expand/collapse animation for secondary panels\n * (corner radius, crop, rotation, opacity, shape panels, color panels).\n *\n * Used in embedded mode to wrap each panel with flex + transition styling.\n */\n\nimport React from 'react';\n\nexport interface SecondaryPanelWrapperProps {\n /** Whether this panel is currently open/expanded */\n isOpen: boolean;\n /** The panel content to render inside the wrapper */\n children: React.ReactNode;\n}\n\nexport const SecondaryPanelWrapper: React.FC<SecondaryPanelWrapperProps> = ({ isOpen, children }) => {\n return (\n <div\n className=\"sc-secondary-toolbar-panel-wrapper\"\n style={{\n display: 'flex',\n flexDirection: 'column',\n flex: isOpen ? 1 : 0,\n minHeight: isOpen ? 0 : undefined,\n transition: 'flex 300ms cubic-bezier(0.32, 0.72, 0, 1)',\n }}\n >\n <div\n className={isOpen ? 'sc-secondary-panel-scroll-container' : ''}\n style={{\n flex: 1,\n display: 'flex',\n flexDirection: 'column',\n overflowY: isOpen ? 'auto' : 'hidden',\n overscrollBehaviorY: 'contain',\n WebkitOverflowScrolling: 'touch',\n transform: isOpen ? 'translateY(0)' : 'translateY(100%)',\n opacity: isOpen ? 1 : 0,\n transition: 'transform 300ms cubic-bezier(0.32, 0.72, 0, 1), opacity 200ms ease-out',\n }}\n >\n {children}\n </div>\n </div>\n );\n};\n\nexport default SecondaryPanelWrapper;\n","/**\n * ColorPanelWrapper - Animated wrapper for color picker secondary panels.\n *\n * Similar to SecondaryPanelWrapper but with minHeight: 0 on the inner\n * scroll container for proper color picker layout.\n */\n\nimport React from 'react';\n\nexport interface ColorPanelWrapperProps {\n /** Whether this panel is currently open/expanded */\n isOpen: boolean;\n /** The panel content to render inside the wrapper */\n children: React.ReactNode;\n}\n\nexport const ColorPanelWrapper: React.FC<ColorPanelWrapperProps> = ({ isOpen, children }) => {\n return (\n <div\n className=\"sc-secondary-toolbar-panel-wrapper\"\n style={{\n display: 'flex',\n flexDirection: 'column',\n flex: isOpen ? 1 : 0,\n minHeight: isOpen ? 0 : undefined,\n transition: 'flex 300ms cubic-bezier(0.32, 0.72, 0, 1)',\n }}\n >\n <div\n className={isOpen ? 'sc-secondary-panel-scroll-container' : ''}\n style={{\n flex: 1,\n minHeight: 0,\n overflowY: isOpen ? undefined : 'hidden',\n overscrollBehaviorY: 'contain',\n WebkitOverflowScrolling: 'touch',\n transform: isOpen ? 'translateY(0)' : 'translateY(100%)',\n opacity: isOpen ? 1 : 0,\n transition: 'transform 300ms cubic-bezier(0.32, 0.72, 0, 1), opacity 200ms ease-out',\n }}\n >\n {children}\n </div>\n </div>\n );\n};\n\nexport default ColorPanelWrapper;\n","/**\n * EmbeddedToolbarLayout - Layout wrapper for embedded mode toolbar.\n *\n * Manages the height animation container, secondary panel wrappers,\n * and empty state display for embedded mode.\n */\n\nimport React from 'react';\nimport { SecondaryPanelWrapper } from './shared/SecondaryPanelWrapper.js';\nimport { ColorPanelWrapper } from './shared/ColorPanelWrapper.js';\n\nexport interface EmbeddedToolbarLayoutProps {\n /** The toolbar content (collapsed header + regular buttons) */\n toolbarContent: React.ReactNode;\n /** Inner content ref for height measurement */\n innerContentRef: React.RefObject<HTMLDivElement | null>;\n /** Whether the toolbar should be rendered */\n shouldRender: boolean;\n /** Whether exit animation is playing */\n isExiting: boolean;\n /** Explicit transition height (null = use CSS Grid) */\n transitionHeight: number | null;\n /** Empty state message content */\n emptyStateContent: React.ReactNode;\n\n // Panel open states\n isAlignPanelOpen: boolean;\n isCornerRadiusPanelOpen: boolean;\n isCropPanelOpen: boolean;\n isRotationPanelOpen: boolean;\n isOpacityPanelOpen: boolean;\n isAdjustPanelOpen: boolean;\n isFontSizePanelOpen: boolean;\n isShapeCornerRadiusPanelOpen: boolean;\n isShapeTransparencyPanelOpen: boolean;\n isShapeSidesPanelOpen: boolean;\n isShapePointsPanelOpen: boolean;\n isShapeInnerRadiusPanelOpen: boolean;\n isShapeColorPanelOpen: boolean;\n isTextColorPanelOpen: boolean;\n isStrokePanelOpen: boolean;\n isShadowPanelOpen: boolean;\n isBlendModePanelOpen: boolean;\n isKnockoutPanelOpen: boolean;\n isDistressTexturePanelOpen: boolean;\n isImageMaskPanelOpen: boolean;\n\n // Panel content\n alignPanel: React.ReactNode;\n cornerRadiusPanel: React.ReactNode;\n cropPanelContent: React.ReactNode;\n rotationPanel: React.ReactNode;\n opacityPanel: React.ReactNode;\n adjustPanel: React.ReactNode;\n fontSizePanel: React.ReactNode;\n shapeCornerRadiusPanel: React.ReactNode;\n shapeTransparencyPanel: React.ReactNode;\n shapeSidesPanel: React.ReactNode;\n shapePointsPanel: React.ReactNode;\n shapeInnerRadiusPanel: React.ReactNode;\n shapeColorPanel: React.ReactNode;\n textColorPanel: React.ReactNode;\n strokePanel: React.ReactNode;\n shadowPanel: React.ReactNode;\n blendModePanel: React.ReactNode;\n knockoutPanel: React.ReactNode;\n distressTexturePanel: React.ReactNode;\n imageMaskPanel: React.ReactNode;\n}\n\nexport const EmbeddedToolbarLayout: React.FC<EmbeddedToolbarLayoutProps> = ({\n toolbarContent,\n innerContentRef,\n shouldRender,\n isExiting,\n transitionHeight,\n emptyStateContent,\n // Panel open states\n isAlignPanelOpen,\n isCornerRadiusPanelOpen,\n isCropPanelOpen,\n isRotationPanelOpen,\n isOpacityPanelOpen,\n isAdjustPanelOpen,\n isFontSizePanelOpen,\n isShapeCornerRadiusPanelOpen,\n isShapeTransparencyPanelOpen,\n isShapeSidesPanelOpen,\n isShapePointsPanelOpen,\n isShapeInnerRadiusPanelOpen,\n isShapeColorPanelOpen,\n isTextColorPanelOpen,\n isStrokePanelOpen,\n isShadowPanelOpen,\n isBlendModePanelOpen,\n isKnockoutPanelOpen,\n isDistressTexturePanelOpen,\n isImageMaskPanelOpen,\n // Panel content\n alignPanel,\n cornerRadiusPanel,\n cropPanelContent,\n rotationPanel,\n opacityPanel,\n adjustPanel,\n fontSizePanel,\n shapeCornerRadiusPanel,\n shapeTransparencyPanel,\n shapeSidesPanel,\n shapePointsPanel,\n shapeInnerRadiusPanel,\n shapeColorPanel,\n textColorPanel,\n strokePanel,\n shadowPanel,\n blendModePanel,\n knockoutPanel,\n distressTexturePanel,\n imageMaskPanel,\n}) => {\n return (\n <div\n className=\"toolbar-embedded-wrapper\"\n style={{\n display: 'flex',\n flexDirection: 'column',\n flex: 1,\n minHeight: 0, // Critical: allows flex children to shrink and enables nested scrolling\n overscrollBehaviorY: 'contain',\n }}\n >\n {/* Empty state when no element selected */}\n {emptyStateContent}\n\n <div\n className=\"toolbar-height-wrapper\"\n style={\n transitionHeight !== null\n ? {\n // During type transitions: use explicit height for direct height-to-height animation\n height: transitionHeight,\n overflow: 'hidden',\n transition: 'height 200ms cubic-bezier(0.22, 1, 0.36, 1)',\n }\n : {\n // Normal show/hide: use CSS Grid for 0fr/1fr animation\n display: 'grid',\n gridTemplateRows: shouldRender && !isExiting ? '1fr' : '0fr',\n transition: 'grid-template-rows 200ms cubic-bezier(0.22, 1, 0.36, 1)',\n }\n }\n >\n <div ref={innerContentRef}>{toolbarContent}</div>\n </div>\n\n {/* Align panel (single selection → artboard) */}\n <SecondaryPanelWrapper isOpen={isAlignPanelOpen}>{alignPanel}</SecondaryPanelWrapper>\n\n {/* Corner radius panel */}\n <SecondaryPanelWrapper isOpen={isCornerRadiusPanelOpen}>{cornerRadiusPanel}</SecondaryPanelWrapper>\n\n {/* Crop panel */}\n <SecondaryPanelWrapper isOpen={isCropPanelOpen}>{cropPanelContent}</SecondaryPanelWrapper>\n\n {/* Rotation panel */}\n <SecondaryPanelWrapper isOpen={isRotationPanelOpen}>{rotationPanel}</SecondaryPanelWrapper>\n\n {/* Opacity panel */}\n <SecondaryPanelWrapper isOpen={isOpacityPanelOpen}>{opacityPanel}</SecondaryPanelWrapper>\n\n {/* Adjust panel (image brightness/contrast/saturation) */}\n <SecondaryPanelWrapper isOpen={isAdjustPanelOpen}>{adjustPanel}</SecondaryPanelWrapper>\n\n {/* Font size panel */}\n <SecondaryPanelWrapper isOpen={isFontSizePanelOpen}>{fontSizePanel}</SecondaryPanelWrapper>\n\n {/* Shape corner radius panel */}\n <SecondaryPanelWrapper isOpen={isShapeCornerRadiusPanelOpen}>\n {shapeCornerRadiusPanel}\n </SecondaryPanelWrapper>\n\n {/* Shape transparency panel */}\n <SecondaryPanelWrapper isOpen={isShapeTransparencyPanelOpen}>\n {shapeTransparencyPanel}\n </SecondaryPanelWrapper>\n\n {/* Shape sides panel (polygon) */}\n <SecondaryPanelWrapper isOpen={isShapeSidesPanelOpen}>{shapeSidesPanel}</SecondaryPanelWrapper>\n\n {/* Shape points panel (star) */}\n <SecondaryPanelWrapper isOpen={isShapePointsPanelOpen}>{shapePointsPanel}</SecondaryPanelWrapper>\n\n {/* Shape inner radius panel (star) */}\n <SecondaryPanelWrapper isOpen={isShapeInnerRadiusPanelOpen}>\n {shapeInnerRadiusPanel}\n </SecondaryPanelWrapper>\n\n {/* Shape fill color panel */}\n <ColorPanelWrapper isOpen={isShapeColorPanelOpen}>{shapeColorPanel}</ColorPanelWrapper>\n\n {/* Text font color panel */}\n <ColorPanelWrapper isOpen={isTextColorPanelOpen}>{textColorPanel}</ColorPanelWrapper>\n\n {/* Stroke panel */}\n <SecondaryPanelWrapper isOpen={isStrokePanelOpen}>{strokePanel}</SecondaryPanelWrapper>\n\n {/* Shadow panel */}\n <SecondaryPanelWrapper isOpen={isShadowPanelOpen}>{shadowPanel}</SecondaryPanelWrapper>\n\n {/* Blend mode panel */}\n <SecondaryPanelWrapper isOpen={isBlendModePanelOpen}>{blendModePanel}</SecondaryPanelWrapper>\n\n {/* Knockout panel */}\n <SecondaryPanelWrapper isOpen={isKnockoutPanelOpen}>{knockoutPanel}</SecondaryPanelWrapper>\n\n {/* Distress texture panel */}\n <SecondaryPanelWrapper isOpen={isDistressTexturePanelOpen}>{distressTexturePanel}</SecondaryPanelWrapper>\n\n {/* Image mask panel */}\n <SecondaryPanelWrapper isOpen={isImageMaskPanelOpen}>{imageMaskPanel}</SecondaryPanelWrapper>\n </div>\n );\n};\n\nexport default EmbeddedToolbarLayout;\n","/**\n * FloatingPanels - Secondary panels rendered in floating mode.\n *\n * These panels appear below the floating toolbar in a portal,\n * positioned relative to the toolbar's screen position.\n */\n\nimport React from 'react';\nimport { SliderRow } from '../ui/index.js';\nimport CropPanel from '../CropPanel.jsx';\nimport type { ImageElement } from '../../core/ImageElement.js';\nimport type { AlignMode } from '../../utils/alignDistribute.js';\nimport { AlignPanel } from './SecondaryPanels.js';\n\nexport interface FloatingCornerRadiusPanelProps {\n toolbarPosition: { top: number; left: number };\n toolbarHeight: number;\n panelWidth: number;\n value: number;\n onChange: (value: number) => void;\n}\n\nexport const FloatingCornerRadiusPanel: React.FC<FloatingCornerRadiusPanelProps> = ({\n toolbarPosition,\n toolbarHeight,\n panelWidth,\n value,\n onChange,\n}) => (\n <div\n className=\"corner-radius-panel\"\n style={{\n position: 'fixed',\n top: `${toolbarPosition.top + toolbarHeight + 8}px`,\n left: `${toolbarPosition.left}px`,\n transform: 'translateX(-50%)',\n padding: '12px 24px',\n marginTop: '-12px',\n borderRadius: 0,\n border: '1px solid var(--divider)',\n boxShadow: '0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1)',\n zIndex: 'var(--sc-z-tooltip)',\n width: `${panelWidth}px`,\n boxSizing: 'border-box',\n }}\n >\n <SliderRow label=\"Radius\" value={value} onChange={onChange} min={0} max={50} unit=\"%\" />\n </div>\n);\n\nexport interface FloatingAlignPanelProps {\n toolbarPosition: { top: number; left: number };\n toolbarHeight: number;\n onAlign: (mode: AlignMode) => void;\n}\n\nexport const FloatingAlignPanel: React.FC<FloatingAlignPanelProps> = ({\n toolbarPosition,\n toolbarHeight,\n onAlign,\n}) => (\n <div\n className=\"sc-align-panel\"\n style={{\n position: 'fixed',\n top: `${toolbarPosition.top + toolbarHeight + 8}px`,\n left: `${toolbarPosition.left}px`,\n transform: 'translateX(-50%)',\n background: 'var(--background)',\n border: '1px solid var(--divider)',\n borderRadius: '12px',\n boxShadow: '0 4px 12px 0 rgb(0 0 0 / 0.15)',\n zIndex: 'var(--sc-z-tooltip)' as React.CSSProperties['zIndex'],\n }}\n >\n <AlignPanel onAlign={onAlign} />\n </div>\n);\n\nexport interface FloatingCropPanelProps {\n toolbarPosition: { top: number; left: number };\n toolbarHeight: number;\n element: ImageElement;\n onElementUpdate: (element: ImageElement) => void;\n}\n\nexport const FloatingCropPanel: React.FC<FloatingCropPanelProps> = ({\n toolbarPosition,\n toolbarHeight,\n element,\n onElementUpdate,\n}) => (\n <div\n className=\"sc-crop-panel\"\n style={{\n position: 'fixed',\n top: `${toolbarPosition.top + toolbarHeight + 8}px`,\n left: `${toolbarPosition.left}px`,\n transform: 'translateX(-50%)',\n background: 'var(--background)',\n border: '1px solid var(--divider)',\n borderRadius: '12px',\n boxShadow: '0 4px 12px 0 rgb(0 0 0 / 0.15)',\n zIndex: 'var(--sc-z-tooltip)',\n minWidth: '300px',\n }}\n >\n <CropPanel element={element} onElementUpdate={onElementUpdate} />\n </div>\n);\n","/**\n * documentColors — collect every colour actually in use in a design.\n *\n * Surfaced in the colour-picker dropdowns (\"Document colors\" /\n * \"Image colors\" rows) so users can match a colour they're already\n * using elsewhere in the artwork instead of eyeballing it.\n *\n * Two kinds of colours are exposed:\n *\n * - **Vector colours** (`collectDocumentColors`) — text colours,\n * rich-text span colours, shape fills, path fills, path strokes,\n * element-level stroke colours, and artboard background. Cheap,\n * synchronous read off the data model.\n *\n * - **Image colours** (`extractImagePalette` / `collectImageColors`) —\n * a small dominant-colour palette per image element. Async, requires\n * pixel access (the image must be CORS-loaded — see CLAUDE.md\n * \"CORS Cache Poisoning\"). Cached by URL.\n */\n\nimport type { BaseElement } from '../core/BaseElement.js';\nimport { TextElement } from '../core/TextElement.js';\nimport { ShapeElement } from '../core/ShapeElement.js';\nimport { ImageElement } from '../core/ImageElement.js';\nimport { GroupElement } from '../core/GroupElement.js';\nimport { PathElement } from '../core/PathElement.js';\nimport type { ArtboardElement } from '../core/ArtboardElement.js';\n\nconst isPaintable = (c: unknown): c is string =>\n typeof c === 'string' && c.length > 0 && c !== 'transparent';\n\n/**\n * Walk one element and push every paint colour it carries into `out`.\n * Recurses into group children. Element-level stroke is only counted\n * when `stroke.enabled === true` so disabled-but-configured strokes\n * don't pollute the palette.\n */\nfunction collectFromElement(el: BaseElement, out: Set<string>): void {\n // Element-level stroke (StrokeConfig) — applies to text, image,\n // shape, group, path uniformly.\n const stroke = (el as { stroke?: { enabled?: boolean; color?: string } })\n .stroke;\n if (stroke?.enabled && isPaintable(stroke.color)) {\n out.add(stroke.color);\n }\n\n if (el instanceof TextElement) {\n if (isPaintable(el.color)) out.add(el.color);\n // Rich-text span colours — each per-character span can override\n // the element default. Skip undefined (means \"inherit element\n // colour\" — already added above).\n const richText = (el as { richText?: { spans?: Array<{ style?: { color?: string } }> } }).richText;\n if (richText?.spans) {\n for (const span of richText.spans) {\n if (isPaintable(span.style?.color)) out.add(span.style!.color!);\n }\n }\n return;\n }\n\n if (el instanceof ShapeElement) {\n const richFill = el.transformData.fill;\n if (richFill) {\n // Rich fill wins over fillColor at render time — collect what paints.\n if (richFill.type === 'solid') {\n if (isPaintable(richFill.color)) out.add(richFill.color);\n } else {\n for (const stop of richFill.stops) {\n if (isPaintable(stop.color)) out.add(stop.color);\n }\n }\n return;\n }\n const fill = el.transformData.fillColor;\n if (isPaintable(fill)) out.add(fill);\n return;\n }\n\n if (el instanceof PathElement) {\n const td = (el as PathElement).transformData;\n if (td.fillEnabled && isPaintable(td.fillColor)) out.add(td.fillColor);\n if (td.strokeEnabled && isPaintable(td.strokeColor)) out.add(td.strokeColor);\n return;\n }\n\n if (el instanceof GroupElement) {\n // Group itself doesn't paint — children do. Recurse.\n for (const child of el.children) {\n collectFromElement(child, out);\n }\n return;\n }\n\n // ImageElement contributes via image-palette extraction, not vector\n // colours.\n}\n\n/**\n * Collect every vector colour in the design. Synchronous.\n *\n * @param elements - Top-level elements (groups recurse internally)\n * @param artboards - Optional. When provided, `backgroundColor` from\n * each artboard is included (real exported background; the UI-only\n * `previewBackgroundColor` is intentionally skipped — it's the\n * shirt-colour preview, not part of the artwork).\n */\nexport function collectDocumentColors(\n elements: ReadonlyArray<BaseElement>,\n artboards?: ReadonlyArray<ArtboardElement>\n): Set<string> {\n const out = new Set<string>();\n for (const el of elements) collectFromElement(el, out);\n if (artboards) {\n for (const ab of artboards) {\n const bg = (ab as { backgroundColor?: string }).backgroundColor;\n if (isPaintable(bg)) out.add(bg);\n }\n }\n return out;\n}\n\n// ============================================================================\n// Image palette extraction\n// ============================================================================\n\nconst IMAGE_PALETTE_CACHE = new Map<string, string[]>();\nconst IMAGE_PALETTE_INFLIGHT = new Map<string, Promise<string[]>>();\n\ntype RGB = { r: number; g: number; b: number };\n\n/**\n * Median cut box — a region of RGB space holding some pixels plus\n * the per-channel ranges (cached so we can pick the longest axis\n * cheaply when deciding which axis to split next).\n */\ntype Box = {\n pixels: RGB[];\n rRange: number;\n gRange: number;\n bRange: number;\n};\n\nfunction computeRanges(pixels: RGB[]): { rRange: number; gRange: number; bRange: number } {\n if (pixels.length === 0) return { rRange: 0, gRange: 0, bRange: 0 };\n let rMin = 255, rMax = 0, gMin = 255, gMax = 0, bMin = 255, bMax = 0;\n for (const p of pixels) {\n if (p.r < rMin) rMin = p.r;\n if (p.r > rMax) rMax = p.r;\n if (p.g < gMin) gMin = p.g;\n if (p.g > gMax) gMax = p.g;\n if (p.b < bMin) bMin = p.b;\n if (p.b > bMax) bMax = p.b;\n }\n return { rRange: rMax - rMin, gRange: gMax - gMin, bRange: bMax - bMin };\n}\n\nfunction boxLongestAxis(box: Box): 'r' | 'g' | 'b' {\n const max = Math.max(box.rRange, box.gRange, box.bRange);\n if (box.rRange === max) return 'r';\n if (box.gRange === max) return 'g';\n return 'b';\n}\n\nfunction boxSize(box: Box): number {\n return Math.max(box.rRange, box.gRange, box.bRange);\n}\n\nfunction splitBox(box: Box): [Box, Box] {\n const axis = boxLongestAxis(box);\n // Sort by the longest axis so the median split actually balances\n // pixel count across the most-spread channel.\n const sorted = box.pixels.slice().sort((a, b) => a[axis] - b[axis]);\n const mid = sorted.length >> 1;\n const leftPixels = sorted.slice(0, mid);\n const rightPixels = sorted.slice(mid);\n return [\n { pixels: leftPixels, ...computeRanges(leftPixels) },\n { pixels: rightPixels, ...computeRanges(rightPixels) },\n ];\n}\n\nfunction averageColor(pixels: RGB[]): RGB {\n let r = 0, g = 0, b = 0;\n for (const p of pixels) {\n r += p.r;\n g += p.g;\n b += p.b;\n }\n const n = pixels.length;\n return {\n r: Math.round(r / n),\n g: Math.round(g / n),\n b: Math.round(b / n),\n };\n}\n\n/**\n * Median-cut quantisation, internal Box-returning variant. Recursively\n * splits the colour-space box with the largest spread until we reach\n * `targetBuckets`. Boxes are returned so callers that need the per-box\n * pixel population (e.g. for sorting before dedupe) can read it.\n */\nfunction medianCutBoxes(pixels: RGB[], targetBuckets: number): Box[] {\n if (pixels.length === 0) return [];\n const boxes: Box[] = [{ pixels, ...computeRanges(pixels) }];\n\n while (boxes.length < targetBuckets) {\n // Always split the box with the largest single-axis spread —\n // that's where we'll get the most colour diversity from one\n // additional bucket.\n let bestIdx = -1;\n let bestSize = 0;\n for (let i = 0; i < boxes.length; i++) {\n const size = boxSize(boxes[i]);\n if (size > bestSize && boxes[i].pixels.length >= 2) {\n bestSize = size;\n bestIdx = i;\n }\n }\n if (bestIdx === -1) break; // every remaining box is unsplittable\n const target = boxes[bestIdx];\n boxes.splice(bestIdx, 1);\n boxes.push(...splitBox(target));\n }\n\n return boxes;\n}\n\n/**\n * Median-cut quantisation. Returns the average colour of each box.\n *\n * Why this beats a frequency histogram for our use case: a frequency\n * histogram returns the most-populated buckets, which means a smooth\n * gradient (sunset reds spread across many adjacent buckets) loses\n * to a flat region (solid black sky) even when the gradient is the\n * visually salient subject. Median cut splits by *spread* in colour\n * space, so red, orange, and yellow each get their own bucket.\n *\n * @internal exported for tests\n */\nexport function medianCut(pixels: RGB[], targetBuckets: number): RGB[] {\n return medianCutBoxes(pixels, targetBuckets).map((box) => averageColor(box.pixels));\n}\n\n/**\n * Redmean ΔE — a cheap perceptual-distance approximation. Pure\n * Euclidean RGB distance treats (50,0,0) vs (0,0,50) as identical,\n * which is wrong because the eye is more sensitive to green than red\n * or blue. Redmean weights each channel by the average of the two\n * reds, which biases the metric toward perceived difference at low\n * cost. See https://www.compuphase.com/cmetric.htm.\n *\n * Returned distance is roughly comparable to a CIE-76 ΔE: ~25 means\n * \"noticeably different,\" ~50+ means \"obviously different.\"\n *\n * @internal exported for tests\n */\nexport function redmeanDistance(a: RGB, b: RGB): number {\n const rMean = (a.r + b.r) / 2;\n const dr = a.r - b.r;\n const dg = a.g - b.g;\n const db = a.b - b.b;\n return Math.sqrt(\n (2 + rMean / 256) * dr * dr +\n 4 * dg * dg +\n (2 + (255 - rMean) / 256) * db * db\n );\n}\n\n/**\n * Drop palette entries that are visually indistinguishable from one\n * we already kept. Walks in input order, so callers should pre-sort\n * by importance (we sort by population — bigger boxes first — so\n * the most-prominent shade in a \"near-duplicate\" cluster wins).\n *\n * @internal exported for tests\n */\nexport function dedupeByPerceptualDistance(\n palette: RGB[],\n threshold: number\n): RGB[] {\n const out: RGB[] = [];\n for (const c of palette) {\n let dup = false;\n for (const kept of out) {\n if (redmeanDistance(c, kept) <= threshold) {\n dup = true;\n break;\n }\n }\n if (!dup) out.push(c);\n }\n return out;\n}\n\n/**\n * Pick a diverse palette from a population-sorted candidate list via\n * furthest-point sampling. The first candidate is taken as the anchor\n * (most populous). Each subsequent pick maximises the minimum redmean\n * distance to every already-picked colour, so the row spans the image's\n * actual colour variation instead of N shades of whatever hue dominates.\n *\n * Candidates closer than `threshold` to an already-picked colour are\n * skipped — that's the dedupe step folded into the same pass. Stops\n * when there are no further candidates above the threshold.\n *\n * @internal exported for tests\n */\nexport function furthestPointPalette(\n candidates: RGB[],\n paletteSize: number,\n threshold: number\n): RGB[] {\n if (candidates.length === 0 || paletteSize <= 0) return [];\n const picked: RGB[] = [candidates[0]];\n const used = new Set<number>([0]);\n while (picked.length < paletteSize) {\n let bestIdx = -1;\n let bestMinDist = -1;\n for (let i = 1; i < candidates.length; i++) {\n if (used.has(i)) continue;\n let minDist = Infinity;\n for (const p of picked) {\n const d = redmeanDistance(candidates[i], p);\n if (d < minDist) minDist = d;\n }\n if (minDist > bestMinDist) {\n bestMinDist = minDist;\n bestIdx = i;\n }\n }\n if (bestIdx === -1 || bestMinDist <= threshold) break;\n picked.push(candidates[bestIdx]);\n used.add(bestIdx);\n }\n return picked;\n}\n\nconst toHex = (n: number) => n.toString(16).padStart(2, '0');\nfunction rgbToHex(c: RGB): string {\n return `#${toHex(c.r)}${toHex(c.g)}${toHex(c.b)}`;\n}\n\n/**\n * Extract up to `paletteSize` dominant colours from an image URL.\n *\n * Implementation:\n * 1. Draw the image into a small offscreen canvas (48×48). Smaller\n * than the source, but enough resolution for dominant colours\n * and *much* faster than walking the full image.\n * 2. Sample every pixel; skip fully-transparent and near-white\n * (background swamps the palette and isn't useful for matching).\n * 3. Run median cut to produce ~2× the requested palette size\n * (gives dedupe headroom).\n * 4. Sort by box population so visually-prominent shades come first\n * within near-duplicate clusters.\n * 5. Drop near-duplicates by redmean-weighted ΔE — without this\n * step a photo with a big black region returns 3 indistinguishable\n * blacks instead of black + the actual subject colours.\n * 6. Truncate to `paletteSize`.\n *\n * Cached per URL in module-scope (cache survives component unmount;\n * wiped on hard reload).\n *\n * Requires `crossOrigin=\"anonymous\"` on the source image. If the\n * image is CORS-tainted, `getImageData` throws and we cache an empty\n * array. Per CLAUDE.md \"CORS Cache Poisoning\" all canvas images\n * already set this.\n */\nexport async function extractImagePalette(\n imageUrl: string,\n paletteSize = 5\n): Promise<string[]> {\n if (!imageUrl) return [];\n const cached = IMAGE_PALETTE_CACHE.get(imageUrl);\n if (cached) return cached;\n const inflight = IMAGE_PALETTE_INFLIGHT.get(imageUrl);\n if (inflight) return inflight;\n\n const promise = (async (): Promise<string[]> => {\n try {\n const img = await loadCorsImage(imageUrl);\n const SAMPLE = 48; // 48×48 = 2304 pixels — plenty for dominant colours.\n const canvas = typeof OffscreenCanvas !== 'undefined'\n ? new OffscreenCanvas(SAMPLE, SAMPLE)\n : (() => {\n const c = document.createElement('canvas');\n c.width = SAMPLE;\n c.height = SAMPLE;\n return c;\n })();\n const ctx = (canvas as HTMLCanvasElement | OffscreenCanvas)\n .getContext('2d') as\n | CanvasRenderingContext2D\n | OffscreenCanvasRenderingContext2D\n | null;\n if (!ctx) return [];\n ctx.drawImage(img, 0, 0, SAMPLE, SAMPLE);\n const { data } = ctx.getImageData(0, 0, SAMPLE, SAMPLE);\n\n const pixels: RGB[] = [];\n for (let i = 0; i < data.length; i += 4) {\n const a = data[i + 3];\n if (a < 128) continue; // skip transparent\n const r = data[i];\n const g = data[i + 1];\n const b = data[i + 2];\n // Skip near-white pixels — typical background.\n if (r > 240 && g > 240 && b > 240) continue;\n pixels.push({ r, g, b });\n }\n if (pixels.length === 0) {\n IMAGE_PALETTE_CACHE.set(imageUrl, []);\n return [];\n }\n\n // Over-extract aggressively so diversity selection has lots of\n // candidates to choose from. Without this, photos dominated by\n // one hue (e.g. green leaves) fill every box with a slight\n // variant of that hue and a visually-prominent minority colour\n // (gold accents on a green background) never makes it into the\n // candidate pool.\n const overExtract = Math.max(paletteSize * 4, 16);\n const boxes = medianCutBoxes(pixels, overExtract);\n // Sort by population so the biggest cluster's average wins\n // as our anchor for furthest-point sampling.\n boxes.sort((a, b) => b.pixels.length - a.pixels.length);\n\n const candidates = boxes.map((box) => averageColor(box.pixels));\n // Furthest-point sampling: pick the most populous colour as the\n // anchor, then each subsequent pick is the candidate with the\n // largest minimum redmean distance to everything already picked.\n // This serves two goals at once — drops perceptually-indistinct\n // near-duplicates (via the threshold cutoff) AND surfaces\n // visually-salient minority colours that pure population-sort\n // would push out of the top-N slice. Threshold tuned against\n // the sunset failure case: (8,8,8) and (24,24,24) sit ~48\n // redmean apart and should collapse into one swatch.\n // Tradeoff: subtle gradients (deep-red vs red, ~33 apart)\n // collapse — but for a \"match a colour in your design\" picker\n // that's the right call. Five obviously-different swatches beats\n // five shades-of-the-same-thing, AND gold on a green photo\n // actually appears in the row.\n const top = furthestPointPalette(candidates, paletteSize, 50).map(rgbToHex);\n\n IMAGE_PALETTE_CACHE.set(imageUrl, top);\n return top;\n } catch {\n // CORS taint, decode failure, etc. Cache empty result so we\n // don't re-attempt every render.\n IMAGE_PALETTE_CACHE.set(imageUrl, []);\n return [];\n } finally {\n IMAGE_PALETTE_INFLIGHT.delete(imageUrl);\n }\n })();\n IMAGE_PALETTE_INFLIGHT.set(imageUrl, promise);\n return promise;\n}\n\nfunction loadCorsImage(url: string): Promise<HTMLImageElement> {\n return new Promise((resolve, reject) => {\n const img = new Image();\n // CORS attr MUST be set before src — see CLAUDE.md gotcha #13.\n img.crossOrigin = 'anonymous';\n img.onload = () => resolve(img);\n img.onerror = () => reject(new Error(`Failed to load image: ${url}`));\n img.src = url;\n });\n}\n\n/**\n * Walk every ImageElement (recursing into groups), pull the unique\n * URLs, extract a small palette per image, and return the deduped\n * union. Order is \"first image first, top-N per image\" so the row\n * has predictable colours. Returns [] if no images.\n */\nexport async function collectImageColors(\n elements: ReadonlyArray<BaseElement>,\n paletteSize = 5\n): Promise<string[]> {\n const urls: string[] = [];\n const seen = new Set<string>();\n const visit = (el: BaseElement) => {\n if (el instanceof ImageElement) {\n const url = el.imageUrl;\n if (url && !seen.has(url)) {\n seen.add(url);\n urls.push(url);\n }\n } else if (el instanceof GroupElement) {\n for (const c of el.children) visit(c);\n }\n };\n for (const el of elements) visit(el);\n if (urls.length === 0) return [];\n\n const palettes = await Promise.all(\n urls.map((u) => extractImagePalette(u, paletteSize))\n );\n const out: string[] = [];\n const dedupe = new Set<string>();\n for (const palette of palettes) {\n for (const c of palette) {\n if (!dedupe.has(c)) {\n dedupe.add(c);\n out.push(c);\n }\n }\n }\n return out;\n}\n\n/**\n * Test-only: clear the in-memory palette caches so unit tests start\n * from a known state.\n * @internal\n */\nexport function _resetImagePaletteCache(): void {\n IMAGE_PALETTE_CACHE.clear();\n IMAGE_PALETTE_INFLIGHT.clear();\n}\n","/**\n * ContextualToolbars - Renders the appropriate toolbar for the selected element type.\n *\n * Dispatches to element-specific toolbars (text, image, shape, path, artboard)\n * based on the current selection in `EditorContext`. Also manages expanded\n * sub-panels (crop, corner radius, effects, rotation) and floating overlays.\n *\n * Place anywhere inside an `EditorProvider` -- it reads selection state from context.\n *\n * @example\n * ```tsx\n * <EditorProvider>\n * <Canvas />\n * <ContextualToolbars />\n * </EditorProvider>\n * ```\n */\n\nimport React, { useState, useCallback, useEffect, useLayoutEffect, useRef, useMemo } from 'react';\nimport { createPortal } from 'react-dom';\nimport { useEditor } from '../contexts/EditorContext.js';\nimport { useViewportContext } from '../contexts/ViewportContext.js';\nimport { useSelectionContext } from '../contexts/SelectionContext.js';\nimport { useToolStateContext } from '../contexts/ToolStateContext.js';\nimport {\n CanvasServicesProvider,\n useCanvasServices,\n type CanvasServices,\n} from '../contexts/CanvasServicesContext.js';\nimport BackButton from './BackButton.jsx';\nimport ImageToolbar from './ImageToolbar.jsx';\nimport ShapeToolbar from './ShapeToolbar.jsx';\nimport ShapeTypeDrawer from './ShapeTypeDrawer.jsx';\nimport PathToolbar from './PathToolbar.jsx';\nimport ArtboardPropertiesToolbar from './ArtboardPropertiesToolbar.jsx';\nimport { TextToolbar } from './TextToolbar.js';\nimport { useTextToolbar } from '../hooks/useTextToolbar.js';\nimport { useCommands } from '../hooks/useCommands.js';\nimport { NEUTRAL_ADJUSTMENTS, normalizeAdjustments } from '../core/image-adjustments.js';\nimport type { EditorElement } from '../contexts/EditorContext.js';\nimport { ImageElement } from '../core/ImageElement.js';\nimport { GroupElement } from '../core/GroupElement.js';\nimport { ShapeElement } from '../core/ShapeElement.js';\nimport { PathElement } from '../core/PathElement.js';\nimport { CollapsedToolbarHeader, ToolbarButton, icons } from './ui';\nimport { LayerLeadingChip } from './LayerLeadingChip.js';\nimport { MultiSelectionToolbar } from './MultiSelectionToolbar.js';\nimport { useAlignDistribute } from '../hooks/useAlignDistribute.js';\nimport {\n GroupElementToolbar,\n ExpandedPanelIcon,\n EmbeddedToolbarLayout,\n FloatingAlignPanel,\n FloatingCornerRadiusPanel,\n FloatingCropPanel,\n AlignPanel,\n CornerRadiusPanel,\n RotationPanel,\n OpacityPanel,\n AdjustPanel,\n FontSizePanel,\n ShapeCornerRadiusPanel,\n ShapeTransparencyPanel,\n ShapeSidesPanel,\n ShapePointsPanel,\n ShapeInnerRadiusPanel,\n ShapeColorPanel,\n TextColorPanel,\n CompositingPanel,\n StrokePanel,\n ShadowPanel,\n BlendModePanel,\n CropPanelContent,\n DistressTexturePanel,\n ImageMaskPanel,\n} from './toolbars/index.js';\nimport type { CompositingMode } from './toolbars/SecondaryPanels.js';\nimport type { CompositingScope, ImageAdjustments, ShapeFill, ShadowConfig, StandardBlendMode } from '../types/index.js';\nimport { isStandardBlendMode } from '../types/index.js';\nimport { shapeFillToCss } from '../core/shape-fill.js';\nimport ArtboardDistressPanel from './ArtboardDistressPanel.jsx';\nimport ArtboardImageMaskPanel from './ArtboardImageMaskPanel.jsx';\nimport { createLogger } from '../utils/logger.js';\nimport { collectDocumentColors, collectImageColors } from '../utils/documentColors.js';\n\nconst logger = createLogger('ContextualToolbars');\n\n// User-facing failure copy. NEVER mention configuration internals here.\nconst REMOVE_BG_UNAVAILABLE = 'Background removal is temporarily unavailable.';\n\n/** Keep host-provided error copy, but never surface configuration internals. */\nfunction safeErrorMessage(err: unknown, fallback: string): string {\n const message = err instanceof Error ? err.message : '';\n if (!message || /VITE_|NEXT_PUBLIC_|\\.env/i.test(message)) return fallback;\n return message;\n}\n\ntype MenuType = 'root' | 'transforms' | 'align' | 'color';\ntype DropdownType = 'fontSize' | 'fontFamily' | null;\n\n/** Panel configuration for collapsed header */\ntype ExpandedPanelConfig = {\n type:\n | 'align'\n | 'cornerRadius'\n | 'effects'\n | 'crop'\n | 'rotation'\n | 'opacity'\n | 'adjust'\n | 'fontSize'\n | 'shapeCornerRadius'\n | 'shapeTransparency'\n | 'shapeSides'\n | 'shapePoints'\n | 'shapeInnerRadius'\n | 'shapeColor'\n | 'textColor'\n | 'stroke'\n | 'shadow'\n | 'blendMode'\n | 'compositing'\n | 'distressTexture'\n | 'imageMask';\n icon: string | React.ReactNode;\n label: string;\n} | null;\n\nexport interface ContextualToolbarsProps {\n /**\n * Positioning mode for the toolbar\n * - 'floating': Positioned relative to selected element (default)\n * - 'embedded': Static positioning for embedding in a container\n */\n mode?: 'floating' | 'embedded';\n\n /**\n * @deprecated Effects panel drawer has been replaced by inline secondary panels.\n * Stroke, masks, distress, and knockout are now accessible directly from the toolbar.\n */\n onOpenEffectsPanel?: () => void;\n\n /**\n * Callback when glyph browser should be opened\n */\n onOpenGlyphBrowser?: () => void;\n\n /**\n * Callback when image should be changed\n */\n onChangeImage?: () => void;\n\n /**\n * Callback when shape type drawer should be opened\n */\n onOpenShapeTypeDrawer?: () => void;\n\n /**\n * Document colors for color picker\n */\n documentColors?: Set<string>;\n\n /**\n * Current viewport width for responsive behavior\n */\n viewportWidth?: number;\n\n /**\n * Responsive breakpoints for layout\n * - full: All controls visible (default: 1024)\n * - compact: Some controls in overflow menu (default: 768)\n * - minimal: Only essential controls, rest in overflow (default: 480)\n */\n breakpoints?: {\n full?: number;\n compact?: number;\n minimal?: number;\n };\n\n /**\n * Whether element has glyphs available\n */\n hasGlyphs?: boolean;\n\n /**\n * Callback to get more menu items for text elements\n */\n getMoreMenuItems?: () => Array<{ label: string; onClick: () => void; icon: React.ReactNode; active?: boolean }>;\n\n /**\n * Callback when artboard is updated\n */\n onArtboardUpdate?: (artboardId: string, oldProps: Record<string, unknown>, newProps: Record<string, unknown>) => void;\n\n /**\n * Artboard screen bounds for positioning toolbars\n */\n artboardScreenBounds?: {\n left: number;\n top: number;\n width: number;\n height: number;\n bottom: number;\n centerX: number;\n };\n\n /**\n * Maximum width for the toolbar. When set, enables flex-wrap for multi-row layout.\n * Can be a number (pixels) or a CSS string (e.g., '100%', '400px').\n */\n maxWidth?: number | string;\n\n /**\n * When true, removes the toolbar background, border, and shadow for a transparent look.\n * Useful when embedding in a custom UI where you want only the controls visible.\n */\n transparent?: boolean;\n\n /**\n * Callback when a secondary panel is expanded or collapsed.\n * Useful for styling the container as a bottom drawer when panels are visible.\n */\n onPanelExpandChange?: (expanded: boolean) => void;\n\n /**\n * Default expanded panel type. Used to open a specific panel on mount.\n * Useful when rendering in a drawer that needs to show a specific panel.\n */\n defaultExpandedPanel?: 'cornerRadius' | 'effects' | 'crop' | 'rotation' | null;\n\n /**\n * Callback when expanded panel changes, passing the panel type.\n * Useful for tracking which specific panel is expanded.\n */\n onExpandedPanelTypeChange?: (panelType: 'cornerRadius' | 'effects' | 'crop' | 'rotation' | null) => void;\n\n /**\n * Callback when crop drawer should be opened.\n * When provided, clicking the crop button will call this instead of showing inline panel.\n * Use this to render the crop controls in a drawer in the parent component.\n */\n onOpenCropDrawer?: () => void;\n\n /**\n * Callback when corner radius drawer should be opened.\n * When provided, clicking the corner radius button will call this instead of showing inline panel.\n * Use this to render the corner radius controls in a drawer in the parent component.\n */\n onOpenCornerRadiusDrawer?: () => void;\n\n /**\n * Style for the close button in expanded panel headers.\n * - 'icon': Shows X icon (default)\n * - 'done': Shows \"Done\" text button\n */\n closeButtonStyle?: 'icon' | 'done';\n\n /**\n * Message to display when no element is selected (embedded mode only).\n * Set to null to hide the empty state completely.\n * Default: \"Tap an element to select and edit\"\n */\n emptyStateMessage?: string | null;\n\n /**\n * Custom content to render when no element is selected (embedded mode only).\n * Replaces the default emptyStateMessage text. Use for live mockup previews, etc.\n */\n emptyStateRender?: React.ReactNode;\n\n /**\n * When true and no element is selected, shows artboard distress panel\n * in the empty state slot (embedded mode only).\n */\n editArtboardMode?: boolean;\n\n /**\n * Called when artboard edit mode should change (e.g. dismissed by selecting\n * an element or clicking the \"Done\" button).\n */\n onEditArtboardModeChange?: (active: boolean) => void;\n\n /**\n * Called when the leading layer thumbnail in the toolbar is clicked.\n * Typical wiring: open the host app's \"Manage Layers\" drawer with\n * the currently-selected layer focused. The selected layer is\n * already tracked by EditorContext so the drawer's `LayersPanel`\n * will highlight the right row automatically.\n *\n * When omitted, the thumbnail is non-interactive (just a visual\n * indicator of the selection).\n */\n onLayerThumbnailClick?: () => void;\n\n /**\n * Privileged-service wiring (background removal, image search / AI\n * generation proxy URLs or providers). Needed when this toolbar is mounted\n * OUTSIDE `SnowconeCanvas` (e.g. a host app with its own chrome via\n * `externalProvider`) — the canvas-internal `CanvasServicesProvider` can't\n * reach it there. When the toolbar renders inside `SnowconeCanvas`, omit\n * this and the ambient context applies; passing it explicitly wins either way.\n */\n services?: CanvasServices;\n\n /**\n * `data-sc-part` value for the toolbar root (the Editor.* parts contract,\n * ADR-0085 §5 — the class-3 floating toolbar is themable and selectable via\n * `data-sc-part` even though the host doesn't position it). Set by the\n * canvas's built-in floating mount; omitted everywhere else.\n * @internal\n */\n partAttr?: string;\n}\n\nexport const ContextualToolbars: React.FC<ContextualToolbarsProps> = ({ services, ...props }) => {\n const inner = <ContextualToolbarsInner {...props} />;\n // Only wrap when the prop is present — an unconditional wrapper with\n // `services={undefined}` would clobber the ambient context from\n // `SnowconeCanvas` with empty services and hide every service-gated control.\n return services ? <CanvasServicesProvider services={services}>{inner}</CanvasServicesProvider> : inner;\n};\n\nconst ContextualToolbarsInner: React.FC<Omit<ContextualToolbarsProps, 'services'>> = ({\n mode = 'floating',\n onOpenGlyphBrowser,\n onChangeImage,\n onOpenShapeTypeDrawer,\n documentColors = new Set(),\n viewportWidth = window.innerWidth,\n breakpoints: _breakpoints = {},\n hasGlyphs = false,\n getMoreMenuItems,\n onArtboardUpdate,\n artboardScreenBounds,\n maxWidth,\n transparent = false,\n onPanelExpandChange,\n defaultExpandedPanel,\n onExpandedPanelTypeChange,\n onOpenCropDrawer,\n onOpenCornerRadiusDrawer,\n closeButtonStyle = 'icon',\n emptyStateMessage = 'Tap an element to select and edit',\n emptyStateRender,\n editArtboardMode = false,\n onEditArtboardModeChange,\n onLayerThumbnailClick,\n partAttr,\n}) => {\n // ── Focused sub-contexts ────────────────────────────────────────────────\n // Use sub-context hooks to avoid re-renders from unrelated state changes.\n const { panOffset } = useViewportContext();\n const { multiSelection, setSelectedId } = useSelectionContext();\n const {\n expandedPanelType: contextExpandedPanelType,\n setExpandedPanelType: setContextExpandedPanelType,\n setIsToolbarMenuOpen,\n isRotating,\n } = useToolStateContext();\n\n // ── Editor context (core state not available in sub-contexts) ──────────\n const {\n elements,\n setElements,\n selectedElement,\n activeChildElement,\n handleElementUpdate,\n artboardManager,\n artboards,\n canvasEditorRef,\n canvasRef,\n executeElementUpdate,\n executeRemoveElement,\n executeAddElement,\n executeReorderElement,\n refreshArtboards,\n } = useEditor();\n\n // ── Privileged services (background removal) ────────────────────────────\n const { removeBackground } = useCanvasServices();\n\n // ── Text toolbar hook ───────────────────────────────────────────────────\n const textToolbar = useTextToolbar({ canvasEditorRef });\n\n // ── Local state ─────────────────────────────────────────────────────────\n const [activeMenu, setActiveMenu] = useState<MenuType>('root');\n const [openDropdown, setOpenDropdown] = useState<DropdownType>(null);\n const [toolbarPosition, setToolbarPosition] = useState<{ top: number; left: number } | null>(null);\n const [_isDragging, setIsDragging] = useState<boolean>(false);\n const [isTransformMenuOpen, setIsTransformMenuOpen] = useState<boolean>(false);\n const [isColorPickerOpen] = useState<boolean>(false);\n const [isTextMoreMenuOpen, setIsTextMoreMenuOpen] = useState<boolean>(false);\n const [isShapeTypeDrawerOpen, setIsShapeTypeDrawerOpen] = useState<boolean>(false);\n\n // ── Expanded panel state ────────────────────────────────────────────────\n const [expandedPanel, setExpandedPanel] = useState<ExpandedPanelConfig>(() => {\n if (!defaultExpandedPanel) return null;\n const panelConfigs: Record<string, ExpandedPanelConfig> = {\n cornerRadius: { type: 'cornerRadius', icon: 'lucide:square-round-corner', label: 'Corner Radius' },\n crop: { type: 'crop', icon: 'lucide:crop', label: 'Crop' },\n rotation: { type: 'rotation', icon: icons.rotateLeft, label: 'Rotate' },\n opacity: { type: 'opacity', icon: 'lucide:blend', label: 'Transparency' },\n effects: { type: 'effects', icon: 'lucide:sparkles', label: 'Effects' },\n };\n return panelConfigs[defaultExpandedPanel] || null;\n });\n\n // ── Animation states ────────────────────────────────────────────────────\n const [isEntering, setIsEntering] = useState<boolean>(false);\n const [isExiting, setIsExiting] = useState<boolean>(false);\n const [shouldRender, setShouldRender] = useState<boolean>(false);\n const [isWaitingForPosition, setIsWaitingForPosition] = useState<boolean>(false);\n const [positionedElementId, setPositionedElementId] = useState<string | null>(null);\n const [transitionHeight, setTransitionHeight] = useState<number | null>(null);\n const [toolbarDimensions, setToolbarDimensions] = useState({ width: 0, height: 0 });\n\n // ── Refs ────────────────────────────────────────────────────────────────\n const toolbarRef = useRef<HTMLDivElement>(null);\n const innerContentRef = useRef<HTMLDivElement>(null);\n const lastKnownHeightRef = useRef<number>(0);\n const prevShouldShowRef = useRef<boolean>(false);\n const isMouseDownRef = useRef<boolean>(false);\n const frozenPositionRef = useRef<{ top: number; left: number } | null>(null);\n const lastElementRotationRef = useRef<number | undefined>(undefined);\n const lastSyncedToContextRef = useRef<string | null>(null);\n const prevContextExpandedPanelTypeRef = useRef(contextExpandedPanelType);\n const prevSelectedIdRef = useRef<string | undefined>(undefined);\n const prevElementTypeRef = useRef<string | undefined>(undefined);\n const prevIsRotatingRef = useRef<boolean>(false);\n const isRotatingRef = useRef<boolean>(false);\n const isDrawerModeAtMount = useRef(!!defaultExpandedPanel);\n const isFullyMountedRef = useRef(false);\n const expandedPanelRef = useRef(expandedPanel);\n const elementForPropertiesRef = useRef<EditorElement | null>(null);\n const elementUpdateHandlerRef = useRef<(el: EditorElement) => void>(() => {});\n const prevStableSelectedIdRef = useRef<string | undefined>(undefined);\n const prevIsCroppingRef = useRef<boolean | undefined>(undefined);\n\n // Keep isRotatingRef current on every render so stale-closure handlers can read it\n isRotatingRef.current = isRotating;\n\n // ── Derived state ───────────────────────────────────────────────────────\n const elementForProperties = activeChildElement || selectedElement;\n const stableElementId = elementForProperties?.id;\n const stableSelectedId = selectedElement?.id;\n const currentElementType = elementForProperties?.transformType;\n const { fontColor, getEffectiveStyle, handleFontColorChange } = textToolbar;\n const shouldShowToolbar = !!(selectedElement && !isRotating);\n\n // ── Element update handler ──────────────────────────────────────────────\n const elementUpdateHandler = useCallback(\n (updatedElement: EditorElement) => {\n if (!selectedElement) return;\n if (activeChildElement) {\n const groupElement = selectedElement as GroupElement;\n const updatedGroup = groupElement.clone() as GroupElement;\n const childIndex = updatedGroup.children.findIndex((c) => c.id === activeChildElement.id);\n if (childIndex !== -1) {\n updatedGroup.children[childIndex] = updatedElement;\n handleElementUpdate(updatedGroup);\n }\n } else {\n handleElementUpdate(updatedElement);\n }\n },\n [selectedElement, activeChildElement, handleElementUpdate]\n );\n\n // ── Image border radius handler ────────────────────────────────────────\n const handleBorderRadiusChange = useCallback(\n (value: number) => {\n if (!elementForProperties || elementForProperties.transformType !== 'image') return;\n const updatedElement = (elementForProperties as ImageElement).clone();\n updatedElement.transformData.borderRadius = value;\n elementUpdateHandler(updatedElement);\n },\n [elementForProperties, elementUpdateHandler]\n );\n\n // ── Remove background (one-shot service action) ────────────────────────\n const [removingBackground, setRemovingBackground] = useState<boolean>(false);\n const [removeBackgroundError, setRemoveBackgroundError] = useState<string | null>(null);\n\n // Elements snapshot for async flows — the provider call can take seconds,\n // so resolve-time application must re-find the element in CURRENT state.\n const elementsRef = useRef(elements);\n elementsRef.current = elements;\n\n const isMountedForServicesRef = useRef(true);\n useEffect(() => {\n isMountedForServicesRef.current = true;\n return () => {\n isMountedForServicesRef.current = false;\n };\n }, []);\n\n // Swap an image element's URL through command history — the canonical\n // \"change the picture\" flow from embed/ImagePanel.tsx, minus the\n // crop/flip/border-radius/dimension resets: background removal returns the\n // SAME picture (with alpha), so the existing crop, flips, radius, and size\n // all stay meaningful.\n const applyRemovedBackgroundUrl = useCallback(\n (elementId: string, processedUrl: string) => {\n const swapImageUrl = (oldImage: ImageElement): ImageElement => {\n const updated = oldImage.clone();\n updated.imageUrl = processedUrl;\n // Reset load state before loading the new bitmap.\n updated.imageLoaded = false;\n updated.imageElement = null;\n updated.onLoadCallback = (loadedElement) => {\n // Load-time adjustments bypass command history (same as ImagePanel).\n const el = loadedElement as ImageElement;\n setElements((prevElements) => prevElements.map((s) => (s.id === el.id ? el : s)));\n };\n updated.loadImage(processedUrl);\n return updated;\n };\n\n const currentElements = elementsRef.current;\n\n // Top-level image element.\n const topLevel = currentElements.find((e) => e.id === elementId);\n if (topLevel) {\n if (!(topLevel instanceof ImageElement)) return;\n executeElementUpdate(topLevel, swapImageUrl(topLevel));\n return;\n }\n\n // Group child — clone the group, swap the child inside the clone.\n for (const el of currentElements) {\n if (!(el instanceof GroupElement)) continue;\n const childIndex = el.children.findIndex((c) => c.id === elementId);\n if (childIndex === -1) continue;\n const child = el.children[childIndex];\n if (!(child instanceof ImageElement)) return;\n const updatedGroup = el.clone() as GroupElement;\n updatedGroup.children[childIndex] = swapImageUrl(child);\n executeElementUpdate(el, updatedGroup);\n return;\n }\n // Element no longer exists (deleted mid-flight) → drop the result.\n },\n [executeElementUpdate, setElements]\n );\n\n const handleRemoveBackground = useCallback(() => {\n if (!removeBackground || removingBackground) return;\n const element = elementForProperties;\n if (!element || !(element instanceof ImageElement) || !element.imageUrl) return;\n\n // Capture the id at click time — the selection (or the element itself)\n // can change/disappear while the provider call is in flight.\n const elementId = element.id;\n\n setRemovingBackground(true);\n setRemoveBackgroundError(null);\n\n removeBackground(element.imageUrl)\n .then((processedUrl) => {\n if (!isMountedForServicesRef.current) return;\n applyRemovedBackgroundUrl(elementId, processedUrl);\n })\n .catch((err: unknown) => {\n logger.error('Error removing background:', err);\n if (!isMountedForServicesRef.current) return;\n setRemoveBackgroundError(safeErrorMessage(err, REMOVE_BG_UNAVAILABLE));\n })\n .finally(() => {\n if (isMountedForServicesRef.current) setRemovingBackground(false);\n });\n }, [removeBackground, removingBackground, elementForProperties, applyRemovedBackgroundUrl]);\n\n // Clear the inline bg-remove error once the selection moves on.\n useEffect(() => {\n setRemoveBackgroundError(null);\n }, [stableElementId]);\n\n // ── Shape property change handlers ─────────────────────────────────────\n const handleShapeBorderRadiusChange = useCallback(\n (value: number) => {\n if (!elementForProperties || elementForProperties.transformType !== 'shape') return;\n const updatedElement = (elementForProperties as ShapeElement).clone();\n updatedElement.transformData.borderRadius = value;\n elementUpdateHandler(updatedElement);\n },\n [elementForProperties, elementUpdateHandler]\n );\n\n const handleShapeOpacityChange = useCallback(\n (value: number) => {\n if (!elementForProperties || elementForProperties.transformType !== 'shape') return;\n const updatedElement = (elementForProperties as ShapeElement).clone();\n updatedElement.transformData.fillOpacity = value;\n elementUpdateHandler(updatedElement);\n },\n [elementForProperties, elementUpdateHandler]\n );\n\n const handleShapeSidesChange = useCallback(\n (value: number) => {\n if (!elementForProperties || elementForProperties.transformType !== 'shape') return;\n const updatedElement = (elementForProperties as ShapeElement).clone();\n updatedElement.transformData.sides = value;\n elementUpdateHandler(updatedElement);\n },\n [elementForProperties, elementUpdateHandler]\n );\n\n const handleShapePointsChange = useCallback(\n (value: number) => {\n if (!elementForProperties || elementForProperties.transformType !== 'shape') return;\n const updatedElement = (elementForProperties as ShapeElement).clone();\n updatedElement.transformData.points = value;\n elementUpdateHandler(updatedElement);\n },\n [elementForProperties, elementUpdateHandler]\n );\n\n const handleShapeInnerRadiusChange = useCallback(\n (value: number) => {\n if (!elementForProperties || elementForProperties.transformType !== 'shape') return;\n const updatedElement = (elementForProperties as ShapeElement).clone();\n updatedElement.transformData.innerRadius = value;\n elementUpdateHandler(updatedElement);\n },\n [elementForProperties, elementUpdateHandler]\n );\n\n const handleShapeFillColorChange = useCallback(\n (color: string) => {\n if (!elementForProperties || elementForProperties.transformType !== 'shape') return;\n const updatedElement = (elementForProperties as ShapeElement).clone();\n updatedElement.transformData.fillColor = color;\n // A rich `fill` wins over `fillColor` at render time — clear it so the\n // picked solid color is what actually renders.\n delete updatedElement.transformData.fill;\n elementUpdateHandler(updatedElement);\n },\n [elementForProperties, elementUpdateHandler]\n );\n\n const handleShapeFillChange = useCallback(\n (fill: ShapeFill | null) => {\n if (!elementForProperties || elementForProperties.transformType !== 'shape') return;\n const updatedElement = (elementForProperties as ShapeElement).clone();\n if (fill === null) {\n delete updatedElement.transformData.fill;\n } else {\n updatedElement.transformData.fill = fill;\n }\n elementUpdateHandler(updatedElement);\n },\n [elementForProperties, elementUpdateHandler]\n );\n\n // ── Align to artboard (single selection) ───────────────────────────────\n // The hook aligns relative to the active artboard when exactly one movable\n // element is selected — the panel below is the single-selection surface\n // for it (multi-selections get inline buttons in MultiSelectionToolbar).\n const { canAlign, align: alignSelection } = useAlignDistribute();\n\n // ── Panel toggle handlers ──────────────────────────────────────────────\n const handleAlignToggle = useCallback(() => {\n setExpandedPanel((prev) =>\n prev?.type === 'align'\n ? null\n : { type: 'align', icon: 'gravity-ui:objects-align-center-vertical', label: 'Position' }\n );\n }, []);\n\n const handleCornerRadiusToggle = useCallback(() => {\n if (onOpenCornerRadiusDrawer) {\n onOpenCornerRadiusDrawer();\n } else {\n setExpandedPanel((prev) =>\n prev?.type === 'cornerRadius'\n ? null\n : { type: 'cornerRadius', icon: 'lucide:square-round-corner', label: 'Corner Radius' }\n );\n }\n }, [onOpenCornerRadiusDrawer]);\n\n const handleCropToggle = useCallback(() => {\n if (onOpenCropDrawer) {\n onOpenCropDrawer();\n } else {\n setExpandedPanel((prev) => (prev?.type === 'crop' ? null : { type: 'crop', icon: 'lucide:crop', label: 'Crop' }));\n }\n }, [onOpenCropDrawer]);\n\n const handleRotationToggle = useCallback(() => {\n setExpandedPanel((prev) =>\n prev?.type === 'rotation' ? null : { type: 'rotation', icon: icons.rotateLeft, label: 'Rotate' }\n );\n }, []);\n\n const handleOpacityToggle = useCallback(() => {\n setExpandedPanel((prev) =>\n prev?.type === 'opacity' ? null : { type: 'opacity', icon: 'lucide:blend', label: 'Transparency' }\n );\n }, []);\n\n const handleAdjustToggle = useCallback(() => {\n setExpandedPanel((prev) =>\n prev?.type === 'adjust' ? null : { type: 'adjust', icon: 'gravity-ui:sliders', label: 'Adjust' }\n );\n }, []);\n\n const handleFontSizeToggle = useCallback(() => {\n setExpandedPanel((prev) =>\n prev?.type === 'fontSize' ? null : { type: 'fontSize', icon: 'lucide:type', label: 'Font Size' }\n );\n }, []);\n\n // Text-box width handler. Custom text and transformed text (wave,\n // arch, etc.) store their bounding-box width on `transformData.width`\n // — the same field the resize handle writes. Updating it from the\n // slider is just a clone + assign, routed through `elementUpdateHandler`\n // so the change lands in undo/redo.\n const handleTextWidthChange = useCallback(\n (next: number) => {\n if (!elementForProperties) return;\n const td = elementForProperties.transformData as { width?: number } | undefined;\n if (!td || td.width === undefined) return;\n const updated = elementForProperties.clone();\n (updated.transformData as { width: number }).width = next;\n elementUpdateHandler(updated);\n },\n [elementForProperties, elementUpdateHandler]\n );\n\n // Read current text-box width if the element exposes one. Used to\n // drive the width slider in the font-size panel.\n const currentTextWidth =\n (elementForProperties?.transformData as { width?: number } | undefined)?.width ?? null;\n\n // Letter-spacing / line-height only apply to straight ('custom') text —\n // curved transforms (circle, arch, wave, …) lay glyphs along their own\n // path math and intentionally ignore both, so the sliders are hidden\n // there (pass null) rather than rendering dead controls.\n const isCustomText = elementForProperties?.transformType === 'custom';\n const currentLetterSpacing = isCustomText ? textToolbar.letterSpacing : null;\n const currentLineHeight = isCustomText ? textToolbar.lineHeight : null;\n\n const handleShapeCornerRadiusToggle = useCallback(() => {\n setExpandedPanel((prev) =>\n prev?.type === 'shapeCornerRadius'\n ? null\n : { type: 'shapeCornerRadius', icon: 'lucide:square-round-corner', label: 'Corner Radius' }\n );\n }, []);\n\n const handleShapeTransparencyToggle = useCallback(() => {\n setExpandedPanel((prev) =>\n prev?.type === 'shapeTransparency'\n ? null\n : { type: 'shapeTransparency', icon: 'lucide:blend', label: 'Transparency' }\n );\n }, []);\n\n const handleShapeSidesToggle = useCallback(() => {\n setExpandedPanel((prev) =>\n prev?.type === 'shapeSides' ? null : { type: 'shapeSides', icon: 'lucide:hexagon', label: 'Sides' }\n );\n }, []);\n\n const handleShapePointsToggle = useCallback(() => {\n setExpandedPanel((prev) =>\n prev?.type === 'shapePoints' ? null : { type: 'shapePoints', icon: 'lucide:star', label: 'Points' }\n );\n }, []);\n\n const handleShapeInnerRadiusToggle = useCallback(() => {\n setExpandedPanel((prev) =>\n prev?.type === 'shapeInnerRadius'\n ? null\n : { type: 'shapeInnerRadius', icon: 'lucide:circle-dashed', label: 'Inner Radius' }\n );\n }, []);\n\n const handleShapeColorToggle = useCallback(() => {\n setExpandedPanel((prev) =>\n prev?.type === 'shapeColor' ? null : { type: 'shapeColor', icon: 'lucide:paint-bucket', label: 'Fill Color' }\n );\n }, []);\n\n const handleTextColorToggle = useCallback(() => {\n setExpandedPanel((prev) =>\n prev?.type === 'textColor' ? null : { type: 'textColor', icon: icons.palette, label: 'Font Color' }\n );\n }, []);\n\n const handleCompositingToggle = useCallback(() => {\n setExpandedPanel((prev) =>\n prev?.type === 'compositing' ? null : { type: 'compositing', icon: 'lucide:scissors', label: 'Clip / Knockout' }\n );\n }, []);\n\n const handleDistressTextureToggle = useCallback(() => {\n setExpandedPanel((prev) =>\n prev?.type === 'distressTexture'\n ? null\n : { type: 'distressTexture', icon: 'lucide:stamp', label: 'Distress Texture' }\n );\n }, []);\n\n const handleImageMaskToggle = useCallback(() => {\n setExpandedPanel((prev) =>\n prev?.type === 'imageMask'\n ? null\n : { type: 'imageMask', icon: 'lucide:venetian-mask', label: 'Image Mask' }\n );\n }, []);\n\n const handleStrokeToggle = useCallback(() => {\n setExpandedPanel((prev) =>\n prev?.type === 'stroke'\n ? null\n : { type: 'stroke', icon: 'lucide:pen-line', label: 'Stroke' }\n );\n }, []);\n\n const handleShadowToggle = useCallback(() => {\n setExpandedPanel((prev) =>\n prev?.type === 'shadow'\n ? null\n : { type: 'shadow', icon: 'gravity-ui:square-dashed-circle', label: 'Shadow' }\n );\n }, []);\n\n const handleBlendModeToggle = useCallback(() => {\n setExpandedPanel((prev) =>\n prev?.type === 'blendMode'\n ? null\n : { type: 'blendMode', icon: 'gravity-ui:circles-intersection', label: 'Blend Mode' }\n );\n }, []);\n\n const handleCloseExpandedPanel = useCallback(() => {\n if (expandedPanel?.type === 'crop' && elementForProperties?.transformType === 'image') {\n const imageElement = elementForProperties as ImageElement;\n if (imageElement.isCropping) {\n const updatedElement = imageElement.clone();\n updatedElement.exitCropMode();\n elementUpdateHandler(updatedElement);\n }\n }\n setExpandedPanel(null);\n }, [expandedPanel, elementForProperties, elementUpdateHandler]);\n\n // ── Layer ordering handlers ────────────────────────────────────────────\n const handleMoveForward = useCallback(() => {\n if (!selectedElement) return;\n const idx = elements.findIndex((e) => e.id === selectedElement.id);\n if (idx < elements.length - 1) {\n const targetElement = elements[idx + 1];\n executeReorderElement(selectedElement.id, targetElement.id, 'after');\n }\n }, [selectedElement, elements, executeReorderElement]);\n\n const handleMoveBackward = useCallback(() => {\n if (!selectedElement) return;\n const idx = elements.findIndex((e) => e.id === selectedElement.id);\n if (idx > 0) {\n const targetElement = elements[idx - 1];\n executeReorderElement(selectedElement.id, targetElement.id, 'before');\n }\n }, [selectedElement, elements, executeReorderElement]);\n\n const handleDeleteElement = useCallback(() => {\n const elementToDelete = activeChildElement || selectedElement;\n // Locked elements ARE deletable — locking gates manipulation\n // (drag/resize/rotate), not removal.\n if (!elementToDelete) return;\n executeRemoveElement(elementToDelete);\n setSelectedId(null);\n }, [activeChildElement, selectedElement, executeRemoveElement, setSelectedId]);\n\n // Lock / unlock toggle for the leading chip in the toolbar. Operates\n // on `elementForProperties` so a focused group child gets locked\n // (not the parent group) — `elementUpdateHandler` already routes the\n // updated child back through the group when needed.\n const handleToggleLock = useCallback(() => {\n if (!elementForProperties) return;\n const next = elementForProperties.clone();\n next.locked = !elementForProperties.locked;\n elementUpdateHandler(next);\n }, [elementForProperties, elementUpdateHandler]);\n\n const handleUngroupElement = useCallback(() => {\n if (!selectedElement || selectedElement.transformType !== 'group') return;\n const group = selectedElement as GroupElement;\n if (!group.children || group.children.length === 0) return;\n\n const artboardId = artboardManager.getArtboardIdForElement(group.id);\n if (!artboardId) return;\n\n const extractedChildren = group.children.map(child => {\n const clone = child.clone();\n clone.x = child.x + group.x;\n clone.y = child.y + group.y;\n return clone;\n });\n\n executeRemoveElement(group);\n extractedChildren.forEach(child => executeAddElement(child, artboardId));\n\n setSelectedId(extractedChildren.length > 0 ? extractedChildren[0].id : null);\n }, [selectedElement, artboardManager, executeRemoveElement, executeAddElement, setSelectedId]);\n\n // ── Rotation / opacity handlers (before multiSelection early return) ──\n const handleRotationChange = useCallback(\n (value: number) => {\n if (!elementForProperties) return;\n const updatedElement = elementForProperties.clone();\n updatedElement.rotation = value;\n elementUpdateHandler(updatedElement);\n },\n [elementForProperties, elementUpdateHandler]\n );\n\n const handleRotate90 = useCallback(() => {\n if (!elementForProperties) return;\n const updatedElement = elementForProperties.clone();\n let newRotation = Math.floor(updatedElement.rotation / 90) * 90 + 90;\n newRotation = ((newRotation % 360) + 360) % 360;\n if (newRotation > 180) {\n newRotation -= 360;\n }\n updatedElement.rotation = newRotation;\n elementUpdateHandler(updatedElement);\n }, [elementForProperties, elementUpdateHandler]);\n\n const handleOpacityChange = useCallback(\n (value: number) => {\n if (!elementForProperties) return;\n const updatedElement = elementForProperties.clone();\n updatedElement.opacity = value;\n elementUpdateHandler(updatedElement);\n },\n [elementForProperties, elementUpdateHandler]\n );\n\n // ── Adjust (brightness/contrast/saturation) handlers ──────────────────\n // Top-level images go through the PUBLIC patch path (useCommands.updateElement)\n // with { coalesce } so an entire slider drag lands as ONE undo step — the run\n // starts on the first tick of a gesture and breaks on commit (slider release)\n // via handleAdjustmentsCommit. Group children aren't top-level store entries,\n // so they use the group-aware clone path like every other child slider.\n const { updateElement: updateElementCommand } = useCommands();\n const adjustRunActiveRef = useRef(false);\n\n const handleAdjustmentsChange = useCallback(\n (adjustments: ImageAdjustments) => {\n if (!elementForProperties || elementForProperties.transformType !== 'image') return;\n if (activeChildElement) {\n const updated = (elementForProperties as ImageElement).clone();\n const normalized = normalizeAdjustments(adjustments);\n if (normalized) {\n updated.transformData.adjustments = normalized;\n } else {\n delete updated.transformData.adjustments;\n }\n elementUpdateHandler(updated);\n return;\n }\n updateElementCommand(\n elementForProperties.id,\n { adjustments },\n { coalesce: adjustRunActiveRef.current }\n );\n adjustRunActiveRef.current = true;\n },\n [elementForProperties, activeChildElement, elementUpdateHandler, updateElementCommand]\n );\n\n const handleAdjustmentsCommit = useCallback(() => {\n adjustRunActiveRef.current = false;\n }, []);\n\n const handleAdjustmentsReset = useCallback(() => {\n // Reset is its own single undo step — never folded into a slider run.\n adjustRunActiveRef.current = false;\n handleAdjustmentsChange({ ...NEUTRAL_ADJUSTMENTS });\n adjustRunActiveRef.current = false;\n }, [handleAdjustmentsChange]);\n\n // ── Compositing handlers (Clip / Knockout) ───────────────────────────\n const handleCompositingModeChange = useCallback(\n (mode: CompositingMode) => {\n if (!elementForProperties) return;\n const updatedElement = elementForProperties.clone();\n updatedElement.blendMode = mode;\n if (!updatedElement.knockoutParts) {\n updatedElement.knockoutParts = { fill: true, scope: 'group' };\n }\n elementUpdateHandler(updatedElement);\n },\n [elementForProperties, elementUpdateHandler]\n );\n\n const handleCompositingFillChange = useCallback(\n (fill: boolean) => {\n if (!elementForProperties) return;\n const updatedElement = elementForProperties.clone();\n const currentMode = updatedElement.blendMode === 'clip' ? 'clip' : 'knockout';\n const newParts = { ...updatedElement.knockoutParts, fill };\n updatedElement.knockoutParts = newParts;\n updatedElement.blendMode = (newParts.fill || newParts.stroke) ? currentMode : 'normal';\n elementUpdateHandler(updatedElement);\n },\n [elementForProperties, elementUpdateHandler]\n );\n\n const handleCompositingStrokeChange = useCallback(\n (stroke: boolean) => {\n if (!elementForProperties) return;\n const updatedElement = elementForProperties.clone();\n const currentMode = updatedElement.blendMode === 'clip' ? 'clip' : 'knockout';\n const newParts = { ...updatedElement.knockoutParts, stroke };\n updatedElement.knockoutParts = newParts;\n updatedElement.blendMode = (newParts.fill || newParts.stroke) ? currentMode : 'normal';\n elementUpdateHandler(updatedElement);\n },\n [elementForProperties, elementUpdateHandler]\n );\n\n const handleCompositingScopeChange = useCallback(\n (scope: CompositingScope) => {\n if (!elementForProperties) return;\n const updatedElement = elementForProperties.clone();\n updatedElement.knockoutParts = { ...updatedElement.knockoutParts, scope };\n elementUpdateHandler(updatedElement);\n },\n [elementForProperties, elementUpdateHandler]\n );\n\n // ── Distress texture handlers ─────────────────────────────────────────\n const handleDistressTextureChange = useCallback(\n (url: string) => {\n if (!elementForProperties) return;\n const updatedElement = elementForProperties.clone();\n if (!url) {\n updatedElement.distressEffect = undefined;\n } else {\n updatedElement.distressEffect = {\n enabled: true,\n style: 'custom',\n intensity: updatedElement.distressEffect?.intensity ?? 50,\n textureUrl: url,\n textureOpacity: updatedElement.distressEffect?.textureOpacity ?? 0.5,\n };\n }\n elementUpdateHandler(updatedElement);\n },\n [elementForProperties, elementUpdateHandler]\n );\n\n const handleDistressOpacityChange = useCallback(\n (pct: number) => {\n if (!elementForProperties) return;\n const updatedElement = elementForProperties.clone();\n if (updatedElement.distressEffect) {\n updatedElement.distressEffect = {\n ...updatedElement.distressEffect,\n textureOpacity: pct / 100,\n };\n }\n elementUpdateHandler(updatedElement);\n },\n [elementForProperties, elementUpdateHandler]\n );\n\n // ── Image mask handlers (quick-mask via masks[] with id='quick-image-mask') ──\n const handleImageMaskImageChange = useCallback(\n (url: string) => {\n if (!elementForProperties) return;\n const updatedElement = elementForProperties.clone();\n if (!url) {\n // Remove quick-image-mask\n updatedElement.masks = (updatedElement.masks || []).filter((m: { id: string }) => m.id !== 'quick-image-mask');\n } else {\n // Store the mask's natural dimensions (512×512 for builtin presets).\n // MaskRenderer uses these to compute object-cover scaling at render time,\n // preserving the mask shape's aspect ratio on non-square images.\n const BUILTIN_MASK_SIZE = 512;\n\n const makeMaskElement = () => ({\n transformType: 'image' as const,\n imageUrl: url,\n x: 0, y: 0, rotation: 0,\n transformData: { type: 'image' as const, width: BUILTIN_MASK_SIZE, height: BUILTIN_MASK_SIZE, cropX: 0, cropY: 0, cropWidth: 1, cropHeight: 1, flipHorizontal: false, flipVertical: false, borderRadius: 0 },\n }) as import('../types/index.js').ImageElementConfig;\n\n // Reset crop when applying a mask — the mask handles clipping,\n // and stale crop values would cause position/rendering issues.\n if ('transformData' in updatedElement && updatedElement.transformData) {\n const td = updatedElement.transformData as Record<string, unknown>;\n td.cropX = 0;\n td.cropY = 0;\n td.cropWidth = 1;\n td.cropHeight = 1;\n }\n\n const existing = (updatedElement.masks || []).find((m: { id: string }) => m.id === 'quick-image-mask');\n if (existing) {\n existing.maskElement = makeMaskElement();\n } else {\n const masks = updatedElement.masks || [];\n masks.push({\n id: 'quick-image-mask',\n type: 'clip',\n maskElement: makeMaskElement(),\n opacity: 1,\n inverted: false,\n });\n updatedElement.masks = masks;\n }\n }\n elementUpdateHandler(updatedElement);\n },\n [elementForProperties, elementUpdateHandler]\n );\n\n const handleImageMaskTypeChange = useCallback(\n (type: 'clip' | 'alpha' | 'luma') => {\n if (!elementForProperties) return;\n const updatedElement = elementForProperties.clone();\n const mask = (updatedElement.masks || []).find((m: { id: string }) => m.id === 'quick-image-mask');\n if (mask) {\n mask.type = type;\n elementUpdateHandler(updatedElement);\n }\n },\n [elementForProperties, elementUpdateHandler]\n );\n\n const handleImageMaskOpacityChange = useCallback(\n (pct: number) => {\n if (!elementForProperties) return;\n const updatedElement = elementForProperties.clone();\n const mask = (updatedElement.masks || []).find((m: { id: string }) => m.id === 'quick-image-mask');\n if (mask) {\n mask.opacity = pct / 100;\n elementUpdateHandler(updatedElement);\n }\n },\n [elementForProperties, elementUpdateHandler]\n );\n\n const handleImageMaskInvertedChange = useCallback(\n (inv: boolean) => {\n if (!elementForProperties) return;\n const updatedElement = elementForProperties.clone();\n const mask = (updatedElement.masks || []).find((m: { id: string }) => m.id === 'quick-image-mask');\n if (mask) {\n mask.inverted = inv;\n elementUpdateHandler(updatedElement);\n }\n },\n [elementForProperties, elementUpdateHandler]\n );\n\n // ── Stroke change handler ─────────────────────────────────────────────\n const handleStrokeChange = useCallback(\n (stroke: import('../types/index.js').StrokeConfig | undefined) => {\n if (!elementForProperties) return;\n const updatedElement = elementForProperties.clone();\n updatedElement.stroke = stroke;\n elementUpdateHandler(updatedElement);\n },\n [elementForProperties, elementUpdateHandler]\n );\n\n // ── Shadow change handler ─────────────────────────────────────────────\n const handleShadowChange = useCallback(\n (shadow: ShadowConfig | undefined) => {\n if (!elementForProperties) return;\n const updatedElement = elementForProperties.clone();\n updatedElement.shadow = shadow;\n elementUpdateHandler(updatedElement);\n },\n [elementForProperties, elementUpdateHandler]\n );\n\n // ── Blend mode change handler ─────────────────────────────────────────\n // 'normal' clears the field back to the default (undefined). Picking a\n // standard mode replaces any knockout/clip compositing mode — the two are\n // mutually exclusive by design (one blendMode field).\n const handleBlendModeChange = useCallback(\n (blendMode: 'normal' | StandardBlendMode) => {\n if (!elementForProperties) return;\n const updatedElement = elementForProperties.clone();\n updatedElement.blendMode = blendMode === 'normal' ? undefined : blendMode;\n elementUpdateHandler(updatedElement);\n },\n [elementForProperties, elementUpdateHandler]\n );\n\n // ── Shape type change handler ──────────────────────────────────────────\n const handleShapeTypeChange = useCallback(\n (newShapeType: string) => {\n if (!elementForProperties || elementForProperties.transformType !== 'shape') return;\n const shapeElement = elementForProperties as ShapeElement;\n const updatedElement = shapeElement.clone() as ShapeElement;\n updatedElement.transformData.shapeType = newShapeType as ShapeElement['transformData']['shapeType'];\n elementUpdateHandler(updatedElement);\n setIsShapeTypeDrawerOpen(false);\n },\n [elementForProperties, elementUpdateHandler]\n );\n\n const handleOpenShapeTypeDrawer = useCallback(() => {\n if (onOpenShapeTypeDrawer) {\n onOpenShapeTypeDrawer();\n } else {\n setIsShapeTypeDrawerOpen(true);\n }\n }, [onOpenShapeTypeDrawer]);\n\n // ── Panel expand change notification ───────────────────────────────────\n useEffect(() => {\n onPanelExpandChange?.(expandedPanel !== null);\n onExpandedPanelTypeChange?.(\n (expandedPanel?.type as 'cornerRadius' | 'effects' | 'crop' | 'rotation' | null) ?? null\n );\n }, [expandedPanel, onPanelExpandChange, onExpandedPanelTypeChange]);\n\n // ── Sync local panel state TO context ──────────────────────────────────\n useEffect(() => {\n const localType = expandedPanel?.type ?? null;\n if (localType !== lastSyncedToContextRef.current) {\n lastSyncedToContextRef.current = localType;\n setContextExpandedPanelType(localType as Parameters<typeof setContextExpandedPanelType>[0]);\n }\n }, [expandedPanel, setContextExpandedPanelType]);\n\n // ── Sync FROM context when it changes externally ───────────────────────\n useEffect(() => {\n const prevType = prevContextExpandedPanelTypeRef.current;\n const currentType = contextExpandedPanelType;\n if (prevType === currentType) return;\n prevContextExpandedPanelTypeRef.current = currentType;\n\n if (prevType !== null && currentType === null && expandedPanel !== null) {\n lastSyncedToContextRef.current = null;\n setExpandedPanel(null);\n return;\n }\n\n if (currentType !== null && expandedPanel?.type !== currentType) {\n type PanelType = NonNullable<ExpandedPanelConfig>['type'];\n const panelConfigs: Record<PanelType, NonNullable<ExpandedPanelConfig>> = {\n align: { type: 'align', icon: 'gravity-ui:objects-align-center-vertical', label: 'Position' },\n crop: { type: 'crop', icon: 'lucide:crop', label: 'Crop' },\n cornerRadius: { type: 'cornerRadius', icon: 'lucide:square-round-corner', label: 'Corner Radius' },\n rotation: { type: 'rotation', icon: icons.rotateLeft, label: 'Rotate' },\n opacity: { type: 'opacity', icon: 'lucide:blend', label: 'Transparency' },\n adjust: { type: 'adjust', icon: 'gravity-ui:sliders', label: 'Adjust' },\n fontSize: { type: 'fontSize', icon: 'lucide:type', label: 'Font Size' },\n effects: { type: 'effects', icon: 'lucide:sparkles', label: 'Effects' },\n shapeCornerRadius: { type: 'shapeCornerRadius', icon: 'lucide:square-round-corner', label: 'Corner Radius' },\n shapeTransparency: { type: 'shapeTransparency', icon: icons.eye, label: 'Transparency' },\n shapeSides: { type: 'shapeSides', icon: 'lucide:triangle', label: 'Sides' },\n shapePoints: { type: 'shapePoints', icon: 'lucide:star', label: 'Points' },\n shapeInnerRadius: { type: 'shapeInnerRadius', icon: 'lucide:circle-dashed', label: 'Inner Radius' },\n shapeColor: { type: 'shapeColor', icon: icons.palette, label: 'Color' },\n textColor: { type: 'textColor', icon: icons.palette, label: 'Color' },\n stroke: { type: 'stroke', icon: 'lucide:pen-line', label: 'Stroke' },\n shadow: { type: 'shadow', icon: 'gravity-ui:square-dashed-circle', label: 'Shadow' },\n blendMode: { type: 'blendMode', icon: 'gravity-ui:circles-intersection', label: 'Blend Mode' },\n compositing: { type: 'compositing', icon: 'lucide:scissors', label: 'Clip / Knockout' },\n distressTexture: { type: 'distressTexture', icon: 'lucide:stamp', label: 'Distress Texture' },\n imageMask: { type: 'imageMask', icon: 'lucide:venetian-mask', label: 'Image Mask' },\n };\n const config = panelConfigs[currentType as PanelType];\n if (config) {\n lastSyncedToContextRef.current = currentType;\n setExpandedPanel(config);\n }\n }\n }, [contextExpandedPanelType, expandedPanel]);\n\n // ── Sync toolbar menu open state to context ────────────────────────────\n useEffect(() => {\n const isAnyMenuOpen =\n expandedPanel !== null ||\n openDropdown !== null ||\n isTransformMenuOpen ||\n isColorPickerOpen ||\n isTextMoreMenuOpen ||\n activeMenu !== 'root';\n setIsToolbarMenuOpen(isAnyMenuOpen);\n }, [expandedPanel, openDropdown, isTransformMenuOpen, isColorPickerOpen, isTextMoreMenuOpen, activeMenu, setIsToolbarMenuOpen]);\n\n // ── Close expanded panel when element changes or is deselected ─────────\n useEffect(() => {\n if (defaultExpandedPanel) return;\n if (prevStableSelectedIdRef.current !== undefined && prevStableSelectedIdRef.current !== stableSelectedId) {\n setExpandedPanel(null);\n }\n prevStableSelectedIdRef.current = stableSelectedId;\n }, [stableSelectedId, defaultExpandedPanel]);\n\n // ── Auto-dismiss artboard edit mode when an element is selected ────────\n useEffect(() => {\n if (editArtboardMode && selectedElement) {\n onEditArtboardModeChange?.(false);\n }\n }, [editArtboardMode, selectedElement, onEditArtboardModeChange]);\n\n // ── Close crop panel when element exits crop mode ──────────────────────\n useEffect(() => {\n const currentIsCropping =\n elementForProperties?.transformType === 'image' ? (elementForProperties as ImageElement).isCropping : false;\n if (expandedPanel?.type === 'crop' && prevIsCroppingRef.current === true && currentIsCropping === false) {\n setExpandedPanel(null);\n }\n prevIsCroppingRef.current = currentIsCropping;\n }, [elementForProperties, expandedPanel?.type]);\n\n // ── Cleanup on unmount: exit crop mode ─────────────────────────────────\n useEffect(() => {\n expandedPanelRef.current = expandedPanel;\n elementForPropertiesRef.current = elementForProperties ?? null;\n elementUpdateHandlerRef.current = elementUpdateHandler;\n });\n\n useEffect(() => {\n const timeoutId = setTimeout(() => {\n isFullyMountedRef.current = true;\n }, 0);\n return () => { clearTimeout(timeoutId); };\n }, []);\n\n useEffect(() => {\n return () => {\n if (!isFullyMountedRef.current) return;\n if (!isDrawerModeAtMount.current) return;\n if (expandedPanelRef.current?.type === 'crop') {\n const element = elementForPropertiesRef.current;\n if (element?.transformType === 'image') {\n const imageElement = element as ImageElement;\n if (imageElement.isCropping) {\n const updatedElement = imageElement.clone();\n updatedElement.exitCropMode();\n elementUpdateHandlerRef.current(updatedElement);\n }\n }\n }\n };\n }, []);\n\n // ── Dragging detection ─────────────────────────────────────────────────\n useEffect(() => {\n let mouseDownPos: { x: number; y: number } | null = null;\n let isDraggingStarted = false;\n const DRAG_THRESHOLD = 3;\n\n const handleMouseDown = (e: MouseEvent) => {\n const target = e.target as HTMLElement;\n if (toolbarRef.current?.contains(target)) return;\n if (\n target.closest('[data-slot=\"popover-content\"]') ||\n target.closest('[data-slot=\"dialog\"]') ||\n target.closest('[role=\"dialog\"]') ||\n target.closest('.popover-content') ||\n target.closest('[data-slot]')\n ) return;\n isMouseDownRef.current = true;\n mouseDownPos = { x: e.clientX, y: e.clientY };\n isDraggingStarted = false;\n };\n\n const handleMouseMove = (e: MouseEvent) => {\n if (mouseDownPos && !isDraggingStarted && !isRotatingRef.current) {\n const deltaX = e.clientX - mouseDownPos.x;\n const deltaY = e.clientY - mouseDownPos.y;\n const distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY);\n if (distance > DRAG_THRESHOLD) {\n isDraggingStarted = true;\n setIsDragging(true);\n }\n }\n };\n\n const handleMouseUp = () => {\n isMouseDownRef.current = false;\n mouseDownPos = null;\n isDraggingStarted = false;\n setIsDragging(false);\n };\n\n window.addEventListener('mousedown', handleMouseDown);\n window.addEventListener('mousemove', handleMouseMove);\n window.addEventListener('mouseup', handleMouseUp);\n return () => {\n window.removeEventListener('mousedown', handleMouseDown);\n window.removeEventListener('mousemove', handleMouseMove);\n window.removeEventListener('mouseup', handleMouseUp);\n };\n }, []);\n\n // ── Toolbar dimension tracking ─────────────────────────────────────────\n useEffect(() => {\n if (!toolbarRef.current) return;\n let timeoutId: number | null = null;\n\n const observer = new ResizeObserver((entries) => {\n if (timeoutId !== null) clearTimeout(timeoutId);\n timeoutId = window.setTimeout(() => {\n for (const entry of entries) {\n const newWidth = entry.contentRect.width;\n const newHeight = entry.contentRect.height;\n setToolbarDimensions((prev) => {\n if (prev.width === newWidth && prev.height === newHeight) return prev;\n return { width: newWidth, height: newHeight };\n });\n }\n }, 50);\n });\n\n observer.observe(toolbarRef.current);\n return () => {\n observer.disconnect();\n if (timeoutId !== null) clearTimeout(timeoutId);\n };\n }, [selectedElement]);\n\n // ── Floating toolbar position calculation ──────────────────────────────\n useEffect(() => {\n if (mode === 'embedded') return;\n if (isExiting) return;\n\n const currentRotation = (activeChildElement || selectedElement)?.rotation;\n lastElementRotationRef.current = currentRotation;\n\n if (!selectedElement) {\n setToolbarPosition(null);\n return;\n }\n\n const updateToolbarPosition = () => {\n try {\n const toolbarWidth = toolbarRef.current?.offsetWidth || toolbarDimensions.width || 0;\n const toolbarHeight = toolbarRef.current?.offsetHeight || toolbarDimensions.height || 48;\n const canvas = canvasRef?.current;\n const elementToPosition = activeChildElement || selectedElement;\n const transformData = elementToPosition.transformData as Record<string, unknown> | undefined;\n const elementBounds = elementToPosition.getBoundingBox?.() || {\n x: elementToPosition.x,\n y: elementToPosition.y,\n width: (transformData?.width as number) || 100,\n height: (transformData?.height as number) || 50,\n };\n\n const activeArtboard = artboardManager.getActiveArtboard();\n const artboardX = activeArtboard?.x || 0;\n const artboardY = activeArtboard?.y || 0;\n const currentZoom = canvasEditorRef?.current?.getZoom?.() || 1;\n\n let elementScreenX: number;\n let elementScreenY: number;\n let elementScreenWidth: number;\n let elementScreenHeight: number;\n\n if (canvas) {\n const canvasRect = canvas.getBoundingClientRect();\n elementScreenX = canvasRect.left + (elementBounds.x - artboardX) * currentZoom;\n elementScreenY = canvasRect.top + (elementBounds.y - artboardY) * currentZoom;\n elementScreenWidth = elementBounds.width * currentZoom;\n elementScreenHeight = elementBounds.height * currentZoom;\n } else if (artboardScreenBounds) {\n elementScreenX = artboardScreenBounds.left + (elementBounds.x - artboardX) * currentZoom;\n elementScreenY = artboardScreenBounds.top + (elementBounds.y - artboardY) * currentZoom;\n elementScreenWidth = elementBounds.width * currentZoom;\n elementScreenHeight = elementBounds.height * currentZoom;\n } else {\n const viewportCenterX = window.innerWidth / 2;\n const viewportCenterY = window.innerHeight / 2;\n elementScreenX = viewportCenterX - (elementBounds.width * currentZoom) / 2;\n elementScreenY = viewportCenterY - (elementBounds.height * currentZoom) / 2;\n elementScreenWidth = elementBounds.width * currentZoom;\n elementScreenHeight = elementBounds.height * currentZoom;\n }\n\n const gap = 12;\n const elementTop = elementScreenY;\n const elementCenterX = elementScreenX + elementScreenWidth / 2;\n\n let top = elementTop - toolbarHeight - gap;\n let left = elementCenterX;\n\n if (toolbarWidth > 0) {\n const padding = 20;\n const minLeft = toolbarWidth / 2 + padding;\n const maxLeft = window.innerWidth - toolbarWidth / 2 - padding;\n left = Math.max(minLeft, Math.min(maxLeft, left));\n }\n\n if (top < 10) {\n top = elementScreenY + elementScreenHeight + gap;\n }\n\n const maxTop = window.innerHeight - toolbarHeight - 10;\n top = Math.min(top, maxTop);\n top = Math.max(10, top);\n\n setToolbarPosition({ top, left });\n setPositionedElementId(elementToPosition.id);\n } catch (error) {\n logger.error('Error calculating toolbar position:', error);\n setToolbarPosition(null);\n }\n };\n\n updateToolbarPosition();\n window.addEventListener('resize', updateToolbarPosition);\n // Class-3 anchoring contract (ADR-0085 §5): this fixed body-portal must\n // stay anchored to the canvas element under page AND nested-container\n // scroll — the position derives from getBoundingClientRect() at update\n // time, so re-running on scroll absorbs any ancestor scroll. Capture\n // phase because scroll events don't bubble (but do capture), reaching\n // nested scrollers; passive keeps scrolling smooth. Mirrors\n // RotationHandle's existing listeners.\n window.addEventListener('scroll', updateToolbarPosition, { passive: true, capture: true });\n return () => {\n window.removeEventListener('resize', updateToolbarPosition);\n window.removeEventListener('scroll', updateToolbarPosition, { capture: true });\n };\n }, [mode, selectedElement, activeChildElement, canvasRef, artboardManager, canvasEditorRef, artboardScreenBounds, toolbarDimensions, isExiting, panOffset]);\n\n // ── Memoized color picker props ────────────────────────────────────────\n const colorPickerValue = getEffectiveStyle().color || fontColor;\n const colorPickerOnChange = useCallback(\n (e: { target: { value: string } }) => handleFontColorChange(e as React.ChangeEvent<HTMLInputElement>),\n [handleFontColorChange]\n );\n\n // Auto-derive every paint colour in the design — text colours,\n // rich-text span colours, shape fills, path fills + strokes,\n // element-level strokes, and artboard backgrounds — and union with\n // whatever the consumer explicitly passed in. Lets the shape /\n // text colour pickers offer \"match a colour already on the page\"\n // without every host app having to plumb the set through.\n // See `utils/documentColors.ts` for the full enumeration.\n const autoDocumentColors = useMemo(\n () => collectDocumentColors(elements, artboards),\n [elements, artboards]\n );\n\n const mergedDocumentColors = useMemo(() => {\n const out = new Set<string>(autoDocumentColors);\n for (const c of documentColors) out.add(c);\n return out;\n }, [autoDocumentColors, documentColors]);\n\n const documentColorsKey = Array.from(mergedDocumentColors).sort().join(',');\n const colorPickerDocumentColors = useMemo(\n () => Array.from(mergedDocumentColors),\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [documentColorsKey]\n );\n\n // Image colours — dominant palette extracted from each ImageElement\n // (recursing into groups), surfaced as a separate row in the\n // colour picker. Async because pixel access requires the image to\n // be loaded; cache lives in `documentColors.ts` so re-renders are\n // free after the first extraction. Empty until the first promise\n // resolves; the picker just hides the row in that case.\n const imageUrlsKey = useMemo(() => {\n const urls: string[] = [];\n const seen = new Set<string>();\n const walk = (el: EditorElement) => {\n if (el instanceof ImageElement) {\n if (el.imageUrl && !seen.has(el.imageUrl)) {\n seen.add(el.imageUrl);\n urls.push(el.imageUrl);\n }\n } else if (el instanceof GroupElement) {\n for (const c of el.children) walk(c as EditorElement);\n }\n };\n for (const el of elements) walk(el);\n urls.sort();\n return urls.join('|');\n }, [elements]);\n\n const [colorPickerImageColors, setColorPickerImageColors] = useState<string[]>([]);\n useEffect(() => {\n if (!imageUrlsKey) {\n setColorPickerImageColors([]);\n return;\n }\n let cancelled = false;\n collectImageColors(elements).then((colors) => {\n if (!cancelled) setColorPickerImageColors(colors);\n });\n return () => {\n cancelled = true;\n };\n // We deliberately key off the stable `imageUrlsKey` so that\n // dragging an image around (which mutates `elements` but not the\n // URL set) doesn't re-trigger palette extraction.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [imageUrlsKey]);\n\n // ── Toolbar div ref callback ───────────────────────────────────────────\n const toolbarDivRef = useCallback((node: HTMLDivElement | null) => {\n if (toolbarRef) {\n // MutableRefObject is needed to write to .current in a callback ref\n (toolbarRef as React.MutableRefObject<HTMLDivElement | null>).current = node;\n if (node) {\n const { width, height } = node.getBoundingClientRect();\n if (width > 0 && height > 0) {\n setToolbarDimensions({ width, height });\n }\n }\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n // ── Freeze toolbar position during rotation ────────────────────────────\n useEffect(() => {\n const wasRotating = prevIsRotatingRef.current;\n const isNowRotating = isRotating;\n if (!wasRotating && isNowRotating && toolbarPosition) {\n frozenPositionRef.current = { ...toolbarPosition };\n }\n if (wasRotating && !isNowRotating) {\n frozenPositionRef.current = null;\n }\n prevIsRotatingRef.current = isRotating;\n }, [isRotating, toolbarPosition]);\n\n // ── Entrance/exit animations ───────────────────────────────────────────\n useEffect(() => {\n const prevShouldShow = prevShouldShowRef.current;\n const prevSelectedId = prevSelectedIdRef.current;\n prevShouldShowRef.current = shouldShowToolbar;\n prevSelectedIdRef.current = stableSelectedId;\n\n if (!prevShouldShow && shouldShowToolbar) {\n setShouldRender(true);\n if (mode === 'embedded') {\n setIsWaitingForPosition(false);\n setIsEntering(true);\n setIsExiting(false);\n const enterTimer = setTimeout(() => { setIsEntering(false); }, 200);\n return () => clearTimeout(enterTimer);\n }\n setIsWaitingForPosition(true);\n setIsEntering(false);\n setIsExiting(false);\n return undefined;\n }\n\n if (prevShouldShow && shouldShowToolbar && prevSelectedId !== stableSelectedId && stableSelectedId !== undefined) {\n if (mode === 'embedded') {\n setIsEntering(false);\n return undefined;\n }\n setIsWaitingForPosition(true);\n setIsEntering(false);\n setIsExiting(false);\n return undefined;\n }\n\n if (prevShouldShow && !shouldShowToolbar) {\n if (isRotating) {\n setShouldRender(false);\n setIsEntering(false);\n setIsExiting(false);\n setIsWaitingForPosition(false);\n return undefined;\n }\n\n if (mode === 'embedded') {\n setIsExiting(true);\n setIsEntering(false);\n if (innerContentRef.current) {\n const currentHeight = innerContentRef.current.offsetHeight;\n setTransitionHeight(currentHeight);\n requestAnimationFrame(() => { setTransitionHeight(0); });\n }\n const exitTimer = setTimeout(() => {\n setShouldRender(false);\n setIsExiting(false);\n setTransitionHeight(null);\n }, 200);\n return () => clearTimeout(exitTimer);\n }\n\n setIsExiting(true);\n setIsEntering(false);\n setIsWaitingForPosition(false);\n const exitTimer = setTimeout(() => {\n setShouldRender(false);\n setIsExiting(false);\n setToolbarPosition(null);\n setPositionedElementId(null);\n }, 150);\n return () => clearTimeout(exitTimer);\n }\n\n return undefined;\n }, [shouldShowToolbar, isRotating, stableSelectedId, mode, currentElementType]);\n\n // ── Trigger entrance animation once position is ready ──────────────────\n useEffect(() => {\n if (isWaitingForPosition && toolbarPosition && positionedElementId === stableElementId) {\n setIsWaitingForPosition(false);\n setIsEntering(true);\n const enterTimer = setTimeout(() => { setIsEntering(false); }, 200);\n return () => clearTimeout(enterTimer);\n }\n return undefined;\n }, [isWaitingForPosition, toolbarPosition, positionedElementId, stableElementId]);\n\n // ── Height transitions for type changes (embedded mode) ────────────────\n useLayoutEffect(() => {\n if (mode !== 'embedded') return;\n const prevType = prevElementTypeRef.current;\n const typeChanged = prevType !== undefined && currentElementType !== undefined && prevType !== currentElementType;\n\n if (typeChanged && lastKnownHeightRef.current > 0 && transitionHeight === null) {\n const startHeight = lastKnownHeightRef.current;\n setTransitionHeight(startHeight);\n requestAnimationFrame(() => {\n requestAnimationFrame(() => {\n if (innerContentRef.current) {\n const newHeight = innerContentRef.current.scrollHeight;\n setTransitionHeight(newHeight);\n setTimeout(() => { setTransitionHeight(null); }, 200);\n }\n });\n });\n }\n\n if (innerContentRef.current && transitionHeight === null && !isEntering && !isExiting) {\n lastKnownHeightRef.current = innerContentRef.current.offsetHeight;\n }\n\n prevElementTypeRef.current = currentElementType;\n }, [mode, currentElementType, transitionHeight, isEntering, isExiting]);\n\n // ── Memoized toolbar style ─────────────────────────────────────────────\n const toolbarStyle = useMemo(() => {\n const maxWidthValue = maxWidth ? (typeof maxWidth === 'number' ? `${maxWidth}px` : maxWidth) : undefined;\n\n if (mode === 'embedded') {\n return {\n borderRadius: maxWidth ? '16px' : '9999px',\n visibility: 'visible' as const,\n position: 'static' as const,\n maxWidth: maxWidthValue,\n display: 'flex',\n justifyContent: 'flex-start',\n };\n }\n\n const position = frozenPositionRef.current || toolbarPosition;\n if (position && !isWaitingForPosition) {\n return {\n top: `${position.top}px`,\n left: `${position.left}px`,\n position: 'fixed' as const,\n transform: 'translateX(-50%)',\n borderRadius: maxWidth ? '16px' : '9999px',\n visibility: 'visible' as const,\n maxWidth: maxWidthValue,\n zIndex: 'var(--sc-z-tooltip)',\n };\n }\n\n return {\n borderRadius: maxWidth ? '16px' : '9999px',\n visibility: 'hidden' as const,\n maxWidth: maxWidthValue,\n position: 'fixed' as const,\n top: '-9999px',\n left: '-9999px',\n zIndex: 'var(--sc-z-tooltip)',\n };\n }, [mode, toolbarPosition, isWaitingForPosition, maxWidth]);\n\n // ── Early return for multi-selection ────────────────────────────────────\n // Multi-selections get their own contextual toolbar (align / distribute)\n // instead of the per-element-type toolbars below.\n if (multiSelection.length > 0) {\n return (\n <MultiSelectionToolbar\n mode={mode}\n artboardScreenBounds={artboardScreenBounds}\n partAttr={partAttr}\n />\n );\n }\n\n // ══════════════════════════════════════════════════════════════════════════\n // RENDER: Toolbar dispatch — select element-specific toolbar\n // ══════════════════════════════════════════════════════════════════════════\n\n const regularToolbarContent = (\n <>\n {/* Leading chip: thumbnail + lock toggle. Replaces the floating\n SelectionChip that used to live top-left of the canvas — now\n inline with the rest of the toolbar buttons. Only shows when\n there's actually a selected element (the empty / artboard\n states render their own content elsewhere). */}\n {activeMenu === 'root' && elementForProperties && (\n <LayerLeadingChip\n element={elementForProperties}\n onToggleLock={handleToggleLock}\n onThumbnailClick={onLayerThumbnailClick}\n />\n )}\n\n {/* Position (align to artboard) — element-type agnostic, so it lives\n here once instead of in every per-element toolbar (new element\n types get it for free). Hidden when the selection has no movable\n element (e.g. the layer is locked — lock gates manipulation). */}\n {activeMenu === 'root' && elementForProperties && canAlign && (\n <ToolbarButton\n icon=\"gravity-ui:objects-align-center-vertical\"\n onClick={handleAlignToggle}\n tooltip=\"Position\"\n active={expandedPanel?.type === 'align'}\n data-testid=\"align-toggle\"\n />\n )}\n\n {/* Image elements */}\n {activeMenu === 'root' && elementForProperties?.transformType === 'image' && (\n <ImageToolbar\n element={elementForProperties as ImageElement}\n onElementUpdate={elementUpdateHandler}\n showUngroupButton={!!activeChildElement && selectedElement?.transformType === 'group'}\n onUngroup={handleUngroupElement}\n onMoveForward={handleMoveForward}\n onMoveBackward={handleMoveBackward}\n onChangeImage={onChangeImage}\n onRemoveBackground={removeBackground ? handleRemoveBackground : undefined}\n removingBackground={removingBackground}\n removeBackgroundError={removeBackgroundError}\n onDelete={handleDeleteElement}\n cornerRadiusExpanded={expandedPanel?.type === 'cornerRadius'}\n onCornerRadiusToggle={handleCornerRadiusToggle}\n cropExpanded={expandedPanel?.type === 'crop'}\n onCropToggle={handleCropToggle}\n adjustExpanded={expandedPanel?.type === 'adjust'}\n onAdjustToggle={handleAdjustToggle}\n rotationExpanded={expandedPanel?.type === 'rotation'}\n onRotationToggle={handleRotationToggle}\n opacityExpanded={expandedPanel?.type === 'opacity'}\n onOpacityToggle={handleOpacityToggle}\n strokeExpanded={expandedPanel?.type === 'stroke'}\n onStrokeToggle={handleStrokeToggle}\n shadowExpanded={expandedPanel?.type === 'shadow'}\n onShadowToggle={handleShadowToggle}\n blendModeExpanded={expandedPanel?.type === 'blendMode'}\n onBlendModeToggle={handleBlendModeToggle}\n knockoutExpanded={expandedPanel?.type === 'compositing'}\n onKnockoutToggle={handleCompositingToggle}\n distressTextureExpanded={expandedPanel?.type === 'distressTexture'}\n onDistressTextureToggle={handleDistressTextureToggle}\n imageMaskExpanded={expandedPanel?.type === 'imageMask'}\n onImageMaskToggle={handleImageMaskToggle}\n />\n )}\n\n {/* Group elements (only when no child is active) */}\n {activeMenu === 'root' && selectedElement?.transformType === 'group' && !activeChildElement && (\n <GroupElementToolbar\n element={selectedElement as GroupElement}\n rotationExpanded={expandedPanel?.type === 'rotation'}\n onRotationToggle={handleRotationToggle}\n opacityExpanded={expandedPanel?.type === 'opacity'}\n onOpacityToggle={handleOpacityToggle}\n strokeExpanded={expandedPanel?.type === 'stroke'}\n onStrokeToggle={handleStrokeToggle}\n shadowExpanded={expandedPanel?.type === 'shadow'}\n onShadowToggle={handleShadowToggle}\n blendModeExpanded={expandedPanel?.type === 'blendMode'}\n onBlendModeToggle={handleBlendModeToggle}\n knockoutExpanded={expandedPanel?.type === 'compositing'}\n onKnockoutToggle={handleCompositingToggle}\n distressTextureExpanded={expandedPanel?.type === 'distressTexture'}\n onDistressTextureToggle={handleDistressTextureToggle}\n imageMaskExpanded={expandedPanel?.type === 'imageMask'}\n onImageMaskToggle={handleImageMaskToggle}\n onUngroup={handleUngroupElement}\n />\n )}\n\n {/* Shape elements */}\n {activeMenu === 'root' && elementForProperties?.transformType === 'shape' && (\n <ShapeToolbar\n element={elementForProperties as ShapeElement}\n onElementUpdate={elementUpdateHandler}\n documentColors={colorPickerDocumentColors}\n imageColors={colorPickerImageColors}\n showUngroupButton={!!activeChildElement && selectedElement?.transformType === 'group'}\n onUngroup={handleUngroupElement}\n onMoveForward={handleMoveForward}\n onMoveBackward={handleMoveBackward}\n onOpenShapeTypeDrawer={handleOpenShapeTypeDrawer}\n onDelete={handleDeleteElement}\n rotationExpanded={expandedPanel?.type === 'rotation'}\n onRotationToggle={handleRotationToggle}\n cornerRadiusExpanded={expandedPanel?.type === 'shapeCornerRadius'}\n onCornerRadiusToggle={handleShapeCornerRadiusToggle}\n transparencyExpanded={expandedPanel?.type === 'shapeTransparency'}\n onTransparencyToggle={handleShapeTransparencyToggle}\n sidesExpanded={expandedPanel?.type === 'shapeSides'}\n onSidesToggle={handleShapeSidesToggle}\n pointsExpanded={expandedPanel?.type === 'shapePoints'}\n onPointsToggle={handleShapePointsToggle}\n innerRadiusExpanded={expandedPanel?.type === 'shapeInnerRadius'}\n onInnerRadiusToggle={handleShapeInnerRadiusToggle}\n colorExpanded={expandedPanel?.type === 'shapeColor'}\n onColorToggle={handleShapeColorToggle}\n strokeExpanded={expandedPanel?.type === 'stroke'}\n onStrokeToggle={handleStrokeToggle}\n shadowExpanded={expandedPanel?.type === 'shadow'}\n onShadowToggle={handleShadowToggle}\n blendModeExpanded={expandedPanel?.type === 'blendMode'}\n onBlendModeToggle={handleBlendModeToggle}\n knockoutExpanded={expandedPanel?.type === 'compositing'}\n onKnockoutToggle={handleCompositingToggle}\n distressTextureExpanded={expandedPanel?.type === 'distressTexture'}\n onDistressTextureToggle={handleDistressTextureToggle}\n imageMaskExpanded={expandedPanel?.type === 'imageMask'}\n onImageMaskToggle={handleImageMaskToggle}\n />\n )}\n\n {/* Path elements */}\n {activeMenu === 'root' && elementForProperties?.transformType === 'path' && (\n <PathToolbar\n element={elementForProperties as PathElement}\n onElementUpdate={elementUpdateHandler}\n onMoveForward={handleMoveForward}\n onMoveBackward={handleMoveBackward}\n />\n )}\n\n {/* Text elements (anything not image/group/shape/path) */}\n {activeMenu === 'root' &&\n elementForProperties &&\n elementForProperties.transformType !== 'image' &&\n elementForProperties.transformType !== 'group' &&\n elementForProperties.transformType !== 'shape' &&\n elementForProperties.transformType !== 'path' && (\n <TextToolbar\n toolbar={textToolbar}\n stableElementId={stableElementId}\n viewportWidth={viewportWidth}\n colorPickerValue={colorPickerValue}\n isColorActive={expandedPanel?.type === 'textColor'}\n onColorToggle={handleTextColorToggle}\n onOpenGlyphBrowser={onOpenGlyphBrowser}\n strokeExpanded={expandedPanel?.type === 'stroke'}\n onStrokeToggle={handleStrokeToggle}\n shadowExpanded={expandedPanel?.type === 'shadow'}\n onShadowToggle={handleShadowToggle}\n blendModeExpanded={expandedPanel?.type === 'blendMode'}\n onBlendModeToggle={handleBlendModeToggle}\n hasGlyphs={hasGlyphs}\n expandedPanel={expandedPanel}\n onRotationToggle={handleRotationToggle}\n onOpacityToggle={handleOpacityToggle}\n onFontSizeToggle={handleFontSizeToggle}\n knockoutExpanded={expandedPanel?.type === 'compositing'}\n onKnockoutToggle={handleCompositingToggle}\n distressTextureExpanded={expandedPanel?.type === 'distressTexture'}\n onDistressTextureToggle={handleDistressTextureToggle}\n imageMaskExpanded={expandedPanel?.type === 'imageMask'}\n onImageMaskToggle={handleImageMaskToggle}\n getMoreMenuItems={getMoreMenuItems}\n onMoveForward={handleMoveForward}\n onMoveBackward={handleMoveBackward}\n onDelete={handleDeleteElement}\n elementForProperties={elementForProperties}\n elements={elements}\n isTransformMenuOpen={isTransformMenuOpen}\n onTransformMenuOpenChange={setIsTransformMenuOpen}\n elementUpdateHandler={elementUpdateHandler}\n showUngroupButton={!!activeChildElement && selectedElement?.transformType === 'group'}\n onUngroup={handleUngroupElement}\n isFontBrowserOpen={openDropdown === 'fontFamily'}\n onFontBrowserToggle={(isOpen) => setOpenDropdown(isOpen ? 'fontFamily' : null)}\n onTextMoreMenuOpenChange={setIsTextMoreMenuOpen}\n />\n )}\n\n {/* Color Menu (legacy) */}\n {activeMenu === 'color' && (\n <div className=\"sc-toolbar-items\">\n <BackButton onClick={() => setActiveMenu('root')} />\n <div className=\"sc-toolbar-scroll\">\n <input\n className=\"sc-toolbar-color\"\n type=\"color\"\n value={fontColor}\n onChange={(e) => { handleFontColorChange(e); }}\n />\n <span className=\"sc-toolbar-label\">{fontColor}</span>\n </div>\n </div>\n )}\n </>\n );\n\n // ── Build toolbar chrome (header + regular content) ────────────────────\n const shapeElement = elementForProperties?.transformType === 'shape' ? (elementForProperties as ShapeElement) : null;\n\n const toolbarContent = shouldRender ? (\n <div\n ref={toolbarDivRef}\n className=\"sc-toolbar\"\n data-sc-part={partAttr}\n data-mode={mode}\n data-wrap={maxWidth ? '' : undefined}\n data-transparent={transparent ? '' : undefined}\n data-panel-expanded={expandedPanel ? '' : undefined}\n data-preserve-selection\n style={{\n ...toolbarStyle,\n opacity: isRotating ? 0 : 1,\n // Embedded (docked) mode is visually transparent chrome — its empty\n // regions (flex gaps, leftover row width when the strip wraps) must\n // not swallow pointer events meant for the canvas behind it. The\n // root opts out and App.css re-enables hits on the actual controls\n // (.sc-toolbar-regular-content > *, .sc-toolbar-collapsed-header).\n // Floating mode keeps its opaque pill fully interactive.\n pointerEvents: isRotating ? 'none' : mode === 'embedded' ? 'none' : 'auto',\n transition: 'opacity 0.05s ease-out',\n }}\n data-entering={isEntering ? '' : undefined}\n data-exiting={isExiting ? '' : undefined}\n >\n <div className=\"sc-toolbar-slide-container\">\n <div className=\"sc-toolbar-regular-content\" data-hidden={expandedPanel ? '' : undefined}>\n {regularToolbarContent}\n </div>\n <div className=\"sc-toolbar-collapsed-header\" data-visible={expandedPanel ? '' : undefined}>\n {expandedPanel && (\n <CollapsedToolbarHeader\n icon={\n <ExpandedPanelIcon\n panelType={expandedPanel.type}\n defaultIcon={expandedPanel.icon}\n textColorValue={colorPickerValue}\n shapeFillColor={\n shapeElement\n ? shapeFillToCss(shapeElement.transformData?.fill, shapeElement.transformData?.fillColor)\n : undefined\n }\n />\n }\n label={expandedPanel.label}\n onClose={handleCloseExpandedPanel}\n closeButtonStyle={closeButtonStyle}\n />\n )}\n </div>\n </div>\n </div>\n ) : null;\n\n // ── Derive panel open states ───────────────────────────────────────────\n const isAlignPanelOpen = expandedPanel?.type === 'align';\n const isCornerRadiusPanelOpen = expandedPanel?.type === 'cornerRadius';\n const isCropPanelOpen = expandedPanel?.type === 'crop';\n const isRotationPanelOpen = expandedPanel?.type === 'rotation';\n const isOpacityPanelOpen = expandedPanel?.type === 'opacity';\n const isAdjustPanelOpen = expandedPanel?.type === 'adjust';\n const isFontSizePanelOpen = expandedPanel?.type === 'fontSize';\n const isShapeCornerRadiusPanelOpen = expandedPanel?.type === 'shapeCornerRadius';\n const isShapeTransparencyPanelOpen = expandedPanel?.type === 'shapeTransparency';\n const isShapeSidesPanelOpen = expandedPanel?.type === 'shapeSides';\n const isShapePointsPanelOpen = expandedPanel?.type === 'shapePoints';\n const isShapeInnerRadiusPanelOpen = expandedPanel?.type === 'shapeInnerRadius';\n const isShapeColorPanelOpen = expandedPanel?.type === 'shapeColor';\n const isTextColorPanelOpen = expandedPanel?.type === 'textColor';\n const isKnockoutPanelOpen = expandedPanel?.type === 'compositing';\n const isDistressTexturePanelOpen = expandedPanel?.type === 'distressTexture';\n const isStrokePanelOpen = expandedPanel?.type === 'stroke';\n const isShadowPanelOpen = expandedPanel?.type === 'shadow';\n const isBlendModePanelOpen = expandedPanel?.type === 'blendMode';\n const isImageMaskPanelOpen = expandedPanel?.type === 'imageMask';\n\n // ── Derive property values for panels ──────────────────────────────────\n const currentBorderRadius =\n elementForProperties?.transformType === 'image'\n ? (elementForProperties as ImageElement).transformData?.borderRadius || 0\n : 0;\n const currentRotation = elementForProperties?.rotation || 0;\n const currentOpacity = elementForProperties?.opacity ?? 1;\n const currentShapeBorderRadius = shapeElement?.transformData?.borderRadius || 0;\n const currentShapeOpacity = shapeElement?.transformData?.fillOpacity ?? 1;\n const currentShapeSides = shapeElement?.transformData?.sides || 5;\n const currentShapePoints = shapeElement?.transformData?.points || 5;\n const currentShapeInnerRadius = shapeElement?.transformData?.innerRadius || 0.4;\n const currentShapeFillColor = shapeElement?.transformData?.fillColor || '#3b82f6';\n const currentShapeFill = shapeElement?.transformData?.fill;\n const compositingFill = elementForProperties?.knockoutParts?.fill ?? false;\n const compositingStroke = elementForProperties?.knockoutParts?.stroke ?? false;\n const compositingScope: CompositingScope = elementForProperties?.knockoutParts?.scope ?? 'group';\n const compositingMode: CompositingMode = elementForProperties?.blendMode === 'clip' ? 'clip' : 'knockout';\n\n // ── Build secondary panel content ──────────────────────────────────────\n const alignPanel = isAlignPanelOpen && elementForProperties\n ? <AlignPanel onAlign={alignSelection} />\n : null;\n\n const cornerRadiusPanel = isCornerRadiusPanelOpen && elementForProperties?.transformType === 'image'\n ? <CornerRadiusPanel value={currentBorderRadius} onChange={handleBorderRadiusChange} />\n : null;\n\n const cropPanelContent = isCropPanelOpen && elementForProperties?.transformType === 'image'\n ? <CropPanelContent element={elementForProperties as ImageElement} onElementUpdate={elementUpdateHandler} />\n : null;\n\n const rotationPanel = isRotationPanelOpen && elementForProperties\n ? <RotationPanel value={currentRotation} onChange={handleRotationChange} onRotate90={handleRotate90} />\n : null;\n\n const opacityPanel = isOpacityPanelOpen && elementForProperties\n ? <OpacityPanel value={currentOpacity} onChange={handleOpacityChange} />\n : null;\n\n const currentAdjustments =\n elementForProperties?.transformType === 'image'\n ? (elementForProperties as ImageElement).transformData?.adjustments\n : undefined;\n\n const adjustPanel = isAdjustPanelOpen && elementForProperties?.transformType === 'image'\n ? (\n <AdjustPanel\n adjustments={currentAdjustments}\n onChange={handleAdjustmentsChange}\n onChangeEnd={handleAdjustmentsCommit}\n onReset={handleAdjustmentsReset}\n />\n )\n : null;\n\n // Font size panel — only relevant for text elements (and circle\n // text via getEffectiveFontSize). useTextToolbar's fontSize value\n // tracks the active text element's size and handleFontSizeChange\n // routes the update through the right element-specific path.\n const fontSizePanel = isFontSizePanelOpen\n ? (\n <FontSizePanel\n value={textToolbar.fontSize}\n onChange={textToolbar.handleFontSizeChange}\n widthValue={currentTextWidth}\n onWidthChange={handleTextWidthChange}\n letterSpacingValue={currentLetterSpacing}\n onLetterSpacingChange={textToolbar.handleLetterSpacingChange}\n lineHeightValue={currentLineHeight}\n onLineHeightChange={textToolbar.handleLineHeightChange}\n />\n )\n : null;\n\n const shapeCornerRadiusPanel = isShapeCornerRadiusPanelOpen && shapeElement\n ? <ShapeCornerRadiusPanel value={currentShapeBorderRadius} onChange={handleShapeBorderRadiusChange} />\n : null;\n\n const shapeTransparencyPanel = isShapeTransparencyPanelOpen && shapeElement\n ? <ShapeTransparencyPanel value={currentShapeOpacity} onChange={handleShapeOpacityChange} />\n : null;\n\n const shapeSidesPanel = isShapeSidesPanelOpen && shapeElement\n ? <ShapeSidesPanel value={currentShapeSides} onChange={handleShapeSidesChange} />\n : null;\n\n const shapePointsPanel = isShapePointsPanelOpen && shapeElement\n ? <ShapePointsPanel value={currentShapePoints} onChange={handleShapePointsChange} />\n : null;\n\n const shapeInnerRadiusPanel = isShapeInnerRadiusPanelOpen && shapeElement\n ? <ShapeInnerRadiusPanel value={currentShapeInnerRadius} onChange={handleShapeInnerRadiusChange} />\n : null;\n\n const shapeColorPanel = isShapeColorPanelOpen && shapeElement\n ? <ShapeColorPanel value={currentShapeFillColor} onChange={handleShapeFillColorChange} fill={currentShapeFill} onFillChange={handleShapeFillChange} documentColors={colorPickerDocumentColors} imageColors={colorPickerImageColors} />\n : null;\n\n const textColorPanel = isTextColorPanelOpen && elementForProperties\n ? <TextColorPanel value={colorPickerValue} onChange={colorPickerOnChange} documentColors={colorPickerDocumentColors} imageColors={colorPickerImageColors} />\n : null;\n\n const knockoutPanel = isKnockoutPanelOpen && elementForProperties\n ? <CompositingPanel\n mode={compositingMode}\n fill={compositingFill}\n stroke={compositingStroke}\n scope={compositingScope}\n onModeChange={handleCompositingModeChange}\n onFillChange={handleCompositingFillChange}\n onStrokeChange={handleCompositingStrokeChange}\n onScopeChange={handleCompositingScopeChange}\n />\n : null;\n\n const strokePanel = isStrokePanelOpen && elementForProperties\n ? <StrokePanel\n stroke={elementForProperties.stroke}\n onChange={handleStrokeChange}\n documentColors={colorPickerDocumentColors}\n imageColors={colorPickerImageColors}\n />\n : null;\n\n const shadowPanel = isShadowPanelOpen && elementForProperties\n ? <ShadowPanel\n shadow={elementForProperties.shadow}\n onChange={handleShadowChange}\n documentColors={colorPickerDocumentColors}\n imageColors={colorPickerImageColors}\n />\n : null;\n\n const blendModePanel = isBlendModePanelOpen && elementForProperties\n ? <BlendModePanel\n blendMode={\n isStandardBlendMode(elementForProperties.blendMode)\n ? elementForProperties.blendMode\n : 'normal'\n }\n onChange={handleBlendModeChange}\n />\n : null;\n\n const distressTexturePanel = isDistressTexturePanelOpen && elementForProperties\n ? <DistressTexturePanel\n textureUrl={elementForProperties.distressEffect?.textureUrl ?? ''}\n opacity={Math.round((elementForProperties.distressEffect?.textureOpacity ?? 0.5) * 100)}\n onTextureChange={handleDistressTextureChange}\n onOpacityChange={handleDistressOpacityChange}\n />\n : null;\n\n const quickMask = elementForProperties?.masks?.find((m: { id: string }) => m.id === 'quick-image-mask');\n const imageMaskPanel = isImageMaskPanelOpen && elementForProperties\n ? <ImageMaskPanel\n imageUrl={(quickMask?.maskElement as { imageUrl?: string })?.imageUrl ?? ''}\n maskType={(quickMask?.type as 'clip' | 'alpha' | 'luma') ?? 'clip'}\n opacity={Math.round((quickMask?.opacity ?? 1) * 100)}\n inverted={quickMask?.inverted ?? false}\n onImageChange={handleImageMaskImageChange}\n onMaskTypeChange={handleImageMaskTypeChange}\n onOpacityChange={handleImageMaskOpacityChange}\n onInvertedChange={handleImageMaskInvertedChange}\n />\n : null;\n\n // ── Empty state ────────────────────────────────────────────────────────\n const emptyStateContent =\n mode === 'embedded' && !selectedElement && !editArtboardMode ? (\n emptyStateRender ? (\n <div className=\"toolbar-empty-state\">{emptyStateRender}</div>\n ) : emptyStateMessage !== null ? (\n <div\n className=\"toolbar-empty-state\"\n style={{\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n padding: '16px 24px',\n color: 'var(--foreground)',\n opacity: 0.5,\n fontSize: '14px',\n textAlign: 'center',\n }}\n >\n {emptyStateMessage}\n </div>\n ) : null\n ) : null;\n\n // ── Artboard edit mode content (embedded only) ────────────────────────\n const artboardEditContent =\n mode === 'embedded' && editArtboardMode && !selectedElement && artboardManager.getActiveArtboard() ? (\n <div className=\"sc:px-4 sc:py-3 sc:flex sc:flex-col sc:gap-3\">\n <CollapsedToolbarHeader\n icon=\"lucide:palette\"\n label=\"Artboard Properties\"\n onClose={() => onEditArtboardModeChange?.(false)}\n closeButtonStyle=\"done\"\n />\n <ArtboardDistressPanel\n distressTexture={artboardManager.getActiveArtboard()!.distressTexture}\n onChange={(distressTexture) => {\n const currentArtboard = artboardManager.getActiveArtboard()!;\n if (onArtboardUpdate) {\n onArtboardUpdate(\n currentArtboard.id,\n { distressTexture: currentArtboard.distressTexture },\n { distressTexture }\n );\n } else {\n artboardManager.updateArtboard(currentArtboard.id, { distressTexture });\n refreshArtboards();\n }\n }}\n />\n <ArtboardImageMaskPanel\n imageMask={artboardManager.getActiveArtboard()!.imageMask}\n onChange={(imageMask) => {\n const currentArtboard = artboardManager.getActiveArtboard()!;\n if (onArtboardUpdate) {\n onArtboardUpdate(\n currentArtboard.id,\n { imageMask: currentArtboard.imageMask },\n { imageMask }\n );\n } else {\n artboardManager.updateArtboard(currentArtboard.id, { imageMask });\n refreshArtboards();\n }\n }}\n />\n </div>\n ) : null;\n\n // ── Embedded content ───────────────────────────────────────────────────\n const embeddedContent =\n mode === 'embedded' ? (\n <EmbeddedToolbarLayout\n toolbarContent={toolbarContent}\n innerContentRef={innerContentRef}\n shouldRender={shouldRender}\n isExiting={isExiting}\n transitionHeight={transitionHeight}\n emptyStateContent={artboardEditContent || emptyStateContent}\n isAlignPanelOpen={isAlignPanelOpen}\n isCornerRadiusPanelOpen={isCornerRadiusPanelOpen}\n isCropPanelOpen={isCropPanelOpen}\n isRotationPanelOpen={isRotationPanelOpen}\n isOpacityPanelOpen={isOpacityPanelOpen}\n isAdjustPanelOpen={isAdjustPanelOpen}\n isFontSizePanelOpen={isFontSizePanelOpen}\n isShapeCornerRadiusPanelOpen={isShapeCornerRadiusPanelOpen}\n isShapeTransparencyPanelOpen={isShapeTransparencyPanelOpen}\n isShapeSidesPanelOpen={isShapeSidesPanelOpen}\n isShapePointsPanelOpen={isShapePointsPanelOpen}\n isShapeInnerRadiusPanelOpen={isShapeInnerRadiusPanelOpen}\n isShapeColorPanelOpen={isShapeColorPanelOpen}\n isTextColorPanelOpen={isTextColorPanelOpen}\n isStrokePanelOpen={isStrokePanelOpen}\n isShadowPanelOpen={isShadowPanelOpen}\n isBlendModePanelOpen={isBlendModePanelOpen}\n isKnockoutPanelOpen={isKnockoutPanelOpen}\n isDistressTexturePanelOpen={isDistressTexturePanelOpen}\n isImageMaskPanelOpen={isImageMaskPanelOpen}\n cornerRadiusPanel={cornerRadiusPanel}\n cropPanelContent={cropPanelContent}\n rotationPanel={rotationPanel}\n opacityPanel={opacityPanel}\n adjustPanel={adjustPanel}\n fontSizePanel={fontSizePanel}\n shapeCornerRadiusPanel={shapeCornerRadiusPanel}\n shapeTransparencyPanel={shapeTransparencyPanel}\n shapeSidesPanel={shapeSidesPanel}\n shapePointsPanel={shapePointsPanel}\n shapeInnerRadiusPanel={shapeInnerRadiusPanel}\n shapeColorPanel={shapeColorPanel}\n textColorPanel={textColorPanel}\n strokePanel={strokePanel}\n shadowPanel={shadowPanel}\n blendModePanel={blendModePanel}\n knockoutPanel={knockoutPanel}\n distressTexturePanel={distressTexturePanel}\n alignPanel={alignPanel}\n imageMaskPanel={imageMaskPanel}\n />\n ) : null;\n\n // ── Floating mode secondary panels ─────────────────────────────────────\n const panelWidth = toolbarDimensions.width > 0 ? Math.max(toolbarDimensions.width, 200) : 280;\n\n const floatingCornerRadiusPanel =\n mode === 'floating' && isCornerRadiusPanelOpen && elementForProperties?.transformType === 'image' && toolbarPosition ? (\n <FloatingCornerRadiusPanel\n toolbarPosition={toolbarPosition}\n toolbarHeight={toolbarDimensions.height || 56}\n panelWidth={panelWidth}\n value={currentBorderRadius}\n onChange={handleBorderRadiusChange}\n />\n ) : null;\n\n const floatingCropPanel =\n mode === 'floating' && isCropPanelOpen && elementForProperties?.transformType === 'image' && toolbarPosition ? (\n <FloatingCropPanel\n toolbarPosition={toolbarPosition}\n toolbarHeight={toolbarDimensions.height || 56}\n element={elementForProperties as ImageElement}\n onElementUpdate={elementUpdateHandler}\n />\n ) : null;\n\n const floatingAlignPanel =\n mode === 'floating' && isAlignPanelOpen && elementForProperties && toolbarPosition ? (\n <FloatingAlignPanel\n toolbarPosition={toolbarPosition}\n toolbarHeight={toolbarDimensions.height || 56}\n onAlign={alignSelection}\n />\n ) : null;\n\n // ══════════════════════════════════════════════════════════════════════════\n // FINAL RENDER\n // ══════════════════════════════════════════════════════════════════════════\n\n return (\n <>\n {/* Contextual toolbar - use portal for floating mode to escape parent overflow:hidden */}\n {mode === 'floating' && typeof document !== 'undefined'\n ? createPortal(\n <>\n {toolbarContent}\n {floatingCornerRadiusPanel}\n {floatingCropPanel}\n {floatingAlignPanel}\n </>,\n document.body\n )\n : embeddedContent}\n\n {/* Artboard Properties Toolbar - Show when no element is selected (floating mode only) */}\n {mode !== 'embedded' && !selectedElement && artboardManager.getActiveArtboard() && onArtboardUpdate && (\n <ArtboardPropertiesToolbar\n artboard={artboardManager.getActiveArtboard()!}\n artboards={artboards}\n onArtboardUpdate={(updatedArtboard) => {\n const currentArtboard = artboardManager.getActiveArtboard()!;\n onArtboardUpdate(\n currentArtboard.id,\n {\n backgroundColor: currentArtboard.backgroundColor,\n backgroundType: currentArtboard.backgroundType,\n backgroundTexture: currentArtboard.backgroundTexture,\n exportBackground: currentArtboard.exportBackground,\n },\n {\n backgroundColor: updatedArtboard.backgroundColor,\n backgroundType: updatedArtboard.backgroundType,\n backgroundTexture: updatedArtboard.backgroundTexture,\n exportBackground: updatedArtboard.exportBackground,\n }\n );\n }}\n onRenameArtboard={(artboardId: string, newName: string) => {\n artboardManager.renameArtboard(artboardId, newName);\n refreshArtboards();\n }}\n onDeleteArtboard={(artboardId: string) => {\n artboardManager.deleteArtboard(artboardId);\n refreshArtboards();\n }}\n artboardScreenBounds={artboardScreenBounds}\n />\n )}\n\n {/* Shape Type Drawer - internal drawer when no external callback is provided */}\n {!onOpenShapeTypeDrawer && elementForProperties?.transformType === 'shape' && (\n <ShapeTypeDrawer\n isOpen={isShapeTypeDrawerOpen}\n onClose={() => setIsShapeTypeDrawerOpen(false)}\n onSelectType={handleShapeTypeChange}\n currentType={(elementForProperties as ShapeElement).transformData.shapeType}\n />\n )}\n </>\n );\n};\n\nexport default ContextualToolbars;\n"],"names":["Checkbox","React","className","checked","variant","props","ref","surface","useSurface","effectiveVariant","jsx","CheckboxPrimitive","cn","Icon","CollapsibleRoot","CollapsiblePrimitive","CollapsibleTrigger","CollapsibleContent","Disclosure","DisclosureTrigger","DisclosureContent","PopoverRoot","PopoverPrimitive","PopoverTrigger","PopoverAnchor","PopoverContent","align","sideOffset","preserveSelection","maxZIndex","children","style","SurfaceContext","PopoverBase","open","onOpenChange","Popover","Select","SelectPrimitive","SelectValue","SelectTrigger","jsxs","SelectScrollUpButton","SelectScrollDownButton","SelectContent","position","SelectLabel","SelectItem","SelectSeparator","Separator","orientation","decorative","SeparatorPrimitive","SliderContext","SliderTrack","SliderPrimitive","SliderThumb","SliderFill","SliderOutput","context","values","SliderBase","value","onValueChange","onChangeEnd","min","max","step","normalizedValue","internalValue","setInternalValue","isDraggingRef","touchMoveHandlerRef","preventScroll","e","handleChange","newValue","handleChangeEnd","handlePointerDown","handlePointerUp","hasChildren","thumbCount","_a","contextValue","Fragment","_","index","Slider","Switch","SwitchPrimitive","CollapsedToolbarHeader","icon","label","onClose","closeButtonStyle","containerRef","useRef","touchStartPos","useEffect","el","handleTouchStart","handleTouchMove","deltaX","deltaY","icons","TouchGuard","SliderRow","onChange","unit","showInput","inputWidth","displayValue","val","SELECTED_CLASSES","UNSELECTED_CLASSES","PresetCarousel","presets","selectedId","onSelect","showOff","size","ariaLabel","scrollToItem","useCallback","button","handleKeyDown","container","buttons","focused","currentIndex","btn","nextIndex","nextButton","presetId","isOffSelected","hasSelection","p","preset","isSelected","isTabbable","u","r","t","c","o","a","i","n","s","f","v","d","h","g","l","m","b","E","C","x","H","M","w","L","D","I","y","q","B","S","T","F","X","Y","U","V","G","J","Q","W","Z","ColorPickerDropdown","memo","documentColors","imageColors","showSquare","allowTransparent","controlledIsOpen","controlledOnOpenChange","embedded","internalIsOpen","setInternalIsOpen","useState","hexInput","setHexInput","localColor","setLocalColor","lastUpdateTimeRef","pendingUpdateRef","onChangeRef","isOpen","setIsOpen","handleColorChange","color","now","timeSinceLastUpdate","localColorRef","handleHexInputChange","input","hexPattern","withHash","handlePresetClick","handleTransparentClick","isTransparent","buttonContent","pickerContent","Button","HexColorPicker","BackIcon","BackButton","onClick","TooltipProvider","Tooltip","TooltipTrigger","TooltipContent","EPSILON","getFeatureApplied","element","td","letterSpacing","lineHeight","_b","_c","isStandardBlendMode","isNeutralAdjustments","ImageToolbar","onElementUpdate","showUngroupButton","onUngroup","onMoveForward","onMoveBackward","onChangeImage","onRemoveBackground","removingBackground","removeBackgroundError","onDelete","cornerRadiusExpanded","onCornerRadiusToggle","cropExpanded","onCropToggle","adjustExpanded","onAdjustToggle","rotationExpanded","onRotationToggle","opacityExpanded","onOpacityToggle","strokeExpanded","onStrokeToggle","shadowExpanded","onShadowToggle","blendModeExpanded","onBlendModeToggle","knockoutExpanded","onKnockoutToggle","distressTextureExpanded","onDistressTextureToggle","imageMaskExpanded","onImageMaskToggle","moreMenuOpen","setMoreMenuOpen","changeImageTooltipDisabled","setChangeImageTooltipDisabled","removeBgTooltipDisabled","setRemoveBgTooltipDisabled","cornerRadiusTooltipDisabled","setCornerRadiusTooltipDisabled","cropTooltipDisabled","setCropTooltipDisabled","adjustTooltipDisabled","setAdjustTooltipDisabled","rotationTooltipDisabled","setRotationTooltipDisabled","opacityTooltipDisabled","setOpacityTooltipDisabled","strokeTooltipDisabled","setStrokeTooltipDisabled","shadowTooltipDisabled","setShadowTooltipDisabled","blendModeTooltipDisabled","setBlendModeTooltipDisabled","knockoutTooltipDisabled","setKnockoutTooltipDisabled","distressTooltipDisabled","setDistressTooltipDisabled","imageMaskTooltipDisabled","setImageMaskTooltipDisabled","isCropping","applied","handleCropToggle","updatedElement","handleFlipHorizontal","handleFlipVertical","ToolbarButton","RotateLeftIcon","ARTBOARD_COLORS","ShapeToolbar","onOpenShapeTypeDrawer","transparencyExpanded","onTransparencyToggle","sidesExpanded","onSidesToggle","pointsExpanded","onPointsToggle","innerRadiusExpanded","onInnerRadiusToggle","colorExpanded","onColorToggle","shapeTypeTooltipDisabled","setShapeTypeTooltipDisabled","transparencyTooltipDisabled","setTransparencyTooltipDisabled","sidesTooltipDisabled","setSidesTooltipDisabled","pointsTooltipDisabled","setPointsTooltipDisabled","innerRadiusTooltipDisabled","setInnerRadiusTooltipDisabled","colorTooltipDisabled","setColorTooltipDisabled","presetDocumentColors","useMemo","effectiveDocumentColors","handleFillColorChange","shapeTypeLabels","currentShapeType","currentLabel","shapeFillToCss","PathToolbar","strokeColorOpen","setStrokeColorOpen","fillColorOpen","setFillColorOpen","strokeWidthOpen","setStrokeWidthOpen","handleStrokeColorChange","handleStrokeEnabledToggle","handleFillEnabledToggle","handleStrokeWidthChange","strokeColor","fillColor","strokeEnabled","fillEnabled","strokeWidth","isClosed","pointCount","Label","BackgroundPickerDropdown","backgroundType","backgroundColor","backgroundTexture","onBackgroundTypeChange","onColorChange","onTextureChange","activeTab","setActiveTab","handleTextureClick","textureId","handleTabChange","tab","defaultTexture","TextureManager","texture","ArtboardDistressPanel","distressTexture","ensureBuiltinTexturesReady","enabled","textureUrl","intensity","presetItems","DISTRESS_TEXTURE_PRESETS","handleEnabledChange","newEnabled","url","preloadTexture","handleTextureSelect","id","handleIntensityChange","ArtboardImageMaskPanel","imageMask","ensureMaskPresetsReady","imageUrl","maskType","opacity","inverted","MASK_IMAGE_PRESETS","handleImageSelect","handleMaskTypeChange","type","handleOpacityChange","handleInvertedChange","ArtboardPropertiesToolbar","artboard","artboards","onArtboardUpdate","onRenameArtboard","onDeleteArtboard","artboardScreenBounds","isEditing","setIsEditing","editingName","setEditingName","inputRef","handleBackgroundTypeChange","updatedArtboard","handleTextureChange","handleExportBackgroundToggle","handleDistressTextureChange","handleImageMaskChange","handleStartEdit","handleSaveEdit","handleCancelEdit","handleDelete","Surface","stripGlyphs","text","char","cp","logger","createLogger","FontBrowserDrawer","_fontFamilies","onToggle","previewText","elements","selectedFontRef","searchQuery","setSearchQuery","selectedCategory","setSelectedCategory","fontsLoadedTrigger","setFontsLoadedTrigger","displayMode","setDisplayMode","cardSize","setCardSize","viewMode","setViewMode","loadedFonts","setLoadedFonts","loadQueueRef","loadingRef","onFontUpload","useCanvasServices","customFonts","useSyncExternalStore","customFontRegistry","fontFileInputRef","fontUploadBusy","setFontUploadBusy","fontUploadError","setFontUploadError","customFamilies","seen","families","font","key","customFamilyKeys","ensureCustomFontsLoaded","error","handleFontFileChange","file","uploaded","loadCustomFont","registerCustomFonts","isEditorError","handleSelectCustom","family","cardSizeScale","styleId","UnifiedFontService","prev","loadFont","forSelection","textToLoad","fontsToLoad","allFonts","fontName","queueFontLoad","alreadyLoaded","alreadyQueued","handleSelect","selectedFont","FontItem","isUsedInDocument","fontItemRef","isLoaded","observer","entries","entry","mainText","showSecondaryLabel","shouldShowTooltip","surfaceContent","prevProps","nextProps","fontsUsedInDocument","usedFonts","addFontIfValid","fontFamily","child","fontSections","TSHIRT_FONTS","recommendedNames","query","remainingFonts","recommendedFonts","otherFonts","renderFontSection","fonts","categories","Drawer","TextField","Input","Tabs","category","CATEGORY_LABELS","TransformControlPanel","controls","onUpdate","draggingValues","setDraggingValues","control","storedValue","newElement","safeStoredValue","currentInternalValue","sliderValue","formatValue","newSliderValue","newInternalValue","updated","TextEffectsDropdown","onTransformTypeChange","currentTransformType","getTransformControls","textTransformTypes","TRANSFORM_TYPES","handleTransformChange","newType","transform","MoreMenu","items","showMenu","setShowMenu","item","FontColorButton","colorPickerValue","isActive","BoldButton","toolbar","ItalicButton","UnderlineButton","UppercaseButton","TextAlignButton","textAlign","handleTextAlignToggle","TextMoreMenu","handleOpenChange","TextToolbar","stableElementId","viewportWidth","isColorActive","onOpenGlyphBrowser","hasGlyphs","expandedPanel","onFontSizeToggle","getMoreMenuItems","elementForProperties","isTransformMenuOpen","onTransformMenuOpenChange","elementUpdateHandler","isFontBrowserOpen","onFontBrowserToggle","onTextMoreMenuOpenChange","glyphTooltipDisabled","setGlyphTooltipDisabled","fontSizeTooltipDisabled","setFontSizeTooltipDisabled","FONT_FAMILIES","convertTransform","sourceElement","targetType","TargetClass","rotationAnchor","currentEffectiveFontSize","config","calculateTransformConfig","effectiveFontSize","transformData","fontSize","minWidth","estimatedTextWidth","targetWidth","targetHeight","archMinWidth","archEstimatedWidth","ARCH_DEFAULTS","waveMinWidth","waveEstimatedWidth","WAVE_DEFAULTS","flagMinWidth","flagEstimatedWidth","FLAG_DEFAULTS","leanMinWidth","leanEstimatedWidth","LEAN_DEFAULTS","useTextToolbar","options","canvasEditorRef","selectedElement","activeChildElement","handleElementUpdate","useEditor","GroupElement","updatedGroup","childIndex","currentElementId","prevElementIdRef","localFontSize","setLocalFontSize","localFontColor","setLocalFontColor","localFontFamily","setLocalFontFamily","localTextAlign","setLocalTextAlign","TextElement","fontColor","textElement","bold","italic","underline","letterCase","setFontSizeValue","newSize","updateFontFamily","newFamily","updateFontColor","newColor","updateTextAlign","alignment","handleFontSizeChange","handleFontSizeIncrement","delta","handleLetterSpacingChange","newSpacing","handleLineHeightChange","newLineHeight","handleFontFamilyChange","handleFontColorChange","handleBoldToggle","handleItalicToggle","handleUnderlineToggle","handleLetterCaseToggle","newCase","isLetterCaseActive","alignments","nextAlign","getEffectiveStyle","selectionStyle","_d","handleTransformTypeChange","transformDef","getTransformById","useLayerPreview","previewUrl","setPreviewUrl","isLoading","setIsLoading","debounceRef","mounted","ImageElement","img","resolve","reject","generateElementPreview","ShapeElement","PathElement","_e","LayerLeadingChip","onToggleLock","onThumbnailClick","locked","SelectionThumbnail","LockIcon","inner","DISTRIBUTE_MIN_COUNT","ALIGN_SELECTION_MIN_COUNT","combinedBounds","minX","minY","maxX","maxY","computeAlign","mode","frame","updates","dx","dy","computeDistribute","EditorError","horizontal","sorted","first","last","span","totalSize","sum","gap","cursor","current","useAlignDistribute","multiSelection","artboardManager","executeCommandBatch","setElements","movableElements","applyUpdates","byId","commands","update","oldElement","replaceWith","distribute","ALIGN_BUTTONS","DISTRIBUTE_BUTTONS","MultiSelectionToolbar","partAttr","canvasRef","panOffset","useViewportContext","canAlign","canDistribute","toolbarRef","setPosition","selectionBounds","updatePosition","toolbarWidth","toolbarHeight","activeArtboard","artboardX","artboardY","currentZoom","canvas","screenX","screenY","canvasRect","screenWidth","screenHeight","top","left","minLeft","maxLeft","content","alignMode","distMode","createPortal","GroupElementToolbar","CropPanel","cropAnchor","setCropAnchor","currentCropWidth","currentCropHeight","handleCropChange","cropX","cropY","cropWidth","cropHeight","handleCropWidthChange","anchor","oldWidth","oldX","widthDiff","newX","handleCropHeightChange","oldHeight","oldY","heightDiff","newY","anchorPositions","pos","PANEL_BODY_CLASSES","COLOR_PANEL_BODY_CLASSES","CornerRadiusPanel","AlignPanel","onAlign","RotationPanel","onRotate90","FontSizePanel","widthValue","onWidthChange","letterSpacingValue","onLetterSpacingChange","lineHeightValue","onLineHeightChange","OpacityPanel","AdjustPanel","adjustments","onReset","NEUTRAL_ADJUSTMENTS","isNeutral","channelRow","channel","ShapeCornerRadiusPanel","ShapeTransparencyPanel","ShapeSidesPanel","ShapePointsPanel","ShapeInnerRadiusPanel","FILL_MODE_LABELS","ShapeColorPanel","fill","onFillChange","gradient","activeStop","setActiveStop","handleModeChange","next","stops","handleStopColorChange","handleAngleChange","angle","activeColor","stop","TextColorPanel","CompositingPanel","stroke","scope","onModeChange","onStrokeChange","onScopeChange","DistressTexturePanel","onOpacityChange","ImageMaskPanel","onImageChange","onMaskTypeChange","onInvertedChange","StrokePanel","showAdvanced","setShowAdvanced","width","lineCap","lineJoin","patch","cap","join","SHADOW_DEFAULTS","ShadowPanel","shadow","blur","offsetX","offsetY","BLEND_MODE_OPTIONS","STANDARD_BLEND_MODES","BlendModePanel","blendMode","CropPanelContent","ExpandedPanelIcon","panelType","defaultIcon","textColorValue","shapeFillColor","SecondaryPanelWrapper","ColorPanelWrapper","EmbeddedToolbarLayout","toolbarContent","innerContentRef","shouldRender","isExiting","transitionHeight","emptyStateContent","isAlignPanelOpen","isCornerRadiusPanelOpen","isCropPanelOpen","isRotationPanelOpen","isOpacityPanelOpen","isAdjustPanelOpen","isFontSizePanelOpen","isShapeCornerRadiusPanelOpen","isShapeTransparencyPanelOpen","isShapeSidesPanelOpen","isShapePointsPanelOpen","isShapeInnerRadiusPanelOpen","isShapeColorPanelOpen","isTextColorPanelOpen","isStrokePanelOpen","isShadowPanelOpen","isBlendModePanelOpen","isKnockoutPanelOpen","isDistressTexturePanelOpen","isImageMaskPanelOpen","alignPanel","cornerRadiusPanel","cropPanelContent","rotationPanel","opacityPanel","adjustPanel","fontSizePanel","shapeCornerRadiusPanel","shapeTransparencyPanel","shapeSidesPanel","shapePointsPanel","shapeInnerRadiusPanel","shapeColorPanel","textColorPanel","strokePanel","shadowPanel","blendModePanel","knockoutPanel","distressTexturePanel","imageMaskPanel","FloatingCornerRadiusPanel","toolbarPosition","panelWidth","FloatingAlignPanel","FloatingCropPanel","isPaintable","collectFromElement","out","richText","richFill","collectDocumentColors","ab","bg","IMAGE_PALETTE_CACHE","IMAGE_PALETTE_INFLIGHT","computeRanges","pixels","rMin","rMax","gMin","gMax","bMin","bMax","boxLongestAxis","box","boxSize","splitBox","axis","mid","leftPixels","rightPixels","averageColor","medianCutBoxes","targetBuckets","boxes","bestIdx","bestSize","target","redmeanDistance","rMean","dr","dg","db","furthestPointPalette","candidates","paletteSize","threshold","picked","used","bestMinDist","minDist","toHex","rgbToHex","extractImagePalette","cached","inflight","promise","loadCorsImage","SAMPLE","ctx","data","overExtract","collectImageColors","urls","visit","palettes","dedupe","palette","REMOVE_BG_UNAVAILABLE","safeErrorMessage","err","fallback","message","ContextualToolbars","services","ContextualToolbarsInner","CanvasServicesProvider","_breakpoints","maxWidth","transparent","onPanelExpandChange","defaultExpandedPanel","onExpandedPanelTypeChange","onOpenCropDrawer","onOpenCornerRadiusDrawer","emptyStateMessage","emptyStateRender","editArtboardMode","onEditArtboardModeChange","onLayerThumbnailClick","setSelectedId","useSelectionContext","contextExpandedPanelType","setContextExpandedPanelType","setIsToolbarMenuOpen","isRotating","useToolStateContext","executeElementUpdate","executeRemoveElement","executeAddElement","executeReorderElement","refreshArtboards","removeBackground","textToolbar","activeMenu","setActiveMenu","openDropdown","setOpenDropdown","setToolbarPosition","_isDragging","setIsDragging","setIsTransformMenuOpen","isColorPickerOpen","isTextMoreMenuOpen","setIsTextMoreMenuOpen","isShapeTypeDrawerOpen","setIsShapeTypeDrawerOpen","setExpandedPanel","isEntering","setIsEntering","setIsExiting","setShouldRender","isWaitingForPosition","setIsWaitingForPosition","positionedElementId","setPositionedElementId","setTransitionHeight","toolbarDimensions","setToolbarDimensions","lastKnownHeightRef","prevShouldShowRef","isMouseDownRef","frozenPositionRef","lastElementRotationRef","lastSyncedToContextRef","prevContextExpandedPanelTypeRef","prevSelectedIdRef","prevElementTypeRef","prevIsRotatingRef","isRotatingRef","isDrawerModeAtMount","isFullyMountedRef","expandedPanelRef","elementForPropertiesRef","elementUpdateHandlerRef","prevStableSelectedIdRef","prevIsCroppingRef","stableSelectedId","currentElementType","shouldShowToolbar","handleBorderRadiusChange","setRemovingBackground","setRemoveBackgroundError","elementsRef","isMountedForServicesRef","applyRemovedBackgroundUrl","elementId","processedUrl","swapImageUrl","oldImage","loadedElement","prevElements","currentElements","topLevel","handleRemoveBackground","handleShapeBorderRadiusChange","handleShapeOpacityChange","handleShapeSidesChange","handleShapePointsChange","handleShapeInnerRadiusChange","handleShapeFillColorChange","handleShapeFillChange","alignSelection","handleAlignToggle","handleCornerRadiusToggle","handleRotationToggle","handleOpacityToggle","handleAdjustToggle","handleFontSizeToggle","handleTextWidthChange","currentTextWidth","isCustomText","currentLetterSpacing","currentLineHeight","handleShapeCornerRadiusToggle","handleShapeTransparencyToggle","handleShapeSidesToggle","handleShapePointsToggle","handleShapeInnerRadiusToggle","handleShapeColorToggle","handleTextColorToggle","handleCompositingToggle","handleDistressTextureToggle","handleImageMaskToggle","handleStrokeToggle","handleShadowToggle","handleBlendModeToggle","handleCloseExpandedPanel","imageElement","handleMoveForward","idx","targetElement","handleMoveBackward","handleDeleteElement","elementToDelete","handleToggleLock","handleUngroupElement","group","artboardId","extractedChildren","clone","handleRotationChange","handleRotate90","newRotation","updateElementCommand","useCommands","adjustRunActiveRef","handleAdjustmentsChange","normalized","normalizeAdjustments","handleAdjustmentsCommit","handleAdjustmentsReset","handleCompositingModeChange","handleCompositingFillChange","currentMode","newParts","handleCompositingStrokeChange","handleCompositingScopeChange","handleDistressOpacityChange","pct","handleImageMaskImageChange","makeMaskElement","existing","masks","handleImageMaskTypeChange","mask","handleImageMaskOpacityChange","handleImageMaskInvertedChange","inv","handleStrokeChange","handleShadowChange","handleBlendModeChange","handleShapeTypeChange","newShapeType","handleOpenShapeTypeDrawer","localType","prevType","currentType","currentIsCropping","timeoutId","mouseDownPos","isDraggingStarted","DRAG_THRESHOLD","handleMouseDown","handleMouseMove","handleMouseUp","newWidth","newHeight","currentRotation","updateToolbarPosition","elementToPosition","elementBounds","elementScreenX","elementScreenY","elementScreenWidth","elementScreenHeight","viewportCenterX","viewportCenterY","elementTop","elementCenterX","maxTop","colorPickerOnChange","autoDocumentColors","mergedDocumentColors","documentColorsKey","colorPickerDocumentColors","imageUrlsKey","walk","colorPickerImageColors","setColorPickerImageColors","cancelled","colors","toolbarDivRef","node","height","wasRotating","isNowRotating","prevShouldShow","prevSelectedId","enterTimer","currentHeight","exitTimer","useLayoutEffect","startHeight","toolbarStyle","maxWidthValue","regularToolbarContent","shapeElement","currentBorderRadius","currentOpacity","currentShapeBorderRadius","currentShapeOpacity","_f","currentShapeSides","_g","currentShapePoints","_h","currentShapeInnerRadius","_i","currentShapeFillColor","_j","currentShapeFill","_k","compositingFill","_l","compositingStroke","_m","compositingScope","_n","compositingMode","currentAdjustments","_o","_p","_q","quickMask","_r","_s","artboardEditContent","currentArtboard","embeddedContent","floatingCornerRadiusPanel","floatingCropPanel","floatingAlignPanel","newName","ShapeTypeDrawer"],"mappings":";;;;;;;;;;;;;;;;AAaA,MAAMA,KAAWC,GAAM;AAAA,EACrB,CAAC,EAAE,WAAAC,GAAW,SAAAC,GAAS,SAAAC,GAAS,GAAGC,EAAA,GAASC,MAAQ;AAElD,UAAMC,IAAUC,GAAA,GACVC,IAAmBL,MAAYG,EAAQ,YAAY,YAAY,WAAW;AAEhF,WACE,gBAAAG;AAAA,MAACC,GAAkB;AAAA,MAAlB;AAAA,QACC,KAAAL;AAAA,QACA,WAAWM;AAAA,UACT;AAAA,UACA;AAAA,UACA;AAAA;AAAA,UAEAH,MAAqB,aAAa;AAAA,UAClCA,MAAqB,YAAY;AAAA,UACjC;AAAA,UACA;AAAA,UACAP;AAAA,QAAA;AAAA,QAEF,SAAAC;AAAA,QACC,GAAGE;AAAA,QAEJ,UAAA,gBAAAK;AAAA,UAACC,GAAkB;AAAA,UAAlB;AAAA,YACC,WAAWC;AAAA,cACT;AAAA,cACA;AAAA,cACA;AAAA,YAAA;AAAA,YAGD,UAAAT,MAAY,kBACX,gBAAAO,EAACG,GAAA,EAAK,MAAK,oBAAmB,WAAU,YAAA,CAAY,IAEpD,gBAAAH,EAACG,GAAA,EAAK,MAAK,oBAAmB,WAAU,YAAA,CAAY;AAAA,UAAA;AAAA,QAAA;AAAA,MAExD;AAAA,IAAA;AAAA,EAGN;AACF;AACAb,GAAS,cAAcW,GAAkB,KAAK;AC/C9C,MAAMG,KAAkBb,GAAM,WAG5B,CAAC,EAAE,WAAAC,GAAW,GAAGG,EAAA,GAASC,MAC1B,gBAAAI;AAAA,EAACK,GAAqB;AAAA,EAArB;AAAA,IACC,KAAAT;AAAA,IACA,WAAWM,GAAGV,CAAS;AAAA,IACtB,GAAGG;AAAA,EAAA;AACN,CACD;AACDS,GAAgB,cAAc;AAE9B,MAAME,KAAqBD,GAAqB,SAE1CE,KAAqBhB,GAAM,WAG/B,CAAC,EAAE,WAAAC,GAAW,GAAGG,EAAA,GAASC,MAC1B,gBAAAI;AAAA,EAACK,GAAqB;AAAA,EAArB;AAAA,IACC,KAAAT;AAAA,IACA,WAAWM;AAAA,MACT;AAAA,MACAV;AAAA,IAAA;AAAA,IAED,GAAGG;AAAA,EAAA;AACN,CACD;AACDY,GAAmB,cAAc;AAKjC,MAAMC,KAAaJ,IACbK,KAAoBH,IACpBI,KAAoBH,ICjCpBI,KAAcC,GAAiB,MAE/BC,KAAiBD,GAAiB,SAElCE,KAAgBF,GAAiB,QASjCG,KAAiBxB,GAAM,WAG3B,CAAC,EAAE,WAAAC,GAAW,OAAAwB,IAAQ,UAAU,YAAAC,IAAa,GAAG,mBAAAC,GAAmB,WAAAC,GAAW,UAAAC,GAAU,OAAAC,GAAO,GAAG1B,EAAA,GAASC,MAC3G,gBAAAI,EAACY,GAAiB,QAAjB,EACC,UAAA,gBAAAZ,EAACsB,GAAe,UAAf,EAAwB,OAAO,EAAE,SAAS,aACzC,UAAA,gBAAAtB;AAAA,EAACY,GAAiB;AAAA,EAAjB;AAAA,IACC,KAAAhB;AAAA,IACA,OAAAoB;AAAA,IACA,YAAAC;AAAA,IACA,2BAAyBC,IAAoB,KAAK;AAAA,IAClD,WAAWhB;AAAA,MACT;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACAV;AAAA,IAAA;AAAA,IAEF,OAAO2B,IAAY,EAAE,GAAGE,GAAO,QAAQ,eAAeA;AAAA,IACrD,GAAG1B;AAAA,IAEH,UAAAyB;AAAA,EAAA;AACH,EAAA,CACF,GACF,CACD;AACDL,GAAe,cAAcH,GAAiB,QAAQ;AAUtD,MAAMW,KAAc,CAAC,EAAE,UAAAH,GAAU,MAAAI,GAAM,cAAAC,GAAc,GAAG9B,EAAA,wBACrDgB,IAAA,EAAY,MAAAa,GAAY,cAAAC,GAA6B,GAAG9B,GACtD,UAAAyB,EAAA,CACH,GAIIM,KAAU,OAAO,OAAOH,IAAa;AAAA,EACzC,SAASV;AAAA,EACT,SAASE;AAAA,EACT,QAAQD;AAAA;AAAA,EAER,QAAQvB,GAAM;AAAA,IACZ,CAAC,EAAE,UAAA6B,GAAU,WAAA5B,GAAW,GAAGG,EAAA,GAASC,MAClC,gBAAAI,EAAC,OAAA,EAAI,KAAAJ,GAAU,WAAAJ,GAAuB,GAAGG,GACtC,UAAAyB,EAAA,CACH;AAAA,EAAA;AAGN,CAAC,GCrEKO,KAASC,GAAgB,MAIzBC,KAAcD,GAAgB,OAO9BE,KAAgBvC,GAAM;AAAA,EAC1B,CAAC,EAAE,WAAAC,GAAW,UAAA4B,GAAU,SAAA1B,GAAS,GAAGC,EAAA,GAASC,MAAQ;AAEnD,UAAMC,IAAUC,GAAA,GACVC,IAAmBL,MAAYG,EAAQ,YAAY,YAAY,WAAW;AAEhF,WACE,gBAAAkC;AAAA,MAACH,GAAgB;AAAA,MAAhB;AAAA,QACC,KAAAhC;AAAA,QACA,WAAWM;AAAA,UACT;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA;AAAA,UAEA;AAAA;AAAA,UAEAH,MAAqB,aAAa;AAAA,UAClCA,MAAqB,YAAY;AAAA,UACjCP;AAAA,QAAA;AAAA,QAED,GAAGG;AAAA,QAEH,UAAA;AAAA,UAAAyB;AAAA,UACD,gBAAApB,EAAC4B,GAAgB,MAAhB,EAAqB,SAAO,IAC3B,UAAA,gBAAA5B;AAAA,YAACG;AAAA,YAAA;AAAA,cACC,MAAK;AAAA,cACL,WAAU;AAAA,YAAA;AAAA,UAAA,EACZ,CACF;AAAA,QAAA;AAAA,MAAA;AAAA,IAAA;AAAA,EAGN;AACF;AACA2B,GAAc,cAAcF,GAAgB,QAAQ;AAEpD,MAAMI,KAAuBzC,GAAM,WAGjC,CAAC,EAAE,WAAAC,GAAW,GAAGG,EAAA,GAASC,MAC1B,gBAAAI;AAAA,EAAC4B,GAAgB;AAAA,EAAhB;AAAA,IACC,KAAAhC;AAAA,IACA,WAAWM,GAAG,uEAAuEV,CAAS;AAAA,IAC7F,GAAGG;AAAA,IAEJ,UAAA,gBAAAK,EAACG,GAAA,EAAK,MAAK,yBAAwB,WAAU,YAAA,CAAY;AAAA,EAAA;AAC3D,CACD;AACD6B,GAAqB,cAAcJ,GAAgB,eAAe;AAElE,MAAMK,KAAyB1C,GAAM,WAGnC,CAAC,EAAE,WAAAC,GAAW,GAAGG,EAAA,GAASC,MAC1B,gBAAAI;AAAA,EAAC4B,GAAgB;AAAA,EAAhB;AAAA,IACC,KAAAhC;AAAA,IACA,WAAWM,GAAG,uEAAuEV,CAAS;AAAA,IAC7F,GAAGG;AAAA,IAEJ,UAAA,gBAAAK,EAACG,GAAA,EAAK,MAAK,2BAA0B,WAAU,YAAA,CAAY;AAAA,EAAA;AAC7D,CACD;AACD8B,GAAuB,cAAcL,GAAgB,iBAAiB;AAEtE,MAAMM,KAAgB3C,GAAM,WAG1B,CAAC,EAAE,WAAAC,GAAW,UAAA4B,GAAU,UAAAe,IAAW,UAAU,GAAGxC,KAASC,MACzD,gBAAAI,EAAC4B,GAAgB,QAAhB,EACC,UAAA,gBAAAG;AAAA,EAACH,GAAgB;AAAA,EAAhB;AAAA,IACC,KAAAhC;AAAA,IACA,WAAWM;AAAA,MACT;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACAiC,MAAa,YACX;AAAA,MACF3C;AAAA,IAAA;AAAA,IAEF,UAAA2C;AAAA,IACC,GAAGxC;AAAA,IAEJ,UAAA;AAAA,MAAA,gBAAAK,EAACgC,IAAA,EAAqB;AAAA,MACtB,gBAAAhC;AAAA,QAAC4B,GAAgB;AAAA,QAAhB;AAAA,UACC,WAAW1B,GAAGiC,MAAa,YAAY,wDAAwD;AAAA,UAE9F,UAAAf;AAAA,QAAA;AAAA,MAAA;AAAA,wBAEFa,IAAA,CAAA,CAAuB;AAAA,IAAA;AAAA,EAAA;AAC1B,EAAA,CACF,CACD;AACDC,GAAc,cAAcN,GAAgB,QAAQ;AAEpD,MAAMQ,KAAc7C,GAAM,WAGxB,CAAC,EAAE,WAAAC,GAAW,GAAGG,EAAA,GAASC,MAC1B,gBAAAI;AAAA,EAAC4B,GAAgB;AAAA,EAAhB;AAAA,IACC,KAAAhC;AAAA,IACA,WAAWM,GAAG,uEAAuEV,CAAS;AAAA,IAC7F,GAAGG;AAAA,EAAA;AACN,CACD;AACDyC,GAAY,cAAcR,GAAgB,MAAM;AAEhD,MAAMS,KAAa9C,GAAM,WAGvB,CAAC,EAAE,WAAAC,GAAW,UAAA4B,GAAU,GAAGzB,KAASC,MACpC,gBAAAmC;AAAA,EAACH,GAAgB;AAAA,EAAhB;AAAA,IACC,KAAAhC;AAAA,IACA,WAAWM;AAAA,MACT;AAAA,MACA;AAAA,MACAV;AAAA,IAAA;AAAA,IAED,GAAGG;AAAA,IAEJ,UAAA;AAAA,MAAA,gBAAAK,EAAC,QAAA,EAAK,WAAU,sFACd,UAAA,gBAAAA,EAAC4B,GAAgB,eAAhB,EACC,UAAA,gBAAA5B,EAACG,GAAA,EAAK,MAAK,oBAAmB,WAAU,YAAA,CAAY,GACtD,GACF;AAAA,MACA,gBAAAH,EAAC4B,GAAgB,UAAhB,EAA0B,UAAAR,EAAA,CAAS;AAAA,IAAA;AAAA,EAAA;AACtC,CACD;AACDiB,GAAW,cAAcT,GAAgB,KAAK;AAE9C,MAAMU,KAAkB/C,GAAM,WAG5B,CAAC,EAAE,WAAAC,GAAW,GAAGG,EAAA,GAASC,MAC1B,gBAAAI,EAAC4B,GAAgB,WAAhB,EAA0B,KAAAhC,GAAU,WAAWM,GAAG,yCAAyCV,CAAS,GAAI,GAAGG,EAAA,CAAO,CACpH;AACD2C,GAAgB,cAAcV,GAAgB,UAAU;ACtJxD,MAAMW,KAAYhD,GAAM,WAGtB,CAAC,EAAE,WAAAC,GAAW,aAAAgD,IAAc,cAAc,YAAAC,IAAa,IAAM,GAAG9C,EAAA,GAASC,MACzE,gBAAAI;AAAA,EAAC0C,GAAmB;AAAA,EAAnB;AAAA,IACC,KAAA9C;AAAA,IACA,YAAA6C;AAAA,IACA,aAAAD;AAAA,IACA,WAAWtC;AAAA,MACT;AAAA,MACAsC,MAAgB,eAAe,yBAAyB;AAAA,MACxDhD;AAAA,IAAA;AAAA,IAED,GAAGG;AAAA,EAAA;AACN,CACD;AACD4C,GAAU,cAAcG,GAAmB,KAAK;ACIhD,MAAMC,KAAgBpD,GAAM,cAAyC,IAAI,GAGnEqD,KAAcrD,GAAM;AAAA,EACxB,CAAC,EAAE,WAAAC,GAAW,UAAA4B,GAAU,GAAGzB,EAAA,GAASC,MAClC,gBAAAI;AAAA,IAAC6C,GAAgB;AAAA,IAAhB;AAAA,MACC,KAAAjD;AAAA,MACA,WAAWM,GAAG,uFAAuFV,CAAS;AAAA,MAC7G,GAAGG;AAAA,MAEH,UAAAyB;AAAA,IAAA;AAAA,EAAA;AAGP;AACAwB,GAAY,cAAc;AAE1B,MAAME,KAAcvD,GAAM;AAAA,EACxB,CAAC,EAAE,WAAAC,GAAW,GAAGG,EAAA,GAASC,MACxB,gBAAAI;AAAA,IAAC6C,GAAgB;AAAA,IAAhB;AAAA,MACC,KAAAjD;AAAA,MAEA,WAAWM;AAAA,QACT;AAAA,QACAV;AAAA,MAAA;AAAA,MAED,GAAGG;AAAA,IAAA;AAAA,EAAA;AAGV;AACAmD,GAAY,cAAc;AAG1B,MAAMC,KAAaxD,GAAM;AAAA,EACvB,CAAC,EAAE,WAAAC,GAAW,GAAGG,EAAA,GAASC,MACxB,gBAAAI,EAAC6C,GAAgB,OAAhB,EAAsB,KAAAjD,GAAU,WAAWM,GAAG,uCAAuCV,CAAS,GAAI,GAAGG,EAAA,CAAO;AAEjH;AACAoD,GAAW,cAAc;AAOzB,MAAMC,KAAezD,GAAM;AAAA,EACzB,CAAC,EAAE,WAAAC,GAAW,UAAA4B,GAAU,GAAGzB,EAAA,GAASC,MAAQ;AAC1C,UAAMqD,IAAU1D,GAAM,WAAWoD,EAAa,GACxCO,KAASD,KAAA,gBAAAA,EAAS,WAAU,CAAC,CAAC;AAEpC,WACE,gBAAAjD,EAAC,QAAA,EAAK,KAAAJ,GAAU,WAAWM,GAAG,oCAAoCV,CAAS,GAAI,GAAGG,GAC/E,UAAA,OAAOyB,KAAa,aACjBA,EAAS,EAAE,OAAO,EAAE,QAAA8B,EAAA,EAAO,CAAG,IAC9B9B,KAAY8B,EAAO,KAAK,KAAK,EAAA,CACnC;AAAA,EAEJ;AACF;AACAF,GAAa,cAAc;AAE3B,MAAMG,KAAa5D,GAAM;AAAA,EACvB,CACE;AAAA,IACE,WAAAC;AAAA,IACA,OAAA4D;AAAA,IACA,eAAAC;AAAA,IACA,aAAAC;AAAA,IACA,KAAAC,IAAM;AAAA,IACN,KAAAC,IAAM;AAAA,IACN,MAAAC,IAAO;AAAA,IACP,UAAArC;AAAA,IACA,GAAGzB;AAAA,EAAA,GAELC,MACG;;AAEH,UAAM8D,IAAkBN,MAAU,SAAa,MAAM,QAAQA,CAAK,IAAIA,IAAQ,CAACA,CAAK,IAAK,QAGnF,CAACO,GAAeC,CAAgB,IAAIrE,GAAM,SAASmE,KAAmB,CAACH,CAAG,CAAC,GAG3EM,IAAgBtE,GAAM,OAAO,EAAK,GAClCuE,IAAsBvE,GAAM,OAAyC,IAAI,GAGzEwE,IAAgBxE,GAAM,YAAY,CAACyE,MAAkB;AACzD,MAAIH,EAAc,WAChBG,EAAE,eAAA;AAAA,IAEN,GAAG,CAAA,CAAE,GAECC,IAAe,CAACC,MAAuB;AAE3C,MAAAL,EAAc,UAAU,IACxBD,EAAiBM,CAAQ,GACzBb,KAAA,QAAAA,EAAgBa;AAAA,IAClB,GAEMC,IAAkB,CAACD,MAAuB;AAC9C,MAAAL,EAAc,UAAU,IACxBP,KAAA,QAAAA,EAAcY;AAAA,IAChB,GAGME,IAAoB7E,GAAM,YAAY,MAAM;AAEhD,MAAKuE,EAAoB,YACvBA,EAAoB,UAAUC,GAC9B,SAAS,iBAAiB,aAAaA,GAAe,EAAE,SAAS,IAAO;AAAA,IAE5E,GAAG,CAACA,CAAa,CAAC,GAGZM,IAAkB9E,GAAM,YAAY,MAAM;AAC9C,MAAAsE,EAAc,UAAU,IACpBC,EAAoB,YACtB,SAAS,oBAAoB,aAAaA,EAAoB,OAAO,GACrEA,EAAoB,UAAU;AAAA,IAElC,GAAG,CAAA,CAAE;AAGL,IAAAvE,GAAM,UAAU,MACP,MAAM;AACX,MAAIuE,EAAoB,WACtB,SAAS,oBAAoB,aAAaA,EAAoB,OAAO;AAAA,IAEzE,GACC,CAAA,CAAE;AAGL,UAAMQ,IAAc/E,GAAM,SAAS,MAAM6B,CAAQ,IAAI,GAG/CmD,KAAab,KAAA,gBAAAA,EAAiB,aAAUc,IAAA7E,EAAM,iBAAN,gBAAA6E,EAAoB,WAAU,GAGtEC,IAAelF,GAAM;AAAA,MACzB,OAAO;AAAA,QACL,QAAQmE,KAAmBC;AAAA,QAC3B,KAAAJ;AAAA,QACA,KAAAC;AAAA,MAAA;AAAA,MAEF,CAACE,GAAiBC,GAAeJ,GAAKC,CAAG;AAAA,IAAA;AAG3C,WACE,gBAAAxD,EAAC2C,GAAc,UAAd,EAAuB,OAAO8B,GAC7B,UAAA,gBAAAzE;AAAA,MAAC6C,GAAgB;AAAA,MAAhB;AAAA,QACC,KAAAjD;AAAA,QACA,WAAWM,GAAG,8EAA8EV,CAAS;AAAA,QACrG,OAAOkE;AAAA,QACP,eAAeO;AAAA,QACf,eAAeE;AAAA,QACf,eAAeC;AAAA,QACf,aAAaC;AAAA,QACb,iBAAiBA;AAAA,QACjB,sBAAsBA;AAAA,QACtB,KAAAd;AAAA,QACA,KAAAC;AAAA,QACA,MAAAC;AAAA,QACC,GAAG9D;AAAA,QAEH,UAAA2E,IACClD,IAEA,gBAAAW,EAAA2C,IAAA,EACE,UAAA;AAAA,UAAA,gBAAA1E,EAAC6C,GAAgB,OAAhB,EAAsB,WAAU,uFAC/B,UAAA,gBAAA7C,EAAC6C,GAAgB,OAAhB,EAAsB,WAAU,sCAAA,CAAsC,EAAA,CACzE;AAAA,UACC,MAAM,KAAK,EAAE,QAAQ0B,EAAA,CAAY,EAAE,IAAI,CAACI,GAAGC,MAC1C,gBAAA5E;AAAA,YAAC6C,GAAgB;AAAA,YAAhB;AAAA,cAEC,WAAU;AAAA,YAAA;AAAA,YADL+B;AAAA,UAAA,CAGR;AAAA,QAAA,EAAA,CACH;AAAA,MAAA;AAAA,IAAA,GAGN;AAAA,EAEJ;AACF;AACAzB,GAAW,cAAcN,GAAgB,KAAK;AAG9C,MAAMgC,KAAS,OAAO,OAAO1B,IAAY;AAAA,EACvC,OAAOP;AAAA,EACP,OAAOE;AAAA,EACP,MAAMC;AAAA,EACN,QAAQC;AACV,CAAC,GCpNK8B,KAASvF,GAAM;AAAA,EAGnB,CAAC,EAAE,WAAAC,GAAW,GAAGG,EAAA,GAASC,MAEtB,gBAAAI;AAAA,IAAC+E,GAAgB;AAAA,IAAhB;AAAA,MACC,WAAW7E;AAAA,QACT;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACAV;AAAA,MAAA;AAAA,MAED,GAAGG;AAAA,MACJ,KAAAC;AAAA,MAEA,UAAA,gBAAAI;AAAA,QAAC+E,GAAgB;AAAA,QAAhB;AAAA,UACC,WAAW7E;AAAA,YACT;AAAA,YACA;AAAA,UAAA;AAAA,QACF;AAAA,MAAA;AAAA,IACF;AAAA,EAAA;AAIR;AACA4E,GAAO,cAAcC,GAAgB,KAAK;ACInC,MAAMC,KAAgE,CAAC;AAAA,EAC5E,MAAAC;AAAA,EACA,OAAAC;AAAA,EACA,SAAAC;AAAA,EACA,WAAA3F;AAAA,EACA,kBAAA4F,IAAmB;AACrB,MAAM;AAEJ,QAAMC,IAAeC,EAAuB,IAAI,GAC1CC,IAAgBD,EAAO,EAAE,GAAG,GAAG,GAAG,GAAG;AAC3C,SAAAE,EAAU,MAAM;AACd,UAAMC,IAAKJ,EAAa;AACxB,QAAI,CAACI,EAAI;AAET,UAAMC,IAAmB,CAAC1B,MAAkB;AAC1C,MAAAuB,EAAc,UAAU;AAAA,QACtB,GAAGvB,EAAE,QAAQ,CAAC,EAAE;AAAA,QAChB,GAAGA,EAAE,QAAQ,CAAC,EAAE;AAAA,MAAA;AAAA,IAEpB,GAEM2B,IAAkB,CAAC3B,MAAkB;AACzC,YAAM4B,IAAS,KAAK,IAAI5B,EAAE,QAAQ,CAAC,EAAE,UAAUuB,EAAc,QAAQ,CAAC,GAChEM,IAAS,KAAK,IAAI7B,EAAE,QAAQ,CAAC,EAAE,UAAUuB,EAAc,QAAQ,CAAC;AAGtE,MAAIK,IAAS,MAAMA,IAASC,KAC1B7B,EAAE,eAAA;AAAA,IAEN;AAEA,WAAAyB,EAAG,iBAAiB,cAAcC,GAAkB,EAAE,SAAS,IAAM,GACrED,EAAG,iBAAiB,aAAaE,GAAiB,EAAE,SAAS,IAAO,GAE7D,MAAM;AACX,MAAAF,EAAG,oBAAoB,cAAcC,CAAgB,GACrDD,EAAG,oBAAoB,aAAaE,CAAe;AAAA,IACrD;AAAA,EACF,GAAG,CAAA,CAAE,GAGH,gBAAA5D;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,KAAKsD;AAAA,MACL,WAAWnF,GAAG,wDAAwDV,CAAS;AAAA,MAC/E,OAAO,EAAE,aAAa,QAAA;AAAA,MAGtB,UAAA;AAAA,QAAA,gBAAAuC,EAAC,OAAA,EAAI,WAAU,gDACZ,UAAA;AAAA,UAAA,OAAOkD,KAAS,WACf,gBAAAjF,EAACG,KAAK,MAAA8E,GAAY,WAAU,0CAAyC,IAErEA;AAAA,UAEF,gBAAAjF,EAAC,QAAA,EAAK,WAAU,kFAAkF,UAAAkF,EAAA,CAAM;AAAA,QAAA,GAC1G;AAAA,QAGCE,MAAqB,SACpB,gBAAApF;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,SAASmF;AAAA,YACT,WAAU;AAAA,YACV,cAAW;AAAA,YACZ,UAAA;AAAA,UAAA;AAAA,QAAA,IAID,gBAAAnF;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,SAASmF;AAAA,YACT,WAAU;AAAA,YACV,cAAW;AAAA,YAEX,4BAAChF,GAAA,EAAK,MAAM2F,GAAM,OAAO,WAAU,yBAAA,CAAyB;AAAA,UAAA;AAAA,QAAA;AAAA,MAC9D;AAAA,IAAA;AAAA,EAAA;AAIR;AAEAd,GAAuB,cAAc;ACpFrC,SAASe,GAAW,EAAE,UAAA3E,GAAU,WAAA5B,KAAgE;AAC9F,QAAMI,IAAM0F,EAAuB,IAAI;AAEvC,SAAAE,EAAU,MAAM;AACd,UAAMC,IAAK7F,EAAI;AACf,QAAI,CAAC6F,EAAI;AAET,UAAMC,IAAmB,CAAC1B,MAAkB;AAE1C,MAAAA,EAAE,gBAAA;AAAA,IACJ,GAEM2B,IAAkB,CAAC3B,MAAkB;AAEzC,MAAAA,EAAE,eAAA,GACFA,EAAE,gBAAA;AAAA,IACJ;AAGA,WAAAyB,EAAG,iBAAiB,cAAcC,GAAkB,EAAE,SAAS,IAAO,GACtED,EAAG,iBAAiB,aAAaE,GAAiB,EAAE,SAAS,IAAO,GAE7D,MAAM;AACX,MAAAF,EAAG,oBAAoB,cAAcC,CAAgB,GACrDD,EAAG,oBAAoB,aAAaE,CAAe;AAAA,IACrD;AAAA,EACF,GAAG,CAAA,CAAE,GAGH,gBAAA3F,EAAC,SAAI,KAAAJ,GAAU,WAAAJ,GAAsB,OAAO,EAAE,aAAa,UACxD,UAAA4B,GACH;AAEJ;AAoCO,MAAM4E,KAAsC,CAAC;AAAA,EAClD,OAAAd;AAAA,EACA,OAAA9B;AAAA,EACA,UAAA6C;AAAA,EACA,aAAA3C;AAAA,EACA,KAAAC;AAAA,EACA,KAAAC;AAAA,EACA,MAAAC,IAAO;AAAA,EACP,MAAAyC,IAAO;AAAA,EACP,WAAAC,IAAY;AAAA,EACZ,YAAAC,IAAa;AAAA,EACb,WAAA5G;AAAA,EACA,SAAAE,IAAU;AACZ,MAAM;AACJ,QAAM2G,IAAe,KAAK,MAAMjD,CAAK;AAErC,SAAI1D,MAAY,8BAGX,OAAA,EAAI,WAAWQ,GAAG,gDAAgDV,CAAS,GAC1E,UAAA;AAAA,IAAA,gBAAAuC,EAAC,OAAA,EAAI,WAAU,8CACb,UAAA;AAAA,MAAA,gBAAA/B,EAAC,QAAA,EAAK,WAAU,oDAAoD,UAAAkF,GAAM;AAAA,MACzEiB,KACC,gBAAAnG;AAAA,QAAC;AAAA,QAAA;AAAA,UACC,MAAK;AAAA,UACL,OAAOqG;AAAA,UACP,UAAU,CAACrC,MAAMiC,EAAS,KAAK,IAAI1C,GAAK,KAAK,IAAIC,GAAK,OAAOQ,EAAE,OAAO,KAAK,CAAC,CAAC,CAAC;AAAA,UAC9E,KAAAT;AAAA,UACA,KAAAC;AAAA,UACA,cAAY,GAAG0B,CAAK;AAAA,UACpB,WAAU;AAAA,UACV,OAAO,EAAE,OAAOkB,EAAA;AAAA,QAAW;AAAA,MAAA;AAAA,IAC7B,GAEJ;AAAA,sBACCL,IAAA,EACC,UAAA,gBAAAhE;AAAA,MAAC8C;AAAA,MAAA;AAAA,QACC,OAAO,CAACzB,CAAK;AAAA,QACb,eAAe,CAACkD,MAAQL,EAASK,EAAI,CAAC,CAAC;AAAA,QACvC,aAAahD,IAAc,CAACgD,MAAkBhD,EAAYgD,EAAI,CAAC,CAAC,IAAI;AAAA,QACpE,KAAA/C;AAAA,QACA,KAAAC;AAAA,QACA,MAAAC;AAAA,QAEA,UAAA;AAAA,UAAA,gBAAAzD,EAAC6E,GAAO,OAAP,EAAa,WAAU,0CACtB,UAAA,gBAAA7E,EAAC6E,GAAO,MAAP,EAAY,WAAU,gBAAA,CAAgB,EAAA,CACzC;AAAA,UACA,gBAAA7E,EAAC6E,GAAO,OAAP,EAAa,WAAU,yBAAA,CAAyB;AAAA,QAAA;AAAA,MAAA;AAAA,IAAA,EACnD,CACF;AAAA,EAAA,GACF,sBAMD,OAAA,EAAI,WAAW3E,GAAG,oCAAoCV,CAAS,GAC9D,UAAA;AAAA,IAAA,gBAAAQ,EAAC,QAAA,EAAK,WAAU,6EAA6E,UAAAkF,GAAM;AAAA,IAClGiB,IACC,gBAAAnG;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,MAAK;AAAA,QACL,OAAOqG;AAAA,QACP,UAAU,CAACrC,MAAMiC,EAAS,KAAK,IAAI1C,GAAK,KAAK,IAAIC,GAAK,OAAOQ,EAAE,OAAO,KAAK,CAAC,CAAC,CAAC;AAAA,QAC9E,KAAAT;AAAA,QACA,KAAAC;AAAA,QACA,cAAY,GAAG0B,CAAK;AAAA,QACpB,WAAU;AAAA,QACV,OAAO,EAAE,OAAOkB,EAAA;AAAA,MAAW;AAAA,IAAA,IAE3B;AAAA,IACJ,gBAAApG,EAAC+F,IAAA,EAAW,WAAU,aACpB,UAAA,gBAAAhE;AAAA,MAAC8C;AAAA,MAAA;AAAA,QACC,OAAO,CAACzB,CAAK;AAAA,QACb,eAAe,CAACkD,MAAQL,EAASK,EAAI,CAAC,CAAC;AAAA,QACvC,aAAahD,IAAc,CAACgD,MAAkBhD,EAAYgD,EAAI,CAAC,CAAC,IAAI;AAAA,QACpE,KAAA/C;AAAA,QACA,KAAAC;AAAA,QACA,MAAAC;AAAA,QAEA,UAAA;AAAA,UAAA,gBAAAzD,EAAC6E,GAAO,OAAP,EAAa,WAAU,0CACtB,UAAA,gBAAA7E,EAAC6E,GAAO,MAAP,EAAY,WAAU,gBAAA,CAAgB,EAAA,CACzC;AAAA,UACA,gBAAA7E,EAAC6E,GAAO,OAAP,EAAa,WAAU,yBAAA,CAAyB;AAAA,QAAA;AAAA,MAAA;AAAA,IAAA,GAErD;AAAA,IACA,gBAAA9C,EAAC,QAAA,EAAK,WAAU,sGACb,UAAA;AAAA,MAAAsE;AAAA,MAAcH;AAAA,IAAA,EAAA,CACjB;AAAA,EAAA,GACF;AAEJ,GC5JMK,KAAmB,oDACnBC,KAAqB,wFAEdC,KAAgD,CAAC;AAAA,EAC5D,SAAAC;AAAA,EACA,YAAAC;AAAA,EACA,UAAAC;AAAA,EACA,SAAAC,IAAU;AAAA,EACV,MAAAC,IAAO;AAAA,EACP,WAAAC,IAAY;AACd,MAAM;AACJ,QAAM1B,IAAeC,EAAuB,IAAI,GAE1C0B,IAAeC,EAAY,CAACC,MAA8B;AAC9D,IAAAA,EAAO,eAAe,EAAE,UAAU,UAAU,OAAO,WAAW,QAAQ,WAAW;AAAA,EACnF,GAAG,CAAA,CAAE,GAECC,IAAgBF;AAAA,IACpB,CAACjD,MAA2C;AAC1C,UAAIA,EAAE,QAAQ,eAAeA,EAAE,QAAQ,aAAc;AACrD,MAAAA,EAAE,eAAA,GACFA,EAAE,gBAAA;AAEF,YAAMoD,IAAY/B,EAAa;AAC/B,UAAI,CAAC+B,EAAW;AAEhB,YAAMC,IAAU,MAAM,KAAKD,EAAU,iBAAoC,wBAAwB,CAAC,GAC5FE,IAAU,SAAS;AACzB,UAAIC,IAAeF,EAAQ,QAAQC,CAAO;AAG1C,MAAIC,MAAiB,OACnBA,IAAeF,EAAQ,UAAU,CAACG,MAAQA,EAAI,aAAa,eAAe,MAAM,MAAM,GAClFD,MAAiB,OAAIA,IAAe;AAG1C,UAAIE;AACJ,MAAIzD,EAAE,QAAQ,eACZyD,IAAYF,IAAeF,EAAQ,SAAS,IAAIE,IAAe,IAAI,IAEnEE,IAAYF,IAAe,IAAIA,IAAe,IAAIF,EAAQ,SAAS;AAGrE,YAAMK,IAAaL,EAAQI,CAAS;AACpC,MAAAC,EAAW,MAAA,GACXV,EAAaU,CAAU;AAGvB,YAAMC,IAAWD,EAAW,aAAa,gBAAgB;AACzD,MAAIC,MAAa,QACff,EAASe,CAAQ;AAAA,IAErB;AAAA,IACA,CAACX,GAAcJ,CAAQ;AAAA,EAAA,GAGnBgB,IAAgBf,KAAW,CAACF,GAE5BkB,IAAehB,IAAU,KAAOH,EAAQ,KAAK,CAACoB,MAAMA,EAAE,OAAOnB,CAAU;AAE7E,SACE,gBAAA5E;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,KAAKsD;AAAA,MACL,WAAU;AAAA,MACV,OAAO,EAAE,UAAU,SAAA;AAAA,MACnB,MAAK;AAAA,MACL,cAAY0B;AAAA,MACZ,WAAWI;AAAA,MAEV,UAAA;AAAA,QAAAN,KACC,gBAAA7G;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,kBAAe;AAAA,YACf,MAAK;AAAA,YACL,iBAAe4H;AAAA,YACf,UAAUA,KAAkB,CAACC,IAAgB,IAAI;AAAA,YACjD,SAAS,MAAMjB,EAAS,EAAE;AAAA,YAC1B,WAAW,yFACTgB,IAAgBrB,KAAmBC,EACrC;AAAA,YACA,OAAO,EAAE,OAAOM,GAAM,QAAQA,EAAA;AAAA,YAC9B,OAAM;AAAA,YAEN,UAAA,gBAAA9G,EAAC,QAAA,EAAK,WAAU,uCAAsC,UAAA,MAAA,CAAG;AAAA,UAAA;AAAA,QAAA;AAAA,QAG5D0G,EAAQ,IAAI,CAACqB,GAAQnD,MAAU;AAC9B,gBAAMoD,IAAarB,MAAeoB,EAAO,IAEnCE,IAAaD,KAAe,CAACnB,KAAW,CAACgB,KAAgBjD,MAAU;AACzE,iBACE,gBAAA5E;AAAA,YAAC;AAAA,YAAA;AAAA,cAEC,kBAAgB+H,EAAO;AAAA,cACvB,MAAK;AAAA,cACL,iBAAeC;AAAA,cACf,UAAUC,IAAa,IAAI;AAAA,cAC3B,SAAS,MAAMrB,EAASmB,EAAO,EAAE;AAAA,cACjC,WAAW,+CACTC,IAAazB,KAAmBC,EAClC;AAAA,cACA,OAAO,EAAE,OAAOM,GAAM,QAAQA,EAAA;AAAA,cAC9B,OAAOiB,EAAO;AAAA,cAEb,YAAO,gBACN,gBAAA/H;AAAA,gBAAC;AAAA,gBAAA;AAAA,kBACC,KAAK+H,EAAO;AAAA,kBACZ,KAAKA,EAAO;AAAA,kBACZ,WAAU;AAAA,kBACV,SAAQ;AAAA,gBAAA;AAAA,cAAA;AAAA,YACV;AAAA,YAlBGA,EAAO;AAAA,UAAA;AAAA,QAsBlB,CAAC;AAAA,MAAA;AAAA,IAAA;AAAA,EAAA;AAGP;ACrJkH,SAASG,KAAG;AAAC,UAAOA,KAAE,OAAO,UAAQ,SAAS,GAAE;AAAC,aAAQC,IAAE,GAAEA,IAAE,UAAU,QAAOA,KAAI;AAAC,UAAI,IAAE,UAAUA,CAAC;AAAE,eAAQC,KAAK,EAAE,QAAO,UAAU,eAAe,KAAK,GAAEA,CAAC,MAAI,EAAEA,CAAC,IAAE,EAAEA,CAAC;AAAA,IAAE;AAAC,WAAO;AAAA,EAAC,GAAG,MAAM,MAAK,SAAS;AAAC;AAAC,SAASC,GAAE,GAAEF,GAAE;AAAC,MAAS,KAAN,KAAQ,QAAM,CAAA;AAAG,MAAI,GAAEC,GAAEE,IAAE,CAAA,GAAGC,IAAE,OAAO,KAAK,CAAC;AAAE,OAAIH,IAAE,GAAEA,IAAEG,EAAE,QAAOH,IAAI,CAAAD,EAAE,QAAQ,IAAEI,EAAEH,CAAC,CAAC,KAAG,MAAIE,EAAE,CAAC,IAAE,EAAE,CAAC;AAAG,SAAOA;AAAC;AAAC,SAASE,GAAE,GAAE;AAAC,MAAIC,IAAEN,EAAE,CAAC,GAAEC,IAAED,EAAE,SAASnE,GAAE;AAAC,IAAAyE,EAAE,WAASA,EAAE,QAAQzE,CAAC;AAAA,EAAC,CAAC;AAAE,SAAOyE,EAAE,UAAQ,GAAEL,EAAE;AAAO;AAAI,IAACM,KAAE,SAAS,GAAEP,GAAE,GAAE;AAAC,SAAgBA,MAAT,WAAaA,IAAE,IAAY,MAAT,WAAa,IAAE,IAAG,IAAE,IAAE,IAAE,IAAEA,IAAEA,IAAE;AAAC,GAAEQ,KAAE,SAAS,GAAE;AAAC,SAAM,aAAY;AAAC,GAAEC,KAAE,SAAS,GAAE;AAAC,SAAO,KAAG,EAAE,cAAc,eAAa;AAAI,GAAEC,KAAE,SAAS,GAAEV,GAAE,GAAE;AAAC,MAAIC,IAAE,EAAE,sBAAqB,GAAGE,IAAEK,GAAER,CAAC,IAAE,SAASnE,GAAEmE,GAAE;AAAC,aAAQM,IAAE,GAAEA,IAAEzE,EAAE,QAAOyE,IAAI,KAAGzE,EAAEyE,CAAC,EAAE,eAAaN,EAAE,QAAOnE,EAAEyE,CAAC;AAAE,WAAOzE,EAAE,CAAC;AAAA,EAAC,EAAEmE,EAAE,SAAQ,CAAC,IAAEA;AAAE,SAAM,EAAC,MAAKO,IAAGJ,EAAE,SAAOF,EAAE,OAAKQ,GAAE,CAAC,EAAE,gBAAcR,EAAE,KAAK,GAAE,KAAIM,IAAGJ,EAAE,SAAOF,EAAE,MAAIQ,GAAE,CAAC,EAAE,gBAAcR,EAAE,MAAM,EAAC;AAAC,GAAEU,KAAE,SAAS,GAAE;AAAC,GAACH,GAAE,CAAC,KAAG,EAAE,eAAc;AAAE,GAAEI,KAAE/E,GAAE,KAAK,SAASsE,GAAE;AAAC,MAAIC,IAAED,EAAE,QAAOU,IAAEV,EAAE,OAAMI,IAAEJ,EAAE,OAAMS,IAAEV,GAAEC,GAAE,CAAC,UAAS,SAAQ,OAAO,CAAC,GAAEW,IAAEd,EAAE,IAAI,GAAEL,IAAEU,GAAED,CAAC,GAAEW,IAAEV,GAAEQ,CAAC,GAAErE,IAAE6D,GAAEE,CAAC,GAAES,IAAEhB,EAAE,IAAI,GAAEiB,IAAEjB,EAAE,EAAE,GAAEkB,IAAEZ,GAAE,WAAU;AAAC,QAAIzE,IAAE,SAASA,GAAE;AAAC,MAAA8E,GAAE9E,CAAC,IAAG2E,GAAE3E,CAAC,IAAEA,EAAE,QAAQ,SAAO,IAAEA,EAAE,UAAQ,MAAIiF,EAAE,UAAQnB,EAAEe,GAAEI,EAAE,SAAQjF,GAAEmF,EAAE,OAAO,CAAC,KAAGV,EAAE,EAAE,GAAE9D,EAAC;AAAA,IAAG,GAAEwD,IAAE,WAAU;AAAC,MAAAM,EAAE,EAAE,GAAE9D,EAAC;AAAA,IAAE;AAAE,aAAS8D,EAAEA,GAAE;AAAC,UAAIL,IAAEgB,EAAE,SAAQd,IAAEM,GAAEK,EAAE,OAAO,GAAEV,IAAEE,IAAEH,EAAE,mBAAiBA,EAAE;AAAoB,MAAAC,EAAEH,IAAE,cAAY,aAAYpE,CAAC,GAAEuE,EAAEH,IAAE,aAAW,WAAUD,CAAC;AAAA,IAAC;AAAC,WAAM,CAAC,SAASnE,GAAE;AAAC,UAAImE,IAAEnE,EAAE,aAAYoE,IAAEa,EAAE;AAAQ,UAAGb,MAAIU,GAAEX,CAAC,GAAE,CAAC,SAASnE,GAAEmE,GAAE;AAAC,eAAOA,KAAG,CAACQ,GAAE3E,CAAC;AAAA,MAAC,EAAEmE,GAAEiB,EAAE,OAAO,KAAGhB,IAAG;AAAC,YAAGO,GAAER,CAAC,GAAE;AAAC,UAAAiB,EAAE,UAAQ;AAAG,cAAId,IAAEH,EAAE,kBAAgB,CAAA;AAAG,UAAAG,EAAE,WAASa,EAAE,UAAQb,EAAE,CAAC,EAAE;AAAA,QAAW;AAAC,QAAAF,EAAE,MAAK,GAAGN,EAAEe,GAAET,GAAED,GAAEgB,EAAE,OAAO,CAAC,GAAEV,EAAE,EAAE;AAAA,MAAC;AAAA,IAAC,GAAE,SAASzE,GAAE;AAAC,UAAImE,IAAEnE,EAAE,SAAOA,EAAE;AAAQ,MAAAmE,IAAE,MAAIA,IAAE,OAAKnE,EAAE,eAAc,GAAGkF,EAAE,EAAC,MAAUf,MAAL,KAAO,OAASA,MAAL,KAAO,QAAK,GAAE,KAASA,MAAL,KAAO,OAASA,MAAL,KAAO,QAAK,EAAC,CAAC;AAAA,IAAE,GAAE,SAASnE,GAAE;AAAC,UAAImE,IAAEnE,EAAE,SAAOA,EAAE;AAAQ,MAAAmE,KAAG,MAAIA,KAAG,MAAIxD,EAAC;AAAA,IAAE,GAAE8D,CAAC;AAAA,EAAC,GAAE,CAACS,GAAEpB,GAAEnD,CAAC,CAAC,GAAE2E,IAAED,EAAE,CAAC,GAAEE,IAAEF,EAAE,CAAC,GAAE,IAAEA,EAAE,CAAC,GAAEG,IAAEH,EAAE,CAAC;AAAE,SAAOjB,EAAE,WAAU;AAAC,WAAOoB;AAAA,EAAC,GAAE,CAACA,CAAC,CAAC,GAAExF,GAAE,cAAc,OAAMkE,GAAE,IAAGa,GAAE,EAAC,cAAaO,GAAE,aAAYA,GAAE,WAAU,+BAA8B,KAAIL,GAAE,WAAUM,GAAE,SAAQ,GAAE,UAAS,GAAE,MAAK,SAAQ,CAAC,CAAC;AAAC,CAAC,GAAEN,KAAE,SAAS,GAAE;AAAC,SAAO,EAAE,OAAO,OAAO,EAAE,KAAK,GAAG;AAAC,GAAEnB,KAAE,SAASK,GAAE;AAAC,MAAIM,IAAEN,EAAE,OAAMC,IAAED,EAAE,MAAK,IAAEA,EAAE,KAAII,IAAW,MAAT,SAAW,MAAG,GAAES,IAAEC,GAAE,CAAC,2BAA0Bd,EAAE,SAAS,CAAC;AAAE,SAAOnE,GAAE,cAAc,OAAM,EAAC,WAAUgF,GAAE,OAAM,EAAC,KAAI,MAAIT,IAAE,KAAI,MAAK,MAAIH,IAAE,IAAG,EAAC,GAAEpE,GAAE,cAAc,OAAM,EAAC,WAAU,gCAA+B,OAAM,EAAC,iBAAgByE,EAAC,EAAC,CAAC,CAAC;AAAC,GAAES,KAAE,SAAS,GAAEf,GAAE,GAAE;AAAC,SAAgBA,MAAT,WAAaA,IAAE,IAAY,MAAT,WAAa,IAAE,KAAK,IAAI,IAAGA,CAAC,IAAG,KAAK,MAAM,IAAE,CAAC,IAAE;AAAC,GAA2CgB,KAAE,SAAS,GAAE;AAAC,SAAOM,GAAEL,GAAE,CAAC,CAAC;AAAC,GAAEA,KAAE,SAAS,GAAE;AAAC,SAAY,EAAE,CAAC,MAAT,QAAa,IAAE,EAAE,UAAU,CAAC,IAAG,EAAE,SAAO,IAAE,EAAC,GAAE,SAAS,EAAE,CAAC,IAAE,EAAE,CAAC,GAAE,EAAE,GAAE,GAAE,SAAS,EAAE,CAAC,IAAE,EAAE,CAAC,GAAE,EAAE,GAAE,GAAE,SAAS,EAAE,CAAC,IAAE,EAAE,CAAC,GAAE,EAAE,GAAE,GAAM,EAAE,WAAN,IAAaF,GAAE,SAAS,EAAE,CAAC,IAAE,EAAE,CAAC,GAAE,EAAE,IAAE,KAAI,CAAC,IAAE,EAAC,IAAE,EAAC,GAAE,SAAS,EAAE,UAAU,GAAE,CAAC,GAAE,EAAE,GAAE,GAAE,SAAS,EAAE,UAAU,GAAE,CAAC,GAAE,EAAE,GAAE,GAAE,SAAS,EAAE,UAAU,GAAE,CAAC,GAAE,EAAE,GAAE,GAAM,EAAE,WAAN,IAAaA,GAAE,SAAS,EAAE,UAAU,GAAE,CAAC,GAAE,EAAE,IAAE,KAAI,CAAC,IAAE,EAAC;AAAC,GAAgcM,KAAE,SAAS,GAAE;AAAC,SAAOE,GAAEC,GAAE,CAAC,CAAC;AAAC,GAAEC,KAAE,SAAS,GAAE;AAAC,MAAIzB,IAAE,EAAE,GAAE,IAAE,EAAE,GAAEC,IAAE,EAAE,GAAEE,KAAG,MAAIH,KAAG,IAAE;AAAI,SAAM,EAAC,GAAEe,GAAE,EAAE,CAAC,GAAE,GAAEA,GAAEZ,IAAE,KAAGA,IAAE,MAAIH,IAAE,IAAE,OAAKG,KAAG,MAAIA,IAAE,MAAIA,KAAG,MAAI,CAAC,GAAE,GAAEY,GAAEZ,IAAE,CAAC,GAAE,GAAEY,GAAEd,GAAE,CAAC,EAAC;AAAC,GAAEyB,KAAE,SAAS,GAAE;AAAC,MAAI1B,IAAEyB,GAAE,CAAC;AAAE,SAAM,SAAOzB,EAAE,IAAE,OAAKA,EAAE,IAAE,QAAMA,EAAE,IAAE;AAAI,GAA+EwB,KAAE,SAAS,GAAE;AAAC,MAAIxB,IAAE,EAAE,GAAE,IAAE,EAAE,GAAEC,IAAE,EAAE,GAAEE,IAAE,EAAE;AAAE,EAAAH,IAAEA,IAAE,MAAI,GAAE,KAAG,KAAIC,KAAG;AAAI,MAAIG,IAAE,KAAK,MAAMJ,CAAC,GAAEa,IAAEZ,KAAG,IAAE,IAAGF,IAAEE,KAAG,KAAGD,IAAEI,KAAG,IAAGF,IAAED,KAAG,KAAG,IAAED,IAAEI,KAAG,IAAGC,IAAED,IAAE;AAAE,SAAM,EAAC,GAAEW,GAAE,MAAI,CAACd,GAAEF,GAAEc,GAAEA,GAAEX,GAAED,CAAC,EAAEI,CAAC,CAAC,GAAE,GAAEU,GAAE,MAAI,CAACb,GAAED,GAAEA,GAAEF,GAAEc,GAAEA,CAAC,EAAER,CAAC,CAAC,GAAE,GAAEU,GAAE,MAAI,CAACF,GAAEA,GAAEX,GAAED,GAAEA,GAAEF,CAAC,EAAEM,CAAC,CAAC,GAAE,GAAEU,GAAEZ,GAAE,CAAC,EAAC;AAAC,GAAulBwB,KAAE,SAAS,GAAE;AAAC,MAAI3B,IAAE,EAAE,SAAS,EAAE;AAAE,SAAOA,EAAE,SAAO,IAAE,MAAIA,IAAEA;AAAC,GAAEuB,KAAE,SAAS,GAAE;AAAC,MAAIvB,IAAE,EAAE,GAAE,IAAE,EAAE,GAAEC,IAAE,EAAE,GAAEE,IAAE,EAAE,GAAEC,IAAED,IAAE,IAAEwB,GAAEZ,GAAE,MAAIZ,CAAC,CAAC,IAAE;AAAG,SAAM,MAAIwB,GAAE3B,CAAC,IAAE2B,GAAE,CAAC,IAAEA,GAAE1B,CAAC,IAAEG;AAAC,GAAEkB,KAAE,SAAS,GAAE;AAAC,MAAItB,IAAE,EAAE,GAAE,IAAE,EAAE,GAAEC,IAAE,EAAE,GAAEE,IAAE,EAAE,GAAEC,IAAE,KAAK,IAAIJ,GAAE,GAAEC,CAAC,GAAEY,IAAET,IAAE,KAAK,IAAIJ,GAAE,GAAEC,CAAC,GAAEF,IAAEc,IAAET,MAAIJ,KAAG,IAAEC,KAAGY,IAAET,MAAI,IAAE,KAAGH,IAAED,KAAGa,IAAE,KAAGb,IAAE,KAAGa,IAAE;AAAE,SAAM,EAAC,GAAEE,GAAE,MAAIhB,IAAE,IAAEA,IAAE,IAAEA,EAAE,GAAE,GAAEgB,GAAEX,IAAES,IAAET,IAAE,MAAI,CAAC,GAAE,GAAEW,GAAEX,IAAE,MAAI,GAAG,GAAE,GAAED,EAAC;AAAC,GAA+DyB,KAAE/F,GAAE,KAAK,SAASmE,GAAE;AAAC,MAAIM,IAAEN,EAAE,KAAIC,IAAED,EAAE,UAAS,IAAEA,EAAE,aAAYI,IAAEU,GAAE,CAAC,uBAAsBd,EAAE,SAAS,CAAC;AAAE,SAAOnE,GAAE,cAAc,OAAM,EAAC,WAAUuE,EAAC,GAAEvE,GAAE,cAAc+E,IAAE,EAAC,QAAO,SAAS/E,GAAE;AAAC,IAAAoE,EAAE,EAAC,GAAE,MAAIpE,EAAE,KAAI,CAAC;AAAA,EAAC,GAAE,OAAM,SAASA,GAAE;AAAC,IAAAoE,EAAE,EAAC,GAAEM,GAAED,IAAE,MAAIzE,EAAE,MAAK,GAAE,GAAG,EAAC,CAAC;AAAA,EAAC,GAAE,OAAM,GAAE,cAAa,OAAM,iBAAgBkF,GAAET,CAAC,GAAE,iBAAgB,OAAM,iBAAgB,IAAG,GAAEzE,GAAE,cAAc8D,IAAE,EAAC,WAAU,+BAA8B,MAAKW,IAAE,KAAI,OAAMoB,GAAE,EAAC,GAAEpB,GAAE,GAAE,KAAI,GAAE,KAAI,GAAE,EAAC,CAAC,EAAC,CAAC,CAAC,CAAC;AAAC,CAAC,GAAEuB,KAAEhG,GAAE,KAAK,SAASmE,GAAE;AAAC,MAAIM,IAAEN,EAAE,MAAKC,IAAED,EAAE,UAAS,IAAEA,EAAE,aAAYI,IAAE,EAAC,iBAAgBsB,GAAE,EAAC,GAAEpB,EAAE,GAAE,GAAE,KAAI,GAAE,KAAI,GAAE,EAAC,CAAC,EAAC;AAAE,SAAOzE,GAAE,cAAc,OAAM,EAAC,WAAU,8BAA6B,OAAMuE,EAAC,GAAEvE,GAAE,cAAc+E,IAAE,EAAC,QAAO,SAAS/E,GAAE;AAAC,IAAAoE,EAAE,EAAC,GAAE,MAAIpE,EAAE,MAAK,GAAE,MAAI,MAAIA,EAAE,IAAG,CAAC;AAAA,EAAC,GAAE,OAAM,SAASA,GAAE;AAAC,IAAAoE,EAAE,EAAC,GAAEM,GAAED,EAAE,IAAE,MAAIzE,EAAE,MAAK,GAAE,GAAG,GAAE,GAAE0E,GAAED,EAAE,IAAE,MAAIzE,EAAE,KAAI,GAAE,GAAG,EAAC,CAAC;AAAA,EAAC,GAAE,OAAM,GAAE,cAAa,SAAQ,kBAAiB,gBAAckF,GAAET,EAAE,CAAC,IAAE,mBAAiBS,GAAET,EAAE,CAAC,IAAE,IAAG,GAAEzE,GAAE,cAAc8D,IAAE,EAAC,WAAU,sCAAqC,KAAI,IAAEW,EAAE,IAAE,KAAI,MAAKA,EAAE,IAAE,KAAI,OAAMoB,GAAEpB,CAAC,EAAC,CAAC,CAAC,CAAC;AAAC,CAAC,GAAEwB,KAAE,SAAS,GAAE9B,GAAE;AAAC,MAAG,MAAIA,EAAE,QAAM;AAAG,WAAQ,KAAK,EAAE,KAAG,EAAE,CAAC,MAAIA,EAAE,CAAC,EAAE,QAAM;AAAG;AAAQ,GAAoE+B,KAAE,SAAS,GAAE/B,GAAE;AAAC,SAAO,EAAE,kBAAgBA,EAAE,YAAW,KAAI8B,GAAEb,GAAE,CAAC,GAAEA,GAAEjB,CAAC,CAAC;AAAC;AAAE,SAASgC,GAAE,GAAE1B,GAAEO,GAAEd,GAAE;AAAC,MAAIG,IAAEG,GAAEQ,CAAC,GAAEN,IAAEF,GAAEN,CAAC,GAAES,IAAEL,EAAE,WAAU;AAAC,WAAO,EAAE,OAAOG,CAAC;AAAA,EAAC,CAAC,GAAEG,IAAED,EAAE,CAAC,GAAEE,IAAEF,EAAE,CAAC,GAAEG,IAAEX,EAAE,EAAC,OAAMM,GAAE,MAAKG,EAAC,CAAC,GAAEG,IAAEZ,EAAE,EAAE;AAAEC,EAAAA,EAAE,WAAU;AAAC,QAAG,CAAC,EAAE,MAAMK,GAAEK,EAAE,QAAQ,KAAK,GAAE;AAAC,UAAIX,IAAE,EAAE,OAAOM,CAAC;AAAE,MAAAK,EAAE,UAAQ,EAAC,MAAKX,GAAE,OAAMM,EAAC,GAAEI,EAAEV,CAAC,GAAEY,EAAE,UAAQ;AAAA,IAAE;AAAA,EAAC,GAAE,CAACN,GAAE,CAAC,CAAC,GAAEL,EAAE,WAAU;AAAC,QAAID;AAAE,IAAA8B,GAAErB,GAAEE,EAAE,QAAQ,IAAI,KAAG,EAAE,MAAMX,IAAE,EAAE,SAASS,CAAC,GAAEE,EAAE,QAAQ,KAAK,MAAIA,EAAE,UAAQ,EAAC,MAAKF,GAAE,OAAMT,EAAC,GAAEE,EAAEF,CAAC,GAAEY,EAAE,UAAQ;AAAA,EAAG,GAAE,CAACH,GAAE,GAAEP,CAAC,CAAC;AAAE,MAAIY,IAAEV,EAAE,SAASvE,GAAE;AAAC,IAAA6E,EAAE,SAASV,GAAE;AAAC,aAAO,OAAO,OAAO,IAAGA,GAAEnE,CAAC;AAAA,IAAC,CAAC;AAAA,EAAC,GAAE,CAAA,CAAE,GAAE8D,IAAES,EAAE,WAAU;AAAC,IAAAQ,EAAE,YAAUA,EAAE,UAAQ,IAAGL,EAAEI,EAAE,QAAQ,KAAK;AAAA,EAAE,GAAE,CAACJ,CAAC,CAAC;AAAE,SAAM,CAACE,GAAEK,GAAEnB,CAAC;AAAC;AAAI,IAAGsC,KAAe,OAAO,SAApB,MAA2BpB,KAAEZ,GAAEiC,KAAE,WAAU;AAAC,SAAwB,OAAO,oBAApB,MAAsC,oBAAkB;AAAO,GAAqBC,KAAE,oBAAI,OAAIC,KAAE,SAAS,GAAE;AAAC,EAAAH,GAAE,WAAU;AAAC,QAAIjC,IAAE,EAAE,UAAQ,EAAE,QAAQ,gBAAc;AAAS,QAAYA,MAAT,UAAY,CAACmC,GAAE,IAAInC,CAAC,GAAE;AAAC,UAAI,IAAEA,EAAE,cAAc,OAAO;AAAE,QAAE,YAAU,itDAAktDmC,GAAE,IAAInC,GAAE,CAAC;AAAE,UAAIC,IAAEiC;AAAI,MAAAjC,KAAG,EAAE,aAAa,SAAQA,CAAC,GAAED,EAAE,KAAK,YAAY,CAAC;AAAA,IAAC;AAAA,EAAC,GAAE,CAAA,CAAE;AAAC,GAAEqC,KAAE,SAAS/B,GAAE;AAAC,MAAIL,IAAEK,EAAE,WAAUH,IAAEG,EAAE,YAAWF,IAAEE,EAAE,OAAMO,IAAWT,MAAT,SAAWD,EAAE,eAAaC,GAAEC,IAAEC,EAAE,UAASC,IAAED,EAAE,aAAY,IAAEJ,GAAEI,GAAE,CAAC,aAAY,cAAa,SAAQ,YAAW,aAAa,CAAC,GAAEG,IAAET,EAAE,IAAI;AAAE,EAAAoC,GAAE3B,CAAC;AAAE,MAAIC,IAAEsB,GAAE7B,GAAEU,GAAER,GAAEE,CAAC,GAAEI,IAAED,EAAE,CAAC,GAAEE,IAAEF,EAAE,CAAC,GAAEf,IAAEe,EAAE,CAAC,GAAEK,IAAED,GAAE,CAAC,kBAAiBb,CAAC,CAAC;AAAE,SAAOpE,GAAE,cAAc,OAAMkE,GAAE,IAAG,GAAE,EAAC,KAAIU,GAAE,WAAUM,EAAC,CAAC,GAAElF,GAAE,cAAcgG,IAAE,EAAC,MAAKlB,GAAE,UAASC,GAAE,aAAYjB,EAAC,CAAC,GAAE9D,GAAE,cAAc+F,IAAE,EAAC,KAAIjB,EAAE,GAAE,UAASC,GAAE,aAAYjB,GAAE,WAAU,+BAA8B,CAAC,CAAC;AAAC,GAAE2C,KAAE,EAAC,cAAa,OAAM,QAAOtB,IAAE,UAAS,SAAS,GAAE;AAAC,SAAOK,GAAE,EAAC,GAAE,EAAE,GAAE,GAAE,EAAE,GAAE,GAAE,EAAE,GAAE,GAAE,EAAC,CAAC;AAAC,GAAE,OAAMU,GAAC,GAAEQ,KAAE,SAASvC,GAAE;AAAC,SAAOnE,GAAE,cAAcwG,IAAEtC,GAAE,IAAGC,GAAE,EAAC,YAAWsC,GAAC,CAAC,CAAC;AAAC;AC6BjvS,MAAME,KAAsBC,GAAK,CAAC;AAAA,EAChC,OAAAxH;AAAA,EACA,UAAA6C;AAAA,EACA,gBAAA4E,IAAiB,CAAA;AAAA,EACjB,aAAAC,IAAc,CAAA;AAAA,EACd,MAAA7F;AAAA,EACA,YAAA8F,IAAa;AAAA,EACb,kBAAAC,IAAmB;AAAA,EACnB,QAAQC;AAAA,EACR,cAAcC;AAAA,EACd,UAAAC,IAAW;AACb,MAAgC;AAC9B,QAAM,CAACC,GAAgBC,CAAiB,IAAIC,EAAS,EAAK,GACpD,CAACC,GAAUC,CAAW,IAAIF,EAASlI,CAAK,GACxC,CAACqI,GAAYC,CAAa,IAAIJ,EAASlI,CAAK,GAC5CuI,IAAoBrG,EAAe,CAAC,GACpCsG,IAAmBtG,EAA8B,IAAI,GACrDzB,IAAgByB,EAAgB,EAAK,GAKrCuG,IAAcvG,EAAOW,CAAQ;AACnC,EAAA4F,EAAY,UAAU5F;AAGtB,QAAM6F,IAASb,MAAqB,SAAYA,IAAmBG,GAC7DW,IAAYb,KAA0BG;AAI5C,EAAA7F,EAAU,MAAM;AACd,IAAI,CAAC3B,EAAc,WAAWT,MAAU,kBACtCoI,EAAYpI,CAAK,GACjBsI,EAActI,CAAK;AAAA,EAEvB,GAAG,CAACA,CAAK,CAAC;AAGV,QAAM4I,IAAoB,CAACC,MAAkB;AAE3C,IAAApI,EAAc,UAAU,IAGxB6H,EAAcO,CAAK,GACnBT,EAAYS,CAAK;AAEjB,UAAMC,IAAM,KAAK,IAAA,GACXC,IAAsBD,IAAMP,EAAkB;AAGpD,IAAIQ,KAAuB,MAGzBN,EAAY,QAAQ,EAAE,QAAQ,EAAE,OAAOI,EAAA,GAAS,GAChDN,EAAkB,UAAUO,GAGxBN,EAAiB,YACnB,aAAaA,EAAiB,OAAO,GACrCA,EAAiB,UAAU,UAIzBA,EAAiB,WACnB,aAAaA,EAAiB,OAAO,GAGvCA,EAAiB,UAAU,WAAW,MAAM;AAG1C,MAAAC,EAAY,QAAQ,EAAE,QAAQ,EAAE,OAAOI,EAAA,GAAS,GAChDN,EAAkB,UAAU,KAAK,IAAA,GACjCC,EAAiB,UAAU,MAE3B/H,EAAc,UAAU;AAAA,IAC1B,GAAG,KAAKsI,CAAmB;AAAA,EAE/B,GAGMC,IAAgB9G,EAAOmG,CAAU;AACvC,EAAAW,EAAc,UAAUX,GAGxBjG,EAAU,MAAM;AACd,UAAMnB,IAAkB,MAAM;AAG5B,MAAIuH,EAAiB,YACnB,aAAaA,EAAiB,OAAO,GACrCA,EAAiB,UAAU,MAE3BC,EAAY,QAAQ,EAAE,QAAQ,EAAE,OAAOO,EAAc,QAAA,GAAW,IAGlE,WAAW,MAAM;AACf,QAAAvI,EAAc,UAAU;AAAA,MAC1B,GAAG,EAAE;AAAA,IACP;AAEA,kBAAO,iBAAiB,aAAaQ,CAAe,GACpD,OAAO,iBAAiB,iBAAiBA,CAAe,GAEjD,MAAM;AACX,aAAO,oBAAoB,aAAaA,CAAe,GACvD,OAAO,oBAAoB,iBAAiBA,CAAe;AAAA,IAC7D;AAAA,EACF,GAAG,CAAA,CAAE,GAGLmB,EAAU,MACD,MAAM;AACX,IAAIoG,EAAiB,WACnB,aAAaA,EAAiB,OAAO;AAAA,EAEzC,GACC,CAAA,CAAE;AAEL,QAAMS,IAAuB,CAACrI,MAA2C;AACvE,UAAMsI,IAAQtI,EAAE,OAAO;AACvB,IAAAwH,EAAYc,CAAK;AAGjB,UAAMC,IAAa,uCACbC,KAAWF,EAAM,WAAW,GAAG,IAAIA,IAAQ,IAAIA,CAAK;AAE1D,IAAIC,EAAW,KAAKC,EAAQ,KAE1BX,EAAY,QAAQ,EAAE,QAAQ,EAAE,OAAOW,GAAA,GAAY;AAAA,EAEvD,GAEMC,IAAoB,CAACR,MAAkB;AAC3C,IAAAD,EAAkBC,CAAK;AAAA,EACzB,GAEMS,KAAyB,MAAM;AAEnC,IAAAb,EAAY,QAAQ,EAAE,QAAQ,EAAE,OAAO,cAAA,GAAiB;AAAA,EAC1D,GAEMc,IAAgBvJ,MAAU,eAE1BwJ,KAAgB7B,IACpB,gBAAA/K;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,WAAW,2EAA2E2M,IAAgB,8BAA8B,EAAE;AAAA,MACtI,OAAOA,IAAgB,KAAK,EAAE,iBAAiBvJ,EAAA;AAAA,IAAM;AAAA,EAAA,IAGvD,gBAAArB,EAAC,OAAA,EAAI,WAAU,uEACZ,UAAA;AAAA,IAAAkD,IAAO,gBAAAjF,EAAC,QAAA,EAAK,WAAU,+CAA+C,UAAAiF,EAAA,CAAK,IAAU,gBAAAjF,EAAC,QAAA,EAAK,WAAU,+DAA8D,UAAA,KAAC;AAAA,IACrK,gBAAAA;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,WAAW,2FAA2F2M,IAAgB,8BAA8B,EAAE;AAAA,QACtJ,OAAOA,IAAgB,KAAK,EAAE,iBAAiBvJ,EAAA;AAAA,MAAM;AAAA,IAAA;AAAA,EACvD,GACF,GAGIyJ,KACJ,gBAAA9K,EAAC,OAAA,EAAI,WAAU,iCACZ,UAAA;AAAA,IAAAiJ,KACC,gBAAAjJ;AAAA,MAAC+K;AAAA,MAAA;AAAA,QACC,SAAQ;AAAA,QACR,WAAW,+FAA+FH,IAAgB,qBAAqB,EAAE;AAAA,QACjJ,SAASD;AAAA,QAET,UAAA;AAAA,UAAA,gBAAA1M,EAAC,OAAA,EAAI,WAAU,qDAAA,CAAqD;AAAA,UACpE,gBAAAA,EAAC,QAAA,EAAK,WAAU,6BAA4B,UAAA,cAAA,CAAW;AAAA,QAAA;AAAA,MAAA;AAAA,IAAA;AAAA,IAI3D,gBAAAA,EAAC,OAAA,EAAI,WAAU,gBACb,UAAA,gBAAAA,EAAC+M,IAAA,EAAe,OAAOJ,IAAgB,YAAYlB,GAAY,UAAUO,EAAA,CAAmB,GAC9F;AAAA,IAEA,gBAAAjK,EAAC,OAAA,EAAI,WAAU,oCACb,UAAA;AAAA,MAAA,gBAAA/B,EAAC,SAAA,EAAM,SAAQ,aAAY,WAAU,gEAA+D,UAAA,OAEpG;AAAA,MACA,gBAAAA;AAAA,QAAC;AAAA,QAAA;AAAA,UACC,IAAG;AAAA,UACH,MAAK;AAAA,UACL,WAAU;AAAA,UACV,OAAOuL;AAAA,UACP,UAAUc;AAAA,UACV,aAAY;AAAA,UACZ,WAAW;AAAA,QAAA;AAAA,MAAA;AAAA,IACb,GACF;AAAA,IAECxB,EAAe,SAAS,KACvB,gBAAA9I,EAAC,OAAA,EAAI,WAAU,kCACb,UAAA;AAAA,MAAA,gBAAA/B,EAAC,OAAA,EAAI,WAAU,mDAAkD,UAAA,mBAAe;AAAA,MAChF,gBAAAA,EAAC,SAAI,WAAU,mCACZ,YAAe,IAAI,CAACiM,GAAOrH,MAC1B,gBAAA5E;AAAA,QAAC;AAAA,QAAA;AAAA,UAEC,WAAW,+GAA+GiM,MAAU7I,IAAQ,sBAAsB,uBAAuB;AAAA,UACzL,OAAO,EAAE,iBAAiB6I,EAAA;AAAA,UAC1B,SAAS,MAAMQ,EAAkBR,CAAK;AAAA,UACtC,cAAYA;AAAA,QAAA;AAAA,QAJPrH;AAAA,MAAA,CAMR,EAAA,CACH;AAAA,IAAA,GACF;AAAA,IAGDkG,EAAY,SAAS,KACpB,gBAAA/I,EAAC,OAAA,EAAI,WAAU,kCACb,UAAA;AAAA,MAAA,gBAAA/B,EAAC,OAAA,EAAI,WAAU,mDAAkD,UAAA,gBAAY;AAAA,MAC7E,gBAAAA,EAAC,SAAI,WAAU,mCACZ,YAAY,IAAI,CAACiM,GAAOrH,MACvB,gBAAA5E;AAAA,QAAC;AAAA,QAAA;AAAA,UAEC,WAAW,+GAA+GiM,MAAU7I,IAAQ,sBAAsB,uBAAuB;AAAA,UACzL,OAAO,EAAE,iBAAiB6I,EAAA;AAAA,UAC1B,SAAS,MAAMQ,EAAkBR,CAAK;AAAA,UACtC,cAAYA;AAAA,QAAA;AAAA,QAJP,OAAOrH,CAAK;AAAA,MAAA,CAMpB,EAAA,CACH;AAAA,IAAA,EAAA,CACF;AAAA,EAAA,GAEJ;AAIF,SAAIuG,IACK0B,KAIP,gBAAA9K,EAACL,IAAA,EAAQ,MAAMoK,GAAQ,cAAcC,GACnC,UAAA;AAAA,IAAA,gBAAA/L,EAACa,IAAA,EAAe,SAAO,IACrB,UAAA,gBAAAb;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,WACE+K,IACI,6JACA;AAAA,QAEN,cAAW;AAAA,QAEV,UAAA6B;AAAA,MAAA;AAAA,IAAA,GAEL;AAAA,sBACC7L,IAAA,EAAe,WAAU,aAAY,WAAS,IAC5C,UAAA8L,GAAA,CACH;AAAA,EAAA,GACF;AAEJ,CAAC;AAEDlC,GAAoB,cAAc;ACpRlC,MAAMqC,KAAW,MACf,gBAAAhN;AAAA,EAAC;AAAA,EAAA;AAAA,IACC,OAAM;AAAA,IACN,QAAO;AAAA,IACP,SAAQ;AAAA,IACR,MAAK;AAAA,IACL,QAAO;AAAA,IACP,aAAY;AAAA,IACZ,WAAU;AAAA,IAEV,UAAA,gBAAAA,EAAC,QAAA,EAAK,GAAE,0BAAA,CAA0B;AAAA,EAAA;AACpC;AAGK,SAASiN,GAAW,EAAE,SAAAC,KAAoC;AAC/D,SACE,gBAAAlN,EAACmN,IAAA,EAAgB,eAAe,KAC9B,4BAACC,IAAA,EACC,UAAA;AAAA,IAAA,gBAAApN,EAACqN,IAAA,EAAe,SAAO,IACrB,UAAA,gBAAArN;AAAA,MAAC8M;AAAA,MAAA;AAAA,QACC,SAAQ;AAAA,QACR,SAAAI;AAAA,QACA,WAAU;AAAA,QACV,cAAW;AAAA,QAEX,4BAACF,IAAA,CAAA,CAAS;AAAA,MAAA;AAAA,IAAA,GAEd;AAAA,IACA,gBAAAhN,EAACsN,MAAe,UAAA,OAAA,CAAI;AAAA,EAAA,EAAA,CACtB,EAAA,CACF;AAEJ;ACpBA,MAAMC,KAAU;AA2BT,SAASC,GAAkBC,GAA8D;;AAC9F,MAAI,CAACA;AACH,WAAO;AAAA,MACL,UAAU;AAAA,MACV,SAAS;AAAA,MACT,QAAQ;AAAA,MACR,UAAU;AAAA,MACV,UAAU;AAAA,MACV,WAAW;AAAA,MACX,QAAQ;AAAA,MACR,WAAW;AAAA,MACX,cAAc;AAAA,MACd,aAAa;AAAA,MACb,mBAAmB;AAAA,MACnB,YAAY;AAAA,IAAA;AAIhB,QAAMC,IAAKD,EAAQ,eAKb,EAAE,eAAAE,GAAe,YAAAC,EAAA,IAAeH;AAKtC,SAAO;AAAA,IACL,UAAU,KAAK,IAAIA,EAAQ,YAAY,CAAC,IAAIF;AAAA,IAC5C,UAAUE,EAAQ,WAAW,KAAK,IAAIF;AAAA,IACtC,UAAQ/I,IAAAiJ,EAAQ,WAAR,gBAAAjJ,EAAgB,aAAY;AAAA,IACpC,UAAUiJ,EAAQ,cAAc,cAAcA,EAAQ,cAAc;AAAA,IACpE,YAAUI,IAAAJ,EAAQ,mBAAR,gBAAAI,EAAwB,aAAY;AAAA,IAC9C,WAAW,CAAC,CAACJ,EAAQ,SAASA,EAAQ,MAAM,SAAS;AAAA,IACrD,UAAQK,IAAAL,EAAQ,WAAR,gBAAAK,EAAgB,aAAY;AAAA,IACpC,WAAWC,GAAoBN,EAAQ,SAAS;AAAA,IAChD,gBAAeC,KAAA,gBAAAA,EAAI,iBAAgB,KAAK;AAAA,IACxC,aAAa,CAACM,GAAqBN,KAAA,gBAAAA,EAAI,WAAW;AAAA,IAClD,qBAAoBA,KAAA,gBAAAA,EAAI,gBAAe,KAAK,IAAIH;AAAA,IAChD,YACE,KAAK,IAAII,KAAiB,CAAC,IAAIJ,MAC9BK,MAAe,UAAa,KAAK,IAAIA,IAAa,GAAG,IAAIL;AAAA,EAAA;AAEhE;ACVA,MAAMU,KAA4C,CAAC;AAAA,EACjD,SAAAR;AAAA,EACA,iBAAAS;AAAA,EACA,mBAAAC,IAAoB;AAAA,EACpB,WAAAC;AAAA,EACA,eAAAC;AAAA,EACA,gBAAAC;AAAA,EACA,eAAAC;AAAA,EACA,oBAAAC;AAAA,EACA,oBAAAC,IAAqB;AAAA,EACrB,uBAAAC,IAAwB;AAAA,EACxB,UAAAC;AAAA,EACA,sBAAAC,IAAuB;AAAA,EACvB,sBAAAC;AAAA,EACA,cAAAC,IAAe;AAAA,EACf,cAAAC;AAAA,EACA,gBAAAC,IAAiB;AAAA,EACjB,gBAAAC;AAAA,EACA,kBAAAC,IAAmB;AAAA,EACnB,kBAAAC;AAAA,EACA,iBAAAC,IAAkB;AAAA,EAClB,iBAAAC;AAAA,EACA,gBAAAC,IAAiB;AAAA,EACjB,gBAAAC;AAAA,EACA,gBAAAC,IAAiB;AAAA,EACjB,gBAAAC;AAAA,EACA,mBAAAC,IAAoB;AAAA,EACpB,mBAAAC;AAAA,EACA,kBAAAC,IAAmB;AAAA,EACnB,kBAAAC;AAAA,EACA,yBAAAC,KAA0B;AAAA,EAC1B,yBAAAC;AAAA,EACA,mBAAAC,IAAoB;AAAA,EACpB,mBAAAC;AACF,MAAM;AACJ,QAAM,CAACC,IAAcC,CAAe,IAAI7E,EAAkB,EAAK,GACzD,CAAC8E,IAA4BC,EAA6B,IAAI/E,EAAS,EAAK,GAC5E,CAACgF,GAAyBC,EAA0B,IAAIjF,EAAS,EAAK,GACtE,CAACkF,IAA6BC,EAA8B,IAAInF,EAAS,EAAK,GAC9E,CAACoF,IAAqBC,EAAsB,IAAIrF,EAAS,EAAK,GAC9D,CAACsF,IAAuBC,EAAwB,IAAIvF,EAAS,EAAK,GAClE,CAACwF,IAAyBC,CAA0B,IAAIzF,EAAS,EAAK,GACtE,CAAC0F,GAAwBC,CAAyB,IAAI3F,EAAS,EAAK,GACpE,CAAC4F,GAAuBC,CAAwB,IAAI7F,EAAS,EAAK,GAClE,CAAC8F,IAAuBC,CAAwB,IAAI/F,EAAS,EAAK,GAClE,CAACgG,IAA0BC,EAA2B,IAAIjG,EAAS,EAAK,GACxE,CAACkG,IAAyBC,EAA0B,IAAInG,EAAS,EAAK,GACtE,CAACoG,IAAyBC,EAA0B,IAAIrG,EAAS,EAAK,GACtE,CAACsG,IAA0BC,EAA2B,IAAIvG,EAAS,EAAK,GAGxEwG,KAAarE,EAAQ,YAKrBsE,KAAUvE,GAAkBC,CAAO,GAEnCuE,IAAmB,MAAM;AAE7B,QADArB,GAAuB,EAAI,GACvBmB,IAAY;AAEd,YAAMG,KAAiBxE,EAAQ,MAAA;AAC/B,MAAAwE,GAAe,aAAA,GACf/D,EAAgB+D,EAAc;AAAA,IAChC,OAAO;AAEL,YAAMA,KAAiBxE,EAAQ,MAAA;AAC/B,MAAAwE,GAAe,cAAA,GACf/D,EAAgB+D,EAAc;AAAA,IAChC;AACA,IAAAlD,KAAA,QAAAA;AAAA,EACF,GAEMmD,KAAuB,MAAM;AACjC,UAAMD,KAAiBxE,EAAQ,MAAA;AAC/B,IAAAwE,GAAe,cAAc,iBAAiB,CAACA,GAAe,cAAc,gBAC5E/D,EAAgB+D,EAAc;AAAA,EAChC,GAEME,KAAqB,MAAM;AAC/B,UAAMF,KAAiBxE,EAAQ,MAAA;AAC/B,IAAAwE,GAAe,cAAc,eAAe,CAACA,GAAe,cAAc,cAC1E/D,EAAgB+D,EAAc;AAAA,EAChC;AAEA,SACE,gBAAAlQ,EAAC,OAAA,EAAI,WAAU,oBAEZ,UAAA;AAAA,IAAAwM,KACC,gBAAAvO;AAAA,MAACoS;AAAA,MAAA;AAAA,QACC,MAAK;AAAA,QACL,SAAS,MAAM;AACb,UAAA/B,GAA8B,EAAI,GAClC9B,EAAA;AAAA,QACF;AAAA,QACA,cAAc,MAAM8B,GAA8B,EAAK;AAAA,QACvD,SAAQ;AAAA,QACR,iBAAiBD;AAAA,MAAA;AAAA,IAAA;AAAA,IAQpB5B,KACC,gBAAAxO;AAAA,MAACoS;AAAA,MAAA;AAAA,QACC,MACE3D,IACE,gBAAAzO,EAACG,GAAA,EAAK,MAAK,qBAAoB,WAAU,0CAAyC,IAElF;AAAA,QAGJ,SAAS,MAAM;AACb,UAAAoQ,GAA2B,EAAI,GAC/B/B,EAAA;AAAA,QACF;AAAA,QACA,cAAc,MAAM+B,GAA2B,EAAK;AAAA,QACpD,SAAS9B,IAAqB,cAAc;AAAA,QAC5C,iBAAiB6B;AAAA,QACjB,UAAU7B,KAAsB,CAAChB,EAAQ;AAAA,QACzC,cAAW;AAAA,MAAA;AAAA,IAAA;AAAA,IAOde,KAAsBE,KACrB,gBAAA1O;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,MAAK;AAAA,QACL,eAAY;AAAA,QACZ,WAAU;AAAA,QAET,UAAA0O;AAAA,MAAA;AAAA,IAAA;AAAA,IAKL,gBAAA1O;AAAA,MAACoS;AAAA,MAAA;AAAA,QACC,MAAK;AAAA,QACL,SAASJ;AAAA,QACT,cAAc,MAAMrB,GAAuB,EAAK;AAAA,QAChD,SAASmB,KAAa,mBAAmB;AAAA,QACzC,iBAAiBpB,MAAuB5B;AAAA,QACxC,QAAQgD,MAAchD;AAAA,MAAA;AAAA,IAAA;AAAA,sBAIvBsD,GAAA,EAAc,MAAK,4BAA2B,SAASF,IAAsB,SAAQ,mBAAkB;AAAA,sBAGvGE,GAAA,EAAc,MAAK,0BAAyB,SAASD,IAAoB,SAAQ,iBAAgB;AAAA,IAKjGlD,KACC,gBAAAjP;AAAA,MAACoS;AAAA,MAAA;AAAA,QACC,MAAK;AAAA,QACL,SAAS,MAAM;AACb,UAAAvB,GAAyB,EAAI,GAC7B5B,EAAA;AAAA,QACF;AAAA,QACA,cAAc,MAAM4B,GAAyB,EAAK;AAAA,QAClD,SAAQ;AAAA,QACR,iBAAiBD,MAAyB5B;AAAA,QAC1C,QAAQA,KAAkB+C,GAAQ;AAAA,QAClC,eAAY;AAAA,QACZ,cAAW;AAAA,MAAA;AAAA,IAAA;AAAA,IAKf,gBAAA/R;AAAA,MAACoS;AAAA,MAAA;AAAA,QACC,MAAM,gBAAApS,EAACqS,IAAA,EAAe,MAAM,IAAI,WAAU,gBAAe;AAAA,QACzD,SAAS,MAAM;AACb,UAAAtB,EAA2B,EAAI,GAC/B5B,KAAA,QAAAA;AAAA,QACF;AAAA,QACA,cAAc,MAAM4B,EAA2B,EAAK;AAAA,QACpD,SAAQ;AAAA,QACR,iBAAiBD,MAA2B5B;AAAA,QAC5C,QAAQA,KAAoB6C,GAAQ;AAAA,MAAA;AAAA,IAAA;AAAA,IAItC,gBAAA/R;AAAA,MAACoS;AAAA,MAAA;AAAA,QACC,MAAK;AAAA,QACL,SAAS,MAAM;AACb,UAAAnB,EAA0B,EAAI,GAC9B5B,KAAA,QAAAA;AAAA,QACF;AAAA,QACA,cAAc,MAAM4B,EAA0B,EAAK;AAAA,QACnD,SAAQ;AAAA,QACR,iBAAiBD,KAA0B5B;AAAA,QAC3C,QAAQA,KAAmB2C,GAAQ;AAAA,MAAA;AAAA,IAAA;AAAA,IAIrC,gBAAA/R;AAAA,MAACoS;AAAA,MAAA;AAAA,QACC,MAAK;AAAA,QACL,SAAS,MAAM;AACb,UAAA3B,GAA+B,EAAI,GACnC5B,KAAA,QAAAA;AAAA,QACF;AAAA,QACA,cAAc,MAAM4B,GAA+B,EAAK;AAAA,QACxD,SAAQ;AAAA,QACR,iBAAiBD,MAA+B5B;AAAA,QAChD,QAAQA,KAAwBmD,GAAQ;AAAA,MAAA;AAAA,IAAA;AAAA,IAIzClC,MACC,gBAAA7P;AAAA,MAACoS;AAAA,MAAA;AAAA,QACC,MAAK;AAAA,QACL,SAAS,MAAM;AACb,UAAAX,GAA2B,EAAI,GAC/B5B,GAAA;AAAA,QACF;AAAA,QACA,cAAc,MAAM4B,GAA2B,EAAK;AAAA,QACpD,SAAQ;AAAA,QACR,iBAAiBD,MAA2B5B;AAAA,QAC5C,QAAQA,KAAoBmC,GAAQ;AAAA,MAAA;AAAA,IAAA;AAAA,IAKvChC,KACC,gBAAA/P;AAAA,MAACoS;AAAA,MAAA;AAAA,QACC,MAAK;AAAA,QACL,SAAS,MAAM;AACb,UAAAT,GAA2B,EAAI,GAC/B5B,EAAA;AAAA,QACF;AAAA,QACA,cAAc,MAAM4B,GAA2B,EAAK;AAAA,QACpD,SAAQ;AAAA,QACR,iBAAiBD,MAA2B5B;AAAA,QAC5C,QAAQA,MAA2BiC,GAAQ;AAAA,MAAA;AAAA,IAAA;AAAA,IAK9C9B,KACC,gBAAAjQ;AAAA,MAACoS;AAAA,MAAA;AAAA,QACC,MAAK;AAAA,QACL,SAAS,MAAM;AACb,UAAAP,GAA4B,EAAI,GAChC5B,EAAA;AAAA,QACF;AAAA,QACA,cAAc,MAAM4B,GAA4B,EAAK;AAAA,QACrD,SAAQ;AAAA,QACR,iBAAiBD,MAA4B5B;AAAA,QAC7C,QAAQA,KAAqB+B,GAAQ;AAAA,MAAA;AAAA,IAAA;AAAA,IAKxCxC,KACC,gBAAAvP;AAAA,MAACoS;AAAA,MAAA;AAAA,QACC,MAAK;AAAA,QACL,SAAS,MAAM;AACb,UAAAjB,EAAyB,EAAI,GAC7B5B,EAAA;AAAA,QACF;AAAA,QACA,cAAc,MAAM4B,EAAyB,EAAK;AAAA,QAClD,SAAQ;AAAA,QACR,iBAAiBD,KAAyB5B;AAAA,QAC1C,QAAQA,KAAkByC,GAAQ;AAAA,MAAA;AAAA,IAAA;AAAA,IAKrCtC,KACC,gBAAAzP;AAAA,MAACoS;AAAA,MAAA;AAAA,QACC,MAAK;AAAA,QACL,SAAS,MAAM;AACb,UAAAf,EAAyB,EAAI,GAC7B5B,EAAA;AAAA,QACF;AAAA,QACA,cAAc,MAAM4B,EAAyB,EAAK;AAAA,QAClD,SAAQ;AAAA,QACR,iBAAiBD,MAAyB5B;AAAA,QAC1C,QAAQA,KAAkBuC,GAAQ;AAAA,MAAA;AAAA,IAAA;AAAA,IAKrCpC,MACC,gBAAA3P;AAAA,MAACoS;AAAA,MAAA;AAAA,QACC,MAAK;AAAA,QACL,SAAS,MAAM;AACb,UAAAb,GAA4B,EAAI,GAChC5B,GAAA;AAAA,QACF;AAAA,QACA,cAAc,MAAM4B,GAA4B,EAAK;AAAA,QACrD,SAAQ;AAAA,QACR,iBAAiBD,MAA4B5B;AAAA,QAC7C,QAAQA,KAAqBqC,GAAQ;AAAA,MAAA;AAAA,IAAA;AAAA,KAKvC1D,KAAiBC,KAAkBK,MACnC,gBAAA5M,EAACL,MAAQ,MAAMwO,IAAc,cAAcC,GACzC,UAAA;AAAA,MAAA,gBAAAnQ,EAACa,MAAe,SAAO,IACrB,UAAA,gBAAAb,EAAC,UAAA,EAAO,WAAU,kBAAiB,cAAW,gBAC5C,UAAA,gBAAAA,EAACG,KAAK,MAAK,4BAA2B,WAAU,YAAA,CAAY,GAC9D,GACF;AAAA,MACA,gBAAAH,EAACe,IAAA,EAAe,OAAM,OAAM,WAAU,oBAAmB,WAAS,IAChE,UAAA,gBAAAgB,EAAC,OAAA,EAAI,WAAU,oCACZ,UAAA;AAAA,QAAAsM,KACC,gBAAAtM,EAACqL,IAAA,EAAQ,eAAe,KACtB,UAAA;AAAA,UAAA,gBAAApN,EAACqN,IAAA,EAAe,SAAO,IACrB,UAAA,gBAAArN;AAAA,YAAC8M;AAAA,YAAA;AAAA,cACC,SAAQ;AAAA,cACR,MAAK;AAAA,cACL,SAAS,MAAM;AACb,gBAAAuB,EAAA,GACA8B,EAAgB,EAAK;AAAA,cACvB;AAAA,cACA,cAAW;AAAA,cAEX,UAAA,gBAAAnQ,EAACG,GAAA,EAAK,MAAK,iCAAgC,WAAU,YAAA,CAAY;AAAA,YAAA;AAAA,UAAA,GAErE;AAAA,UACA,gBAAAH,EAACsN,MAAe,UAAA,eAAA,CAAY;AAAA,QAAA,GAC9B;AAAA,QAEDgB,KACC,gBAAAvM,EAACqL,IAAA,EAAQ,eAAe,KACtB,UAAA;AAAA,UAAA,gBAAApN,EAACqN,IAAA,EAAe,SAAO,IACrB,UAAA,gBAAArN;AAAA,YAAC8M;AAAA,YAAA;AAAA,cACC,SAAQ;AAAA,cACR,MAAK;AAAA,cACL,SAAS,MAAM;AACb,gBAAAwB,EAAA,GACA6B,EAAgB,EAAK;AAAA,cACvB;AAAA,cACA,cAAW;AAAA,cAEX,UAAA,gBAAAnQ,EAACG,GAAA,EAAK,MAAK,iCAAgC,WAAU,YAAA,CAAY;AAAA,YAAA;AAAA,UAAA,GAErE;AAAA,UACA,gBAAAH,EAACsN,MAAe,UAAA,gBAAA,CAAa;AAAA,QAAA,GAC/B;AAAA,QAEDqB,KACC,gBAAA5M,EAACqL,IAAA,EAAQ,eAAe,KACtB,UAAA;AAAA,UAAA,gBAAApN,EAACqN,IAAA,EAAe,SAAO,IACrB,UAAA,gBAAArN;AAAA,YAAC8M;AAAA,YAAA;AAAA,cACC,SAAQ;AAAA,cACR,MAAK;AAAA,cACL,SAAS,MAAM;AACb,gBAAAqD,EAAgB,EAAK,GACrBxB,EAAA;AAAA,cACF;AAAA,cACA,cAAW;AAAA,cAEX,4BAACxO,GAAA,EAAK,MAAM2F,GAAM,OAAO,WAAU,YAAA,CAAY;AAAA,YAAA;AAAA,UAAA,GAEnD;AAAA,UACA,gBAAA9F,EAACsN,MAAe,UAAA,SAAA,CAAM;AAAA,QAAA,EAAA,CACxB;AAAA,MAAA,EAAA,CAEJ,EAAA,CACF;AAAA,IAAA,GACF;AAAA,IAIDa,KAAqBC,KACpB,gBAAArM,EAACqL,IAAA,EAAQ,OAAO,KACd,UAAA;AAAA,MAAA,gBAAApN,EAACqN,IAAA,EAAe,SAAO,IACrB,UAAA,gBAAArN,EAAC8M,GAAA,EAAO,SAAQ,SAAQ,MAAK,MAAK,SAASsB,GAAW,UAAA,UAAA,CAEtD,GACF;AAAA,MACA,gBAAApO,EAACsN,MAAe,UAAA,qBAAA,CAAkB;AAAA,IAAA,EAAA,CACpC;AAAA,EAAA,GAEJ;AAEJ,GClcagF,KAAmC;AAAA,EAC9C,EAAE,IAAI,SAAS,MAAM,SAAS,OAAO,UAAA;AAAA,EACrC,EAAE,IAAI,cAAc,MAAM,cAAc,OAAO,UAAA;AAAA,EAC/C,EAAE,IAAI,eAAe,MAAM,eAAe,OAAO,UAAA;AAAA,EACjD,EAAE,IAAI,aAAa,MAAM,aAAa,OAAO,UAAA;AAAA,EAC7C,EAAE,IAAI,SAAS,MAAM,SAAS,OAAO,UAAA;AAAA,EACrC,EAAE,IAAI,UAAU,MAAM,UAAU,OAAO,UAAA;AAAA,EACvC,EAAE,IAAI,QAAQ,MAAM,QAAQ,OAAO,UAAA;AAAA,EACnC,EAAE,IAAI,UAAU,MAAM,UAAU,OAAO,UAAA;AAAA,EACvC,EAAE,IAAI,QAAQ,MAAM,QAAQ,OAAO,UAAA;AAAA,EACnC,EAAE,IAAI,SAAS,MAAM,SAAS,OAAO,UAAA;AACvC,GCoEMC,KAA4C,CAAC;AAAA,EACjD,SAAA9E;AAAA,EACA,iBAAAS;AAAA,EACA,gBAAArD;AAAA,EACA,aAAAC;AAAA,EACA,mBAAAqD,IAAoB;AAAA,EACpB,WAAAC;AAAA,EACA,eAAAC;AAAA,EACA,gBAAAC;AAAA,EACA,uBAAAkE;AAAA,EACA,UAAA7D;AAAA,EACA,kBAAAO,IAAmB;AAAA,EACnB,kBAAAC;AAAA,EACA,sBAAAP,IAAuB;AAAA,EACvB,sBAAAC;AAAA,EACA,sBAAA4D,IAAuB;AAAA,EACvB,sBAAAC;AAAA,EACA,eAAAC,IAAgB;AAAA,EAChB,eAAAC;AAAA,EACA,gBAAAC,IAAiB;AAAA,EACjB,gBAAAC;AAAA,EACA,qBAAAC,IAAsB;AAAA,EACtB,qBAAAC;AAAA,EACA,eAAAC,IAAgB;AAAA,EAChB,eAAAC;AAAA,EACA,gBAAA5D,IAAiB;AAAA,EACjB,gBAAAC;AAAA,EACA,gBAAAC,KAAiB;AAAA,EACjB,gBAAAC;AAAA,EACA,mBAAAC,KAAoB;AAAA,EACpB,mBAAAC;AAAA,EACA,kBAAAC,IAAmB;AAAA,EACnB,kBAAAC;AAAA,EACA,yBAAAC,IAA0B;AAAA,EAC1B,yBAAAC;AAAA,EACA,mBAAAC,IAAoB;AAAA,EACpB,mBAAAC;AACF,MAAM;AACJ,QAAM,CAACC,IAAcC,CAAe,IAAI7E,EAAkB,EAAK,GACzD,CAAC6H,IAA0BC,EAA2B,IAAI9H,EAAkB,EAAK,GACjF,CAACwF,IAAyBC,EAA0B,IAAIzF,EAAkB,EAAK,GAC/E,CAACkF,IAA6BC,EAA8B,IAAInF,EAAkB,EAAK,GACvF,CAAC+H,IAA6BC,EAA8B,IAAIhI,EAAkB,EAAK,GACvF,CAACiI,GAAsBC,CAAuB,IAAIlI,EAAkB,EAAK,GACzE,CAACmI,GAAuBC,CAAwB,IAAIpI,EAAkB,EAAK,GAC3E,CAACqI,GAA4BC,EAA6B,IAAItI,EAAkB,EAAK,GACrF,CAACuI,GAAsBC,EAAuB,IAAIxI,EAAkB,EAAK,GACzE,CAAC4F,IAAuBC,EAAwB,IAAI7F,EAAkB,EAAK,GAC3E,CAAC8F,IAAuBC,EAAwB,IAAI/F,EAAkB,EAAK,GAC3E,CAACgG,IAA0BC,EAA2B,IAAIjG,EAAkB,EAAK,GACjF,CAACkG,IAAyBC,EAA0B,IAAInG,EAAkB,EAAK,GAC/E,CAACoG,IAAyBC,CAA0B,IAAIrG,EAAkB,EAAK,GAC/E,CAACsG,IAA0BC,EAA2B,IAAIvG,EAAkB,EAAK,GAMjFyI,KAAuBC,GAAQ,MAAM1B,GAAgB,IAAI,CAACjK,OAAMA,GAAE,KAAK,GAAG,EAAE,GAC5E4L,KAA0BD,GAAQ,MAClCnJ,KAAkBA,EAAe,SAAS,IAAUA,IACjDkJ,IACN,CAAClJ,GAAgBkJ,EAAoB,CAAC,GAKnChC,KAAUvE,GAAkBC,CAAO,GAEnCyG,KAAwB,CAAClQ,OAAqC;AAClE,UAAMiO,KAAiBxE,EAAQ,MAAA;AAC/B,IAAAwE,GAAe,cAAc,YAAYjO,GAAE,OAAO,OAGlD,OAAOiO,GAAe,cAAc,MACpC/D,EAAgB+D,EAAc;AAAA,EAChC,GAQMkC,KAA6C;AAAA,IACjD,WAAW;AAAA,IACX,QAAQ;AAAA,IACR,SAAS;AAAA,IACT,UAAU;AAAA,IACV,SAAS;AAAA,IACT,MAAM;AAAA,IACN,MAAM;AAAA,EAAA,GAGFC,KAAmB3G,EAAQ,cAAc,WACzC4G,KAAeF,GAAgBC,EAAgB,KAAK;AAE1D,SACE,gBAAArS,EAAC,OAAA,EAAI,WAAU,oBAEZ,UAAA;AAAA,IAAAyQ,KACC,gBAAAxS;AAAA,MAACoS;AAAA,MAAA;AAAA,QACC,MAAMtM,GAAM;AAAA,QACZ,SAAS,MAAM;AACb,UAAAsN,GAA4B,EAAI,GAChCZ,EAAA;AAAA,QACF;AAAA,QACA,cAAc,MAAMY,GAA4B,EAAK;AAAA,QACrD,SAAS,iBAAiBiB,EAAY;AAAA,QACtC,iBAAiBlB;AAAA,MAAA;AAAA,IAAA;AAAA,IAKpBD,IACC,gBAAAnR,EAACqL,IAAA,EAAQ,OAAO,KACd,UAAA;AAAA,MAAA,gBAAApN,EAACqN,IAAA,EAAe,SAAO,IACrB,UAAA,gBAAArN;AAAA,QAAC;AAAA,QAAA;AAAA,UACC,WAAU;AAAA,UACV,SAAS,MAAM;AACb,YAAA8T,GAAwB,EAAI,GAC5BZ,EAAA;AAAA,UACF;AAAA,UACA,cAAc,MAAMY,GAAwB,EAAK;AAAA,UACjD,cAAW;AAAA,UACX,eAAab;AAAA,UAEb,UAAA,gBAAAjT;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,WAAU;AAAA,cACV,OAAO,EAAE,YAAYsU,GAAe7G,EAAQ,cAAc,MAAMA,EAAQ,cAAc,SAAS,EAAA;AAAA,YAAE;AAAA,UAAA;AAAA,QACnG;AAAA,MAAA,GAEJ;AAAA,MACC,CAACoG,KAAwB,CAACZ,KAAiB,gBAAAjT,EAACsN,MAAe,UAAA,aAAA,CAAU;AAAA,IAAA,EAAA,CACxE,IAEA,gBAAAvL,EAACqL,IAAA,EAAQ,OAAO,KACd,UAAA;AAAA,MAAA,gBAAApN,EAACqN,IAAA,EAAe,SAAO,IACrB,UAAA,gBAAArN,EAAC,OAAA,EACC,UAAA,gBAAAA;AAAA,QAAC2K;AAAA,QAAA;AAAA,UACC,OAAO8C,EAAQ,cAAc,aAAa;AAAA,UAC1C,UAAUyG;AAAA,UACV,gBAAgBD;AAAA,UAChB,aAAAnJ;AAAA,UACA,YAAY;AAAA,QAAA;AAAA,MAAA,GAEhB,EAAA,CACF;AAAA,MACA,gBAAA9K,EAACsN,MAAe,UAAA,aAAA,CAAU;AAAA,IAAA,GAC5B;AAAA,IAIDG,EAAQ,cAAc,cAAc,eAAeoB,KAClD,gBAAA7O;AAAA,MAACoS;AAAA,MAAA;AAAA,QACC,MAAK;AAAA,QACL,SAAS,MAAM;AACb,UAAA3B,GAA+B,EAAI,GACnC5B,EAAA;AAAA,QACF;AAAA,QACA,cAAc,MAAM4B,GAA+B,EAAK;AAAA,QACxD,SAAQ;AAAA,QACR,iBAAiBD,MAA+B5B;AAAA,QAChD,QAAQA,KAAwBmD,GAAQ;AAAA,MAAA;AAAA,IAAA;AAAA,IAK3CtE,EAAQ,cAAc,cAAc,aAAamF,KAChD,gBAAA5S;AAAA,MAACoS;AAAA,MAAA;AAAA,QACC,MAAK;AAAA,QACL,SAAS,MAAM;AACb,UAAAoB,EAAwB,EAAI,GAC5BZ,EAAA;AAAA,QACF;AAAA,QACA,cAAc,MAAMY,EAAwB,EAAK;AAAA,QACjD,SAAQ;AAAA,QACR,iBAAiBD,KAAwBZ;AAAA,QACzC,QAAQA;AAAA,MAAA;AAAA,IAAA;AAAA,IAKXlF,EAAQ,cAAc,cAAc,UAAUqF,KAC7C,gBAAA9S;AAAA,MAACoS;AAAA,MAAA;AAAA,QACC,MAAK;AAAA,QACL,SAAS,MAAM;AACb,UAAAsB,EAAyB,EAAI,GAC7BZ,EAAA;AAAA,QACF;AAAA,QACA,cAAc,MAAMY,EAAyB,EAAK;AAAA,QAClD,SAAQ;AAAA,QACR,iBAAiBD,KAAyBZ;AAAA,QAC1C,QAAQA;AAAA,MAAA;AAAA,IAAA;AAAA,IAKXpF,EAAQ,cAAc,cAAc,UAAUuF,KAC7C,gBAAAhT;AAAA,MAACoS;AAAA,MAAA;AAAA,QACC,MAAK;AAAA,QACL,SAAS,MAAM;AACb,UAAAwB,GAA8B,EAAI,GAClCZ,EAAA;AAAA,QACF;AAAA,QACA,cAAc,MAAMY,GAA8B,EAAK;AAAA,QACvD,SAAQ;AAAA,QACR,iBAAiBD,KAA8BZ;AAAA,QAC/C,QAAQA;AAAA,MAAA;AAAA,IAAA;AAAA,IAKXL,KACC,gBAAA1S;AAAA,MAACoS;AAAA,MAAA;AAAA,QACC,MAAK;AAAA,QACL,SAAS,MAAM;AACb,UAAAkB,GAA+B,EAAI,GACnCZ,EAAA;AAAA,QACF;AAAA,QACA,cAAc,MAAMY,GAA+B,EAAK;AAAA,QACxD,SAAQ;AAAA,QACR,iBAAiBD,MAA+BZ;AAAA,QAChD,QAAQA,KAAwBV,GAAQ;AAAA,MAAA;AAAA,IAAA;AAAA,IAK3C5C,KACC,gBAAAnP;AAAA,MAACoS;AAAA,MAAA;AAAA,QACC,MAAM,gBAAApS,EAACqS,IAAA,EAAe,MAAM,IAAI,WAAU,gBAAe;AAAA,QACzD,SAAS,MAAM;AACb,UAAAtB,GAA2B,EAAI,GAC/B5B,EAAA;AAAA,QACF;AAAA,QACA,cAAc,MAAM4B,GAA2B,EAAK;AAAA,QACpD,SAAQ;AAAA,QACR,iBAAiBD,MAA2B5B;AAAA,QAC5C,QAAQA,KAAoB6C,GAAQ;AAAA,MAAA;AAAA,IAAA;AAAA,IAKvClC,KACC,gBAAA7P;AAAA,MAACoS;AAAA,MAAA;AAAA,QACC,MAAK;AAAA,QACL,SAAS,MAAM;AACb,UAAAX,GAA2B,EAAI,GAC/B5B,EAAA;AAAA,QACF;AAAA,QACA,cAAc,MAAM4B,GAA2B,EAAK;AAAA,QACpD,SAAQ;AAAA,QACR,iBAAiBD,MAA2B5B;AAAA,QAC5C,QAAQA,KAAoBmC,GAAQ;AAAA,MAAA;AAAA,IAAA;AAAA,IAKvChC,MACC,gBAAA/P;AAAA,MAACoS;AAAA,MAAA;AAAA,QACC,MAAK;AAAA,QACL,SAAS,MAAM;AACb,UAAAT,EAA2B,EAAI,GAC/B5B,GAAA;AAAA,QACF;AAAA,QACA,cAAc,MAAM4B,EAA2B,EAAK;AAAA,QACpD,SAAQ;AAAA,QACR,iBAAiBD,MAA2B5B;AAAA,QAC5C,QAAQA,KAA2BiC,GAAQ;AAAA,MAAA;AAAA,IAAA;AAAA,IAK9C9B,MACC,gBAAAjQ;AAAA,MAACoS;AAAA,MAAA;AAAA,QACC,MAAK;AAAA,QACL,SAAS,MAAM;AACb,UAAAP,GAA4B,EAAI,GAChC5B,GAAA;AAAA,QACF;AAAA,QACA,cAAc,MAAM4B,GAA4B,EAAK;AAAA,QACrD,SAAQ;AAAA,QACR,iBAAiBD,MAA4B5B;AAAA,QAC7C,QAAQA,KAAqB+B,GAAQ;AAAA,MAAA;AAAA,IAAA;AAAA,IAKxCxC,KACC,gBAAAvP;AAAA,MAACoS;AAAA,MAAA;AAAA,QACC,MAAK;AAAA,QACL,SAAS,MAAM;AACb,UAAAjB,GAAyB,EAAI,GAC7B5B,EAAA;AAAA,QACF;AAAA,QACA,cAAc,MAAM4B,GAAyB,EAAK;AAAA,QAClD,SAAQ;AAAA,QACR,iBAAiBD,MAAyB5B;AAAA,QAC1C,QAAQA,KAAkByC,GAAQ;AAAA,MAAA;AAAA,IAAA;AAAA,IAKrCtC,KACC,gBAAAzP;AAAA,MAACoS;AAAA,MAAA;AAAA,QACC,MAAK;AAAA,QACL,SAAS,MAAM;AACb,UAAAf,GAAyB,EAAI,GAC7B5B,EAAA;AAAA,QACF;AAAA,QACA,cAAc,MAAM4B,GAAyB,EAAK;AAAA,QAClD,SAAQ;AAAA,QACR,iBAAiBD,MAAyB5B;AAAA,QAC1C,QAAQA,MAAkBuC,GAAQ;AAAA,MAAA;AAAA,IAAA;AAAA,IAKrCpC,MACC,gBAAA3P;AAAA,MAACoS;AAAA,MAAA;AAAA,QACC,MAAK;AAAA,QACL,SAAS,MAAM;AACb,UAAAb,GAA4B,EAAI,GAChC5B,GAAA;AAAA,QACF;AAAA,QACA,cAAc,MAAM4B,GAA4B,EAAK;AAAA,QACrD,SAAQ;AAAA,QACR,iBAAiBD,MAA4B5B;AAAA,QAC7C,QAAQA,MAAqBqC,GAAQ;AAAA,MAAA;AAAA,IAAA;AAAA,KAKvC1D,KAAiBC,KAAkBK,MACnC,gBAAA5M,EAACL,MAAQ,MAAMwO,IAAc,cAAcC,GACzC,UAAA;AAAA,MAAA,gBAAAnQ,EAACa,MAAe,SAAO,IACrB,UAAA,gBAAAb,EAAC,UAAA,EAAO,WAAU,kBAAiB,cAAW,gBAC5C,UAAA,gBAAAA,EAACG,KAAK,MAAK,4BAA2B,WAAU,YAAA,CAAY,GAC9D,GACF;AAAA,MACA,gBAAAH,EAACe,IAAA,EAAe,OAAM,OAAM,WAAU,oBAAmB,WAAS,IAChE,UAAA,gBAAAgB,EAAC,OAAA,EAAI,WAAU,oCACZ,UAAA;AAAA,QAAAsM,KACC,gBAAAtM,EAACqL,IAAA,EAAQ,eAAe,KACtB,UAAA;AAAA,UAAA,gBAAApN,EAACqN,IAAA,EAAe,SAAO,IACrB,UAAA,gBAAArN;AAAA,YAAC8M;AAAA,YAAA;AAAA,cACC,SAAQ;AAAA,cACR,MAAK;AAAA,cACL,SAAS,MAAM;AACb,gBAAAuB,EAAA,GACA8B,EAAgB,EAAK;AAAA,cACvB;AAAA,cACA,cAAW;AAAA,cAEX,UAAA,gBAAAnQ,EAACG,GAAA,EAAK,MAAK,iCAAgC,WAAU,YAAA,CAAY;AAAA,YAAA;AAAA,UAAA,GAErE;AAAA,UACA,gBAAAH,EAACsN,MAAe,UAAA,eAAA,CAAY;AAAA,QAAA,GAC9B;AAAA,QAEDgB,KACC,gBAAAvM,EAACqL,IAAA,EAAQ,eAAe,KACtB,UAAA;AAAA,UAAA,gBAAApN,EAACqN,IAAA,EAAe,SAAO,IACrB,UAAA,gBAAArN;AAAA,YAAC8M;AAAA,YAAA;AAAA,cACC,SAAQ;AAAA,cACR,MAAK;AAAA,cACL,SAAS,MAAM;AACb,gBAAAwB,EAAA,GACA6B,EAAgB,EAAK;AAAA,cACvB;AAAA,cACA,cAAW;AAAA,cAEX,UAAA,gBAAAnQ,EAACG,GAAA,EAAK,MAAK,iCAAgC,WAAU,YAAA,CAAY;AAAA,YAAA;AAAA,UAAA,GAErE;AAAA,UACA,gBAAAH,EAACsN,MAAe,UAAA,gBAAA,CAAa;AAAA,QAAA,GAC/B;AAAA,QAEDqB,KACC,gBAAA5M,EAACqL,IAAA,EAAQ,eAAe,KACtB,UAAA;AAAA,UAAA,gBAAApN,EAACqN,IAAA,EAAe,SAAO,IACrB,UAAA,gBAAArN;AAAA,YAAC8M;AAAA,YAAA;AAAA,cACC,SAAQ;AAAA,cACR,MAAK;AAAA,cACL,SAAS,MAAM;AACb,gBAAAqD,EAAgB,EAAK,GACrBxB,EAAA;AAAA,cACF;AAAA,cACA,cAAW;AAAA,cAEX,4BAACxO,GAAA,EAAK,MAAM2F,GAAM,OAAO,WAAU,YAAA,CAAY;AAAA,YAAA;AAAA,UAAA,GAEnD;AAAA,UACA,gBAAA9F,EAACsN,MAAe,UAAA,SAAA,CAAM;AAAA,QAAA,EAAA,CACxB;AAAA,MAAA,EAAA,CAEJ,EAAA,CACF;AAAA,IAAA,GACF;AAAA,IAIDa,KAAqBC,KACpB,gBAAArM,EAACqL,IAAA,EAAQ,OAAO,KACd,UAAA;AAAA,MAAA,gBAAApN,EAACqN,IAAA,EAAe,SAAO,IACrB,UAAA,gBAAArN,EAAC8M,GAAA,EAAO,SAAQ,SAAQ,MAAK,MAAK,SAASsB,GAAW,UAAA,UAAA,CAEtD,GACF;AAAA,MACA,gBAAApO,EAACsN,MAAe,UAAA,qBAAA,CAAkB;AAAA,IAAA,EAAA,CACpC;AAAA,EAAA,GAEJ;AAEJ,GC1eMiH,KAA0C,CAAC,EAAE,SAAA9G,GAAS,iBAAAS,GAAiB,eAAAG,GAAe,gBAAAC,QAAqB;AAC/G,QAAM,CAACkG,GAAiBC,CAAkB,IAAInJ,EAAkB,EAAK,GAC/D,CAACoJ,GAAeC,CAAgB,IAAIrJ,EAAkB,EAAK,GAC3D,CAACsJ,GAAiBC,CAAkB,IAAIvJ,EAAkB,EAAK,GAE/DwJ,IAA0B,CAAC7I,MAAkB;AACjD,UAAMgG,IAAiBxE,EAAQ,MAAA;AAC/B,IAAAwE,EAAe,cAAc,cAAchG,GAC3CiC,EAAgB+D,CAAc,GAC9BwC,EAAmB,EAAK;AAAA,EAC1B,GAEMP,IAAwB,CAACjI,MAAkB;AAC/C,UAAMgG,IAAiBxE,EAAQ,MAAA;AAC/B,IAAAwE,EAAe,cAAc,YAAYhG,GACzCiC,EAAgB+D,CAAc,GAC9B0C,EAAiB,EAAK;AAAA,EACxB,GAEMI,IAA4B,MAAM;AACtC,UAAM9C,IAAiBxE,EAAQ,MAAA;AAC/B,IAAAwE,EAAe,cAAc,gBAAgB,CAACA,EAAe,cAAc,eAC3E/D,EAAgB+D,CAAc;AAAA,EAChC,GAEM+C,IAA0B,MAAM;AACpC,UAAM/C,IAAiBxE,EAAQ,MAAA;AAC/B,IAAAwE,EAAe,cAAc,cAAc,CAACA,EAAe,cAAc,aACzE/D,EAAgB+D,CAAc;AAAA,EAChC,GAEMgD,IAA0B,CAAC7R,MAAkB;AACjD,UAAM6O,IAAiBxE,EAAQ,MAAA;AAC/B,IAAAwE,EAAe,cAAc,cAAc7O,GAC3C8K,EAAgB+D,CAAc;AAAA,EAChC,GAEMiD,IAAczH,EAAQ,cAAc,eAAe,WACnD0H,IAAY1H,EAAQ,cAAc,aAAa,WAC/C2H,IAAgB3H,EAAQ,cAAc,iBAAiB,IACvD4H,IAAc5H,EAAQ,cAAc,eAAe,IACnD6H,IAAc7H,EAAQ,cAAc,eAAe,GACnD8H,IAAW9H,EAAQ,cAAc,QACjC+H,IAAa/H,EAAQ,cAAc,OAAO;AAEhD,SACE,gBAAA1L,EAAC,SAAI,WAAU,uJAAsJ,OAAO,EAAE,QAAQ,0BAEpL,UAAA;AAAA,IAAA,gBAAAA,EAAC,OAAA,EAAI,WAAU,iFACb,UAAA;AAAA,MAAA,gBAAA/B,EAAC,QAAA,EAAK,WAAU,oBAAmB,UAAA,QAAI;AAAA,MACvC,gBAAA+B,EAAC,QAAA,EAAK,WAAU,qCACb,UAAA;AAAA,QAAAyT;AAAA,QAAW;AAAA,QAAEA,MAAe,IAAI,UAAU;AAAA,QAC1CD,KAAY;AAAA,MAAA,EAAA,CACf;AAAA,IAAA,GACF;AAAA,IAGA,gBAAAxT,EAACqL,IAAA,EAAQ,OAAO,KACd,UAAA;AAAA,MAAA,gBAAApN,EAACqN,IAAA,EAAe,SAAO,IACrB,UAAA,gBAAArN;AAAA,QAAC8M;AAAA,QAAA;AAAA,UACC,SAASsI,IAAgB,YAAY;AAAA,UACrC,SAASL;AAAA,UACT,WAAU;AAAA,UACX,UAAA;AAAA,QAAA;AAAA,MAAA,GAGH;AAAA,MACA,gBAAA/U,EAACsN,IAAA,EAAgB,UAAA8H,IAAgB,mBAAmB,gBAAA,CAAgB;AAAA,IAAA,GACtE;AAAA,IAGCA,KACC,gBAAArT,EAACL,IAAA,EAAQ,MAAM8S,GAAiB,cAAcC,GAC5C,UAAA;AAAA,MAAA,gBAAAzU,EAACa,IAAA,EAAe,SAAO,IACrB,UAAA,gBAAAb;AAAA,QAAC;AAAA,QAAA;AAAA,UACC,WAAU;AAAA,UACV,OAAO,EAAE,YAAYkV,EAAA;AAAA,UACrB,OAAM;AAAA,QAAA;AAAA,MAAA,GAEV;AAAA,MACA,gBAAAlV,EAACe,MAAe,OAAM,SAAQ,WAAU,UACtC,UAAA,gBAAAgB,EAAC,OAAA,EAAI,WAAU,uEACb,UAAA;AAAA,QAAA,gBAAA/B,EAAC,SAAI,WAAU,6CACZ,UAAAsS,GAAgB,IAAI,CAACrG,MACpB,gBAAAjM;AAAA,UAAC8M;AAAA,UAAA;AAAA,YAEC,SAAS,MAAMgI,EAAwB7I,EAAM,KAAK;AAAA,YAClD,cAAYA,EAAM;AAAA,YAClB,WAAW,gGACTiJ,MAAgBjJ,EAAM,QAClB,sDACA,uDACN;AAAA,YACA,OAAO,EAAE,YAAYA,EAAM,MAAA;AAAA,UAAM;AAAA,UAR5BA,EAAM;AAAA,QAAA,CAUd,GACH;AAAA,QACA,gBAAAjM;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,MAAK;AAAA,YACL,OAAOkV;AAAA,YACP,UAAU,CAAClR,MAAM8Q,EAAwB9Q,EAAE,OAAO,KAAK;AAAA,YACvD,WAAU;AAAA,UAAA;AAAA,QAAA;AAAA,MACZ,EAAA,CACF,EAAA,CACF;AAAA,IAAA,GACF;AAAA,IAIDoR,KACC,gBAAArT,EAACL,IAAA,EAAQ,MAAMkT,GAAiB,cAAcC,GAC5C,UAAA;AAAA,MAAA,gBAAA7U,EAACa,IAAA,EAAe,SAAO,IACrB,UAAA,gBAAAkB,EAAC+K,KAAO,SAAQ,SAAQ,WAAU,yBAC/B,UAAA;AAAA,QAAAwI;AAAA,QAAY;AAAA,MAAA,EAAA,CACf,EAAA,CACF;AAAA,MACA,gBAAAtV,EAACe,MAAe,OAAM,SAAQ,WAAU,UACtC,UAAA,gBAAAf,EAAC,OAAA,EAAI,WAAU,uEACb,UAAA,gBAAA+B;AAAA,QAAC8C;AAAA,QAAA;AAAA,UACC,OAAO,CAACyQ,CAAW;AAAA,UACnB,eAAe,CAAChP,MAAQ2O,EAAwB3O,EAAI,CAAC,CAAC;AAAA,UACtD,KAAK;AAAA,UACL,KAAK;AAAA,UACL,MAAM;AAAA,UACN,WAAU;AAAA,UAEV,UAAA;AAAA,YAAA,gBAAAtG,EAACyV,MAAM,UAAA,aAAA,CAAU;AAAA,YACjB,gBAAAzV,EAAC6E,GAAO,QAAP,EAAc;AAAA,YACf,gBAAA7E,EAAC6E,GAAO,OAAP,EAAa;AAAA,YACd,gBAAA7E,EAAC6E,GAAO,OAAP,CAAA,CAAa;AAAA,UAAA;AAAA,QAAA;AAAA,MAAA,GAElB,EAAA,CACF;AAAA,IAAA,GACF;AAAA,IAGF,gBAAA7E,EAAC,OAAA,EAAI,WAAU,+CAAA,CAA+C;AAAA,IAG9D,gBAAA+B,EAACqL,IAAA,EAAQ,OAAO,KACd,UAAA;AAAA,MAAA,gBAAApN,EAACqN,IAAA,EAAe,SAAO,IACrB,UAAA,gBAAArN;AAAA,QAAC8M;AAAA,QAAA;AAAA,UACC,SAASuI,IAAc,YAAY;AAAA,UACnC,SAASL;AAAA,UACT,WAAU;AAAA,UACX,UAAA;AAAA,QAAA;AAAA,MAAA,GAGH;AAAA,MACA,gBAAAhV,EAACsN,IAAA,EAAgB,UAAA+H,IAAc,iBAAiB,cAAA,CAAc;AAAA,IAAA,GAChE;AAAA,IAGCA,KACC,gBAAAtT,EAACL,IAAA,EAAQ,MAAMgT,GAAe,cAAcC,GAC1C,UAAA;AAAA,MAAA,gBAAA3U,EAACa,IAAA,EAAe,SAAO,IACrB,UAAA,gBAAAb;AAAA,QAAC;AAAA,QAAA;AAAA,UACC,WAAU;AAAA,UACV,OAAO,EAAE,YAAYmV,EAAA;AAAA,UACrB,OAAM;AAAA,QAAA;AAAA,MAAA,GAEV;AAAA,MACA,gBAAAnV,EAACe,MAAe,OAAM,SAAQ,WAAU,UACtC,UAAA,gBAAAgB,EAAC,OAAA,EAAI,WAAU,uEACb,UAAA;AAAA,QAAA,gBAAA/B,EAAC,SAAI,WAAU,6CACZ,UAAAsS,GAAgB,IAAI,CAACrG,MACpB,gBAAAjM;AAAA,UAAC8M;AAAA,UAAA;AAAA,YAEC,SAAS,MAAMoH,EAAsBjI,EAAM,KAAK;AAAA,YAChD,cAAYA,EAAM;AAAA,YAClB,WAAW,gGACTkJ,MAAclJ,EAAM,QAChB,sDACA,uDACN;AAAA,YACA,OAAO,EAAE,YAAYA,EAAM,MAAA;AAAA,UAAM;AAAA,UAR5BA,EAAM;AAAA,QAAA,CAUd,GACH;AAAA,QACA,gBAAAjM;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,MAAK;AAAA,YACL,OAAOmV;AAAA,YACP,UAAU,CAACnR,MAAMkQ,EAAsBlQ,EAAE,OAAO,KAAK;AAAA,YACrD,WAAU;AAAA,UAAA;AAAA,QAAA;AAAA,MACZ,EAAA,CACF,EAAA,CACF;AAAA,IAAA,GACF;AAAA,IAGF,gBAAAhE,EAAC,OAAA,EAAI,WAAU,+CAAA,CAA+C;AAAA,IAG7DqO,KACC,gBAAAtM,EAACqL,IAAA,EAAQ,OAAO,KACd,UAAA;AAAA,MAAA,gBAAApN,EAACqN,MAAe,SAAO,IACrB,UAAA,gBAAArN,EAAC8M,GAAA,EAAO,SAAQ,SAAQ,SAASuB,GAC/B,UAAA,gBAAArO,EAACG,KAAK,MAAK,iCAAgC,WAAU,iBAAA,CAAiB,GACxE,GACF;AAAA,MACA,gBAAAH,EAACsN,MAAe,UAAA,eAAA,CAAY;AAAA,IAAA,GAC9B;AAAA,IAGDgB,KACC,gBAAAvM,EAACqL,IAAA,EAAQ,OAAO,KACd,UAAA;AAAA,MAAA,gBAAApN,EAACqN,MAAe,SAAO,IACrB,UAAA,gBAAArN,EAAC8M,GAAA,EAAO,SAAQ,SAAQ,SAASwB,GAC/B,UAAA,gBAAAtO,EAACG,KAAK,MAAK,iCAAgC,WAAU,iBAAA,CAAiB,GACxE,GACF;AAAA,MACA,gBAAAH,EAACsN,MAAe,UAAA,gBAAA,CAAa;AAAA,IAAA,EAAA,CAC/B;AAAA,EAAA,GAEJ;AAEJ,GCnNMoI,KAA2B9K,GAAK,CAAC;AAAA,EACrC,gBAAA+K;AAAA,EACA,iBAAAC;AAAA,EACA,mBAAAC;AAAA,EACA,wBAAAC;AAAA,EACA,eAAAC;AAAA,EACA,iBAAAC;AACF,MAAqC;AACnC,QAAM,CAAClK,GAAQC,CAAS,IAAIT,EAAS,EAAK,GACpC,CAAC2K,GAAWC,CAAY,IAAI5K,EAAwB,OAAO,GAC3D,CAACC,GAAUC,CAAW,IAAIF,EAASsK,CAAe;AAGxD,EAAApQ,EAAU,MAAM;AACd,IACE0Q,EADEP,MAAmB,YACR,YAEA,OAFS;AAAA,EAI1B,GAAG,CAACA,CAAc,CAAC,GAGnBnQ,EAAU,MAAM;AACd,IAAIoQ,MAAoB,iBACtBpK,EAAYoK,CAAe;AAAA,EAE/B,GAAG,CAACA,CAAe,CAAC;AAEpB,QAAM5J,IAAoB,CAACC,MAAkB;AAC3C,IAAAT,EAAYS,CAAK,GACjB8J,EAAc9J,CAAK,GACnB6J,EAAuB,OAAO;AAAA,EAChC,GAEMzJ,IAAuB,CAACrI,MAA2C;AACvE,UAAMsI,IAAQtI,EAAE,OAAO;AACvB,IAAAwH,EAAYc,CAAK;AAGjB,UAAMC,IAAa,uCACbC,IAAWF,EAAM,WAAW,GAAG,IAAIA,IAAQ,IAAIA,CAAK;AAE1D,IAAIC,EAAW,KAAKC,CAAQ,MAC1BuJ,EAAcvJ,CAAQ,GACtBsJ,EAAuB,OAAO;AAAA,EAElC,GAEMpJ,IAAyB,MAAM;AACnC,IAAAqJ,EAAc,aAAa,GAC3BD,EAAuB,aAAa;AAAA,EACtC,GAEMK,IAAqB,CAACC,MAAsB;AAChD,IAAAJ,EAAgBI,CAAS,GACzBN,EAAuB,SAAS;AAAA,EAClC,GAEMO,IAAkB,CAACC,MAAuB;AAE9C,QADAJ,EAAaI,CAAG,GACZA,MAAQ;AACV,MAAAR,EAAuBF,MAAoB,gBAAgB,gBAAgB,OAAO;AAAA,aACzEU,MAAQ,WAAW;AAC5B,UAAI,CAACT,GAAmB;AAEtB,cAAMU,IAAiBC,GAAe,eAAA,EAAiB,CAAC;AACxD,QAAID,KACFP,EAAgBO,EAAe,EAAE;AAAA,MAErC;AACA,MAAAT,EAAuB,SAAS;AAAA,IAClC;AAAA,EACF,GAEMnJ,IAAgBiJ,MAAoB;AAE1C,SACE,gBAAA7T,EAACL,IAAA,EAAQ,MAAMoK,GAAQ,cAAcC,GACnC,UAAA;AAAA,IAAA,gBAAA/L,EAACa,MAAe,SAAO,IACrB,4BAACiM,GAAA,EAAO,SAAShB,IAAS,YAAY,SAAS,cAAW,cACxD,UAAA,gBAAA9L,EAACG,KAAK,MAAM2F,GAAM,SAAS,WAAU,kBAAiB,GACxD,EAAA,CACF;AAAA,sBACC/E,IAAA,EAAe,WAAU,oBACxB,UAAA,gBAAAgB,EAAC,OAAA,EAAI,WAAU,iDAEb,UAAA;AAAA,MAAA,gBAAAA,EAAC,OAAA,EAAI,WAAU,0DACb,UAAA;AAAA,QAAA,gBAAA/B;AAAA,UAAC8M;AAAA,UAAA;AAAA,YACC,SAAQ;AAAA,YACR,MAAK;AAAA,YACL,WAAW,aAAamJ,MAAc,UAAU,6CAA6C,EAAE;AAAA,YAC/F,SAAS,MAAMI,EAAgB,OAAO;AAAA,YACvC,UAAA;AAAA,UAAA;AAAA,QAAA;AAAA,QAGD,gBAAArW;AAAA,UAAC8M;AAAA,UAAA;AAAA,YACC,SAAQ;AAAA,YACR,MAAK;AAAA,YACL,WAAW,aAAamJ,MAAc,YAAY,6CAA6C,EAAE;AAAA,YACjG,SAAS,MAAMI,EAAgB,SAAS;AAAA,YACzC,UAAA;AAAA,UAAA;AAAA,QAAA;AAAA,QAGD,gBAAArW;AAAA,UAAC8M;AAAA,UAAA;AAAA,YACC,SAAQ;AAAA,YACR,MAAK;AAAA,YACL,WAAU;AAAA,YACV,UAAQ;AAAA,YACR,cAAW;AAAA,YACZ,UAAA;AAAA,UAAA;AAAA,QAAA;AAAA,MAED,GACF;AAAA,MAGCmJ,MAAc,WACb,gBAAAlU,EAAC,OAAA,EAAI,WAAU,gCACb,UAAA;AAAA,QAAA,gBAAAA;AAAA,UAAC+K;AAAA,UAAA;AAAA,YACC,SAAQ;AAAA,YACR,WAAW,+FAA+FH,IAAgB,qBAAqB,EAAE;AAAA,YACjJ,SAASD;AAAA,YAET,UAAA;AAAA,cAAA,gBAAA1M,EAAC,OAAA,EAAI,WAAU,qDAAA,CAAqD;AAAA,cACpE,gBAAAA,EAAC,QAAA,EAAK,WAAU,6BAA4B,UAAA,cAAA,CAAW;AAAA,YAAA;AAAA,UAAA;AAAA,QAAA;AAAA,0BAGxD+M,IAAA,EAAe,OAAOJ,IAAgB,YAAYiJ,GAAiB,UAAU5J,GAAmB;AAAA,QAEjG,gBAAAjK,EAAC,OAAA,EAAI,WAAU,oCACb,UAAA;AAAA,UAAA,gBAAA/B,EAAC,SAAA,EAAM,SAAQ,gBAAe,WAAU,gEAA+D,UAAA,OAEvG;AAAA,UACA,gBAAAA;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,IAAG;AAAA,cACH,MAAK;AAAA,cACL,WAAU;AAAA,cACV,OAAOuL;AAAA,cACP,UAAUc;AAAA,cACV,aAAY;AAAA,cACZ,WAAW;AAAA,YAAA;AAAA,UAAA;AAAA,QACb,EAAA,CACF;AAAA,MAAA,GACF;AAAA,MAID4J,MAAc,aACb,gBAAAlU,EAAC,OAAA,EAAI,WAAU,gCACb,UAAA;AAAA,QAAA,gBAAA/B,EAAC,OAAA,EAAI,WAAU,mDAAkD,UAAA,oBAAgB;AAAA,QACjF,gBAAAA,EAAC,SAAI,WAAU,qCACZ,aAAe,eAAA,EAAiB,IAAI,CAACyW,MACpC,gBAAAzW;AAAA,UAAC;AAAA,UAAA;AAAA,YAEC,WAAW,kHACT6V,MAAsBY,EAAQ,KAC1B,sBACA,kDACN;AAAA,YACA,SAAS,MAAMN,EAAmBM,EAAQ,EAAE;AAAA,YAC5C,cAAYA,EAAQ;AAAA,YAEpB,UAAA,gBAAAzW,EAAC,SAAI,KAAKyW,EAAQ,KAAK,KAAKA,EAAQ,MAAM,WAAU,iCAAA,CAAiC;AAAA,UAAA;AAAA,UAThFA,EAAQ;AAAA,QAAA,CAWhB,EAAA,CACH;AAAA,MAAA,GACF;AAAA,MAIDR,MAAc,cACb,gBAAAlU,EAAC,OAAA,EAAI,WAAU,gGACb,UAAA;AAAA,QAAA,gBAAA/B,EAAC,OAAA,EAAI,WAAU,cAAa,UAAA,wBAAoB;AAAA,QAChD,gBAAAA,EAAC,OAAA,EAAI,WAAU,cAAa,UAAA,cAAA,CAAW;AAAA,MAAA,EAAA,CACzC;AAAA,IAAA,EAAA,CAEJ,EAAA,CACF;AAAA,EAAA,GACF;AAEJ,CAAC;AAED0V,GAAyB,cAAc;ACjLvC,MAAMgB,KAAwB,CAAC,EAAE,iBAAAC,GAAiB,UAAA1Q,QAA2C;AAC3F,EAAA2Q,GAAA;AAEA,QAAMC,KAAUF,KAAA,gBAAAA,EAAiB,YAAW,IACtCG,KAAaH,KAAA,gBAAAA,EAAiB,eAAc,IAC5CI,KAAYJ,KAAA,gBAAAA,EAAiB,cAAa,IAE1CK,IAA4BC,GAAyB,IAAI,CAACnP,OAAO,EAAE,IAAIA,EAAE,YAAY,MAAMA,EAAE,MAAM,cAAcA,EAAE,eAAe,GAElIoP,IAAsB,CAACC,MAAwB;AACnD,QAAIA,GAAY;AACd,YAAMC,IAAMN,KAAcG,GAAyB,CAAC,EAAE;AACtD,MAAAI,GAAeD,CAAG,GAClBnR,EAAS;AAAA,QACP,SAAS;AAAA,QACT,YAAYmR;AAAA,QACZ,WAAAL;AAAA,MAAA,CACD;AAAA,IACH;AACE,MAAA9Q,EAAS,MAAS;AAAA,EAEtB,GAEMqR,IAAsBrQ;AAAA,IAC1B,CAACsQ,MAAe;AACd,MAAAF,GAAeE,CAAE,GACjBtR,EAAS;AAAA,QACP,SAAS;AAAA,QACT,YAAYsR;AAAA,QACZ,WAAAR;AAAA,MAAA,CACD;AAAA,IACH;AAAA,IACA,CAAC9Q,GAAU8Q,CAAS;AAAA,EAAA,GAGhBS,IAAwB,CAACpU,MAAoB;AACjD,IAAKuT,KACL1Q,EAAS;AAAA,MACP,GAAG0Q;AAAA,MACH,WAAWvT,EAAM,CAAC;AAAA,IAAA,CACnB;AAAA,EACH;AAEA,2BACG5C,IAAA,EAAW,MAAMqW,GAAS,cAAcK,GAAqB,WAAU,YACtE,UAAA;AAAA,IAAA,gBAAAlX,EAACS,MAAkB,WAAU,aAC3B,UAAA,gBAAAsB,EAAC,OAAA,EAAI,WAAU,wDACb,UAAA;AAAA,MAAA,gBAAA/B,EAACyV,MAAM,UAAA,mBAAA,CAAgB;AAAA,MACvB,gBAAAzV;AAAA,QAAC8E;AAAA,QAAA;AAAA,UACC,SAAS+R;AAAA,UACT,iBAAiBK;AAAA,UACjB,SAAS,CAAClT,MAAwBA,EAAE,gBAAA;AAAA,QAAgB;AAAA,MAAA;AAAA,IACtD,EAAA,CACF,EAAA,CACF;AAAA,IACA,gBAAAjC,EAACrB,IAAA,EAAkB,WAAU,0CAC3B,UAAA;AAAA,MAAA,gBAAAV;AAAA,QAACyG;AAAA,QAAA;AAAA,UACC,SAASuQ;AAAA,UACT,YAAYF;AAAA,UACZ,UAAUQ;AAAA,UACV,SAAS;AAAA,UACT,WAAU;AAAA,QAAA;AAAA,MAAA;AAAA,MAIZ,gBAAAtX;AAAA,QAACgG;AAAA,QAAA;AAAA,UACC,OAAM;AAAA,UACN,OAAO+Q;AAAA,UACP,UAAU,CAACnO,MAAM4O,EAAsB,CAAC5O,CAAC,CAAC;AAAA,UAC1C,KAAK;AAAA,UACL,KAAK;AAAA,UACL,MAAM;AAAA,UACN,MAAK;AAAA,QAAA;AAAA,MAAA;AAAA,IACP,EAAA,CACF;AAAA,EAAA,GACF;AAEJ,GC7EM6O,KAAyB,CAAC,EAAE,WAAAC,GAAW,UAAAzR,QAA4C;AACvF,EAAA0R,GAAA;AAEA,QAAMd,KAAUa,KAAA,gBAAAA,EAAW,YAAW,IAChCE,KAAWF,KAAA,gBAAAA,EAAW,aAAY,IAClCG,KAAWH,KAAA,gBAAAA,EAAW,aAAY,QAClCI,KAAUJ,KAAA,gBAAAA,EAAW,YAAW,KAChCK,KAAWL,KAAA,gBAAAA,EAAW,aAAY,IAElCV,IAA4BgB,GAAmB,IAAI,CAAClQ,OAAO,EAAE,IAAIA,EAAE,UAAU,MAAMA,EAAE,MAAM,cAAcA,EAAE,eAAe,GAE1HoP,IAAsB,CAACC,MAAwB;AACnD,QAAIA,GAAY;AACd,YAAMC,IAAMQ,KAAYI,GAAmB,CAAC,EAAE;AAC9C,MAAA/R,EAAS;AAAA,QACP,SAAS;AAAA,QACT,UAAUmR;AAAA,QACV,UAAAS;AAAA,QACA,SAAAC;AAAA,QACA,UAAAC;AAAA,MAAA,CACD;AAAA,IACH;AACE,MAAA9R,EAAS,MAAS;AAAA,EAEtB,GAEMgS,IAAoBhR;AAAA,IACxB,CAACsQ,MAAe;AACd,MAAAtR,EAAS;AAAA,QACP,SAAS;AAAA,QACT,UAAUsR;AAAA,QACV,UAAAM;AAAA,QACA,SAAAC;AAAA,QACA,UAAAC;AAAA,MAAA,CACD;AAAA,IACH;AAAA,IACA,CAAC9R,GAAU4R,GAAUC,GAASC,CAAQ;AAAA,EAAA,GAGlCG,IAAuB,CAACC,MAAoC;AAChE,IAAKT,KACLzR,EAAS,EAAE,GAAGyR,GAAW,UAAUS,GAAM;AAAA,EAC3C,GAEMC,IAAsB,CAAChV,MAAoB;AAC/C,IAAKsU,KACLzR,EAAS,EAAE,GAAGyR,GAAW,SAAStU,EAAM,CAAC,GAAG;AAAA,EAC9C,GAEMiV,IAAuB,CAAC5Y,MAAqB;AACjD,IAAKiY,KACLzR,EAAS,EAAE,GAAGyR,GAAW,UAAUjY,GAAS;AAAA,EAC9C;AAEA,2BACGe,IAAA,EAAW,MAAMqW,GAAS,cAAcK,GAAqB,WAAU,YACtE,UAAA;AAAA,IAAA,gBAAAlX,EAACS,MAAkB,WAAU,aAC3B,UAAA,gBAAAsB,EAAC,OAAA,EAAI,WAAU,wDACb,UAAA;AAAA,MAAA,gBAAA/B,EAACyV,MAAM,UAAA,aAAA,CAAU;AAAA,MACjB,gBAAAzV;AAAA,QAAC8E;AAAA,QAAA;AAAA,UACC,SAAS+R;AAAA,UACT,iBAAiBK;AAAA,UACjB,SAAS,CAAClT,MAAwBA,EAAE,gBAAA;AAAA,QAAgB;AAAA,MAAA;AAAA,IACtD,EAAA,CACF,EAAA,CACF;AAAA,IACA,gBAAAjC,EAACrB,IAAA,EAAkB,WAAU,0CAC3B,UAAA;AAAA,MAAA,gBAAAV;AAAA,QAACyG;AAAA,QAAA;AAAA,UACC,SAASuQ;AAAA,UACT,YAAYY;AAAA,UACZ,UAAUK;AAAA,UACV,SAAS;AAAA,UACT,WAAU;AAAA,QAAA;AAAA,MAAA;AAAA,MAIZ,gBAAAlW,EAAC,OAAA,EAAI,WAAU,oCACb,UAAA;AAAA,QAAA,gBAAA/B,EAACyV,IAAA,EAAM,WAAU,cAAa,UAAA,QAAI;AAAA,QAClC,gBAAAzV,EAAC,OAAA,EAAI,WAAU,wEACX,UAAA,CAAC,QAAQ,SAAS,MAAM,EAAY,IAAI,CAACmY,MACzC,gBAAAnY;AAAA,UAAC;AAAA,UAAA;AAAA,YAEC,WAAW,iEACT6X,MAAaM,IACT,6CACA,sCACN;AAAA,YACA,SAAS,MAAMD,EAAqBC,CAAI;AAAA,YAEvC,UAAAA;AAAA,UAAA;AAAA,UARIA;AAAA,QAAA,CAUR,EAAA,CACH;AAAA,MAAA,GACF;AAAA,MAGA,gBAAAnY;AAAA,QAACgG;AAAA,QAAA;AAAA,UACC,OAAM;AAAA,UACN,OAAO8R;AAAA,UACP,UAAU,CAAClP,MAAMwP,EAAoB,CAACxP,CAAC,CAAC;AAAA,UACxC,KAAK;AAAA,UACL,KAAK;AAAA,UACL,MAAM;AAAA,UACN,MAAK;AAAA,QAAA;AAAA,MAAA;AAAA,MAIP,gBAAA7G,EAAC,SAAA,EAAM,WAAU,kEACf,UAAA;AAAA,QAAA,gBAAA/B,EAACV,IAAA,EAAS,SAASyY,GAAU,iBAAiB,CAACnP,MAAMyP,EAAqBzP,MAAM,EAAI,EAAA,CAAG;AAAA,QAAE;AAAA,MAAA,EAAA,CAE3F;AAAA,IAAA,EAAA,CACF;AAAA,EAAA,GACF;AAEJ,GC/GM0P,KAAsE,CAAC;AAAA,EAC3E,UAAAC;AAAA,EACA,WAAAC;AAAA,EACA,kBAAAC;AAAA,EACA,kBAAAC;AAAA,EACA,kBAAAC;AAAA,EACA,sBAAAC;AACF,MAAM;AACJ,QAAM,CAACC,GAAWC,CAAY,IAAIxN,EAAS,EAAK,GAC1C,CAACyN,GAAaC,CAAc,IAAI1N,EAAS,EAAE,GAC3C,CAAC4E,GAAcC,CAAe,IAAI7E,EAAS,EAAK,GAChD2N,IAAW3T,EAAyB,IAAI,GAExC4T,IAA6B,CAACf,MAAiC;AACnE,UAAMgB,IAAkBZ,EAAS,MAAA;AACjC,IAAAY,EAAgB,iBAAiBhB,GACjCM,EAAiBU,CAAe;AAAA,EAClC,GAEMnN,IAAoB,CAACC,MAAkB;AAC3C,UAAMkN,IAAkBZ,EAAS,MAAA;AACjC,IAAAY,EAAgB,kBAAkBlN,GAClCwM,EAAiBU,CAAe;AAAA,EAClC,GAEMC,IAAsB,CAAChD,MAAsB;AACjD,UAAM+C,IAAkBZ,EAAS,MAAA;AACjC,IAAAY,EAAgB,oBAAoB/C,GACpCqC,EAAiBU,CAAe;AAAA,EAClC,GAEME,IAA+B,CAAC5Z,MAAqB;AACzD,UAAM0Z,IAAkBZ,EAAS,MAAA;AACjC,IAAAY,EAAgB,mBAAmB1Z,GACnCgZ,EAAiBU,CAAe;AAAA,EAClC,GAEMG,IAA8B,CAAC3C,MAAyD;AAC5F,UAAMwC,IAAkBZ,EAAS,MAAA;AACjC,IAAAY,EAAgB,kBAAkBxC,GAClC8B,EAAiBU,CAAe;AAAA,EAClC,GAEMI,IAAwB,CAAC7B,MAA6C;AAC1E,UAAMyB,IAAkBZ,EAAS,MAAA;AACjC,IAAAY,EAAgB,YAAYzB,GAC5Be,EAAiBU,CAAe;AAAA,EAClC,GAEMK,IAAkB,MAAM;AAC5B,IAAAV,EAAa,EAAI,GACjBE,EAAeT,EAAS,IAAI;AAAA,EAC9B,GAEMkB,IAAiB,MAAM;AAC3B,IAAIV,EAAY,UACdL,EAAiBH,EAAS,IAAIQ,EAAY,KAAA,CAAM,GAElDD,EAAa,EAAK,GAClBE,EAAe,EAAE;AAAA,EACnB,GAEMU,IAAmB,MAAM;AAC7B,IAAAZ,EAAa,EAAK,GAClBE,EAAe,EAAE;AAAA,EACnB,GAEM7R,IAAgB,CAACnD,MAA2B;AAChD,IAAIA,EAAE,QAAQ,UACZyV,EAAA,IACSzV,EAAE,QAAQ,YACnB0V,EAAA;AAAA,EAEJ,GAEMC,IAAe,MAAM;AACzB,QAAInB,EAAU,UAAU,GAAG;AACzB,YAAM,iCAAiC;AACvC;AAAA,IACF;AAEA,IAAID,EAAS,gBAAA,IAAoB,KAC3B,CAAC,QAAQ,WAAWA,EAAS,IAAI,UAAUA,EAAS,iBAAiB,cAAc,KAKzFI,EAAiBJ,EAAS,EAAE;AAAA,EAC9B;AAGA,SAAA/S,EAAU,MAAM;AACd,IAAIqT,KAAaI,EAAS,YACxBA,EAAS,QAAQ,MAAA,GACjBA,EAAS,QAAQ,OAAA;AAAA,EAErB,GAAG,CAACJ,CAAS,CAAC,GAGZ,gBAAA9W;AAAA,IAAC6X;AAAA,IAAA;AAAA,MACC,WAAU;AAAA,MACV,OAAO;AAAA,QACL,MAAM;AAAA,QACN,KAAKhB,IAAuB,GAAGA,EAAqB,MAAM,EAAE,OAAO;AAAA,QACnE,WAAW;AAAA,MAAA;AAAA,MAIZ,UAAA;AAAA,QAAAC,IACC,gBAAA9W,EAAC,OAAA,EAAI,WAAU,oCACb,UAAA;AAAA,UAAA,gBAAA/B;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,KAAKiZ;AAAA,cACL,MAAK;AAAA,cACL,OAAOF;AAAA,cACP,UAAU,CAAC/U,MAAMgV,EAAehV,EAAE,OAAO,KAAK;AAAA,cAC9C,WAAWmD;AAAA,cACX,WAAU;AAAA,YAAA;AAAA,UAAA;AAAA,UAEZ,gBAAApF,EAACqL,IAAA,EAAQ,OAAO,KACd,UAAA;AAAA,YAAA,gBAAApN,EAACqN,MAAe,SAAO,IACrB,4BAACP,GAAA,EAAO,SAAQ,SAAQ,SAAS2M,GAAgB,cAAW,QAC1D,UAAA,gBAAAzZ,EAACG,KAAK,MAAM2F,GAAM,OAAO,WAAU,aAAY,GACjD,EAAA,CACF;AAAA,YACA,gBAAA9F,EAACsN,MAAe,UAAA,OAAA,CAAI;AAAA,UAAA,GACtB;AAAA,UACA,gBAAAvL,EAACqL,IAAA,EAAQ,OAAO,KACd,UAAA;AAAA,YAAA,gBAAApN,EAACqN,MAAe,SAAO,IACrB,4BAACP,GAAA,EAAO,SAAQ,SAAQ,SAAS4M,GAAkB,cAAW,UAC5D,UAAA,gBAAA1Z,EAACG,KAAK,MAAM2F,GAAM,OAAO,WAAU,aAAY,GACjD,EAAA,CACF;AAAA,YACA,gBAAA9F,EAACsN,MAAe,UAAA,SAAA,CAAM;AAAA,UAAA,EAAA,CACxB;AAAA,QAAA,EAAA,CACF,IAEA,gBAAAvL,EAAC,OAAA,EAAI,WAAU,oCACb,UAAA;AAAA,UAAA,gBAAA/B,EAAC,QAAA,EAAK,WAAU,oDAAoD,UAAAuY,EAAS,MAAK;AAAA,UAClF,gBAAAxW,EAACqL,IAAA,EAAQ,OAAO,KACd,UAAA;AAAA,YAAA,gBAAApN,EAACqN,MAAe,SAAO,IACrB,4BAACP,GAAA,EAAO,SAAQ,SAAQ,SAAS0M,GAAiB,cAAW,UAC3D,UAAA,gBAAAxZ,EAACG,KAAK,MAAM2F,GAAM,QAAQ,WAAU,aAAY,GAClD,EAAA,CACF;AAAA,YACA,gBAAA9F,EAACsN,MAAe,UAAA,SAAA,CAAM;AAAA,UAAA,GACxB;AAAA,UACA,gBAAAvL,EAACqL,IAAA,EAAQ,OAAO,KACd,UAAA;AAAA,YAAA,gBAAApN,EAACqN,IAAA,EAAe,SAAO,IACrB,UAAA,gBAAArN,EAAC8M,KAAO,SAAQ,SAAQ,SAAS6M,GAAc,UAAUnB,EAAU,UAAU,GAAG,cAAW,UACzF,UAAA,gBAAAxY,EAACG,GAAA,EAAK,MAAM2F,GAAM,OAAO,WAAU,YAAA,CAAY,EAAA,CACjD,EAAA,CACF;AAAA,YACA,gBAAA9F,EAACsN,MAAe,UAAA,SAAA,CAAM;AAAA,UAAA,EAAA,CACxB;AAAA,QAAA,GACF;AAAA,QAGF,gBAAAtN,EAACuC,IAAA,EAAU,aAAY,YAAW,WAAU,UAAS;AAAA,QAGrD,gBAAAvC;AAAA,UAAC0V;AAAA,UAAA;AAAA,YACC,gBAAgB6C,EAAS;AAAA,YACzB,iBAAiBA,EAAS;AAAA,YAC1B,mBAAmBA,EAAS;AAAA,YAC5B,wBAAwBW;AAAA,YACxB,eAAelN;AAAA,YACf,iBAAiBoN;AAAA,UAAA;AAAA,QAAA;AAAA,QAGnB,gBAAApZ,EAACuC,IAAA,EAAU,aAAY,YAAW,WAAU,UAAS;AAAA,QAGrD,gBAAAR,EAAC,OAAA,EAAI,WAAU,6DACZ,UAAA;AAAA,UAAA,KAAK,MAAMwW,EAAS,KAAK;AAAA,UAAE;AAAA,UAAI,KAAK,MAAMA,EAAS,MAAM;AAAA,QAAA,GAC5D;AAAA,QAEA,gBAAAvY,EAACuC,IAAA,EAAU,aAAY,YAAW,WAAU,UAAS;AAAA,QAGrD,gBAAAR,EAACL,IAAA,EAAQ,MAAMwO,GAAc,cAAcC,GACzC,UAAA;AAAA,UAAA,gBAAAnQ,EAACa,MAAe,SAAO,IACrB,4BAACiM,GAAA,EAAO,SAASoD,IAAe,YAAY,SAAS,cAAW,gBAC9D,UAAA,gBAAAlQ,EAACG,KAAK,MAAM2F,GAAM,MAAM,WAAU,aAAY,GAChD,EAAA,CACF;AAAA,4BACC/E,IAAA,EAAe,OAAM,OACpB,UAAA,gBAAAgB,EAAC,OAAA,EAAI,WAAU,iDACb,UAAA;AAAA,YAAA,gBAAAA,EAAC,OAAA,EAAI,WAAU,oCACb,UAAA;AAAA,cAAA,gBAAA/B;AAAA,gBAAC8E;AAAA,gBAAA;AAAA,kBACC,SAASyT,EAAS;AAAA,kBAClB,iBAAiBc;AAAA,gBAAA;AAAA,cAAA;AAAA,cAEnB,gBAAArZ,EAACyV,MAAM,UAAA,oBAAA,CAAiB;AAAA,YAAA,GAC1B;AAAA,8BACClT,IAAA,EAAU;AAAA,YACX,gBAAAvC;AAAA,cAAC0W;AAAA,cAAA;AAAA,gBACC,iBAAiB6B,EAAS;AAAA,gBAC1B,UAAUe;AAAA,cAAA;AAAA,YAAA;AAAA,YAEZ,gBAAAtZ;AAAA,cAACyX;AAAA,cAAA;AAAA,gBACC,WAAWc,EAAS;AAAA,gBACpB,UAAUgB;AAAA,cAAA;AAAA,YAAA;AAAA,UACZ,EAAA,CACF,EAAA,CACF;AAAA,QAAA,EAAA,CACF;AAAA,MAAA;AAAA,IAAA;AAAA,EAAA;AAGN;ACnOO,SAASM,GAAYC,GAAsB;AAGhD,SAAO,MAAM,KAAKA,CAAI,EACnB,OAAO,CAACC,MAAS;AAChB,UAAMC,IAAKD,EAAK,YAAY,CAAC;AAC7B,WAAO,CAACC,KAAMA,IAAK,UAAWA,IAAK;AAAA,EACrC,CAAC,EACA,KAAK,EAAE;AACZ;ACGA,MAAMC,KAASC,GAAa,mBAAmB,GAazCC,KAAoB,CAAC;AAAA,EACzB,OAAA/W;AAAA,EACA,UAAA6C;AAAA,EACA,cAAcmU;AAAA,EACd,QAAAtO;AAAA,EACA,UAAAuO;AAAA,EACA,WAAW1V;AAAA,EACX,aAAA2V;AAAA,EACA,UAAAC;AACF,MAA8B;AAC5B,QAAMC,IAAkBlV,EAAuB,IAAI,GAC7C,CAACmV,GAAaC,CAAc,IAAIpP,EAAS,EAAE,GAC3C,CAACqP,GAAkBC,CAAmB,IAAItP,EAA+B,KAAK,GAC9E,CAACuP,GAAoBC,CAAqB,IAAIxP,EAAS,CAAC,GACxD,CAACyP,GAAaC,CAAc,IAAI1P,EAAsC,MAAM,GAC5E,CAAC2P,GAAUC,CAAW,IAAI5P,EAAuC,QAAQ,GACzE,CAAC6P,GAAUC,CAAW,IAAI9P,EAA6B,SAAS,GAChE,CAAC+P,GAAaC,CAAc,IAAIhQ,EAAsB,oBAAI,KAAK,GAC/DiQ,IAAejW,EAAiB,EAAE,GAClCkW,IAAalW,EAAO,EAAK,GAMzB,EAAE,cAAAmW,EAAA,IAAiBC,GAAA,GACnBC,KAAcC;AAAA,IAClBC,GAAmB;AAAA,IACnBA,GAAmB;AAAA,IACnBA,GAAmB;AAAA,EAAA,GAEfC,IAAmBxW,EAAyB,IAAI,GAChD,CAACyW,IAAgBC,EAAiB,IAAI1Q,EAAS,EAAK,GACpD,CAAC2Q,GAAiBC,CAAkB,IAAI5Q;AAAA,IAC5C;AAAA,EAAA,GAKI6Q,IAAiBnI,GAAQ,MAAM;AACnC,UAAMoI,wBAAW,IAAA,GACXC,IAAqB,CAAA;AAC3B,eAAWC,KAAQX,IAAa;AAC9B,YAAMY,IAAMD,EAAK,OAAO,KAAA,EAAO,YAAA;AAC/B,MAAIF,EAAK,IAAIG,CAAG,MAChBH,EAAK,IAAIG,CAAG,GACZF,EAAS,KAAKC,EAAK,MAAM;AAAA,IAC3B;AACA,WAAOD;AAAA,EACT,GAAG,CAACV,EAAW,CAAC,GAIVa,KAAmBxI;AAAA,IACvB,MAAM,IAAI,IAAImI,EAAe,IAAI,CAACxT,MAAMA,EAAE,KAAA,EAAO,YAAA,CAAa,CAAC;AAAA,IAC/D,CAACwT,CAAc;AAAA,EAAA;AAMjB,EAAA3W,EAAU,MAAM;AACd,IAAI,CAACsG,KAAU6P,GAAY,WAAW,KACjCc,GAAwBd,IAAa;AAAA,MACxC,aAAa,CAACe,MAAU;AACtBzC,QAAAA,GAAO,MAAM,+BAA+ByC,CAAK,GACjDR,EAAmB,EAAE,MAAMQ,EAAM,MAAM,SAASA,EAAM,SAAS;AAAA,MACjE;AAAA,IAAA,CACD;AAAA,EACH,GAAG,CAAC5Q,GAAQ6P,EAAW,CAAC;AAExB,QAAMgB,IAAuB,OAAO3Y,MAA2C;;AAC7E,UAAM4Y,KAAOpY,IAAAR,EAAE,OAAO,UAAT,gBAAAQ,EAAiB;AAE9B,QADAR,EAAE,OAAO,QAAQ,IACb,GAAC4Y,KAAQ,CAACnB,IAEd;AAAA,MAAAO,GAAkB,EAAI,GACtBE,EAAmB,IAAI;AACvB,UAAI;AACF,cAAMW,IAAW,MAAMpB,EAAamB,CAAI,GAClCN,IAAmB;AAAA,UACvB,QAAQO,EAAS;AAAA,UACjB,KAAKA,EAAS;AAAA,UACd,GAAIA,EAAS,WAAW,UAAa,EAAE,QAAQA,EAAS,OAAA;AAAA,UACxD,GAAIA,EAAS,UAAU,UAAa,EAAE,OAAOA,EAAS,MAAA;AAAA,QAAM;AAK9D,cAAMC,GAAeR,CAAI,GACzBS,GAAoB,CAACT,CAAI,CAAC,GAE1BrW,EAAS,EAAE,QAAQ,EAAE,OAAOqW,EAAK,OAAA,GAAU,GAC3C,WAAW,MAAMjC,EAAS,EAAK,GAAG,CAAC;AAAA,MACrC,SAASqC,GAAO;AACdzC,QAAAA,GAAO,MAAM,uBAAuByC,CAAK,GACzCR,EAAmB;AAAA,UACjB,MAAMc,GAAcN,CAAK,IAAIA,EAAM,OAAO;AAAA,UAC1C,SAASA,aAAiB,QAAQA,EAAM,UAAU,OAAOA,CAAK;AAAA,QAAA,CAC/D;AAAA,MACH,UAAA;AACE,QAAAV,GAAkB,EAAK;AAAA,MACzB;AAAA;AAAA,EACF,GAEMiB,KAAqB,CAACC,MAAmB;AAI7C,IAAAjX,EAAS,EAAE,QAAQ,EAAE,OAAOiX,EAAA,GAAU,GACtC,WAAW,MAAM7C,EAAS,EAAK,GAAG,CAAC;AAAA,EACrC,GAcM8C,KAXmB,CAACrW,MAA+C;AACvE,YAAQA,GAAA;AAAA,MACN,KAAK;AACH,eAAO;AAAA,MACT,KAAK;AACH,eAAO;AAAA,MACT,KAAK;AACH,eAAO;AAAA,IAAA;AAAA,EAEb,GAEuCmU,CAAQ;AAG/C,EAAAzV,EAAU,MAAM;AACd,UAAM4X,IAAU;AAChB,QAAI,CAAC,SAAS,eAAeA,CAAO,GAAG;AACrC,YAAM/b,IAAQ,SAAS,cAAc,OAAO;AAC5C,MAAAA,EAAM,KAAK+b,GACX/b,EAAM,cAAc,kEACpB,SAAS,KAAK,YAAYA,CAAK;AAAA,IACjC;AAAA,EACF,GAAG,CAAA,CAAE,GAGLmE,EAAU,MAAM;AACd,IAAK6X,GAAmB,mBACtBA,GAAmB,aAChB,KAAK,MAAM;AACV,MAAAvC,EAAsB,CAACwC,MAASA,IAAO,CAAC;AAAA,IAC1C,CAAC,EACA,MAAM,CAACZ,MAAU;AAChBzC,MAAAA,GAAO,MAAM,yBAAyByC,CAAK;AAAA,IAC7C,CAAC;AAAA,EAEP,GAAG,CAAA,CAAE;AAIL,QAAMa,KAAW,OAAOjB,GAAsBkB,IAAwB,OAAU;AAC9E,QAAI;AACF,UAAIA;AAEF,cAAMH,GAAmB,SAASf,CAAI;AAAA,eAC7BA,EAAK,YAAY;AAI1B,cAAMmB,IAAanD,IAAc,GAAGA,CAAW,GAAGgC,EAAK,IAAI,KAAKA,EAAK;AACrE,QAAAe,GAAmB,yBAAyBf,EAAK,MAAMmB,CAAU;AAAA,MACnE;AAEE,cAAMJ,GAAmB,SAASf,CAAI;AAGxC,MAAAhB,EAAe,CAACgC,MAAS,IAAI,IAAIA,CAAI,EAAE,IAAIhB,EAAK,IAAI,CAAC;AAAA,IACvD,SAASI,GAAO;AACdzC,MAAAA,GAAO,MAAM,uBAAuBqC,EAAK,IAAI,KAAKI,CAAK;AAAA,IACzD;AAAA,EACF;AAGA,EAAAlX,EAAU,MAAM;AAyBd,KAxBqB,YAAY;AAC/B,UAAIgW,EAAW,WAAWD,EAAa,QAAQ,WAAW,EAAG;AAE7D,MAAAC,EAAW,UAAU;AAGrB,YAAMkC,IAAc,CAAC,GAAGnC,EAAa,OAAO;AAC5C,MAAAA,EAAa,UAAU,CAAA;AAEvB,YAAMoC,IAAWN,GAAmB,YAAA;AAGpC,YAAM,QAAQ;AAAA,QACZK,EAAY,IAAI,OAAOE,MAAa;AAClC,gBAAMtB,IAAOqB,EAAS,KAAK,CAAChV,OAAMA,GAAE,SAASiV,CAAQ;AACrD,UAAItB,KAAQ,CAACjB,EAAY,IAAIuC,CAAQ,KACnC,MAAML,GAASjB,CAAI;AAAA,QAEvB,CAAC;AAAA,MAAA,GAGHd,EAAW,UAAU;AAAA,IACvB,GAEA;AAAA,EACF,GAAG,CAACH,CAAW,CAAC;AAGhB,QAAMwC,KAAgB,CAACD,MAAqB;AAE1C,UAAME,IAAgBzC,EAAY,IAAIuC,CAAQ,GACxCG,IAAgBxC,EAAa,QAAQ,SAASqC,CAAQ;AAE5D,IAAI,CAACE,KAAiB,CAACC,MACrBxC,EAAa,QAAQ,KAAKqC,CAAQ,GAE9B,CAACpC,EAAW,WAAWD,EAAa,QAAQ,WAAW,KACzDD,EAAe,CAACgC,MAAS,IAAI,IAAIA,CAAI,CAAC;AAAA,EAG5C;AAGA,EAAA9X,EAAU,MAAM;AACd,IAAIsG,KAEF,WAAW,MAAM;AACf,MAAI0O,EAAgB,WAClBA,EAAgB,QAAQ,eAAe,EAAE,UAAU,UAAU,OAAO,UAAU;AAAA,IAElF,GAAG,GAAG,GAGH1O,MACH4O,EAAe,EAAE,GACjBE,EAAoB,KAAK,GAEzByC,GAAmB,kBAAA,GAEnB/B,EAAe,oBAAI,KAAK;AAAA,EAE5B,GAAG,CAACxP,GAAQ1I,CAAK,CAAC,GAIlBoC,EAAU,MAAM;AACd,QAAIpC,KAAS,CAACiY,EAAY,IAAIjY,CAAK,GAAG;AAEpC,YAAMkZ,IADWe,GAAmB,YAAA,EACd,KAAK,CAAC1U,MAAMA,EAAE,SAASvF,CAAK;AAClD,MAAIkZ,KACFiB,GAASjB,GAAM,EAAI;AAAA,IAEvB;AAAA,EACF,GAAG,CAAClZ,GAAOiY,GAAaR,CAAkB,CAAC,GAG3CrV,EAAU,MAAM;AACd,IAAIiV,EAAY,UACdG,EAAoB,KAAK;AAAA,EAE7B,GAAG,CAACH,CAAW,CAAC;AAEhB,QAAMuD,KAAe,OAAOd,MAAmB;AAG7C,UAAMe,IADWZ,GAAmB,YAAA,EACN,KAAK,CAAC1U,MAAMA,EAAE,SAASuU,CAAM;AAC3D,QAAIe;AACF,UAAI;AAEF,cAAMV,GAASU,GAAc,EAAI;AAAA,MACnC,QAAgB;AACdhE,QAAAA,GAAO,KAAK,uBAAuBiD,CAAM,qBAAqB;AAAA,MAChE;AAGF,IAAAjX,EAAS,EAAE,QAAQ,EAAE,OAAOiX,EAAA,GAAU,GAEtC,WAAW,MAAM7C,EAAS,EAAK,GAAG,CAAC;AAAA,EACrC,GAGM6D,KAAW3e,GAAM;AAAA,IACrB,CAAC,EAAE,MAAA+c,GAAM,kBAAA6B,IAAmB,SAAkE;AAC5F,YAAMC,IAAc9Y,EAAuB,IAAI,GACzC0C,IAAa5E,MAAUkZ,EAAK,MAC5B+B,IAAWhD,EAAY,IAAIiB,EAAK,IAAI;AAG1C,MAAA9W,EAAU,MAAM;AACd,YAAI,CAAC4Y,EAAY,QAAS;AAE1B,cAAME,KAAW,IAAI;AAAA,UACnB,CAACC,OAAY;AACX,YAAAA,GAAQ,QAAQ,CAACC,OAAU;AACzB,cAAIA,GAAM,kBAAkB,CAACH,KAC3BR,GAAcvB,EAAK,IAAI;AAAA,YAE3B,CAAC;AAAA,UACH;AAAA,UACA,EAAE,YAAY,QAAA;AAAA;AAAA,QAAQ;AAGxB,eAAAgC,GAAS,QAAQF,EAAY,OAAO,GAE7B,MAAME,GAAS,WAAA;AAAA,MACxB,GAAG,CAAChC,EAAK,MAAM+B,CAAQ,CAAC;AAGxB,UAAII,KAAW,IACXC,IAAqB;AAEzB,MAAI3D,MAAgB,UAClB0D,KAAWnC,EAAK,MAChBoC,IAAqB,MACZ3D,MAAgB,aACzB0D,KAAWnE,KAAegC,EAAK,MAE/BoC,IAAqBP,MAGrBM,KAAWnE,KAAegC,EAAK,MAC/BoC,IAAqB;AAIvB,YAAMC,KAAoB5D,MAAgB,aAAa,CAAC2D,GAElDE,KACJ,gBAAA7c;AAAA,QAAC6X;AAAA,QAAA;AAAA,UACC,KAAK,CAACnU,OAAO;AAEX,YAAIuC,KAAcwS,MAChBA,EAAgB,UAAU/U,KAE5B2Y,EAAY,UAAU3Y;AAAA,UACxB;AAAA,UACA,WAAW,8GAA8G0V,MAAa,YAAY,aAAa,YAAY,IAAInT,IAAa,qBAAqB,6CAA6C;AAAA,UAC9P,SAAS2W,KAAoB,SAAY,MAAMX,GAAa1B,EAAK,IAAI;AAAA,UACrE,MAAMqC,KAAoB,SAAY;AAAA,UACtC,cAAYA,KAAoB,SAAY,UAAUrC,EAAK,IAAI;AAAA,UAC/D,UAAUqC,KAAoB,SAAY;AAAA,UAC1C,WACEA,KACI,SACA,CAAC3a,OAAM;AACL,aAAIA,GAAE,QAAQ,WAAWA,GAAE,QAAQ,SACjCA,GAAE,eAAA,GACFga,GAAa1B,EAAK,IAAI;AAAA,UAE1B;AAAA,UAEN,OAAO;AAAA,YACL,WAAW,GAAGoC,IAAqB,KAAKvB,IAAgB,KAAKA,CAAa;AAAA,YAC1E,SAAS,GAAG,IAAIA,CAAa,MAAM,KAAKA,CAAa;AAAA,YACrD,KAAK,GAAG,IAAIA,CAAa;AAAA,UAAA;AAAA,UAI1B,UAAA;AAAA,YAAA,CAACkB,KACA,gBAAAre;AAAA,cAAC;AAAA,cAAA;AAAA,gBACC,WAAU;AAAA,gBACV,OAAO;AAAA,kBACL,SAAS;AAAA,gBAAA;AAAA,cACX;AAAA,YAAA;AAAA,YAIJ,gBAAAA;AAAA,cAAC;AAAA,cAAA;AAAA,gBACC,WAAU;AAAA,gBACV,OAAO;AAAA,kBACL,kBAAkBqe,IAAW,IAAI/B,EAAK,IAAI,kBAAkB;AAAA,kBAC5D,UAAU,GAAG,KAAKa,CAAa;AAAA,kBAC/B,SAASkB,IAAW,IAAI;AAAA,gBAAA;AAAA,gBAGzB,UAAAI;AAAA,cAAA;AAAA,YAAA;AAAA,YAEFC,KACC,gBAAA1e;AAAA,cAAC;AAAA,cAAA;AAAA,gBACC,WAAU;AAAA,gBACV,OAAO;AAAA,kBACL,UAAU,GAAG,IAAImd,CAAa;AAAA,kBAC9B,SAASkB,IAAW,IAAI;AAAA,gBAAA;AAAA,gBAGzB,UAAA/B,EAAK;AAAA,cAAA;AAAA,YAAA;AAAA,UACR;AAAA,QAAA;AAAA,MAAA;AAMN,aAAIqC,KAEA,gBAAA5c,EAACqL,IAAA,EAAwB,eAAe,KACtC,UAAA;AAAA,QAAA,gBAAApN,EAACqN,IAAA,EAAe,SAAO,IACrB,UAAA,gBAAArN;AAAA,UAAC8M;AAAA,UAAA;AAAA,YACC,WAAU;AAAA,YACV,OAAO,EAAE,OAAOqO,MAAa,YAAY,SAAS,OAAA;AAAA,YAClD,SAAS,MAAM6C,GAAa1B,EAAK,IAAI;AAAA,YACrC,cAAY,UAAUA,EAAK,IAAI;AAAA,YAE/B,UAAA,gBAAAva;AAAA,cAAC6X;AAAA,cAAA;AAAA,gBACC,KAAK,CAACnU,OAAO;AAEX,kBAAIuC,KAAcwS,MAChBA,EAAgB,UAAU/U,KAE5B2Y,EAAY,UAAU3Y;AAAA,gBACxB;AAAA,gBACA,WAAW,8GAA8G0V,MAAa,YAAY,aAAa,YAAY,IAAInT,IAAa,qBAAqB,6CAA6C;AAAA,gBAC9P,OAAO;AAAA,kBACL,WAAW,GAAG0W,IAAqB,KAAKvB,IAAgB,KAAKA,CAAa;AAAA,kBAC1E,SAAS,GAAG,IAAIA,CAAa,MAAM,KAAKA,CAAa;AAAA,kBACrD,KAAK,GAAG,IAAIA,CAAa;AAAA,gBAAA;AAAA,gBAI1B,UAAA;AAAA,kBAAA,CAACkB,KACA,gBAAAre;AAAA,oBAAC;AAAA,oBAAA;AAAA,sBACC,WAAU;AAAA,sBACV,OAAO;AAAA,wBACL,SAAS;AAAA,sBAAA;AAAA,oBACX;AAAA,kBAAA;AAAA,kBAIJ,gBAAAA;AAAA,oBAAC;AAAA,oBAAA;AAAA,sBACC,WAAU;AAAA,sBACV,OAAO;AAAA,wBACL,kBAAkBqe,IAAW,IAAI/B,EAAK,IAAI,kBAAkB;AAAA,wBAC5D,UAAU,GAAG,KAAKa,CAAa;AAAA,wBAC/B,SAASkB,IAAW,IAAI;AAAA,sBAAA;AAAA,sBAGzB,UAAAI;AAAA,oBAAA;AAAA,kBAAA;AAAA,kBAEFC,KACC,gBAAA1e;AAAA,oBAAC;AAAA,oBAAA;AAAA,sBACC,WAAU;AAAA,sBACV,OAAO;AAAA,wBACL,UAAU,GAAG,IAAImd,CAAa;AAAA,wBAC9B,SAASkB,IAAW,IAAI;AAAA,sBAAA;AAAA,sBAGzB,UAAA/B,EAAK;AAAA,oBAAA;AAAA,kBAAA;AAAA,gBACR;AAAA,cAAA;AAAA,YAAA;AAAA,UAEJ;AAAA,QAAA,GAEJ;AAAA,QACA,gBAAAtc,EAACsN,MAAe,MAAK,OACnB,4BAAC,KAAA,EAAG,UAAAgP,EAAK,MAAK,EAAA,CAChB;AAAA,MAAA,EAAA,GA3DYA,EAAK,IA4DnB,sBAII/c,GAAM,UAAN,EAAgC,UAAAqf,GAAA,GAAZtC,EAAK,IAAsB;AAAA,IACzD;AAAA,IACA,CAACuC,GAAWC,MAEHD,EAAU,KAAK,SAASC,EAAU,KAAK,QAAQD,EAAU,qBAAqBC,EAAU;AAAA,EACjG,GAIIC,KAAsB/K,GAAQ,MAAM;AACxC,QAAI,CAACuG,EAAU,QAAO,oBAAI,IAAA;AAE1B,UAAMyE,wBAAgB,IAAA,GAEhBC,IAAiB,CAACxZ,MAAgC;AAEtD,YAAMyZ,IAAazZ,EAAG,YAChBqU,IAAOrU,EAAG;AAChB,MAAIyZ,KAAcpF,KACED,GAAYC,CAAI,EAEpB,OAAO,SAAS,KAC5BkF,EAAU,IAAIE,CAAU;AAAA,IAG9B;AAEA,WAAA3E,EAAS,QAAQ,CAAC9U,MAAO;AACvB,MAAAwZ,EAAexZ,CAAE,GAGbA,EAAG,YAAY,MAAM,QAAQA,EAAG,QAAQ,KACzCA,EAAG,SAAuC,QAAQ,CAAC0Z,MAAU;AAC5D,QAAAF,EAAeE,CAAK;AAAA,MACtB,CAAC;AAAA,IAEL,CAAC,GAEMH;AAAA,EACT,GAAG,CAACzE,CAAQ,CAAC,GAGP6E,KAAepL,GAAQ,MAAM;AAKjC,UAAM2J,KACJN,GAAmB,cAAA,IAAkBA,GAAmB,YAAA,IAAgBgC,IAEvE,OAAO,CAAC/C,MAAS,CAACE,GAAiB,IAAIF,EAAK,KAAK,OAAO,YAAA,CAAa,CAAC,GAEnEgD,IAAmB,IAAI,IAAID,GAAa,IAAI,CAAC1W,MAAMA,EAAE,IAAI,CAAC,GAG1DqW,IAA8B,CAAA;AACpC,IAAArB,EAAS,QAAQ,CAACrB,MAAS;AACzB,UAAIyC,GAAoB,IAAIzC,EAAK,IAAI;AAEnC,YAAI7B,GAAa;AACf,gBAAM8E,KAAQ9E,EAAY,YAAA;AAC1B,UAAI6B,EAAK,KAAK,YAAA,EAAc,SAASiD,EAAK,KACxCP,EAAU,KAAK1C,CAAI;AAAA,QAEvB;AACE,UAAA0C,EAAU,KAAK1C,CAAI;AAAA,IAGzB,CAAC;AAGD,QAAIkD,IAAiB7B,EAAS,OAAO,CAACrB,MAAS,CAACyC,GAAoB,IAAIzC,EAAK,IAAI,CAAC;AAQlF,QALI3B,MAAqB,UACvB6E,IAAiBA,EAAe,OAAO,CAAClD,MAASA,EAAK,aAAa3B,CAAgB,IAIjFF,GAAa;AACf,YAAM8E,IAAQ9E,EAAY,YAAA;AAC1B,MAAA+E,IAAiBA,EAAe,OAAO,CAAClD,OAASA,GAAK,KAAK,YAAA,EAAc,SAASiD,CAAK,CAAC;AAAA,IAC1F;AAGA,UAAME,IAAqC,CAAA,GACrCC,KAA+B,CAAA;AAErC,WAAAF,EAAe,QAAQ,CAAClD,MAAS;AAC/B,MAAIgD,EAAiB,IAAIhD,EAAK,IAAI,IAChCmD,EAAiB,KAAKnD,CAAI,IAE1BoD,GAAW,KAAKpD,CAAI;AAAA,IAExB,CAAC,GAGD0C,EAAU,KAAK,CAACzW,GAAGW,OAAMX,EAAE,KAAK,cAAcW,GAAE,IAAI,CAAC,GACrDuW,EAAiB,KAAK,CAAClX,GAAGW,OAAMX,EAAE,KAAK,cAAcW,GAAE,IAAI,CAAC,GAC5DwW,GAAW,KAAK,CAACnX,GAAGW,OAAMX,EAAE,KAAK,cAAcW,GAAE,IAAI,CAAC,GAE/C,EAAE,WAAA8V,GAAW,kBAAAS,GAAkB,YAAAC,GAAA;AAAA,EACxC,GAAG,CAACjF,GAAaE,GAAkBE,GAAoBkE,IAAqBvC,EAAgB,CAAC,GAGvFmD,KAAoB,CAACC,GAAyBzB,IAAmB,OACjEhD,MAAa,YAGb,gBAAAnb,EAAC,OAAA,EAAI,WAAU,iFACZ,YAAM,IAAI,CAACsc,MACV,gBAAAtc,EAACke,MAAyB,MAAA5B,GAAY,kBAAA6B,EAAA,GAAvB7B,EAAK,IAAsD,CAC3E,GACH,IAKA,gBAAAtc;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,WAAU;AAAA,MACV,OAAO;AAAA,QACL,SAAS;AAAA,QACT,qBAAqB,4BAA4B,MAAMmd,CAAa;AAAA,QACpE,KAAK;AAAA,MAAA;AAAA,MAGN,UAAAyC,EAAM,IAAI,CAACtD,MACV,gBAAAtc,EAACke,MAAyB,MAAA5B,GAAY,kBAAA6B,KAAvB7B,EAAK,IAAsD,CAC3E;AAAA,IAAA;AAAA,EAAA,GAOHuD,KAA0C;AAAA,IAC9C;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EAAA;AAGF,SACE,gBAAA9d,EAAA2C,IAAA,EAQE,UAAA;AAAA,IAAA,gBAAA1E;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,SAAS,MAAMqa,EAAS,CAACvO,CAAM;AAAA,QAC/B,WAAW,kRAAkRA,IAAS,uCAAuC,mBAAmB;AAAA,QAChW,cAAYA,IAAS,uBAAuB;AAAA,QAC5C,OAAO1I;AAAA,QAEP,UAAA,gBAAApD;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,WAAU;AAAA,YACV,OAAO,EAAE,kBAAkB,IAAIoD,CAAK,iBAAiB,YAAY,IAAA;AAAA,YAEhE,UAAAA;AAAA,UAAA;AAAA,QAAA;AAAA,MACH;AAAA,IAAA;AAAA,IAGF,gBAAApD;AAAA,MAAC8f;AAAA,MAAA;AAAA,QACC,QAAAhU;AAAA,QACA,SAAS,MAAMuO,EAAS,EAAK;AAAA,QAC7B,OAAM;AAAA,QACN,aAAY;AAAA,QACZ,QAAO;AAAA,QACP,WAAU;AAAA,QACV,iBAAiB;AAAA,QACjB,kBAAkB;AAAA,QAClB,YAAY;AAAA,QACZ,sBAAsB;AAAA,QAMtB,UAAA,gBAAAra,EAAC,OAAA,EAAI,WAAU,4CACb,UAAA,gBAAAA,EAAC,OAAA,EAAI,WAAU,yBAEb,UAAA,gBAAA+B,EAAC,OAAA,EAAI,WAAU,gCAEb,UAAA;AAAA,UAAA,gBAAA/B,EAAC,SAAI,WAAU,mBACb,UAAA,gBAAA+B,EAAC6X,IAAA,EAAQ,WAAU,oBACjB,UAAA;AAAA,YAAA,gBAAA5Z,EAAC+f,IAAA,EAAU,WAAU,aAAY,cAAW,gBAC1C,UAAA,gBAAA/f;AAAA,cAACggB;AAAA,cAAA;AAAA,gBACC,MAAK;AAAA,gBACL,WAAU;AAAA,gBACV,aAAY;AAAA,gBACZ,OAAOvF;AAAA,gBACP,UAAU,CAACzW,MAAM0W,EAAe1W,EAAE,OAAO,KAAK;AAAA,gBAC9C,WAAS;AAAA,gBACT,cAAW;AAAA,cAAA;AAAA,YAAA,GAEf;AAAA,YAEA,gBAAAhE;AAAA,cAACigB;AAAA,cAAA;AAAA,gBACC,OAAOhF;AAAA,gBACP,eAAe,CAAC7X,MAAU8X,EAAY9X,CAAqC;AAAA,gBAE3E,UAAA,gBAAApD,EAACigB,GAAK,eAAL,EACC,4BAACA,GAAK,MAAL,EAAU,cAAW,aACpB,UAAA;AAAA,kBAAA,gBAAAle,EAACke,GAAK,KAAL,EAAS,IAAG,SAAQ,WAAU,+BAA8B,cAAW,mBAAkB,UAAA;AAAA,oBAAA;AAAA,oBAExF,gBAAAjgB,EAACigB,GAAK,WAAL,CAAA,CAAe;AAAA,kBAAA,GAClB;AAAA,kBACA,gBAAAle,EAACke,GAAK,KAAL,EAAS,IAAG,UAAS,WAAU,iCAAgC,cAAW,oBAAmB,UAAA;AAAA,oBAAA;AAAA,oBAE5F,gBAAAjgB,EAACigB,GAAK,WAAL,CAAA,CAAe;AAAA,kBAAA,GAClB;AAAA,kBACA,gBAAAle,EAACke,GAAK,KAAL,EAAS,IAAG,SAAQ,WAAU,+BAA8B,cAAW,mBAAkB,UAAA;AAAA,oBAAA;AAAA,oBAExF,gBAAAjgB,EAACigB,GAAK,WAAL,CAAA,CAAe;AAAA,kBAAA,EAAA,CAClB;AAAA,gBAAA,EAAA,CACF,EAAA,CACF;AAAA,cAAA;AAAA,YAAA;AAAA,YAGF,gBAAAjgB;AAAA,cAAC8M;AAAA,cAAA;AAAA,gBACC,SAAQ;AAAA,gBACR,SAAS,MAAM;AACb,kBAAAkO,EAAe,CAACsC,MACVA,MAAS,SAAe,SACxBA,MAAS,SAAe,YACrB,MACR;AAAA,gBACH;AAAA,gBACA,cACEvC,MAAgB,SACZ,wBACAA,MAAgB,SACd,sBACA;AAAA,gBAER,WAAU;AAAA,gBAET,UAAAA,MAAgB,SACf,gBAAA/a,EAACG,GAAA,EAAK,MAAK,sBAAqB,WAAU,iBAAA,CAAiB,IACzD4a,MAAgB,2BACjB5a,GAAA,EAAK,MAAK,eAAc,WAAU,iBAAA,CAAiB,sBAEnDA,GAAA,EAAK,MAAK,sBAAqB,WAAU,iBAAA,CAAiB;AAAA,cAAA;AAAA,YAAA;AAAA,YAI/D,gBAAAH;AAAA,cAAC8M;AAAA,cAAA;AAAA,gBACC,SAAQ;AAAA,gBACR,SAAS,MAAMsO,EAAYD,MAAa,SAAS,YAAY,MAAM;AAAA,gBACnE,cAAYA,MAAa,SAAS,2BAA2B;AAAA,gBAC7D,WAAU;AAAA,gBAET,UAAAA,MAAa,SACZ,gBAAAnb,EAACG,GAAA,EAAK,MAAK,mBAAkB,WAAU,iBAAA,CAAiB,IAExD,gBAAAH,EAACG,GAAA,EAAK,MAAK,mBAAkB,WAAU,iBAAA,CAAiB;AAAA,cAAA;AAAA,YAAA;AAAA,UAE5D,EAAA,CACF,EAAA,CACF;AAAA,UAGA,gBAAA4B,EAAC,OAAA,EAAI,WAAU,0CAEb,UAAA;AAAA,YAAA,gBAAA/B;AAAA,cAAC;AAAA,cAAA;AAAA,gBACC,WAAU;AAAA,gBACV,OAAO;AAAA,kBACL,QAAQ;AAAA,kBACR,YACE;AAAA,kBACF,QAAQ;AAAA,gBAAA;AAAA,cACV;AAAA,YAAA;AAAA,YAIF,gBAAAA,EAAC,OAAA,EAAI,WAAU,+CACb,UAAA,gBAAAA,EAAC,OAAA,EAAI,WAAU,uCACZ,UAAA6f,GAAW,IAAI,CAACK,MAAa;AAC5B,oBAAMhb,IAAQgb,MAAa,QAAQ,QAAQC,GAAgBD,CAAwB;AAEnF,qBACE,gBAAAlgB;AAAA,gBAAC8M;AAAA,gBAAA;AAAA,kBAEC,MAAK;AAAA,kBACL,SAAS6N,MAAqBuF,IAAW,YAAY;AAAA,kBACrD,SAAS,MAAMtF,EAAoBsF,CAAQ;AAAA,kBAC3C,WAAW,eAAevF,MAAqBuF,IAAW,KAAK,wBAAwB;AAAA,kBAEtF,UAAAhb;AAAA,gBAAA;AAAA,gBANIgb;AAAA,cAAA;AAAA,YASX,CAAC,GACH,EAAA,CACF;AAAA,UAAA,GACF;AAAA,UAGA,gBAAAne,EAAC,OAAA,EAAI,WAAU,aAIX,UAAA;AAAA,aAAAoa,EAAe,SAAS,KAAKV,MAAiB,CAAChB,uBAC9C,OAAA,EAAI,WAAU,sBAAqB,gBAAa,0BAC/C,UAAA;AAAA,cAAA,gBAAAza,EAAC,OAAA,EAAI,WAAU,4GAA2G,UAAA,cAE1H;AAAA,cACA,gBAAA+B,EAAC,OAAA,EAAI,WAAU,kFACZ,UAAA;AAAA,gBAAAoa,EAAe,IAAI,CAACe,MAGjB,gBAAAld;AAAA,kBAAC4Z;AAAA,kBAAA;AAAA,oBAEC,gBAAa;AAAA,oBACb,eAAasD;AAAA,oBACb,WAAW,uHANI9Z,MAAU8Z,IAMsH,qBAAqB,6CAA6C;AAAA,oBACjN,SAAS,MAAMD,GAAmBC,CAAM;AAAA,oBACxC,MAAK;AAAA,oBACL,cAAY,UAAUA,CAAM;AAAA,oBAC5B,UAAU;AAAA,oBACV,WAAW,CAAClZ,MAAM;AAChB,uBAAIA,EAAE,QAAQ,WAAWA,EAAE,QAAQ,SACjCA,EAAE,eAAA,GACFiZ,GAAmBC,CAAM;AAAA,oBAE7B;AAAA,oBACA,OAAO;AAAA,sBACL,WAAW,GAAG,KAAKC,CAAa;AAAA,sBAChC,SAAS,GAAG,IAAIA,CAAa,MAAM,KAAKA,CAAa;AAAA,oBAAA;AAAA,oBAGvD,UAAA,gBAAAnd;AAAA,sBAAC;AAAA,sBAAA;AAAA,wBACC,WAAU;AAAA,wBACV,OAAO;AAAA,0BACL,kBAAkB,IAAIkd,CAAM;AAAA,0BAC5B,UAAU,GAAG,KAAKC,CAAa;AAAA,wBAAA;AAAA,wBAGhC,UAAApC,MAAgB,SAASmC,IAAS5C,KAAe4C;AAAA,sBAAA;AAAA,oBAAA;AAAA,kBACpD;AAAA,kBA3BKA;AAAA,gBAAA,CA8BV;AAAA,gBACAzB,KACC,gBAAA1Z,EAAA2C,IAAA,EACE,UAAA;AAAA,kBAAA,gBAAA1E;AAAA,oBAAC;AAAA,oBAAA;AAAA,sBACC,KAAK8b;AAAA,sBACL,MAAK;AAAA,sBACL,QAAO;AAAA,sBACP,WAAU;AAAA,sBACV,gBAAa;AAAA,sBACb,eAAY;AAAA,sBACZ,cAAW;AAAA,sBACX,UAAUa;AAAA,oBAAA;AAAA,kBAAA;AAAA,kBAEZ,gBAAA5a;AAAA,oBAAC+K;AAAA,oBAAA;AAAA,sBACC,SAAQ;AAAA,sBACR,gBAAa;AAAA,sBACb,eAAY;AAAA,sBACZ,SAAS,MAAA;;AAAM,gCAAAtI,IAAAsX,EAAiB,YAAjB,gBAAAtX,EAA0B;AAAA;AAAA,sBACzC,UAAUuX;AAAA,sBACV,cAAW;AAAA,sBAEX,UAAA;AAAA,wBAAA,gBAAA/b,EAACG,GAAA,EAAK,MAAK,iBAAgB,WAAU,aAAY;AAAA,wBAChD4b,KAAiB,eAAe;AAAA,sBAAA;AAAA,oBAAA;AAAA,kBAAA;AAAA,gBACnC,EAAA,CACF;AAAA,cAAA,GAEJ;AAAA,cACCE,KACC,gBAAAjc;AAAA,gBAAC;AAAA,gBAAA;AAAA,kBACC,WAAU;AAAA,kBACV,gBAAa;AAAA,kBACZ,GAAIic,EAAgB,QAAQ,EAAE,sBAAsBA,EAAgB,KAAA;AAAA,kBACrE,MAAK;AAAA,kBAEJ,UAAAA,EAAgB;AAAA,gBAAA;AAAA,cAAA;AAAA,YACnB,GAEJ;AAAA,YAIDmD,GAAa,UAAU,SAAS,KAC/B,gBAAArd,EAAC,OAAA,EAAI,WAAU,sBACb,UAAA;AAAA,cAAA,gBAAA/B,EAAC,OAAA,EAAI,WAAU,4GAA2G,UAAA,oBAE1H;AAAA,cACC2f,GAAkBP,GAAa,WAAW,EAAI;AAAA,YAAA,GACjD;AAAA,YAGDA,GAAa,iBAAiB,WAAW,KAAKA,GAAa,WAAW,WAAW,IAChF,gBAAApf,EAAC,OAAA,EAAI,WAAU,4EAA2E,UAAA,iBAAA,CAAc,IAExG,gBAAA+B,EAAA2C,IAAA,EAEG,UAAA;AAAA,cAAA0a,GAAa,iBAAiB,SAAS,KACtC,gBAAArd,EAAC,OAAA,EAAI,WAAU,UACb,UAAA;AAAA,gBAAA,gBAAA/B,EAAC,OAAA,EAAI,WAAU,4GAA2G,UAAA,eAE1H;AAAA,gBACC2f,GAAkBP,GAAa,gBAAgB;AAAA,cAAA,GAClD;AAAA,cAIDA,GAAa,WAAW,SAAS,KAChC,gBAAArd,EAAC,OAAA,EAAI,WAAU,UACb,UAAA;AAAA,gBAAA,gBAAA/B,EAAC,OAAA,EAAI,WAAU,4GAA2G,UAAA,aAE1H;AAAA,gBACC2f,GAAkBP,GAAa,UAAU;AAAA,cAAA,EAAA,CAC5C;AAAA,YAAA,EAAA,CAEJ;AAAA,UAAA,EAAA,CAEJ;AAAA,QAAA,EAAA,CACF,GACF,EAAA,CACF;AAAA,MAAA;AAAA,IAAA;AAAA,EACF,GACF;AAEJ,GCz4BMnF,KAASC,GAAa,uBAAuB,GAQtCkG,KAA8D,CAAC,EAAE,SAAA3S,GAAS,UAAA4S,GAAU,UAAAC,QAAe;AAE9G,QAAM,CAACC,GAAgBC,CAAiB,IAAIlV,EAAiC,CAAA,CAAE;AAE/E,2BACG,OAAA,EAAI,WAAU,0BACZ,UAAA+U,EAAS,IAAI,CAACI,MAAY;AAEzB,UAAMC,IACHjT,EAAQ,cAA0CgT,EAAQ,GAAG,KAAKA,EAAQ,wBAAwBA,EAAQ;AAG7G,QAAIA,EAAQ,SAAS;AACnB,aACE,gBAAA1e,EAAC,OAAA,EAAsB,WAAU,wCAC/B,UAAA;AAAA,QAAA,gBAAA/B;AAAA,UAAC8E;AAAA,UAAA;AAAA,YACC,IAAI,WAAW2b,EAAQ,GAAG;AAAA,YAC1B,SAASC;AAAA,YACT,iBAAiB,CAACjhB,MAAqB;AACrC,oBAAMkhB,IAAalT,EAAQ,MAAA;AAC1B,cAAAkT,EAAW,cAA0CF,EAAQ,GAAG,IAAIhhB,GACrE6gB,EAASK,CAAU;AAAA,YACrB;AAAA,UAAA;AAAA,QAAA;AAAA,QAEF,gBAAA3gB,EAACyV,MAAM,SAAS,WAAWgL,EAAQ,GAAG,IAAK,YAAQ,MAAA,CAAM;AAAA,MAAA,EAAA,GAVjDA,EAAQ,GAWlB;AAMJ,UAAMG,IAAkB,OAAOF,KAAgB,YAAY,CAAC,MAAMA,CAAW,IACzEA,IACCD,EAAQ,wBAAwB,GAG/BI,IAAuBN,EAAeE,EAAQ,GAAG,MAAM,SACzDF,EAAeE,EAAQ,GAAG,IAC1BG,GAGEE,IAAcL,EAAQ,WAAWA,EAAQ,SAASI,CAAoB,IAAIA,GAG1EE,IAAc,CAAC3d,MAA0B;AAE7C,YAAMO,IAAgB8c,EAAQ,aAAaA,EAAQ,WAAWrd,CAAK,IAAIA;AAGvE,aAAI,OAAOO,KAAkB,YAAY,MAAMA,CAAa,KAC1DsW,GAAO,KAAK,0BAA0BtW,GAAe,gBAAgB8c,EAAQ,GAAG,GACzE,OAGFA,EAAQ,YACXA,EAAQ,UAAU9c,CAAa,IAC/B,kBAAkB8c,KAAWA,EAAQ,eACnC,IAAI9c,IAAgB,KAAK,QAAQ,CAAC,CAAC,MACnCA,EAAc,QAAQ,CAAC;AAAA,IAC/B;AAEA,WACE,gBAAA5B,EAAC,OAAA,EAAsB,WAAU,iCAC/B,UAAA;AAAA,MAAA,gBAAAA,EAAC,OAAA,EAAI,WAAU,8BACb,UAAA;AAAA,QAAA,gBAAA/B,EAACyV,IAAA,EAAO,YAAQ,MAAA,CAAM;AAAA,0BACrB,QAAA,EAAK,WAAU,oCAAoC,UAAAsL,EAAYD,CAAW,EAAA,CAAE;AAAA,MAAA,GAC/E;AAAA,MACA,gBAAA9gB;AAAA,QAAC6E;AAAA,QAAA;AAAA,UACC,OAAO,CAACic,CAAW;AAAA,UACnB,eAAe,CAACxa,MAAQ;AAEtB,kBAAM0a,IAAiB1a,EAAI,CAAC,GACtB2a,IAAmBR,EAAQ,aAC7BA,EAAQ,WAAWO,CAAc,IACjCA;AACJ,YAAAR,EAAkB,CAAAlD,OAAS,EAAE,GAAGA,GAAM,CAACmD,EAAQ,GAAG,GAAGQ,EAAA,EAAmB;AAAA,UAC1E;AAAA,UACA,aAAa,CAAC3a,MAAQ;AAEpB,kBAAM0a,IAAiB1a,EAAI,CAAC,GACtBqa,IAAalT,EAAQ,MAAA;AAC1B,YAAAkT,EAAW,cAA0CF,EAAQ,GAAG,IAAIA,EAAQ,aACzEA,EAAQ,WAAWO,CAAc,IACjCA,GACJV,EAASK,CAAU,GAEnBH,EAAkB,CAAAlD,MAAQ;AACxB,oBAAM4D,IAAU,EAAE,GAAG5D,EAAA;AACrB,4BAAO4D,EAAQT,EAAQ,GAAG,GACnBS;AAAA,YACT,CAAC;AAAA,UACH;AAAA,UACA,KAAK;AAAA,UACL,KAAK;AAAA,UACL,MAAMT,EAAQ,QAAQ;AAAA,UACtB,WAAU;AAAA,QAAA;AAAA,MAAA;AAAA,IACZ,EAAA,GAlCQA,EAAQ,GAmClB;AAAA,EAEJ,CAAC,EAAA,CACH;AAEJ,GCzGaU,KAA0D,CAAC;AAAA,EACtE,SAAA1T;AAAA,EACA,uBAAA2T;AAAA,EACA,iBAAAlT;AAAA,EACA,QAAQjD;AAAA,EACR,cAAcC;AAChB,MAAM;AACJ,QAAM,CAACE,GAAgBC,CAAiB,IAAIC,EAAS,EAAK,GAGpDQ,IAASb,MAAqB,SAAYA,IAAmBG,GAC7DW,IAAYb,KAA0BG,GAEtCgW,IAAuB5T,EAAQ,eAC/B4S,IAAWiB,GAAqBD,CAAoB,GAGpDE,IAAqBC,GAAgB;AAAA,IACzC,CAACpZ,MAAMA,EAAE,aAAaA,EAAE,OAAO,WAAWA,EAAE,OAAO,WAAWA,EAAE,OAAO,WAAWA,EAAE,OAAO;AAAA,EAAA,GAGvFqZ,IAAwB,CAACC,MAAoB;AACjD,IAAIA,MAAYL,KACdD,EAAsBM,CAAwB;AAAA,EAElD;AAEA,SACE,gBAAA3f,EAACL,IAAA,EAAQ,MAAMoK,GAAQ,cAAcC,GACnC,UAAA;AAAA,IAAA,gBAAA/L,EAACa,MAAe,SAAO,IACrB,UAAA,gBAAAb,EAAC,UAAA,EAAO,WAAU,kBAAiB,cAAW,gBAC5C,UAAA,gBAAAA,EAACG,KAAK,MAAM2F,GAAM,MAAM,WAAU,aAAY,GAChD,EAAA,CACF;AAAA,IACA,gBAAA9F,EAACe,IAAA,EAAe,OAAM,SAAQ,WAAU,uBAAsB,WAAS,IACrE,UAAA,gBAAAgB,EAAC,OAAA,EAAI,WAAU,uBAEb,UAAA;AAAA,MAAA,gBAAAA,EAAC,OAAA,EAAI,WAAU,gBACb,UAAA;AAAA,QAAA,gBAAA/B,EAACyV,MAAM,UAAA,cAAA,CAAW;AAAA,QAClB,gBAAA1T,EAACJ,IAAA,EAAO,OAAO0f,GAAsB,eAAeI,GAClD,UAAA;AAAA,UAAA,gBAAAzhB,EAAC8B,IAAA,EACC,UAAA,gBAAA9B,EAAC6B,IAAA,EAAY,aAAY,iBAAgB,GAC3C;AAAA,UACA,gBAAA7B,EAACkC,MAAc,OAAO,EAAE,QAAQ,WAAA,GAC7B,YAAmB,IAAI,CAACyf,MACvB,gBAAA3hB,EAACqC,IAAA,EAA8B,OAAOsf,EAAU,IAC7C,YAAU,MAAA,GADIA,EAAU,EAE3B,CACD,EAAA,CACH;AAAA,QAAA,EAAA,CACF;AAAA,MAAA,GACF;AAAA,MAGCtB,EAAS,SAAS,KACjB,gBAAArgB,EAACogB,MAAsB,SAAA3S,GAAkB,UAAA4S,GAAoB,UAAUnS,EAAA,CAAiB;AAAA,IAAA,EAAA,CAE5F,EAAA,CACF;AAAA,EAAA,GACF;AAEJ,GChEM0T,KAAW,CAAC,EAAE,OAAAC,QAA2B;AAC7C,QAAM,CAACC,GAAUC,CAAW,IAAIzW,EAAS,EAAK;AAE9C,SACE,gBAAAvJ,EAACL,IAAA,EAAQ,MAAMogB,GAAU,cAAcC,GACrC,UAAA;AAAA,IAAA,gBAAA/hB,EAACa,MAAe,SAAO,IACrB,UAAA,gBAAAb,EAAC,UAAA,EAAO,WAAU,kBAAiB,cAAW,gBAC5C,UAAA,gBAAAA,EAACG,KAAK,MAAM2F,GAAM,gBAAgB,WAAU,aAAY,GAC1D,EAAA,CACF;AAAA,IACA,gBAAA9F,EAACe,MAAe,OAAM,SAAQ,WAAU,oBAAmB,WAAS,IAClE,UAAA,gBAAAf,EAAC,OAAA,EAAI,WAAU,oCACZ,UAAA6hB,EAAM,IAAI,CAACG,GAAMpd,MAChB,gBAAA7C,EAACqL,IAAA,EAAoB,OAAO,KAC1B,UAAA;AAAA,MAAA,gBAAApN,EAACqN,IAAA,EAAe,SAAO,IACrB,UAAA,gBAAArN;AAAA,QAAC8M;AAAA,QAAA;AAAA,UACC,SAASkV,EAAK,SAAS,YAAY;AAAA,UACnC,MAAK;AAAA,UACL,SAAS,MAAM;AACb,YAAAA,EAAK,QAAA,GACLD,EAAY,EAAK;AAAA,UACnB;AAAA,UACA,cAAYC,EAAK;AAAA,UAEhB,UAAAA,EAAK;AAAA,QAAA;AAAA,MAAA,GAEV;AAAA,MACA,gBAAAhiB,EAACsN,IAAA,EAAgB,UAAA0U,EAAK,MAAA,CAAM;AAAA,IAAA,KAdhBpd,CAed,CACD,EAAA,CACH,EAAA,CACF;AAAA,EAAA,GACF;AAEJ;AC9CO,SAASqd,GAAgB,EAAE,kBAAAC,GAAkB,UAAAC,GAAU,SAAAjV,KAAiC;AAC7F,SACE,gBAAAnL,EAACqL,IAAA,EAAQ,OAAO,KACd,UAAA;AAAA,IAAA,gBAAApN,EAACqN,IAAA,EAAe,SAAO,IACrB,UAAA,gBAAArN;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,WAAU;AAAA,QACV,SAAAkN;AAAA,QACA,cAAW;AAAA,QACX,eAAaiV;AAAA,QAEb,UAAA,gBAAApgB,EAAC,OAAA,EAAI,WAAU,uEACb,UAAA;AAAA,UAAA,gBAAA/B,EAAC,QAAA,EAAK,WAAU,+DAA8D,UAAA,KAAC;AAAA,UAC/E,gBAAAA;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,WAAU;AAAA,cACV,OAAO,EAAE,iBAAiBkiB,EAAA;AAAA,YAAiB;AAAA,UAAA;AAAA,QAC7C,EAAA,CACF;AAAA,MAAA;AAAA,IAAA,GAEJ;AAAA,IACC,CAACC,KAAY,gBAAAniB,EAACsN,IAAA,EAAe,UAAA,aAAA,CAAU;AAAA,EAAA,GAC1C;AAEJ;ACvBO,SAAS8U,GAAW,EAAE,SAAAC,KAA4B;AACvD,SACE,gBAAAriB;AAAA,IAACoS;AAAA,IAAA;AAAA,MACC,MAAMtM,GAAM;AAAA,MACZ,SAASuc,EAAQ;AAAA,MACjB,QAAQA,EAAQ,kBAAA,EAAoB;AAAA,MACpC,SAAQ;AAAA,IAAA;AAAA,EAAA;AAGd;ACTO,SAASC,GAAa,EAAE,SAAAD,KAA8B;AAC3D,SACE,gBAAAriB;AAAA,IAACoS;AAAA,IAAA;AAAA,MACC,MAAMtM,GAAM;AAAA,MACZ,SAASuc,EAAQ;AAAA,MACjB,QAAQA,EAAQ,kBAAA,EAAoB;AAAA,MACpC,SAAQ;AAAA,IAAA;AAAA,EAAA;AAGd;ACTO,SAASE,GAAgB,EAAE,SAAAF,KAAiC;AACjE,SACE,gBAAAriB;AAAA,IAACoS;AAAA,IAAA;AAAA,MACC,MAAMtM,GAAM;AAAA,MACZ,SAASuc,EAAQ;AAAA,MACjB,QAAQA,EAAQ,kBAAA,EAAoB;AAAA,MACpC,SAAQ;AAAA,IAAA;AAAA,EAAA;AAGd;ACTO,SAASG,GAAgB,EAAE,SAAAH,KAAiC;AACjE,SACE,gBAAAriB;AAAA,IAACoS;AAAA,IAAA;AAAA,MACC,MAAK;AAAA,MACL,SAASiQ,EAAQ;AAAA,MACjB,QAAQA,EAAQ,mBAAA;AAAA,MAChB,SAAQ;AAAA,IAAA;AAAA,EAAA;AAGd;ACTO,SAASI,GAAgB,EAAE,SAAAJ,KAAiC;AACjE,QAAM,EAAE,WAAAK,GAAW,uBAAAC,EAAA,IAA0BN,GACvCpd,IACJyd,MAAc,SAAS5c,GAAM,YAAY4c,MAAc,WAAW5c,GAAM,cAAcA,GAAM;AAE9F,SACE,gBAAA9F;AAAA,IAACoS;AAAA,IAAA;AAAA,MACC,MAAAnN;AAAA,MACA,SAAS0d;AAAA,MACT,SAAS,SAASD,EAAU,OAAO,CAAC,EAAE,gBAAgBA,EAAU,MAAM,CAAC,CAAC;AAAA,IAAA;AAAA,EAAA;AAG9E;ACCO,SAASE,GAAa,EAAE,eAAAvU,GAAe,gBAAAC,GAAgB,UAAAK,GAAU,cAAAlN,KAAmC;AACzG,QAAM,CAACqK,GAAQC,CAAS,IAAIT,EAAS,EAAK,GAEpCuX,IAAmB,CAACrhB,MAAkB;AAC1C,IAAAuK,EAAUvK,CAAI,GACdC,KAAA,QAAAA,EAAeD;AAAA,EACjB;AAEA,SACE,gBAAAO,EAACL,IAAA,EAAQ,MAAMoK,GAAQ,cAAc+W,GACnC,UAAA;AAAA,IAAA,gBAAA7iB,EAACa,MAAe,SAAO,IACrB,UAAA,gBAAAb,EAAC,UAAA,EAAO,WAAU,kBAAiB,cAAW,gBAC5C,UAAA,gBAAAA,EAACG,KAAK,MAAK,4BAA2B,WAAU,YAAA,CAAY,GAC9D,GACF;AAAA,IACA,gBAAAH,EAACe,IAAA,EAAe,OAAM,OAAM,WAAU,oBAAmB,WAAS,IAChE,UAAA,gBAAAgB,EAAC,OAAA,EAAI,WAAU,oCACb,UAAA;AAAA,MAAA,gBAAAA,EAACqL,IAAA,EAAQ,eAAe,KACtB,UAAA;AAAA,QAAA,gBAAApN,EAACqN,IAAA,EAAe,SAAO,IACrB,UAAA,gBAAArN;AAAA,UAAC8M;AAAA,UAAA;AAAA,YACC,SAAQ;AAAA,YACR,MAAK;AAAA,YACL,SAAS,MAAM;AACb,cAAAuB,EAAA,GACAwU,EAAiB,EAAK;AAAA,YACxB;AAAA,YACA,cAAW;AAAA,YAEX,UAAA,gBAAA7iB,EAACG,GAAA,EAAK,MAAK,iCAAgC,WAAU,YAAA,CAAY;AAAA,UAAA;AAAA,QAAA,GAErE;AAAA,QACA,gBAAAH,EAACsN,MAAe,UAAA,eAAA,CAAY;AAAA,MAAA,GAC9B;AAAA,MACA,gBAAAvL,EAACqL,IAAA,EAAQ,eAAe,KACtB,UAAA;AAAA,QAAA,gBAAApN,EAACqN,IAAA,EAAe,SAAO,IACrB,UAAA,gBAAArN;AAAA,UAAC8M;AAAA,UAAA;AAAA,YACC,SAAQ;AAAA,YACR,MAAK;AAAA,YACL,SAAS,MAAM;AACb,cAAAwB,EAAA,GACAuU,EAAiB,EAAK;AAAA,YACxB;AAAA,YACA,cAAW;AAAA,YAEX,UAAA,gBAAA7iB,EAACG,GAAA,EAAK,MAAK,iCAAgC,WAAU,YAAA,CAAY;AAAA,UAAA;AAAA,QAAA,GAErE;AAAA,QACA,gBAAAH,EAACsN,MAAe,UAAA,gBAAA,CAAa;AAAA,MAAA,GAC/B;AAAA,MACA,gBAAAvL,EAACqL,IAAA,EAAQ,eAAe,KACtB,UAAA;AAAA,QAAA,gBAAApN,EAACqN,IAAA,EAAe,SAAO,IACrB,UAAA,gBAAArN;AAAA,UAAC8M;AAAA,UAAA;AAAA,YACC,SAAQ;AAAA,YACR,MAAK;AAAA,YACL,SAAS,MAAM;AACb,cAAA+V,EAAiB,EAAK,GACtBlU,EAAA;AAAA,YACF;AAAA,YACA,cAAW;AAAA,YAEX,4BAACxO,GAAA,EAAK,MAAM2F,GAAM,OAAO,WAAU,YAAA,CAAY;AAAA,UAAA;AAAA,QAAA,GAEnD;AAAA,QACA,gBAAA9F,EAACsN,MAAe,UAAA,SAAA,CAAM;AAAA,MAAA,EAAA,CACxB;AAAA,IAAA,EAAA,CACF,EAAA,CACF;AAAA,EAAA,GACF;AAEJ;ACnBO,SAASwV,GAAY;AAAA,EAC1B,SAAAT;AAAA,EACA,iBAAAU;AAAA,EACA,eAAAC,IAAgB,OAAO;AAAA,EACvB,kBAAAd;AAAA,EACA,eAAAe;AAAA,EACA,eAAA/P;AAAA,EACA,oBAAAgQ;AAAA,EACA,WAAAC,IAAY;AAAA,EACZ,eAAAC;AAAA,EACA,kBAAAjU;AAAA,EACA,iBAAAE;AAAA,EACA,kBAAAgU;AAAA,EACA,gBAAA/T,IAAiB;AAAA,EACjB,gBAAAC;AAAA,EACA,gBAAAC,IAAiB;AAAA,EACjB,gBAAAC;AAAA,EACA,mBAAAC,IAAoB;AAAA,EACpB,mBAAAC;AAAA,EACA,kBAAAC,IAAmB;AAAA,EACnB,kBAAAC;AAAA,EACA,yBAAAC,IAA0B;AAAA,EAC1B,yBAAAC;AAAA,EACA,mBAAAC,IAAoB;AAAA,EACpB,mBAAAC;AAAA,EACA,kBAAAqT;AAAA,EACA,eAAAjV;AAAA,EACA,gBAAAC;AAAA,EACA,UAAAK;AAAA,EACA,sBAAA4U;AAAA,EACA,UAAAhJ;AAAA,EACA,qBAAAiJ;AAAA,EACA,2BAAAC;AAAA,EACA,sBAAAC;AAAA,EACA,mBAAAvV,KAAoB;AAAA,EACpB,WAAAC;AAAA,EACA,mBAAAuV,KAAoB;AAAA,EACpB,qBAAAC;AAAA,EACA,0BAAAC;AACF,GAAqB;AAEnB,QAAM,CAAC3S,IAAuBC,EAAwB,IAAI7F,EAAS,EAAK,GAClE,CAACwY,IAAsBC,EAAuB,IAAIzY,EAAS,EAAK,GAChE,CAACwF,IAAyBC,EAA0B,IAAIzF,EAAS,EAAK,GACtE,CAAC0Y,IAAyBC,EAA0B,IAAI3Y,EAAS,EAAK,GAKtEyG,IAAUvE,GAAkB+V,EAAoB,GAChD,CAACvS,GAAwBC,CAAyB,IAAI3F,EAAS,EAAK,GACpE,CAAC8F,GAAuBC,CAAwB,IAAI/F,EAAS,EAAK,GAClE,CAACgG,IAA0BC,CAA2B,IAAIjG,EAAS,EAAK,GACxE,CAACkG,IAAyBC,EAA0B,IAAInG,EAAS,EAAK,GACtE,CAACoG,IAAyBC,EAA0B,IAAIrG,EAAS,EAAK,GACtE,CAACsG,IAA0BC,EAA2B,IAAIvG,EAAS,EAAK;AAE9E,SACE,gBAAAvJ,EAAC,OAAA,EAA4C,WAAU,oBAErD,UAAA;AAAA,IAAA,gBAAA/B;AAAA,MAACma;AAAA,MAAA;AAAA,QACC,OAAOkI,EAAQ,kBAAA,EAAoB,cAAcA,EAAQ;AAAA,QACzD,UAAU,CAACre,OAAqCqe,EAAQ,uBAAuBre,GAAE,OAAO,KAAK;AAAA,QAC7F,cAAckgB;AAAA,QACd,QAAQP;AAAA,QACR,UAAUC;AAAA,QACV,WAAWZ,IAAgB;AAAA,QAC3B,aAAa,UAAUO,KAAwBA,GAA0C,OAAO;AAAA,QAChG,UAAAhJ;AAAA,MAAA;AAAA,IAAA;AAAA,IAUF,gBAAAva;AAAA,MAACoS;AAAA,MAAA;AAAA,QACC,MAAK;AAAA,QACL,SAAS,MAAM;AACb,UAAA6R,GAA2B,EAAI,GAC/BZ,EAAA;AAAA,QACF;AAAA,QACA,cAAc,MAAMY,GAA2B,EAAK;AAAA,QACpD,SAAS,eAAe,KAAK,MAAM5B,EAAQ,QAAQ,CAAC;AAAA,QACpD,iBAAiB2B,OAA2BZ,KAAA,gBAAAA,EAAe,UAAS;AAAA,QACpE,SAAQA,KAAA,gBAAAA,EAAe,UAAS,cAAcrR,EAAQ;AAAA,MAAA;AAAA,IAAA;AAAA,IAIxD,gBAAA/R;AAAA,MAACiiB;AAAA,MAAA;AAAA,QACC,kBAAAC;AAAA,QACA,UAAUe;AAAA,QACV,SAAS/P;AAAA,MAAA;AAAA,IAAA;AAAA,IAIX,gBAAAlT,EAACoiB,MAAW,SAAAC,GAAkB;AAAA,IAC9B,gBAAAriB,EAACsiB,MAAa,SAAAD,GAAkB;AAAA,IAChC,gBAAAriB,EAACuiB,MAAgB,SAAAF,GAAkB;AAAA,IACnC,gBAAAriB,EAACwiB,MAAgB,SAAAH,GAAkB;AAAA,IAGnC,gBAAAriB,EAACyiB,MAAgB,SAAAJ,GAAkB;AAAA,IAGnC,gBAAAriB;AAAA,MAACmhB;AAAA,MAAA;AAAA,QACC,SAASoC;AAAA,QACT,uBAAuBlB,EAAQ;AAAA,QAC/B,iBAAiBqB;AAAA,QACjB,QAAQF;AAAA,QACR,cAAcC;AAAA,MAAA;AAAA,IAAA;AAAA,IAIflU,KACC,gBAAAvP;AAAA,MAACoS;AAAA,MAAA;AAAA,QACC,MAAK;AAAA,QACL,SAAS,MAAM;AACb,UAAAjB,GAAyB,EAAI,GAC7B5B,EAAA;AAAA,QACF;AAAA,QACA,cAAc,MAAM4B,GAAyB,EAAK;AAAA,QAClD,SAAQ;AAAA,QACR,iBAAiBD,MAAyB5B;AAAA,QAC1C,QAAQA,KAAkByC,EAAQ;AAAA,MAAA;AAAA,IAAA;AAAA,IAKtC,gBAAA/R;AAAA,MAACoS;AAAA,MAAA;AAAA,QACC,MAAM,gBAAApS,EAACqS,IAAA,EAAe,MAAM,IAAI,WAAU,gBAAe;AAAA,QACzD,SAAS,MAAM;AACb,UAAAtB,GAA2B,EAAI,GAC/B5B,EAAA;AAAA,QACF;AAAA,QACA,cAAc,MAAM4B,GAA2B,EAAK;AAAA,QACpD,SAAQ;AAAA,QACR,iBAAiBD,OAA2BsS,KAAA,gBAAAA,EAAe,UAAS;AAAA,QACpE,SAAQA,KAAA,gBAAAA,EAAe,UAAS,cAAcrR,EAAQ;AAAA,MAAA;AAAA,IAAA;AAAA,IAIxD,gBAAA/R;AAAA,MAACoS;AAAA,MAAA;AAAA,QACC,MAAK;AAAA,QACL,SAAS,MAAM;AACb,UAAAnB,EAA0B,EAAI,GAC9B5B,EAAA;AAAA,QACF;AAAA,QACA,cAAc,MAAM4B,EAA0B,EAAK;AAAA,QACnD,SAAQ;AAAA,QACR,iBAAiBD,MAA0BoS,KAAA,gBAAAA,EAAe,UAAS;AAAA,QACnE,SAAQA,KAAA,gBAAAA,EAAe,UAAS,aAAarR,EAAQ;AAAA,MAAA;AAAA,IAAA;AAAA,IAItDtC,KACC,gBAAAzP;AAAA,MAACoS;AAAA,MAAA;AAAA,QACC,MAAK;AAAA,QACL,SAAS,MAAM;AACb,UAAAf,EAAyB,EAAI,GAC7B5B,EAAA;AAAA,QACF;AAAA,QACA,cAAc,MAAM4B,EAAyB,EAAK;AAAA,QAClD,SAAQ;AAAA,QACR,iBAAiBD,KAAyB5B;AAAA,QAC1C,QAAQA,KAAkBuC,EAAQ;AAAA,MAAA;AAAA,IAAA;AAAA,IAKrCpC,KACC,gBAAA3P;AAAA,MAACoS;AAAA,MAAA;AAAA,QACC,MAAK;AAAA,QACL,SAAS,MAAM;AACb,UAAAb,EAA4B,EAAI,GAChC5B,EAAA;AAAA,QACF;AAAA,QACA,cAAc,MAAM4B,EAA4B,EAAK;AAAA,QACrD,SAAQ;AAAA,QACR,iBAAiBD,MAA4B5B;AAAA,QAC7C,QAAQA,KAAqBqC,EAAQ;AAAA,MAAA;AAAA,IAAA;AAAA,IAKxClC,KACC,gBAAA7P;AAAA,MAACoS;AAAA,MAAA;AAAA,QACC,MAAK;AAAA,QACL,SAAS,MAAM;AACb,UAAAX,GAA2B,EAAI,GAC/B5B,EAAA;AAAA,QACF;AAAA,QACA,cAAc,MAAM4B,GAA2B,EAAK;AAAA,QACpD,SAAQ;AAAA,QACR,iBAAiBD,MAA2B5B;AAAA,QAC5C,QAAQA,KAAoBmC,EAAQ;AAAA,MAAA;AAAA,IAAA;AAAA,IAKvChC,KACC,gBAAA/P;AAAA,MAACoS;AAAA,MAAA;AAAA,QACC,MAAK;AAAA,QACL,SAAS,MAAM;AACb,UAAAT,GAA2B,EAAI,GAC/B5B,EAAA;AAAA,QACF;AAAA,QACA,cAAc,MAAM4B,GAA2B,EAAK;AAAA,QACpD,SAAQ;AAAA,QACR,iBAAiBD,MAA2B5B;AAAA,QAC5C,QAAQA,KAA2BiC,EAAQ;AAAA,MAAA;AAAA,IAAA;AAAA,IAK9C9B,KACC,gBAAAjQ;AAAA,MAACoS;AAAA,MAAA;AAAA,QACC,MAAK;AAAA,QACL,SAAS,MAAM;AACb,UAAAP,GAA4B,EAAI,GAChC5B,EAAA;AAAA,QACF;AAAA,QACA,cAAc,MAAM4B,GAA4B,EAAK;AAAA,QACrD,SAAQ;AAAA,QACR,iBAAiBD,MAA4B5B;AAAA,QAC7C,QAAQA,KAAqB+B,EAAQ;AAAA,MAAA;AAAA,IAAA;AAAA,IAKzC,gBAAA/R;AAAA,MAACoS;AAAA,MAAA;AAAA,QACC,MAAK;AAAA,QACL,SAAS,MAAM;AACb,UAAA2R,GAAwB,EAAI,GAC5Bb,KAAA,QAAAA;AAAA,QACF;AAAA,QACA,cAAc,MAAMa,GAAwB,EAAK;AAAA,QACjD,SAASZ,IAAY,sBAAsB;AAAA,QAC3C,iBAAiBW;AAAA,QACjB,UAAU,CAACX;AAAA,QACX,WAAYA,IAA8B,KAAlB;AAAA,MAAkB;AAAA,IAAA;AAAA,IAI3CG,KAAoB,gBAAAtjB,EAAC4hB,IAAA,EAAS,OAAO0B,IAAiB,CAAG;AAAA,IAG1D,gBAAAtjB;AAAA,MAAC4iB;AAAA,MAAA;AAAA,QACC,eAAAvU;AAAA,QACA,gBAAAC;AAAA,QACA,UAAAK;AAAA,QACA,cAAckV;AAAA,MAAA;AAAA,IAAA;AAAA,IAIf1V,MACC,gBAAAnO,EAAC,UAAA,EAAO,WAAU,kBAAiB,SAASoO,GAAW,UAAA,UAAA,CAEvD;AAAA,EAAA,EAAA,GA1MM,gBAAgB2U,CAAe,EA4MzC;AAEJ;ACpTO,SAASoB,GACdC,GACAC,GACAC,GACa;AAEb,QAAMC,IAAiBH,EAAc,kBAAA;AAGrC,MAAII;AACJ,EAAIJ,EAAc,kBAAkB,YAAY,0BAA0BA,IAExEI,IAA4BJ,EAAoE,qBAAA,IAEhGI,IAA2BJ,EAAc;AAI3C,QAAMK,IAASC,GAAyBN,GAAeC,GAAYG,GAA0BD,CAAc;AAG3G,SAAO,IAAID,EAAY;AAAA,IACrB,IAAIF,EAAc;AAAA,IAClB,MAAMA,EAAc;AAAA,IACpB,GAAGK,EAAO;AAAA,IACV,GAAGA,EAAO;AAAA,IACV,UAAUL,EAAc;AAAA,IACxB,UAAUK,EAAO;AAAA,IACjB,YAAYL,EAAc;AAAA,IAC1B,OAAOA,EAAc;AAAA,IACrB,WAAWA,EAAc;AAAA,IACzB,eAAeK,EAAO;AAAA,EAAA,CACvB;AACH;AAMA,SAASC,GACPN,GACAC,GACAM,GACAJ,GACiB;AACjB,MAAIK,GACAvb,GAAWO;AACf,QAAMib,IAAWF;AAEjB,UAAQN,GAAA;AAAA,IACN,KAAK;AAMH,MAAAO,IAAgB,EAAE,QAHCD,IAAoB,MAEX,GACF,OAAO,EAAA,GAEjCtb,IAAIkb,EAAe,GACnB3a,IAAI2a,EAAe;AACnB;AAAA,IAEF,KAAK;AAGH,YAAMO,IAAW,KACXC,IAAqBJ,IAAoBP,EAAc,KAAK,SAAS,KACrEY,IAAc,KAAK,IAAID,GAAoBD,CAAQ;AAEzD,MAAAF,IAAgB,EAAE,OAAOI,EAAA;AAGzB,YAAMC,IAAeN,IAAoB;AACzC,MAAAtb,IAAIkb,EAAe,IAAIS,IAAc,GACrCpb,IAAI2a,EAAe,IAAIU,IAAe;AACtC;AAAA,IAEF,KAAK;AAEH,YAAMC,IAAe,KACfC,IAAqBR,IAAoBP,EAAc,KAAK,SAAS;AAC3E,MAAAQ,IAAgB;AAAA,QACd,OAAO,KAAK,IAAIO,GAAoBD,CAAY;AAAA,QAChD,YAAYE,GAAc;AAAA,MAAA,GAG5B/b,IAAIkb,EAAe,GACnB3a,IAAI2a,EAAe;AACnB;AAAA,IAEF,KAAK;AAEH,YAAMc,IAAe,KACfC,IAAqBX,IAAoBP,EAAc,KAAK,SAAS;AAC3E,MAAAQ,IAAgB;AAAA,QACd,OAAO,KAAK,IAAIU,GAAoBD,CAAY;AAAA,QAChD,WAAWE,GAAc;AAAA,QACzB,WAAWA,GAAc;AAAA,MAAA,GAE3Blc,IAAIkb,EAAe,GACnB3a,IAAI2a,EAAe;AACnB;AAAA,IAEF,KAAK;AAEH,YAAMiB,IAAe,KACfC,IAAqBd,IAAoBP,EAAc,KAAK,SAAS;AAC3E,MAAAQ,IAAgB;AAAA,QACd,OAAO,KAAK,IAAIa,GAAoBD,CAAY;AAAA,QAChD,WAAWE,GAAc;AAAA,QACzB,WAAWA,GAAc;AAAA,MAAA,GAE3Brc,IAAIkb,EAAe,GACnB3a,IAAI2a,EAAe;AACnB;AAAA,IAEF,KAAK;AAEH,YAAMoB,IAAe,KACfC,IAAqBjB,IAAoBP,EAAc,KAAK,SAAS;AAC3E,MAAAQ,IAAgB;AAAA,QACd,OAAO,KAAK,IAAIgB,GAAoBD,CAAY;AAAA,QAChD,YAAYE,GAAc;AAAA,MAAA,GAE5Bxc,IAAIkb,EAAe,GACnB3a,IAAI2a,EAAe;AACnB;AAAA,IAEF;AAEE,MAAAK,IAAgB,EAAE,OAAO,IAAA,GACzBvb,IAAIkb,EAAe,GACnB3a,IAAI2a,EAAe;AAAA,EAAA;AAGvB,SAAO,EAAE,GAAAlb,GAAG,GAAAO,GAAG,UAAAib,GAAU,eAAAD,EAAA;AAC3B;ACjEO,SAASkB,GAAeC,IAAiC,IAA0B;AACxF,QAAM,EAAE,iBAAAC,MAAoBD,GAEtB;AAAA,IACJ,iBAAAE;AAAA,IACA,oBAAAC;AAAA,IACA,qBAAAC;AAAA,EAAA,IACEC,GAAA,GAGE7C,IAAuB2C,KAAsBD,GAG7CvC,IAAuBzc;AAAA,IAC3B,CAACgL,MAAkC;AACjC,UAAKgU;AAEL,YAAIC,GAAoB;AAEtB,cAAI,EAAED,aAA2BI,IAAe;AAChD,gBAAMC,IAAeL,EAAgB,MAAA,GAC/BM,IAAaD,EAAa,SAAS,UAAU,CAACje,MAAMA,EAAE,OAAO6d,EAAmB,EAAE;AACxF,UAAIK,MAAe,OACjBD,EAAa,SAASC,CAAU,IAAItU,GACpCkU,EAAoBG,CAAY;AAAA,QAEpC;AACE,UAAAH,EAAoBlU,CAAc;AAAA,IAEtC;AAAA,IACA,CAACgU,GAAiBC,GAAoBC,CAAmB;AAAA,EAAA,GAIrDK,IAAmBjD,KAAA,gBAAAA,EAAsB,IACzCkD,IAAmBnhB,EAA2B,MAAS,GAGvD,CAACohB,GAAeC,CAAgB,IAAIrb,EAAiB,EAAE,GACvD,CAACsb,GAAgBC,CAAiB,IAAIvb,EAAiB,SAAS,GAChE,CAACwb,GAAiBC,CAAkB,IAAIzb,EAAiB,OAAO,GAChE,CAAC0b,GAAgBC,CAAiB,IAAI3b,EAAoB,QAAQ;AAGxE,EAAA9F,EAAU,MAAM;AACd,IAAIghB,MAAqBC,EAAiB,YACxCA,EAAiB,UAAUD,GAEvBjD,KAAwBA,aAAgC2D,OACtD3D,EAAqB,kBAAkB,YAAY,0BAA0BA,IAC/EoD,EAAiB,KAAK,MAAOpD,EAAyC,qBAAA,CAAsB,CAAC,IACpFA,EAAqB,aAAa,UAC3CoD,EAAiB,KAAK,MAAMpD,EAAqB,QAAQ,CAAC,GAExDA,EAAqB,UAAU,UACjCsD,EAAkBtD,EAAqB,KAAK,GAE1CA,EAAqB,eAAe,UACtCwD,EAAmBxD,EAAqB,UAAU,GAEpD0D,EAAkB1D,EAAqB,aAAa,QAAQ;AAAA,EAGlE,GAAG,CAACiD,GAAkBjD,CAAoB,CAAC;AAG3C,QAAMsB,IAAW6B,GACXS,IAAYP,GACZ1H,IAAa4H,GACbpE,IAAYsE,GAGZI,IAAc7D,aAAgC2D,KAAc3D,IAAuB,MACnF5V,KAAgByZ,KAAA,gBAAAA,EAAa,kBAAiB,GAC9CxZ,KAAawZ,KAAA,gBAAAA,EAAa,eAAc,KACxCC,KAAOD,KAAA,gBAAAA,EAAa,SAAQ,IAC5BE,KAASF,KAAA,gBAAAA,EAAa,WAAU,IAChCG,MAAYH,KAAA,gBAAAA,EAAa,cAAa,IAEtCI,KAAcJ,KAAA,gBAAAA,EAAgD,eAAwB,QAGtFK,KAAmBxgB;AAAA,IACvB,CAACygB,MAAoB;AAEnB,UADAf,EAAiBe,CAAO,GACpB,CAACnE,KAAwB,EAAEA,aAAgC2D,IAAc;AAE7E,YAAMjV,IAAiBsR,EAAqB,MAAA;AAC5C,MAAItR,EAAe,kBAAkB,YAAY,0BAA0BA,IACxEA,EAAmC,qBAAqByV,CAAO,IAEhEzV,EAAe,YAAYyV,CAAO,GAGhCzV,EAAe,YACjBA,EAAe,SAAS,mBAAmB,UAAU,GAGvDyR,EAAqBzR,CAAc;AAAA,IACrC;AAAA,IACA,CAACsR,GAAsBG,CAAoB;AAAA,EAAA,GAGvCiE,KAAmB1gB;AAAA,IACvB,CAAC2gB,MAAsB;AAErB,UADAb,EAAmBa,CAAS,GACxB,CAACrE,KAAwB,EAAEA,aAAgC2D,IAAc;AAE7E,YAAMjV,IAAiBsR,EAAqB,MAAA;AAC5C,MAAAtR,EAAe,aAAa2V,GAExB3V,EAAe,YACjBA,EAAe,SAAS,mBAAmB,YAAY,GAGzDyR,EAAqBzR,CAAc;AAAA,IACrC;AAAA,IACA,CAACsR,GAAsBG,CAAoB;AAAA,EAAA,GAGvCmE,IAAkB5gB;AAAA,IACtB,CAAC6gB,MAAqB;AAEpB,UADAjB,EAAkBiB,CAAQ,GACtB,CAACvE,KAAwB,EAAEA,aAAgC2D,IAAc;AAE7E,YAAMjV,IAAiBsR,EAAqB,MAAA;AAC5C,MAAAtR,EAAe,QAAQ6V,GACnB7V,EAAe,YACjBA,EAAe,SAAS,mBAAmB,OAAO,GAEpDyR,EAAqBzR,CAAc;AAAA,IACrC;AAAA,IACA,CAACsR,GAAsBG,CAAoB;AAAA,EAAA,GAGvCqE,IAAkB9gB;AAAA,IACtB,CAAC+gB,MAAyB;AAExB,UADAf,EAAkBe,CAAS,GACvB,CAACzE,KAAwB,EAAEA,aAAgC2D,IAAc;AAE7E,YAAMjV,IAAiBsR,EAAqB,MAAA;AAC5C,MAAAtR,EAAe,YAAY+V,GAC3BtE,EAAqBzR,CAAc;AAAA,IACrC;AAAA,IACA,CAACsR,GAAsBG,CAAoB;AAAA,EAAA,GAIvCuE,IAAuBhhB;AAAA,IAC3B,CAACygB,MAAoB;;AACnB,OAAIljB,IAAAwhB,KAAA,gBAAAA,EAAiB,YAAjB,QAAAxhB,EAA0B,kBAC5BwhB,EAAgB,QAAQ,oBAAoB,EAAE,UAAU0B,GAAS,IAEjED,GAAiBC,CAAO;AAAA,IAE5B;AAAA,IACA,CAACD,IAAkBzB,CAAe;AAAA,EAAA,GAG9BkC,KAA0BjhB;AAAA,IAC9B,CAACkhB,MAAkB;AACjB,YAAMT,IAAU7C,IAAWsD;AAC3B,MAAIT,KAAW,KAAKA,KAAW,OAC7BO,EAAqBP,CAAO;AAAA,IAEhC;AAAA,IACA,CAAC7C,GAAUoD,CAAoB;AAAA,EAAA,GAM3BG,IAA4BnhB;AAAA,IAChC,CAACohB,MAAuB;;AACtB,WAAI7jB,IAAAwhB,KAAA,gBAAAA,EAAiB,YAAjB,QAAAxhB,EAA0B,iBAAiB;AAC7C,QAAAwhB,EAAgB,QAAQ,oBAAoB,EAAE,eAAeqC,GAAY;AACzE;AAAA,MACF;AACA,UAAI,CAAC9E,KAAwB,EAAEA,aAAgC2D,IAAc;AAE7E,YAAMjV,IAAiBsR,EAAqB,MAAA;AAC5C,MAAAtR,EAAe,gBAAgBoW,GAC3BpW,EAAe,YACjBA,EAAe,SAAS,mBAAmB,eAAe,GAE5DyR,EAAqBzR,CAAc;AAAA,IACrC;AAAA,IACA,CAACsR,GAAsBG,GAAsBsC,CAAe;AAAA,EAAA,GAKxDsC,KAAyBrhB;AAAA,IAC7B,CAACshB,MAA0B;AACzB,UAAI,CAAChF,KAAwB,EAAEA,aAAgC2D,IAAc;AAE7E,YAAMjV,IAAiBsR,EAAqB,MAAA;AAC5C,MAAAtR,EAAe,aAAasW,GAC5B7E,EAAqBzR,CAAc;AAAA,IACrC;AAAA,IACA,CAACsR,GAAsBG,CAAoB;AAAA,EAAA,GAGvC8E,KAAyBvhB;AAAA,IAC7B,CAAC2gB,MAAsB;;AACrB,OAAIpjB,IAAAwhB,KAAA,gBAAAA,EAAiB,YAAjB,QAAAxhB,EAA0B,kBAC5BwhB,EAAgB,QAAQ,oBAAoB,EAAE,YAAY4B,GAAW,IAErED,GAAiBC,CAAS;AAAA,IAE9B;AAAA,IACA,CAACD,IAAkB3B,CAAe;AAAA,EAAA,GAG9ByC,IAAwBxhB;AAAA,IAC5B,CAACjD,MAA2C;;AAC1C,YAAM8jB,IAAW9jB,EAAE,OAAO;AAE1B,QADkBQ,IAAAwhB,KAAA,gBAAAA,EAAiB,YAAjB,gBAAAxhB,EAA0B,qBAC3BwhB,KAAA,QAAAA,EAAiB,WAChCA,EAAgB,QAAQ,oBAAoB,EAAE,OAAO8B,GAAU,IAE/DD,EAAgBC,CAAQ;AAAA,IAE5B;AAAA,IACA,CAACD,GAAiB7B,CAAe;AAAA,EAAA,GAG7B0C,KAAmBzhB,EAAY,MAAM;;AACzC,SAAIzC,IAAAwhB,KAAA,gBAAAA,EAAiB,YAAjB,QAAAxhB,EAA0B;AAC5B,MAAAwhB,EAAgB,QAAQ,yBAAyB,MAAM;AAAA,SAClD;AACL,UAAI,CAACzC,KAAwB,EAAEA,aAAgC2D,IAAc;AAC7E,YAAMhG,IAAUqC,EAAqB,MAAA;AACrC,MAAArC,EAAQ,OAAO,CAACmG,GACZnG,EAAQ,YACVA,EAAQ,SAAS,mBAAmB,MAAM,GAE5CwC,EAAqBxC,CAAO;AAAA,IAC9B;AAAA,EACF,GAAG,CAACmG,GAAM9D,GAAsBG,GAAsBsC,CAAe,CAAC,GAEhE2C,KAAqB1hB,EAAY,MAAM;;AAC3C,SAAIzC,IAAAwhB,KAAA,gBAAAA,EAAiB,YAAjB,QAAAxhB,EAA0B;AAC5B,MAAAwhB,EAAgB,QAAQ,yBAAyB,QAAQ;AAAA,SACpD;AACL,UAAI,CAACzC,KAAwB,EAAEA,aAAgC2D,IAAc;AAC7E,YAAMhG,IAAUqC,EAAqB,MAAA;AACrC,MAAArC,EAAQ,SAAS,CAACoG,GACdpG,EAAQ,YACVA,EAAQ,SAAS,mBAAmB,QAAQ,GAE9CwC,EAAqBxC,CAAO;AAAA,IAC9B;AAAA,EACF,GAAG,CAACoG,GAAQ/D,GAAsBG,GAAsBsC,CAAe,CAAC,GAElE4C,KAAwB3hB,EAAY,MAAM;;AAC9C,SAAIzC,IAAAwhB,KAAA,gBAAAA,EAAiB,YAAjB,QAAAxhB,EAA0B;AAC5B,MAAAwhB,EAAgB,QAAQ,yBAAyB,WAAW;AAAA,SACvD;AACL,UAAI,CAACzC,KAAwB,EAAEA,aAAgC2D,IAAc;AAC7E,YAAMhG,IAAUqC,EAAqB,MAAA;AACrC,MAAArC,EAAQ,YAAY,CAACqG,IACjBrG,EAAQ,YACVA,EAAQ,SAAS,mBAAmB,WAAW,GAEjDwC,EAAqBxC,CAAO;AAAA,IAC9B;AAAA,EACF,GAAG,CAACqG,IAAWhE,GAAsBG,GAAsBsC,CAAe,CAAC,GAErE6C,KAAyB5hB,EAAY,MAAM;AAC/C,QAAI,CAACsc,EAAsB;AAC3B,UAAMuF,IAAUtB,MAAe,cAAc,SAAS,aAChDtG,IAAUqC,EAAqB,MAAA;AAEpC,IAAArC,EAA+C,aAAa4H,GAC7DpF,EAAqBxC,CAAO;AAAA,EAC9B,GAAG,CAACsG,GAAYjE,GAAsBG,CAAoB,CAAC,GAErDqF,KAAqB9hB,EAAY,MAC9BugB,MAAe,aACrB,CAACA,CAAU,CAAC,GAET7E,KAAwB1b,EAAY,MAAM;AAC9C,UAAM+hB,IAA0B,CAAC,QAAQ,UAAU,OAAO,GACpDzhB,IAAeyhB,EAAW,QAAQtG,CAAS,GAC3CuG,IAAYD,GAAYzhB,IAAe,KAAKyhB,EAAW,MAAM;AACnE,IAAAjB,EAAgBkB,CAAS;AAAA,EAC3B,GAAG,CAACvG,GAAWqF,CAAe,CAAC,GAGzBmB,KAAoBjiB,EAAY,MAAsB;;AAC1D,SAAI4G,KAAArJ,IAAAwhB,KAAA,gBAAAA,EAAiB,YAAjB,gBAAAxhB,EAA0B,kBAA1B,QAAAqJ,EAAA,KAAArJ,IAA6C;AAC/C,YAAM2kB,KAAiBC,KAAAtb,IAAAkY,EAAgB,SAAQ,sBAAxB,gBAAAoD,EAAA,KAAAtb;AACvB,UAAIqb;AACF,eAAO;AAAA,UACL,YAAYA,EAAe,cAAcjK;AAAA,UACzC,UAAUiK,EAAe,YAAYtE;AAAA,UACrC,OAAOsE,EAAe,SAAShC;AAAA,UAC/B,MAAMgC,EAAe,QAAQ9B;AAAA,UAC7B,QAAQ8B,EAAe,UAAU7B;AAAA,UACjC,WAAW6B,EAAe,aAAa5B;AAAA,QAAA;AAAA,IAG7C;AACA,WAAO;AAAA,MACL,YAAArI;AAAA,MACA,UAAA2F;AAAA,MACA,OAAOsC;AAAA,MACP,MAAAE;AAAA,MACA,QAAAC;AAAA,MACA,WAAAC;AAAA,IAAA;AAAA,EAEJ,GAAG,CAACvB,GAAiB9G,GAAY2F,GAAUsC,GAAWE,GAAMC,GAAQC,EAAS,CAAC,GAGxE8B,KAA4BpiB;AAAA,IAChC,CAACya,MAA2B;AAC1B,UAAI,CAAC6B,EAAsB;AAE3B,YAAM+F,IAAeC,GAAiB7H,CAAO;AAC7C,UAAI,EAAC4H,KAAA,QAAAA,EAAc,WAAW;AAE9B,YAAMpI,IAAUiD,GAAiBZ,GAAqC7B,GAAS4H,EAAa,SAA4E;AACxK,MAAA5F,EAAqBxC,CAAO;AAAA,IAC9B;AAAA,IACA,CAACqC,GAAsBG,CAAoB;AAAA,EAAA;AAG7C,SAAO;AAAA,IACL,UAAAmB;AAAA,IACA,WAAAsC;AAAA,IACA,YAAAjI;AAAA,IACA,WAAAwD;AAAA,IACA,MAAA2E;AAAA,IACA,QAAAC;AAAA,IACA,WAAAC;AAAA,IACA,YAAAC;AAAA,IACA,eAAA7Z;AAAA,IACA,YAAAC;AAAA,IACA,sBAAAqa;AAAA,IACA,yBAAAC;AAAA,IACA,2BAAAE;AAAA,IACA,wBAAAE;AAAA,IACA,wBAAAE;AAAA,IACA,uBAAAC;AAAA,IACA,kBAAAC;AAAA,IACA,oBAAAC;AAAA,IACA,uBAAAC;AAAA,IACA,wBAAAC;AAAA,IACA,oBAAAE;AAAA,IACA,uBAAApG;AAAA,IACA,mBAAAuG;AAAA,IACA,2BAAAG;AAAA,EAAA;AAEJ;ACnaA,MAAMpP,KAASC,GAAa,iBAAiB;AAiCtC,SAASsP,GAAgBzD,GAAwD;;AACtF,QAAM,EAAE,SAAAtY,GAAS,MAAA3G,IAAO,KAAK,iBAAA8O,IAAkB,eAAe,SAAAiB,IAAU,OAASkP,GAE3E,CAAC0D,GAAYC,CAAa,IAAIpe,EAAwB,IAAI,GAC1D,CAACqe,GAAWC,CAAY,IAAIte,EAAS,EAAK,GAC1Cue,IAAcvkB,EAA6C,IAAI;AAErE,SAAAE,EAAU,MAAM;AACd,QAAI,CAACqR,GAAS;AACZ,MAAA6S,EAAc,IAAI,GAClBE,EAAa,EAAK;AAClB;AAAA,IACF;AAEA,QAAIE,IAAU;AACd,WAAAF,EAAa,EAAI,GAGbC,EAAY,WACd,aAAaA,EAAY,OAAO,GAGlCA,EAAY,UAAU,WAAW,MAAM;AA6CrC,OA5CwB,YAAY;AAClC,YAAI;AAEF,cAAIpc,aAAmBsc,MAAgBtc,EAAQ,UAAU;AACvD,kBAAMuc,IAAM,IAAI,MAAA;AAShB,gBARAA,EAAI,cAAc,aAElB,MAAM,IAAI,QAAc,CAACC,GAASC,MAAW;AAC3C,cAAAF,EAAI,SAAS,MAAMC,EAAA,GACnBD,EAAI,UAAU,MAAME,EAAO,IAAI,MAAM,sBAAsB,CAAC,GAC5DF,EAAI,MAAMvc,EAAQ;AAAA,YACpB,CAAC,GAEG,CAACqc,EAAS;AAAA,UAChB;AAGA,gBAAM1S,IAAM+S,GAAuB1c,GAAS;AAAA,YAC1C,OAAO3G;AAAA,YACP,QAAQA;AAAA,YACR,SAAS;AAAA,YACT,iBAAA8O;AAAA,UAAA,CACD;AAED,UAAIkU,MACFJ,EAActS,CAAG,GACjBwS,EAAa,EAAK;AAAA,QAEtB,SAASlN,GAAO;AAGd,cAFAzC,GAAO,KAAK,+BAA+ByC,CAAK,GAE5CoN,GAAS;AACX,kBAAM1S,IAAM+S,GAAuB1c,GAAS;AAAA,cAC1C,OAAO3G;AAAA,cACP,QAAQA;AAAA,cACR,SAAS;AAAA,cACT,iBAAA8O;AAAA,YAAA,CACD;AACD,YAAA8T,EAActS,CAAG,GACjBwS,EAAa,EAAK;AAAA,UACpB;AAAA,QACF;AAAA,MACF,GAEA;AAAA,IACF,GAAG,EAAE,GAEE,MAAM;AACX,MAAAE,IAAU,IACND,EAAY,WACd,aAAaA,EAAY,OAAO;AAAA,IAEpC;AAAA,EACF,GAAG;AAAA,IACDpc,EAAQ;AAAA,IACRmI;AAAA,IACA9O;AAAA,IACA+P;AAAA;AAAA,IAEApJ,EAAQ;AAAA,IACRA,EAAQ;AAAA,IACRA,EAAQ;AAAA;AAAA,IAERA,EAAQ;AAAA,IACRA,aAAmByZ,KAAczZ,EAAQ,OAAO;AAAA,IAChDA,aAAmByZ,KAAczZ,EAAQ,WAAW;AAAA,IACpDA,aAAmByZ,KAAczZ,EAAQ,aAAa;AAAA,IACtDA,aAAmByZ,KAAczZ,EAAQ,QAAQ;AAAA,IACjDA,aAAmBsc,KAAetc,EAAQ,WAAW;AAAA,IACrDA,aAAmBsc,KAAetc,EAAQ,cAAc;AAAA,IACxDA,aAAmBsc,KAAetc,EAAQ,aAAa;AAAA,IACvDA,aAAmB2c,MAAe5lB,IAAAiJ,EAAQ,kBAAR,gBAAAjJ,EAAuB,YAAY;AAAA,IACrEiJ,aAAmB2c,MAAevc,IAAAJ,EAAQ,kBAAR,gBAAAI,EAAuB,OAAO;AAAA,IAChEJ,aAAmB4c,MAAcjB,KAAAtb,IAAAL,EAAQ,kBAAR,gBAAAK,EAAuB,WAAvB,gBAAAsb,EAA+B,SAAS;AAAA,IACzE3b,aAAmB4Y,MAAeiE,IAAA7c,EAAQ,aAAR,gBAAA6c,EAAkB,SAAS;AAAA,EAAA,CAC9D,GAEM,EAAE,YAAAb,GAAY,WAAAE,EAAA;AACvB;AC1IO,SAASY,GAAiB;AAAA,EAC/B,SAAA9c;AAAA,EACA,cAAA+c;AAAA,EACA,kBAAAC;AACF,GAOG;AACD,MAAI,CAAChd,EAAS,QAAO;AACrB,QAAMid,IAASjd,EAAQ,WAAW;AAClC,SACE,gBAAA1L,EAAA2C,IAAA,EACE,UAAA;AAAA,IAAA,gBAAA1E;AAAA,MAAC2qB;AAAA,MAAA;AAAA,QACC,SAAAld;AAAA,QACA,SAASgd;AAAA,MAAA;AAAA,IAAA;AAAA,IAEX,gBAAAzqB;AAAA,MAACoS;AAAA,MAAA;AAAA,QACC,MAAM,gBAAApS,EAAC4qB,IAAA,EAAS,QAAAF,EAAA,CAAgB;AAAA,QAChC,SAASF;AAAA,QACT,QAAQE;AAAA,QACR,SAASA,IAAS,iBAAiB;AAAA,QACnC,cAAYA,IAAS,iBAAiB;AAAA,MAAA;AAAA,IAAA;AAAA,EACxC,GACF;AAEJ;AAOA,SAASC,GAAmB;AAAA,EAC1B,SAAAld;AAAA,EACA,SAAAP;AACF,GAGG;AAID,QAAM,EAAE,YAAAuc,EAAA,IAAeD,GAAgB;AAAA,IACrC,SAAA/b;AAAA,IACA,MAAM;AAAA,IACN,iBAAiB;AAAA,EAAA,CAClB,GAEKod,IACJ,gBAAA7qB;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,WAAU;AAAA,MACV,OAAO,EAAE,YAAY,6CAAA;AAAA,MAEpB,UAAAypB,IACC,gBAAAzpB;AAAA,QAAC;AAAA,QAAA;AAAA,UACC,KAAKypB;AAAA,UACL,KAAI;AAAA,UACJ,OAAO,EAAE,OAAO,QAAQ,QAAQ,QAAQ,WAAW,UAAA;AAAA,QAAU;AAAA,MAAA,IAE7D;AAAA,IAAA;AAAA,EAAA;AAOR,SAAIvc,IAEA,gBAAAlN;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,MAAK;AAAA,MACL,SAAAkN;AAAA,MACA,eAAe,CAAClJ,MAAMA,EAAE,gBAAA;AAAA,MACxB,aAAa,CAACA,MAAMA,EAAE,gBAAA;AAAA,MACtB,cAAW;AAAA,MACX,OAAM;AAAA,MACN,WAAU;AAAA,MAET,UAAA6mB;AAAA,IAAA;AAAA,EAAA,IAKL,gBAAA7qB;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,eAAW;AAAA,MACX,WAAU;AAAA,MAET,UAAA6qB;AAAA,IAAA;AAAA,EAAA;AAGP;AAKA,SAASD,GAAS,EAAE,QAAAF,KAA+B;AACjD,SACE,gBAAA3oB,EAAC,OAAA,EAAI,OAAM,MAAK,QAAO,MAAK,SAAQ,aAAY,MAAK,QAAO,eAAW,IACrE,UAAA;AAAA,IAAA,gBAAA/B;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,GAAE;AAAA,QACF,GAAE;AAAA,QACF,OAAM;AAAA,QACN,QAAO;AAAA,QACP,IAAG;AAAA,QACH,QAAO;AAAA,QACP,aAAY;AAAA,QACZ,MAAM0qB,IAAS,iBAAiB;AAAA,QAChC,aAAaA,IAAS,OAAO;AAAA,MAAA;AAAA,IAAA;AAAA,IAE9BA,IACC,gBAAA1qB;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,GAAE;AAAA,QACF,QAAO;AAAA,QACP,aAAY;AAAA,QACZ,eAAc;AAAA,MAAA;AAAA,IAAA,IAGhB,gBAAAA;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,GAAE;AAAA,QACF,QAAO;AAAA,QACP,aAAY;AAAA,QACZ,eAAc;AAAA,MAAA;AAAA,IAAA;AAAA,EAChB,GAEJ;AAEJ;ACpIO,MAAM8qB,KAAuB,GAIvBC,KAA4B;AAuBlC,SAASC,GAAenJ,GAAqD;AAClF,MAAIA,EAAM,WAAW,EAAG,QAAO;AAC/B,MAAIoJ,IAAO,OACPC,IAAO,OACPC,IAAO,QACPC,IAAO;AACX,aAAWpJ,KAAQH;AACjB,IAAAoJ,IAAO,KAAK,IAAIA,GAAMjJ,EAAK,KAAK,CAAC,GACjCkJ,IAAO,KAAK,IAAIA,GAAMlJ,EAAK,KAAK,CAAC,GACjCmJ,IAAO,KAAK,IAAIA,GAAMnJ,EAAK,KAAK,IAAIA,EAAK,KAAK,KAAK,GACnDoJ,IAAO,KAAK,IAAIA,GAAMpJ,EAAK,KAAK,IAAIA,EAAK,KAAK,MAAM;AAEtD,SAAO,EAAE,GAAGiJ,GAAM,GAAGC,GAAM,OAAOC,IAAOF,GAAM,QAAQG,IAAOF,EAAA;AAChE;AAOO,SAASG,GACdxJ,GACAyJ,GACAC,GACkB;AAClB,QAAMC,IAA4B,CAAA;AAClC,aAAWxJ,KAAQH,GAAO;AACxB,QAAI4J,IAAK,GACLC,IAAK;AACT,YAAQJ,GAAA;AAAA,MACN,KAAK;AACH,QAAAG,IAAKF,EAAM,IAAIvJ,EAAK,KAAK;AACzB;AAAA,MACF,KAAK;AACH,QAAAyJ,IAAKF,EAAM,IAAIA,EAAM,QAAQ,KAAKvJ,EAAK,KAAK,IAAIA,EAAK,KAAK,QAAQ;AAClE;AAAA,MACF,KAAK;AACH,QAAAyJ,IAAKF,EAAM,IAAIA,EAAM,SAASvJ,EAAK,KAAK,IAAIA,EAAK,KAAK;AACtD;AAAA,MACF,KAAK;AACH,QAAA0J,IAAKH,EAAM,IAAIvJ,EAAK,KAAK;AACzB;AAAA,MACF,KAAK;AACH,QAAA0J,IAAKH,EAAM,IAAIA,EAAM,SAAS,KAAKvJ,EAAK,KAAK,IAAIA,EAAK,KAAK,SAAS;AACpE;AAAA,MACF,KAAK;AACH,QAAA0J,IAAKH,EAAM,IAAIA,EAAM,UAAUvJ,EAAK,KAAK,IAAIA,EAAK,KAAK;AACvD;AAAA,IAAA;AAEJ,KAAIyJ,MAAO,KAAKC,MAAO,MACrBF,EAAQ,KAAK,EAAE,IAAIxJ,EAAK,IAAI,GAAGA,EAAK,IAAIyJ,GAAI,GAAGzJ,EAAK,IAAI0J,GAAI;AAAA,EAEhE;AACA,SAAOF;AACT;AAWO,SAASG,GACd9J,GACAyJ,GACkB;AAClB,MAAIzJ,EAAM,SAASiJ;AACjB,UAAM,IAAIc;AAAA,MACR;AAAA,MACA,cAAcN,CAAI,mBAAmBR,EAAoB,0BAA0BjJ,EAAM,MAAM;AAAA,MAG/F,EAAE,MAAAyJ,GAAM,OAAOzJ,EAAM,QAAQ,KAAKiJ,GAAA;AAAA,IAAqB;AAI3D,QAAMe,IAAaP,MAAS,cACtBQ,IAAS,CAAC,GAAGjK,CAAK,EAAE;AAAA,IAAK,CAACtZ,GAAGW,MACjC2iB,IACItjB,EAAE,KAAK,IAAIA,EAAE,KAAK,QAAQ,KAAKW,EAAE,KAAK,IAAIA,EAAE,KAAK,QAAQ,KACzDX,EAAE,KAAK,IAAIA,EAAE,KAAK,SAAS,KAAKW,EAAE,KAAK,IAAIA,EAAE,KAAK,SAAS;AAAA,EAAA,GAG3D6iB,IAAQD,EAAO,CAAC,GAChBE,IAAOF,EAAOA,EAAO,SAAS,CAAC,GAC/BG,IAAOJ,IACTG,EAAK,KAAK,IAAIA,EAAK,KAAK,QAAQD,EAAM,KAAK,IAC3CC,EAAK,KAAK,IAAIA,EAAK,KAAK,SAASD,EAAM,KAAK,GAC1CG,IAAYJ,EAAO;AAAA,IACvB,CAACK,GAAKnK,MAASmK,KAAON,IAAa7J,EAAK,KAAK,QAAQA,EAAK,KAAK;AAAA,IAC/D;AAAA,EAAA,GAEIoK,KAAOH,IAAOC,MAAcJ,EAAO,SAAS,IAE5CN,IAA4B,CAAA;AAClC,MAAIa,IAASR,IAAaE,EAAM,KAAK,IAAIA,EAAM,KAAK;AACpD,aAAW/J,KAAQ8J,GAAQ;AACzB,UAAMQ,IAAUT,IAAa7J,EAAK,KAAK,IAAIA,EAAK,KAAK,GAC/CmG,IAAQkE,IAASC;AACvB,IAAInE,MAAU,KACZqD,EAAQ,KAAK;AAAA,MACX,IAAIxJ,EAAK;AAAA,MACT,GAAGA,EAAK,KAAK6J,IAAa1D,IAAQ;AAAA,MAClC,GAAGnG,EAAK,KAAK6J,IAAa,IAAI1D;AAAA,IAAA,CAC/B,GAEHkE,MAAWR,IAAa7J,EAAK,KAAK,QAAQA,EAAK,KAAK,UAAUoK;AAAA,EAChE;AACA,SAAOZ;AACT;AC9GO,SAASe,KAA+C;AAC7D,QAAM,EAAE,UAAAhS,GAAU,gBAAAiS,GAAgB,iBAAAvG,GAAiB,iBAAAwG,GAAiB,qBAAAC,GAAqB,aAAAC,EAAA,IACvFvG,GAAA,GAIIwG,IAAkB5Y,GAAQ,OAE5BwY,EAAe,SAAS,IACpBjS,EAAS,OAAO,CAAC9U,MAAO+mB,EAAe,SAAS/mB,EAAG,EAAE,CAAC,IACtDwgB,IACE,CAACA,CAAe,IAChB,CAAA,GACQ,OAAO,CAACxgB,MAAO,CAACA,EAAG,MAAM,GACxC,CAAC8U,GAAUiS,GAAgBvG,CAAe,CAAC,GAExC4G,IAAe5lB;AAAA,IACnB,CAACukB,MAA8B;AAC7B,UAAIA,EAAQ,WAAW,EAAG;AAC1B,YAAMsB,IAAO,IAAI,IAAIF,EAAgB,IAAI,CAACnnB,MAAO,CAACA,EAAG,IAAIA,CAAE,CAAC,CAAC,GACvDsnB,IAAWvB,EAAQ,QAAQ,CAACwB,MAAW;AAC3C,cAAMC,IAAaH,EAAK,IAAIE,EAAO,EAAE;AACrC,YAAI,CAACC,EAAY,QAAO,CAAA;AAExB,cAAMtM,IAAasM,EAAW,MAAA;AAC9B,QAAAtM,EAAW,IAAIqM,EAAO,GACtBrM,EAAW,IAAIqM,EAAO;AACtB,cAAME,IAAc,CAACznB,MAAsB;AACzC,UAAAknB,EAAY,CAACrP,MAASA,EAAK,IAAI,CAAC5U,MAAOA,EAAE,OAAOjD,EAAG,KAAKA,IAAKiD,CAAE,CAAC;AAAA,QAClE;AACA,eAAO,CAAC,EAAE,SAAS,MAAMwkB,EAAYvM,CAAU,GAAG,MAAM,MAAMuM,EAAYD,CAAU,GAAG;AAAA,MACzF,CAAC;AAED,MAAAP,EAAoBK,CAAQ;AAAA,IAC9B;AAAA,IACA,CAACH,GAAiBF,GAAqBC,CAAW;AAAA,EAAA,GAG9C3rB,IAAQiG;AAAA,IACZ,CAACqkB,MAAoB;AACnB,YAAMzJ,IAAyB+K,EAAgB,IAAI,CAACnnB,OAAQ;AAAA,QAC1D,IAAIA,EAAG;AAAA,QACP,GAAGA,EAAG;AAAA,QACN,GAAGA,EAAG;AAAA,QACN,MAAMA,EAAG,eAAA;AAAA,MAAe,EACxB;AACF,UAAI8lB,IAAQ1J,EAAM,UAAUkJ,KAA4BC,GAAenJ,CAAK,IAAI;AAChF,UAAI,CAAC0J,GAAO;AAEV,cAAMhT,IAAWkU,EAAgB,kBAAA;AACjC,YAAI,CAAClU,EAAU;AACf,QAAAgT,IAAQ,EAAE,GAAGhT,EAAS,GAAG,GAAGA,EAAS,GAAG,OAAOA,EAAS,OAAO,QAAQA,EAAS,OAAA;AAAA,MAClF;AACA,MAAAsU,EAAaxB,GAAaxJ,GAAOyJ,GAAMC,CAAK,CAAC;AAAA,IAC/C;AAAA,IACA,CAACqB,GAAiBH,GAAiBI,CAAY;AAAA,EAAA,GAG3CM,IAAalmB;AAAA,IACjB,CAACqkB,MAAyB;AACxB,YAAMzJ,IAAyB+K,EAAgB,IAAI,CAACnnB,OAAQ;AAAA,QAC1D,IAAIA,EAAG;AAAA,QACP,GAAGA,EAAG;AAAA,QACN,GAAGA,EAAG;AAAA,QACN,MAAMA,EAAG,eAAA;AAAA,MAAe,EACxB;AAEF,MAAAonB,EAAalB,GAAkB9J,GAAOyJ,CAAI,CAAC;AAAA,IAC7C;AAAA,IACA,CAACsB,GAAiBC,CAAY;AAAA,EAAA;AAGhC,SAAO;AAAA,IACL,cAAcD,EAAgB;AAAA,IAC9B,UAAUA,EAAgB,UAAU;AAAA,IACpC,eAAeA,EAAgB,UAAU9B;AAAA,IACzC,OAAA9pB;AAAA,IACA,YAAAmsB;AAAA,EAAA;AAEJ;AC3GO,MAAMC,KAA2C;AAAA,EACtD,EAAE,MAAM,QAAQ,MAAM,iCAAiC,OAAO,aAAA;AAAA,EAC9D,EAAE,MAAM,YAAY,MAAM,8CAA8C,OAAO,2BAAA;AAAA,EAC/E,EAAE,MAAM,SAAS,MAAM,kCAAkC,OAAO,cAAA;AAAA,EAChE,EAAE,MAAM,OAAO,MAAM,gCAAgC,OAAO,YAAA;AAAA,EAC5D,EAAE,MAAM,YAAY,MAAM,4CAA4C,OAAO,yBAAA;AAAA,EAC7E,EAAE,MAAM,UAAU,MAAM,mCAAmC,OAAO,eAAA;AACpE,GAEaC,KAAqD;AAAA,EAChE,EAAE,MAAM,cAAc,MAAM,+CAA+C,OAAO,0BAAA;AAAA,EAClF,EAAE,MAAM,YAAY,MAAM,6CAA6C,OAAO,wBAAA;AAChF,GCQaC,KAA8D,CAAC;AAAA,EAC1E,MAAAhC,IAAO;AAAA,EACP,sBAAA1S;AAAA,EACA,UAAA2U;AACF,MAAM;AACJ,QAAM,EAAE,UAAAhT,GAAU,gBAAAiS,GAAgB,iBAAAC,GAAiB,WAAAe,GAAW,iBAAAxH,EAAA,IAAoBI,GAAA,GAC5E,EAAE,WAAAqH,EAAA,IAAcC,GAAA,GAChB,EAAE,UAAAC,GAAU,eAAAC,GAAe,OAAA5sB,GAAO,YAAAmsB,EAAA,IAAeZ,GAAA,GAEjDsB,IAAavoB,EAAuB,IAAI,GACxC,CAACnD,GAAU2rB,CAAW,IAAIxiB,EAA+C,IAAI,GAI7EyiB,IAAkB/Z,GAAQ,MAAM;AACpC,UAAM6N,IAAyBtH,EAC5B,OAAO,CAAC9U,MAAO+mB,EAAe,SAAS/mB,EAAG,EAAE,CAAC,EAC7C,IAAI,CAACA,OAAQ,EAAE,IAAIA,EAAG,IAAI,GAAGA,EAAG,GAAG,GAAGA,EAAG,GAAG,MAAMA,EAAG,eAAA,EAAe,EAAI;AAC3E,WAAOulB,GAAenJ,CAAK;AAAA,EAC7B,GAAG,CAACtH,GAAUiS,CAAc,CAAC;AAiE7B,MA5DAhnB,EAAU,MAAM;AACd,QAAI8lB,MAAS,WAAY;AACzB,QAAI,CAACyC,GAAiB;AACpB,MAAAD,EAAY,IAAI;AAChB;AAAA,IACF;AAEA,UAAME,IAAiB,MAAM;;AAC3B,YAAMC,MAAezpB,IAAAqpB,EAAW,YAAX,gBAAArpB,EAAoB,gBAAe,GAClD0pB,MAAgBrgB,KAAAggB,EAAW,YAAX,gBAAAhgB,GAAoB,iBAAgB,IACpDsgB,IAAiB1B,EAAgB,kBAAA,GACjC2B,KAAYD,KAAA,gBAAAA,EAAgB,MAAK,GACjCE,KAAYF,KAAA,gBAAAA,EAAgB,MAAK,GACjCG,MAAclF,KAAAtb,KAAAkY,KAAA,gBAAAA,EAAiB,YAAjB,gBAAAlY,GAA0B,YAA1B,gBAAAsb,EAAA,KAAAtb,QAAyC,GACvDygB,KAASf,KAAA,gBAAAA,EAAW;AAE1B,UAAIgB,GACAC;AACJ,UAAIF,IAAQ;AACV,cAAMG,KAAaH,GAAO,sBAAA;AAC1B,QAAAC,IAAUE,GAAW,QAAQX,EAAgB,IAAIK,KAAaE,GAC9DG,KAAUC,GAAW,OAAOX,EAAgB,IAAIM,KAAaC;AAAA,MAC/D,OAAW1V,KACT4V,IAAU5V,EAAqB,QAAQmV,EAAgB,IAAIK,KAAaE,GACxEG,KAAU7V,EAAqB,OAAOmV,EAAgB,IAAIM,KAAaC,MAEvEE,IAAU,OAAO,aAAa,IAAKT,EAAgB,QAAQO,IAAe,GAC1EG,KAAU,OAAO,cAAc,IAAKV,EAAgB,SAASO,IAAe;AAE9E,YAAMK,KAAcZ,EAAgB,QAAQO,GACtCM,IAAeb,EAAgB,SAASO,GAExClC,IAAM;AACZ,UAAIyC,IAAMJ,KAAUP,IAAgB9B,GAChC0C,KAAON,IAAUG,KAAc;AAEnC,UAAIV,IAAe,GAAG;AAEpB,cAAMc,KAAUd,IAAe,IAAI,IAC7Be,KAAU,OAAO,aAAaf,IAAe,IAAI;AACvD,QAAAa,KAAO,KAAK,IAAIC,IAAS,KAAK,IAAIC,IAASF,EAAI,CAAC;AAAA,MAClD;AACA,MAAID,IAAM,OACRA,IAAMJ,KAAUG,IAAexC,IAEjCyC,IAAM,KAAK,IAAIA,GAAK,OAAO,cAAcX,IAAgB,EAAE,GAC3DW,IAAM,KAAK,IAAI,IAAIA,CAAG,GAEtBf,EAAY,EAAE,KAAAe,GAAK,MAAAC,IAAM;AAAA,IAC3B;AAEA,WAAAd,EAAA,GACA,OAAO,iBAAiB,UAAUA,CAAc,GAChD,OAAO,iBAAiB,UAAUA,GAAgB,EAAE,SAAS,IAAM,SAAS,IAAM,GAC3E,MAAM;AACX,aAAO,oBAAoB,UAAUA,CAAc,GACnD,OAAO,oBAAoB,UAAUA,GAAgB,EAAE,SAAS,IAAM;AAAA,IACxE;AAAA,EACF,GAAG,CAAC1C,GAAMyC,GAAiBtB,GAAiBe,GAAWxH,GAAiBpN,GAAsB6U,CAAS,CAAC,GAEpG,CAACE,KAAYnB,EAAe,WAAW,EAAG,QAAO;AAErD,QAAMnrB,IACJiqB,MAAS,aACL,EAAE,cAAc,UAAU,UAAU,UAAU,SAAS,QAAQ,gBAAgB,aAAA,IAC/EnpB,IACE;AAAA,IACE,KAAK,GAAGA,EAAS,GAAG;AAAA,IACpB,MAAM,GAAGA,EAAS,IAAI;AAAA,IACtB,UAAU;AAAA,IACV,WAAW;AAAA,IACX,cAAc;AAAA,IACd,QAAQ;AAAA,EAAA,IAEV;AAAA,IACE,cAAc;AAAA,IACd,YAAY;AAAA,IACZ,UAAU;AAAA,IACV,KAAK;AAAA,IACL,MAAM;AAAA,IACN,QAAQ;AAAA,EAAA,GAGZ8sB,IACJ,gBAAAjvB;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,KAAK6tB;AAAA,MACL,WAAU;AAAA,MACV,gBAAcN,KAAY;AAAA,MAC1B,eAAY;AAAA,MACZ,aAAWjC;AAAA,MACX,2BAAuB;AAAA,MACvB,OAAAjqB;AAAA,MAEA,UAAA,gBAAAU,EAAC,OAAA,EAAI,WAAU,oBACZ,UAAA;AAAA,QAAAqrB,GAAc,IAAI,CAAC,EAAE,MAAM8B,GAAW,MAAAjqB,GAAM,OAAAC,QAC3C,gBAAAlF;AAAA,UAACoS;AAAA,UAAA;AAAA,YAEC,MAAAnN;AAAA,YACA,SAAS,MAAMjE,EAAMkuB,CAAS;AAAA,YAC9B,SAAShqB;AAAA,YACT,eAAa,SAASgqB,CAAS;AAAA,UAAA;AAAA,UAJ1BA;AAAA,QAAA,CAMR;AAAA,QAIAtB,KACCP,GAAmB,IAAI,CAAC,EAAE,MAAM8B,GAAU,MAAAlqB,GAAM,OAAAC,EAAA,MAC9C,gBAAAlF;AAAA,UAACoS;AAAA,UAAA;AAAA,YAEC,MAAAnN;AAAA,YACA,SAAS,MAAMkoB,EAAWgC,CAAQ;AAAA,YAClC,SAASjqB;AAAA,YACT,eAAa,cAAciqB,CAAQ;AAAA,UAAA;AAAA,UAJ9BA;AAAA,QAAA,CAMR;AAAA,MAAA,EAAA,CACL;AAAA,IAAA;AAAA,EAAA;AAIJ,SAAO7D,MAAS,aAAa8D,GAAaH,GAAS,SAAS,IAAI,IAAIA;AACtE,GCpIaI,KAA0D,CAAC;AAAA,EACtE,SAAA5hB;AAAA,EACA,kBAAAyB,IAAmB;AAAA,EACnB,kBAAAC;AAAA,EACA,iBAAAC,IAAkB;AAAA,EAClB,iBAAAC;AAAA,EACA,gBAAAC,IAAiB;AAAA,EACjB,gBAAAC;AAAA,EACA,gBAAAC,IAAiB;AAAA,EACjB,gBAAAC;AAAA,EACA,mBAAAC,IAAoB;AAAA,EACpB,mBAAAC;AAAA,EACA,kBAAAC,IAAmB;AAAA,EACnB,kBAAAC;AAAA,EACA,yBAAAC,IAA0B;AAAA,EAC1B,yBAAAC;AAAA,EACA,mBAAAC,IAAoB;AAAA,EACpB,mBAAAC;AAAA,EACA,WAAA7B;AACF,MAAM;AACJ,QAAM,CAAC0C,GAAyBC,CAA0B,IAAIzF,EAAS,EAAK,GACtE,CAAC0F,GAAwBC,CAAyB,IAAI3F,EAAS,EAAK,GACpE,CAAC4F,GAAuBC,CAAwB,IAAI7F,EAAS,EAAK,GAClE,CAAC8F,GAAuBC,CAAwB,IAAI/F,EAAS,EAAK,GAClE,CAACgG,IAA0BC,CAA2B,IAAIjG,EAAS,EAAK,GACxE,CAACkG,IAAyBC,EAA0B,IAAInG,EAAS,EAAK,GACtE,CAACoG,GAAyBC,CAA0B,IAAIrG,EAAS,EAAK,GACtE,CAACsG,GAA0BC,EAA2B,IAAIvG,EAAS,EAAK,GAKxEyG,IAAUvE,GAAkBC,KAAW,IAAI;AAEjD,SACE,gBAAA1L,EAAC,OAAA,EAAI,WAAU,oBAEb,UAAA;AAAA,IAAA,gBAAA/B;AAAA,MAACoS;AAAA,MAAA;AAAA,QACC,MAAM,gBAAApS,EAACqS,IAAA,EAAe,MAAM,IAAI,WAAU,gBAAe;AAAA,QACzD,SAAS,MAAM;AACb,UAAAtB,EAA2B,EAAI,GAC/B5B,EAAA;AAAA,QACF;AAAA,QACA,cAAc,MAAM4B,EAA2B,EAAK;AAAA,QACpD,SAAQ;AAAA,QACR,iBAAiBD,KAA2B5B;AAAA,QAC5C,QAAQA,KAAoB6C,EAAQ;AAAA,MAAA;AAAA,IAAA;AAAA,IAItC,gBAAA/R;AAAA,MAACoS;AAAA,MAAA;AAAA,QACC,MAAK;AAAA,QACL,SAAS,MAAM;AACb,UAAAnB,EAA0B,EAAI,GAC9B5B,EAAA;AAAA,QACF;AAAA,QACA,cAAc,MAAM4B,EAA0B,EAAK;AAAA,QACnD,SAAQ;AAAA,QACR,iBAAiBD,KAA0B5B;AAAA,QAC3C,QAAQA,KAAmB2C,EAAQ;AAAA,MAAA;AAAA,IAAA;AAAA,IAIpCxC,KACC,gBAAAvP;AAAA,MAACoS;AAAA,MAAA;AAAA,QACC,MAAK;AAAA,QACL,SAAS,MAAM;AACb,UAAAjB,EAAyB,EAAI,GAC7B5B,EAAA;AAAA,QACF;AAAA,QACA,cAAc,MAAM4B,EAAyB,EAAK;AAAA,QAClD,SAAQ;AAAA,QACR,iBAAiBD,KAAyB5B;AAAA,QAC1C,QAAQA,KAAkByC,EAAQ;AAAA,MAAA;AAAA,IAAA;AAAA,IAKrCtC,KACC,gBAAAzP;AAAA,MAACoS;AAAA,MAAA;AAAA,QACC,MAAK;AAAA,QACL,SAAS,MAAM;AACb,UAAAf,EAAyB,EAAI,GAC7B5B,EAAA;AAAA,QACF;AAAA,QACA,cAAc,MAAM4B,EAAyB,EAAK;AAAA,QAClD,SAAQ;AAAA,QACR,iBAAiBD,KAAyB5B;AAAA,QAC1C,QAAQA,KAAkBuC,EAAQ;AAAA,MAAA;AAAA,IAAA;AAAA,IAKrCpC,KACC,gBAAA3P;AAAA,MAACoS;AAAA,MAAA;AAAA,QACC,MAAK;AAAA,QACL,SAAS,MAAM;AACb,UAAAb,EAA4B,EAAI,GAChC5B,EAAA;AAAA,QACF;AAAA,QACA,cAAc,MAAM4B,EAA4B,EAAK;AAAA,QACrD,SAAQ;AAAA,QACR,iBAAiBD,MAA4B5B;AAAA,QAC7C,QAAQA,KAAqBqC,EAAQ;AAAA,MAAA;AAAA,IAAA;AAAA,IAKxClC,KACC,gBAAA7P;AAAA,MAACoS;AAAA,MAAA;AAAA,QACC,MAAK;AAAA,QACL,SAAS,MAAM;AACb,UAAAX,GAA2B,EAAI,GAC/B5B,EAAA;AAAA,QACF;AAAA,QACA,cAAc,MAAM4B,GAA2B,EAAK;AAAA,QACpD,SAAQ;AAAA,QACR,iBAAiBD,MAA2B5B;AAAA,QAC5C,QAAQA,KAAoBmC,EAAQ;AAAA,MAAA;AAAA,IAAA;AAAA,IAKvChC,KACC,gBAAA/P;AAAA,MAACoS;AAAA,MAAA;AAAA,QACC,MAAK;AAAA,QACL,SAAS,MAAM;AACb,UAAAT,EAA2B,EAAI,GAC/B5B,EAAA;AAAA,QACF;AAAA,QACA,cAAc,MAAM4B,EAA2B,EAAK;AAAA,QACpD,SAAQ;AAAA,QACR,iBAAiBD,KAA2B5B;AAAA,QAC5C,QAAQA,KAA2BiC,EAAQ;AAAA,MAAA;AAAA,IAAA;AAAA,IAK9C9B,KACC,gBAAAjQ;AAAA,MAACoS;AAAA,MAAA;AAAA,QACC,MAAK;AAAA,QACL,SAAS,MAAM;AACb,UAAAP,GAA4B,EAAI,GAChC5B,EAAA;AAAA,QACF;AAAA,QACA,cAAc,MAAM4B,GAA4B,EAAK;AAAA,QACrD,SAAQ;AAAA,QACR,iBAAiBD,KAA4B5B;AAAA,QAC7C,QAAQA,KAAqB+B,EAAQ;AAAA,MAAA;AAAA,IAAA;AAAA,IAIzC,gBAAAhQ,EAACqL,IAAA,EAAQ,eAAe,KACtB,UAAA;AAAA,MAAA,gBAAApN,EAACqN,IAAA,EAAe,SAAO,IACrB,UAAA,gBAAArN,EAAC8M,GAAA,EAAO,SAAQ,SAAQ,MAAK,MAAK,SAASsB,GAAW,UAAA,UAAA,CAEtD,GACF;AAAA,MACA,gBAAApO,EAACsN,MAAe,UAAA,qBAAA,CAAkB;AAAA,IAAA,EAAA,CACpC;AAAA,EAAA,GACF;AAEJ;AC7LA,SAASvH,GAAW,EAAE,UAAA3E,GAAU,WAAA5B,KAAgE;AAC9F,QAAMI,IAAM0F,EAAuB,IAAI;AAEvC,SAAAE,EAAU,MAAM;AACd,UAAMC,IAAK7F,EAAI;AACf,QAAI,CAAC6F,EAAI;AAET,UAAMC,IAAmB,CAAC1B,MAAkB;AAE1C,MAAAA,EAAE,gBAAA;AAAA,IACJ,GAEM2B,IAAkB,CAAC3B,MAAkB;AAEzC,MAAAA,EAAE,eAAA,GACFA,EAAE,gBAAA;AAAA,IACJ;AAGA,WAAAyB,EAAG,iBAAiB,cAAcC,GAAkB,EAAE,SAAS,IAAO,GACtED,EAAG,iBAAiB,aAAaE,GAAiB,EAAE,SAAS,IAAO,GAE7D,MAAM;AACX,MAAAF,EAAG,oBAAoB,cAAcC,CAAgB,GACrDD,EAAG,oBAAoB,aAAaE,CAAe;AAAA,IACrD;AAAA,EACF,GAAG,CAAA,CAAE,GAGH,gBAAA3F,EAAC,SAAI,KAAAJ,GAAU,WAAAJ,GAAsB,OAAO,EAAE,aAAa,UACxD,UAAA4B,GACH;AAEJ;AA8BO,MAAMkuB,KAAsC,CAAC,EAAE,SAAA7hB,GAAS,iBAAAS,GAAiB,WAAA1O,QAAgB;;AAE9F,QAAM,CAAC+vB,GAAYC,CAAa,IAAIlkB,EAAqB,QAAQ,GAG3DjG,IAAeC,EAAuB,IAAI,GAC1CC,IAAgBD,EAAO,EAAE,GAAG,GAAG,GAAG,GAAG;AAC3C,EAAAE,EAAU,MAAM;AACd,UAAMC,IAAKJ,EAAa;AACxB,QAAI,CAACI,EAAI;AAET,UAAMC,IAAmB,CAAC1B,MAAkB;AAC1C,MAAAuB,EAAc,UAAU;AAAA,QACtB,GAAGvB,EAAE,QAAQ,CAAC,EAAE;AAAA,QAChB,GAAGA,EAAE,QAAQ,CAAC,EAAE;AAAA,MAAA;AAAA,IAEpB,GAEM2B,IAAkB,CAAC3B,MAAkB;AACzC,YAAM4B,IAAS,KAAK,IAAI5B,EAAE,QAAQ,CAAC,EAAE,UAAUuB,EAAc,QAAQ,CAAC,GAChEM,IAAS,KAAK,IAAI7B,EAAE,QAAQ,CAAC,EAAE,UAAUuB,EAAc,QAAQ,CAAC;AAGtE,MAAIK,IAAS,MAAMA,IAASC,KAC1B7B,EAAE,eAAA;AAAA,IAEN;AAEA,WAAAyB,EAAG,iBAAiB,cAAcC,GAAkB,EAAE,SAAS,IAAM,GACrED,EAAG,iBAAiB,aAAaE,GAAiB,EAAE,SAAS,IAAO,GAE7D,MAAM;AACX,MAAAF,EAAG,oBAAoB,cAAcC,CAAgB,GACrDD,EAAG,oBAAoB,aAAaE,CAAe;AAAA,IACrD;AAAA,EACF,GAAG,CAAA,CAAE;AAGL,QAAM8pB,MAAmBjrB,IAAAiJ,EAAQ,kBAAR,gBAAAjJ,EAAuB,cAAa,GACvDkrB,MAAoB7hB,IAAAJ,EAAQ,kBAAR,gBAAAI,EAAuB,eAAc,GAGzD8hB,IAAmB1oB;AAAA,IACvB,CAAC2oB,GAAeC,GAAeC,GAAmBC,MAAuB;AACvE,YAAM9d,IAAiBxE,EAAQ,MAAA;AAC/B,MAAAwE,EAAe,WAAW2d,GAAOC,GAAOC,GAAWC,GAAY,EAAI,GACnE7hB,EAAgB+D,CAAc;AAAA,IAChC;AAAA,IACA,CAACxE,GAASS,CAAe;AAAA,EAAA,GAGrB8hB,IAAwB/oB;AAAA,IAC5B,CAAC7D,GAAe6sB,IAAqBV,MAAe;AAClD,YAAMW,IAAWziB,EAAQ,cAAc,WACjC0iB,IAAO1iB,EAAQ,cAAc,OAC7B2iB,IAAYhtB,IAAQ8sB;AAE1B,UAAIG,IAAOF;AAEX,MAAIF,EAAO,SAAS,QAAQ,IAC1BI,IAAOF,IAAOC,IAAY,IACjBH,EAAO,SAAS,OAAO,MAChCI,IAAOF,IAAOC,IAIhBC,IAAO,KAAK,IAAI,GAAG,KAAK,IAAI,IAAIjtB,GAAOitB,CAAI,CAAC,GAE5CV,EAAiBU,GAAM5iB,EAAQ,cAAc,OAAOrK,GAAOqK,EAAQ,cAAc,UAAU;AAAA,IAC7F;AAAA,IACA,CAACA,GAASkiB,GAAkBJ,CAAU;AAAA,EAAA,GAGlCe,IAAyBrpB;AAAA,IAC7B,CAAC7D,GAAe6sB,IAAqBV,MAAe;AAClD,YAAMgB,IAAY9iB,EAAQ,cAAc,YAClC+iB,IAAO/iB,EAAQ,cAAc,OAC7BgjB,IAAartB,IAAQmtB;AAE3B,UAAIG,IAAOF;AAEX,MAAIP,EAAO,SAAS,QAAQ,KAAKA,MAAW,WAC1CS,IAAOF,IAAOC,IAAa,IAClBR,EAAO,SAAS,QAAQ,MACjCS,IAAOF,IAAOC,IAIhBC,IAAO,KAAK,IAAI,GAAG,KAAK,IAAI,IAAIttB,GAAOstB,CAAI,CAAC,GAE5Cf,EAAiBliB,EAAQ,cAAc,OAAOijB,GAAMjjB,EAAQ,cAAc,WAAWrK,CAAK;AAAA,IAC5F;AAAA,IACA,CAACqK,GAASkiB,GAAkBJ,CAAU;AAAA,EAAA,GAIlCoB,IAAgC;AAAA,IACpC;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EAAA;AAGF,SACE,gBAAA3wB;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,KAAKqF;AAAA,MACL,2BAAuB;AAAA,MACvB,WAAWnF,GAAG,4CAA4CV,CAAS;AAAA,MACnE,OAAO,EAAE,aAAa,QAAA;AAAA,MAEtB,4BAAC,OAAA,EAAI,WAAU,2LAEb,UAAA,gBAAAuC,EAAC,OAAA,EAAI,WAAU,+CAEb,UAAA;AAAA,QAAA,gBAAAA,EAAC,OAAA,EAAI,WAAU,gCACb,UAAA;AAAA,UAAA,gBAAA/B,EAAC,QAAA,EAAK,WAAU,kDAAiD,UAAA,UAAM;AAAA,4BACtE,OAAA,EAAI,WAAU,0DACZ,UAAA2wB,EAAgB,IAAI,CAACC,MACpB,gBAAA5wB;AAAA,YAAC;AAAA,YAAA;AAAA,cAEC,SAAS,MAAMwvB,EAAcoB,CAAG;AAAA,cAChC,WAAW1wB;AAAAA,gBACT;AAAA,gBACAqvB,MAAeqB,KAAO;AAAA,cAAA;AAAA,cAExB,OAAOA,EAAI,QAAQ,KAAK,GAAG;AAAA,cAE3B,UAAA,gBAAA5wB;AAAA,gBAAC;AAAA,gBAAA;AAAA,kBACC,WAAWE;AAAAA,oBACT;AAAA,oBACAqvB,MAAeqB,KAAO;AAAA,kBAAA;AAAA,gBACxB;AAAA,cAAA;AAAA,YACF;AAAA,YAbKA;AAAA,UAAA,CAeR,EAAA,CACH;AAAA,QAAA,GACF;AAAA,QAGA,gBAAA7uB,EAAC,OAAA,EAAI,WAAU,sDAEb,UAAA;AAAA,UAAA,gBAAAA,EAAC,OAAA,EAAI,WAAU,gDACb,UAAA;AAAA,YAAA,gBAAAA,EAAC,OAAA,EAAI,WAAU,8CACb,UAAA;AAAA,cAAA,gBAAA/B,EAAC,QAAA,EAAK,WAAU,kDAAiD,UAAA,SAAK;AAAA,cACtE,gBAAAA;AAAA,gBAAC;AAAA,gBAAA;AAAA,kBACC,MAAK;AAAA,kBACL,OAAO,KAAK,MAAMyvB,IAAmB,GAAG;AAAA,kBACxC,UAAU,CAACzrB,MAAMgsB,EAAsB,KAAK,IAAI,IAAI,KAAK,IAAI,KAAK,OAAOhsB,EAAE,OAAO,KAAK,CAAC,CAAC,IAAI,GAAG;AAAA,kBAChG,KAAK;AAAA,kBACL,KAAK;AAAA,kBACL,WAAU;AAAA,gBAAA;AAAA,cAAA;AAAA,YACZ,GACF;AAAA,8BAEC+B,IAAA,EACC,UAAA,gBAAAhE;AAAA,cAAC8C;AAAA,cAAA;AAAA,gBACC,OAAO,CAAC4qB,IAAmB,GAAG;AAAA,gBAC9B,eAAe,CAACnpB,MAAQ0pB,EAAsB1pB,EAAI,CAAC,IAAI,GAAG;AAAA,gBAC1D,KAAK;AAAA,gBACL,KAAK;AAAA,gBACL,MAAM;AAAA,gBAEN,UAAA;AAAA,kBAAA,gBAAAtG,EAAC6E,GAAO,OAAP,EAAa,WAAU,8BACtB,UAAA,gBAAA7E,EAAC6E,GAAO,MAAP,EAAY,WAAU,gBAAA,CAAgB,EAAA,CACzC;AAAA,kBACA,gBAAA7E,EAAC6E,GAAO,OAAP,CAAA,CAAa;AAAA,gBAAA;AAAA,cAAA;AAAA,YAAA,EAChB,CACF;AAAA,UAAA,GACF;AAAA,UAGA,gBAAA9C,EAAC,OAAA,EAAI,WAAU,gDACb,UAAA;AAAA,YAAA,gBAAAA,EAAC,OAAA,EAAI,WAAU,8CACb,UAAA;AAAA,cAAA,gBAAA/B,EAAC,QAAA,EAAK,WAAU,kDAAiD,UAAA,UAAM;AAAA,cACvE,gBAAAA;AAAA,gBAAC;AAAA,gBAAA;AAAA,kBACC,MAAK;AAAA,kBACL,OAAO,KAAK,MAAM0vB,IAAoB,GAAG;AAAA,kBACzC,UAAU,CAAC1rB,MAAMssB,EAAuB,KAAK,IAAI,IAAI,KAAK,IAAI,KAAK,OAAOtsB,EAAE,OAAO,KAAK,CAAC,CAAC,IAAI,GAAG;AAAA,kBACjG,KAAK;AAAA,kBACL,KAAK;AAAA,kBACL,WAAU;AAAA,gBAAA;AAAA,cAAA;AAAA,YACZ,GACF;AAAA,8BAEC+B,IAAA,EACC,UAAA,gBAAAhE;AAAA,cAAC8C;AAAA,cAAA;AAAA,gBACC,OAAO,CAAC6qB,IAAoB,GAAG;AAAA,gBAC/B,eAAe,CAACppB,MAAQgqB,EAAuBhqB,EAAI,CAAC,IAAI,GAAG;AAAA,gBAC3D,KAAK;AAAA,gBACL,KAAK;AAAA,gBACL,MAAM;AAAA,gBAEN,UAAA;AAAA,kBAAA,gBAAAtG,EAAC6E,GAAO,OAAP,EAAa,WAAU,8BACtB,UAAA,gBAAA7E,EAAC6E,GAAO,MAAP,EAAY,WAAU,gBAAA,CAAgB,EAAA,CACzC;AAAA,kBACA,gBAAA7E,EAAC6E,GAAO,OAAP,CAAA,CAAa;AAAA,gBAAA;AAAA,cAAA;AAAA,YAAA,EAChB,CACF;AAAA,UAAA,EAAA,CACF;AAAA,QAAA,EAAA,CACF;AAAA,MAAA,EAAA,CACF,EAAA,CACF;AAAA,IAAA;AAAA,EAAA;AAGN;;;;8CCzRMgsB,KACJ,qGAEIC,KACJ,2LASWC,KAAsD,CAAC,EAAE,OAAA3tB,GAAO,UAAA6C,QAC3E,gBAAAjG;AAAA,EAAC;AAAA,EAAA;AAAA,IACC,WAAU;AAAA,IACV,2BAAuB;AAAA,IACvB,OAAO,EAAE,aAAa,QAAA;AAAA,IAEtB,4BAAC,OAAA,EAAI,WAAW6wB,IACd,UAAA,gBAAA7wB,EAACgG,MAAU,OAAM,UAAS,OAAA5C,GAAc,UAAA6C,GAAoB,KAAK,GAAG,KAAK,IAAI,MAAK,KAAI,EAAA,CACxF;AAAA,EAAA;AACF,GAiBW+qB,KAAwC,CAAC,EAAE,SAAAC,EAAA,MACtD,gBAAAjxB,EAAC,OAAA,EAAI,WAAU,mCAAkC,2BAAuB,IAAC,OAAO,EAAE,aAAa,QAAA,GAC7F,UAAA,gBAAAA,EAAC,OAAA,EAAI,WAAW6wB,IACd,UAAA,gBAAA7wB,EAAC,SAAI,WAAU,sDACZ,UAAAotB,GAAc,IAAI,CAAC,EAAE,MAAA9B,GAAM,MAAArmB,GAAM,OAAAC,QAChC,gBAAAlF;AAAA,EAACoS;AAAA,EAAA;AAAA,IAEC,MAAAnN;AAAA,IACA,SAAS,MAAMgsB,EAAQ3F,CAAI;AAAA,IAC3B,SAASpmB;AAAA,IACT,eAAa,SAASomB,CAAI;AAAA,EAAA;AAAA,EAJrBA;AAKP,CACD,EAAA,CACH,GACF,GACF,GAWW4F,KAA8C,CAAC,EAAE,OAAA9tB,GAAO,UAAA6C,GAAU,YAAAkrB,QAC7E,gBAAAnxB;AAAA,EAAC;AAAA,EAAA;AAAA,IACC,WAAU;AAAA,IACV,2BAAuB;AAAA,IACvB,OAAO,EAAE,aAAa,QAAA;AAAA,IAEtB,4BAAC,OAAA,EAAI,WAAW6wB,IACd,UAAA,gBAAA9uB,EAAC,OAAA,EAAI,WAAU,iCACb,UAAA;AAAA,MAAA,gBAAA/B;AAAA,QAACgG;AAAA,QAAA;AAAA,UACC,OAAM;AAAA,UACN,OAAA5C;AAAA,UACA,UAAA6C;AAAA,UACA,KAAK;AAAA,UACL,KAAK;AAAA,UACL,MAAK;AAAA,UACL,WAAS;AAAA,UACT,YAAW;AAAA,UACX,SAAQ;AAAA,UACR,WAAU;AAAA,QAAA;AAAA,MAAA;AAAA,MAGZ,gBAAAjG,EAAC,OAAA,EAAI,WAAU,aACb,UAAA,gBAAAA,EAACoS,GAAA,EAAc,MAAMtM,GAAM,iBAAiB,SAASqrB,GAAY,SAAQ,kBAAiB,EAAA,CAC5F;AAAA,IAAA,EAAA,CACF,EAAA,CACF;AAAA,EAAA;AACF,GA4CWC,KAA8C,CAAC;AAAA,EAC1D,OAAAhuB;AAAA,EACA,UAAA6C;AAAA,EACA,YAAAorB;AAAA,EACA,eAAAC;AAAA,EACA,oBAAAC;AAAA,EACA,uBAAAC;AAAA,EACA,iBAAAC;AAAA,EACA,oBAAAC;AACF,MACE,gBAAA1xB;AAAA,EAAC;AAAA,EAAA;AAAA,IACC,WAAU;AAAA,IACV,2BAAuB;AAAA,IACvB,gBAAa;AAAA,IACb,OAAO,EAAE,aAAa,QAAA;AAAA,IAEtB,UAAA,gBAAA+B,EAAC,OAAA,EAAI,WAAW8uB,IACd,UAAA;AAAA,MAAA,gBAAA7wB;AAAA,QAACgG;AAAA,QAAA;AAAA,UACC,OAAM;AAAA,UACN,OAAO,KAAK,MAAM5C,CAAK;AAAA,UACvB,UAAA6C;AAAA,UACA,KAAK;AAAA,UACL,KAAK;AAAA,UACL,MAAM;AAAA,UACN,MAAK;AAAA,UACL,WAAS;AAAA,UACT,YAAW;AAAA,QAAA;AAAA,MAAA;AAAA,MAEZsrB,KAAsB,QAAQC,KAC7B,gBAAAxxB,EAAC,OAAA,EAAI,gBAAa,0BAChB,UAAA,gBAAAA;AAAA,QAACgG;AAAA,QAAA;AAAA,UACC,OAAM;AAAA,UACN,OAAOurB;AAAA,UACP,UAAUC;AAAA,UACV,KAAK;AAAA,UACL,KAAK;AAAA,UACL,MAAM;AAAA,UACN,MAAK;AAAA,UACL,WAAS;AAAA,UACT,YAAW;AAAA,QAAA;AAAA,MAAA,GAEf;AAAA,MAEDC,KAAmB,QAAQC,KAC1B,gBAAA1xB,EAAC,OAAA,EAAI,gBAAa,uBAChB,UAAA,gBAAAA;AAAA,QAACgG;AAAA,QAAA;AAAA,UACC,OAAM;AAAA,UACN,OAAOyrB;AAAA,UACP,UAAUC;AAAA,UACV,KAAK;AAAA,UACL,KAAK;AAAA,UACL,MAAM;AAAA,UACN,MAAK;AAAA,UACL,WAAS;AAAA,UACT,YAAW;AAAA,QAAA;AAAA,MAAA,GAEf;AAAA,MAEDL,KAAc,QAAQC,KACrB,gBAAAtxB;AAAA,QAACgG;AAAA,QAAA;AAAA,UACC,OAAM;AAAA,UACN,OAAO,KAAK,MAAMqrB,CAAU;AAAA,UAC5B,UAAUC;AAAA,UACV,KAAK;AAAA,UACL,KAAK;AAAA,UACL,MAAM;AAAA,UACN,MAAK;AAAA,UACL,WAAS;AAAA,UACT,YAAW;AAAA,QAAA;AAAA,MAAA;AAAA,IACb,EAAA,CAEJ;AAAA,EAAA;AACF,GAYWK,KAA4C,CAAC,EAAE,OAAAvuB,GAAO,UAAA6C,QACjE,gBAAAjG;AAAA,EAAC;AAAA,EAAA;AAAA,IACC,WAAU;AAAA,IACV,2BAAuB;AAAA,IACvB,OAAO,EAAE,aAAa,QAAA;AAAA,IAEtB,UAAA,gBAAAA,EAAC,OAAA,EAAI,WAAW6wB,IACd,UAAA,gBAAA7wB;AAAA,MAACgG;AAAA,MAAA;AAAA,QACC,OAAM;AAAA,QACN,OAAO,KAAK,MAAM5C,IAAQ,GAAG;AAAA,QAC7B,UAAU,CAACwF,MAAM3C,EAAS2C,IAAI,GAAG;AAAA,QACjC,KAAK;AAAA,QACL,KAAK;AAAA,QACL,MAAK;AAAA,MAAA;AAAA,IAAA,EACP,CACF;AAAA,EAAA;AACF,GAqBWgpB,KAA0C,CAAC,EAAE,aAAAC,GAAa,UAAA5rB,GAAU,aAAA3C,GAAa,SAAAwuB,QAAc;AAC1G,QAAMxF,IAA4BuF,KAAe,EAAE,GAAGE,GAAA,GAChDC,IAAYhkB,GAAqB6jB,CAAW,GAE5CI,IAAa,CAAC/sB,GAAegtB,wBAChC,OAAA,EAAI,eAAa,UAAUA,CAAO,IACjC,UAAA,gBAAAlyB;AAAA,IAACgG;AAAA,IAAA;AAAA,MACC,OAAAd;AAAA,MACA,OAAO,KAAK,MAAMonB,EAAQ4F,CAAO,IAAI,GAAG;AAAA,MACxC,UAAU,CAACtpB,MAAM3C,EAAS,EAAE,GAAGqmB,GAAS,CAAC4F,CAAO,GAAGtpB,IAAI,KAAK;AAAA,MAC5D,aAAatF,IAAc,MAAMA,EAAA,IAAgB;AAAA,MACjD,KAAK;AAAA,MACL,KAAK;AAAA,MACL,MAAK;AAAA,IAAA;AAAA,EAAA,GAET;AAGF,SACE,gBAAAtD;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,WAAU;AAAA,MACV,2BAAuB;AAAA,MACvB,eAAY;AAAA,MACZ,OAAO,EAAE,aAAa,QAAA;AAAA,MAEtB,UAAA,gBAAA+B,EAAC,OAAA,EAAI,WAAW8uB,IACb,UAAA;AAAA,QAAAoB,EAAW,cAAc,YAAY;AAAA,QACrCA,EAAW,YAAY,UAAU;AAAA,QACjCA,EAAW,cAAc,YAAY;AAAA,QACtC,gBAAAjyB,EAAC,OAAA,EAAI,WAAU,0BACb,UAAA,gBAAAA;AAAA,UAAC8M;AAAA,UAAA;AAAA,YACC,SAAQ;AAAA,YACR,MAAK;AAAA,YACL,SAASglB;AAAA,YACT,UAAUE;AAAA,YACV,eAAY;AAAA,YACZ,cAAW;AAAA,YACZ,UAAA;AAAA,UAAA;AAAA,QAAA,EAED,CACF;AAAA,MAAA,EAAA,CACF;AAAA,IAAA;AAAA,EAAA;AAGN,GASaG,KAAgE,CAAC,EAAE,OAAA/uB,GAAO,UAAA6C,QACrF,gBAAAjG;AAAA,EAAC;AAAA,EAAA;AAAA,IACC,WAAU;AAAA,IACV,2BAAuB;AAAA,IACvB,OAAO,EAAE,aAAa,QAAA;AAAA,IAEtB,4BAAC,OAAA,EAAI,WAAW6wB,IACd,UAAA,gBAAA7wB,EAACgG,MAAU,OAAM,UAAS,OAAA5C,GAAc,UAAA6C,GAAoB,KAAK,GAAG,KAAK,IAAI,MAAK,KAAI,EAAA,CACxF;AAAA,EAAA;AACF,GAYWmsB,KAAgE,CAAC,EAAE,OAAAhvB,GAAO,UAAA6C,QACrF,gBAAAjG;AAAA,EAAC;AAAA,EAAA;AAAA,IACC,WAAU;AAAA,IACV,2BAAuB;AAAA,IACvB,OAAO,EAAE,aAAa,QAAA;AAAA,IAEtB,UAAA,gBAAAA,EAAC,OAAA,EAAI,WAAW6wB,IACd,UAAA,gBAAA7wB;AAAA,MAACgG;AAAA,MAAA;AAAA,QACC,OAAM;AAAA,QACN,OAAO,KAAK,MAAM5C,IAAQ,GAAG;AAAA,QAC7B,UAAU,CAACkD,MAAQL,EAASK,IAAM,GAAG;AAAA,QACrC,KAAK;AAAA,QACL,KAAK;AAAA,QACL,MAAK;AAAA,MAAA;AAAA,IAAA,EACP,CACF;AAAA,EAAA;AACF,GAUW+rB,KAAkD,CAAC,EAAE,OAAAjvB,GAAO,UAAA6C,QACvE,gBAAAjG;AAAA,EAAC;AAAA,EAAA;AAAA,IACC,WAAU;AAAA,IACV,2BAAuB;AAAA,IACvB,OAAO,EAAE,aAAa,QAAA;AAAA,IAEtB,UAAA,gBAAAA,EAAC,OAAA,EAAI,WAAW6wB,IACd,4BAAC7qB,IAAA,EAAU,OAAM,SAAQ,OAAA5C,GAAc,UAAA6C,GAAoB,KAAK,GAAG,KAAK,IAAI,EAAA,CAC9E;AAAA,EAAA;AACF,GAUWqsB,KAAoD,CAAC,EAAE,OAAAlvB,GAAO,UAAA6C,QACzE,gBAAAjG;AAAA,EAAC;AAAA,EAAA;AAAA,IACC,WAAU;AAAA,IACV,2BAAuB;AAAA,IACvB,OAAO,EAAE,aAAa,QAAA;AAAA,IAEtB,UAAA,gBAAAA,EAAC,OAAA,EAAI,WAAW6wB,IACd,4BAAC7qB,IAAA,EAAU,OAAM,UAAS,OAAA5C,GAAc,UAAA6C,GAAoB,KAAK,GAAG,KAAK,IAAI,EAAA,CAC/E;AAAA,EAAA;AACF,GAYWssB,KAA8D,CAAC,EAAE,OAAAnvB,GAAO,UAAA6C,QACnF,gBAAAjG;AAAA,EAAC;AAAA,EAAA;AAAA,IACC,WAAU;AAAA,IACV,2BAAuB;AAAA,IACvB,OAAO,EAAE,aAAa,QAAA;AAAA,IAEtB,UAAA,gBAAAA,EAAC,OAAA,EAAI,WAAW6wB,IACd,UAAA,gBAAA7wB;AAAA,MAACgG;AAAA,MAAA;AAAA,QACC,OAAM;AAAA,QACN,OAAO,KAAK,MAAM5C,IAAQ,GAAG;AAAA,QAC7B,UAAU,CAACkD,MAAQL,EAASK,IAAM,GAAG;AAAA,QACrC,KAAK;AAAA,QACL,KAAK;AAAA,QACL,MAAK;AAAA,MAAA;AAAA,IAAA,EACP,CACF;AAAA,EAAA;AACF,GAoBIksB,KAAkD;AAAA,EACtD,OAAO;AAAA,EACP,QAAQ;AAAA,EACR,QAAQ;AACV,GAEaC,KAAkD,CAAC;AAAA,EAC9D,OAAArvB;AAAA,EACA,UAAA6C;AAAA,EACA,MAAAysB;AAAA,EACA,cAAAC;AAAA,EACA,gBAAA9nB;AAAA,EACA,aAAAC;AACF,MAAM;;AACJ,QAAMwgB,KAAsBoH,KAAA,gBAAAA,EAAM,UAAS,aAAYA,KAAA,gBAAAA,EAAM,UAAS,WAAWA,EAAK,OAAO,SACvFE,KAAWF,KAAA,gBAAAA,EAAM,UAAS,aAAYA,KAAA,gBAAAA,EAAM,UAAS,WAAWA,IAAO,MACvE,CAACG,GAAYC,CAAa,IAAIxnB,EAAS,CAAC,GAExCynB,IAAmB9rB;AAAA,IACvB,CAAC+rB,MAAwB;;AACvB,UAAIA,MAAS1H,KAAQ,CAACqH,EAAc;AACpC,UAAIK,MAAS,SAAS;AAGpB,QAAA/sB,IAASzB,IAAAouB,KAAA,gBAAAA,EAAU,MAAM,OAAhB,gBAAApuB,EAAoB,UAASpB,CAAK;AAC3C;AAAA,MACF;AAGA,YAAM6vB,IAAQL,IACVA,EAAS,MAAM,IAAI,CAAClqB,OAAO,EAAE,GAAGA,EAAA,EAAI,IACpC;AAAA,QACE,EAAE,QAAQ,GAAG,OAAOtF,EAAA;AAAA,QACpB,EAAE,QAAQ,GAAG,OAAO,UAAA;AAAA,MAAU;AAEpC,MAAAuvB;AAAA,QACEK,MAAS,WACL,EAAE,MAAM,UAAU,QAAOJ,KAAA,gBAAAA,EAAU,UAAS,WAAWA,EAAS,QAAQ,KAAK,OAAAK,EAAA,IAC7E,EAAE,MAAM,UAAU,OAAAA,EAAA;AAAA,MAAM,GAE9BH,EAAc,CAAC;AAAA,IACjB;AAAA,IACA,CAACxH,GAAMsH,GAAUxvB,GAAO6C,GAAU0sB,CAAY;AAAA,EAAA,GAG1CO,IAAwBjsB;AAAA,IAC5B,CAACgF,MAAkB;AACjB,UAAI,CAAC2mB,KAAY,CAACD,EAAc;AAChC,YAAMM,IAAQL,EAAS,MAAM,IAAI,CAAClqB,GAAGF,MAAOA,MAAMqqB,IAAa,EAAE,GAAGnqB,GAAG,OAAAuD,EAAA,IAAU,EAAE,GAAGvD,GAAI;AAC1F,MAAAiqB;AAAA,QACEC,EAAS,SAAS,WAAW,EAAE,MAAM,UAAU,OAAOA,EAAS,OAAO,OAAAK,EAAA,IAAU,EAAE,MAAM,UAAU,OAAAA,EAAA;AAAA,MAAM;AAAA,IAE5G;AAAA,IACA,CAACL,GAAUC,GAAYF,CAAY;AAAA,EAAA,GAG/BQ,IAAoBlsB;AAAA,IACxB,CAACmsB,MAAkB;AACjB,OAAIR,KAAA,gBAAAA,EAAU,UAAS,YAAY,CAACD,KACpCA,EAAa,EAAE,MAAM,UAAU,OAAAS,GAAO,OAAOR,EAAS,MAAM,IAAI,CAAClqB,OAAO,EAAE,GAAGA,EAAA,EAAI,GAAG;AAAA,IACtF;AAAA,IACA,CAACkqB,GAAUD,CAAY;AAAA,EAAA,GAGnBU,IAAcT,MAAYpuB,IAAAouB,EAAS,MAAMC,CAAU,MAAzB,gBAAAruB,EAA4B,UAASpB,IAASA;AAE9E,SACE,gBAAApD;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,WAAU;AAAA,MACV,2BAAuB;AAAA,MACvB,OAAO,EAAE,aAAa,QAAA;AAAA,MAEtB,UAAA,gBAAA+B,EAAC,OAAA,EAAI,WAAW+uB,IAEb,UAAA;AAAA,QAAA6B,KACC,gBAAA5wB,EAAC,OAAA,EAAI,WAAU,oCACb,UAAA;AAAA,UAAA,gBAAA/B,EAACyV,IAAA,EAAM,WAAU,6CAA4C,UAAA,QAAI;AAAA,UACjE,gBAAAzV,EAAC,OAAA,EAAI,WAAU,wEACX,UAAA,CAAC,SAAS,UAAU,QAAQ,EAAY,IAAI,CAACiJ,MAC7C,gBAAAjJ;AAAA,YAAC;AAAA,YAAA;AAAA,cAEC,WAAW,6FAA6FsrB,MAASriB,IAAI,6CAA6C,sCAAsC;AAAA,cACxM,SAAS,MAAM8pB,EAAiB9pB,CAAC;AAAA,cACjC,gBAAcqiB,MAASriB;AAAA,cAEtB,aAAiBA,CAAC;AAAA,YAAA;AAAA,YALdA;AAAA,UAAA,CAOR,EAAA,CACH;AAAA,QAAA,GACF;AAAA,QAID2pB,KACC,gBAAA7wB,EAAA2C,IAAA,EACE,UAAA;AAAA,UAAA,gBAAA3C,EAAC,OAAA,EAAI,WAAU,oCACb,UAAA;AAAA,YAAA,gBAAA/B,EAACyV,IAAA,EAAM,WAAU,6CAA4C,UAAA,SAAK;AAAA,YAClE,gBAAAzV,EAAC,SAAI,WAAU,oCACZ,YAAS,MAAM,IAAI,CAACszB,GAAM9qB,MACzB,gBAAAxI;AAAA,cAAC;AAAA,cAAA;AAAA,gBAEC,WAAW,gEAAgEwI,MAAMqqB,IAAa,sBAAsB,mBAAmB;AAAA,gBACvI,OAAO,EAAE,iBAAiBS,EAAK,MAAA;AAAA,gBAC/B,SAAS,MAAMR,EAActqB,CAAC;AAAA,gBAC9B,cAAY,sBAAsBA,IAAI,CAAC;AAAA,gBACvC,gBAAcA,MAAMqqB;AAAA,cAAA;AAAA,cALfrqB;AAAA,YAAA,CAOR,EAAA,CACH;AAAA,UAAA,GACF;AAAA,UACCoqB,EAAS,SAAS,YACjB,gBAAA5yB;AAAA,YAACgG;AAAA,YAAA;AAAA,cACC,OAAM;AAAA,cACN,OAAO,KAAK,MAAM4sB,EAAS,KAAK;AAAA,cAChC,UAAUO;AAAA,cACV,KAAK;AAAA,cACL,KAAK;AAAA,cACL,MAAK;AAAA,YAAA;AAAA,UAAA;AAAA,QACP,GAEJ;AAAA,QAGF,gBAAAnzB;AAAA,UAAC2K;AAAA,UAAA;AAAA,YACC,OAAO0oB;AAAA,YACP,UAAU,CAACrvB,MACT4uB,IAAWM,EAAsBlvB,EAAE,OAAO,KAAK,IAAIiC,EAASjC,EAAE,OAAO,KAAK;AAAA,YAE5E,gBAAA6G;AAAA,YACA,aAAAC;AAAA,YACA,YAAY;AAAA,YACZ,UAAU;AAAA,UAAA;AAAA,QAAA;AAAA,MACZ,EAAA,CACF;AAAA,IAAA;AAAA,EAAA;AAGN,GAWayoB,KAAgD,CAAC,EAAE,OAAAnwB,GAAO,UAAA6C,GAAU,gBAAA4E,GAAgB,aAAAC,QAC/F,gBAAA9K;AAAA,EAAC;AAAA,EAAA;AAAA,IACC,WAAU;AAAA,IACV,2BAAuB;AAAA,IACvB,OAAO,EAAE,aAAa,QAAA;AAAA,IAEtB,UAAA,gBAAAA,EAAC,OAAA,EAAI,WAAW8wB,IACd,UAAA,gBAAA9wB,EAAC2K,IAAA,EAAoB,OAAAvH,GAAc,UAAA6C,GAAoB,gBAAA4E,GAAgC,aAAAC,GAA0B,UAAU,GAAA,CAAM,EAAA,CACnI;AAAA,EAAA;AACF,GAkBW0oB,KAAoD,CAAC;AAAA,EAChE,MAAAlI;AAAA,EACA,MAAAoH;AAAA,EACA,QAAAe;AAAA,EACA,OAAAC;AAAA,EACA,cAAAC;AAAA,EACA,cAAAhB;AAAA,EACA,gBAAAiB;AAAA,EACA,eAAAC;AACF,MACE,gBAAA7zB;AAAA,EAAC;AAAA,EAAA;AAAA,IACC,WAAU;AAAA,IACV,2BAAuB;AAAA,IACvB,OAAO,EAAE,aAAa,QAAA;AAAA,IAEtB,UAAA,gBAAA+B,EAAC,OAAA,EAAI,WAAW8uB,IAEd,UAAA;AAAA,MAAA,gBAAA9uB,EAAC,OAAA,EAAI,WAAU,oCACb,UAAA;AAAA,QAAA,gBAAA/B,EAACyV,IAAA,EAAM,WAAU,6CAA4C,UAAA,QAAI;AAAA,QACjE,gBAAA1T,EAAC,OAAA,EAAI,WAAU,wEACb,UAAA;AAAA,UAAA,gBAAA/B;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,WAAW,6FAA6FsrB,MAAS,SAAS,6CAA6C,sCAAsC;AAAA,cAC7M,SAAS,MAAMqI,EAAa,MAAM;AAAA,cACnC,UAAA;AAAA,YAAA;AAAA,UAAA;AAAA,UAGD,gBAAA3zB;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,WAAW,6FAA6FsrB,MAAS,aAAa,6CAA6C,sCAAsC;AAAA,cACjN,SAAS,MAAMqI,EAAa,UAAU;AAAA,cACvC,UAAA;AAAA,YAAA;AAAA,UAAA;AAAA,QAED,EAAA,CACF;AAAA,MAAA,GACF;AAAA,MAGA,gBAAA5xB,EAAC,OAAA,EAAI,WAAU,oCACb,UAAA;AAAA,QAAA,gBAAAA,EAAC,SAAA,EAAM,WAAU,kFACf,UAAA;AAAA,UAAA,gBAAA/B,EAACV,IAAA,EAAS,SAASozB,GAAM,iBAAiB,CAAC9pB,MAAM+pB,EAAa/pB,MAAM,EAAI,EAAA,CAAG;AAAA,UAAE;AAAA,QAAA,GAE/E;AAAA,QACA,gBAAA7G,EAAC,SAAA,EAAM,WAAU,kFACf,UAAA;AAAA,UAAA,gBAAA/B,EAACV,IAAA,EAAS,SAASm0B,GAAQ,iBAAiB,CAAC7qB,MAAMgrB,EAAehrB,MAAM,EAAI,EAAA,CAAG;AAAA,UAAE;AAAA,QAAA,EAAA,CAEnF;AAAA,MAAA,GACF;AAAA,MAGA,gBAAA7G,EAAC,OAAA,EAAI,WAAU,oCACb,UAAA;AAAA,QAAA,gBAAA/B,EAACyV,IAAA,EAAM,WAAU,6CAA4C,UAAA,SAAK;AAAA,QAClE,gBAAA1T,EAAC,OAAA,EAAI,WAAU,wEACb,UAAA;AAAA,UAAA,gBAAA/B;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,WAAW,6FAA6F0zB,MAAU,UAAU,6CAA6C,sCAAsC;AAAA,cAC/M,SAAS,MAAMG,EAAc,OAAO;AAAA,cACrC,UAAA;AAAA,YAAA;AAAA,UAAA;AAAA,UAGD,gBAAA7zB;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,WAAW,6FAA6F0zB,MAAU,aAAa,6CAA6C,sCAAsC;AAAA,cAClN,SAAS,MAAMG,EAAc,UAAU;AAAA,cACxC,UAAA;AAAA,YAAA;AAAA,UAAA;AAAA,QAED,EAAA,CACF;AAAA,MAAA,EAAA,CACF;AAAA,IAAA,EAAA,CACF;AAAA,EAAA;AACF,GAkBWC,KAA4D,CAAC;AAAA,EACxE,YAAAhd;AAAA,EACA,SAAAgB;AAAA,EACA,iBAAA9B;AAAA,EACA,iBAAA+d;AACF,MAAM;AAEJ,EAAAnd,GAAA;AAEA,QAAMI,IAA4BC,GAAyB,IAAI,CAACnP,OAAO,EAAE,IAAIA,EAAE,YAAY,MAAMA,EAAE,MAAM,cAAcA,EAAE,eAAe,GAElIkW,IAAe/W;AAAA,IACnB,CAACsQ,MAAe;AACd,MAAIA,QAAmBA,CAAE,GACzBvB,EAAgBuB,CAAE;AAAA,IACpB;AAAA,IACA,CAACvB,CAAe;AAAA,EAAA;AAGlB,SACE,gBAAAhW;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,WAAU;AAAA,MACV,2BAAuB;AAAA,MACvB,OAAO,EAAE,aAAa,QAAA;AAAA,MAEtB,UAAA,gBAAA+B,EAAC,OAAA,EAAI,WAAW8uB,IACd,UAAA;AAAA,QAAA,gBAAA7wB;AAAA,UAACyG;AAAA,UAAA;AAAA,YACC,SAASuQ;AAAA,YACT,YAAYF;AAAA,YACZ,UAAUkH;AAAA,YACV,WAAU;AAAA,UAAA;AAAA,QAAA;AAAA,QAIZ,gBAAAhe;AAAA,UAACgG;AAAA,UAAA;AAAA,YACC,OAAM;AAAA,YACN,OAAO8R;AAAA,YACP,UAAUic;AAAA,YACV,KAAK;AAAA,YACL,KAAK;AAAA,YACL,MAAK;AAAA,UAAA;AAAA,QAAA;AAAA,MACP,EAAA,CACF;AAAA,IAAA;AAAA,EAAA;AAGN,GAeaC,KAAgD,CAAC;AAAA,EAC5D,UAAApc;AAAA,EACA,UAAAC;AAAA,EACA,SAAAC;AAAA,EACA,UAAAC;AAAA,EACA,eAAAkc;AAAA,EACA,kBAAAC;AAAA,EACA,iBAAAH;AAAA,EACA,kBAAAI;AACF,MAAM;AAEJ,EAAAxc,GAAA;AAEA,QAAMX,IAA4BgB,GAAmB,IAAI,CAAClQ,OAAO,EAAE,IAAIA,EAAE,UAAU,MAAMA,EAAE,MAAM,cAAcA,EAAE,eAAe;AAEhI,SACE,gBAAA9H;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,WAAU;AAAA,MACV,2BAAuB;AAAA,MACvB,OAAO,EAAE,aAAa,QAAA;AAAA,MAEtB,UAAA,gBAAA+B,EAAC,OAAA,EAAI,WAAW8uB,IACd,UAAA;AAAA,QAAA,gBAAA7wB;AAAA,UAACyG;AAAA,UAAA;AAAA,YACC,SAASuQ;AAAA,YACT,YAAYY;AAAA,YACZ,UAAUqc;AAAA,YACV,WAAU;AAAA,UAAA;AAAA,QAAA;AAAA,QAIZ,gBAAAlyB,EAAC,OAAA,EAAI,WAAU,oCACb,UAAA;AAAA,UAAA,gBAAA/B,EAACyV,IAAA,EAAM,WAAU,6CAA4C,UAAA,QAAI;AAAA,UACjE,gBAAAzV,EAAC,OAAA,EAAI,WAAU,wEACX,UAAA,CAAC,QAAQ,SAAS,MAAM,EAAY,IAAI,CAACmY,MACzC,gBAAAnY;AAAA,YAAC;AAAA,YAAA;AAAA,cAEC,WAAW,2GACT6X,MAAaM,IACT,6CACA,sCACN;AAAA,cACA,SAAS,MAAM+b,EAAiB/b,CAAI;AAAA,cAEnC,UAAAA;AAAA,YAAA;AAAA,YARIA;AAAA,UAAA,CAUR,EAAA,CACH;AAAA,QAAA,GACF;AAAA,QAGA,gBAAAnY;AAAA,UAACgG;AAAA,UAAA;AAAA,YACC,OAAM;AAAA,YACN,OAAO8R;AAAA,YACP,UAAUic;AAAA,YACV,KAAK;AAAA,YACL,KAAK;AAAA,YACL,MAAK;AAAA,UAAA;AAAA,QAAA;AAAA,QAIP,gBAAAhyB,EAAC,SAAA,EAAM,WAAU,kFACf,UAAA;AAAA,UAAA,gBAAA/B,EAACV,IAAA,EAAS,SAASyY,GAAU,iBAAiB,CAACnP,MAAMurB,EAAiBvrB,MAAM,EAAI,EAAA,CAAG;AAAA,UAAE;AAAA,QAAA,EAAA,CAEvF;AAAA,MAAA,EAAA,CACF;AAAA,IAAA;AAAA,EAAA;AAGN,GAWawrB,KAA0C,CAAC,EAAE,QAAAX,GAAQ,UAAAxtB,GAAU,gBAAA4E,GAAgB,aAAAC,QAAkB;AAC5G,QAAM,CAACupB,GAAcC,CAAe,IAAIhpB,EAAS,EAAK,GAEhDuL,KAAU4c,KAAA,gBAAAA,EAAQ,YAAW,IAC7BxnB,KAAQwnB,KAAA,gBAAAA,EAAQ,UAAS,WACzBc,KAAQd,KAAA,gBAAAA,EAAQ,UAAS,GACzB3b,KAAU2b,KAAA,gBAAAA,EAAQ,YAAW,GAC7Be,KAAUf,KAAA,gBAAAA,EAAQ,YAAW,QAC7BgB,KAAWhB,KAAA,gBAAAA,EAAQ,aAAY,SAE/Bvc,IAAsBjQ;AAAA,IAC1B,CAACkQ,MAAwB;AACvB,MACElR,EADEkR,IACO,EAAE,SAAS,IAAM,OAAAlL,GAAO,OAAAsoB,GAAO,SAAAC,GAAS,UAAAC,GAAU,SAAA3c,MAElD,MAF2D;AAAA,IAIxE;AAAA,IACA,CAAC7R,GAAUgG,GAAOsoB,GAAOC,GAASC,GAAU3c,CAAO;AAAA,EAAA,GAG/CkV,IAAS/lB;AAAA,IACb,CAACytB,MAAiC;AAChC,MAAKjB,KACLxtB,EAAS,EAAE,GAAGwtB,GAAQ,GAAGiB,GAAO;AAAA,IAClC;AAAA,IACA,CAACjB,GAAQxtB,CAAQ;AAAA,EAAA;AAGnB,SACE,gBAAAjG;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,WAAU;AAAA,MACV,2BAAuB;AAAA,MACvB,OAAO,EAAE,aAAa,QAAA;AAAA,MAEtB,UAAA,gBAAA+B,EAAC,OAAA,EAAI,WAAW8uB,IAEd,UAAA;AAAA,QAAA,gBAAA9uB,EAAC,OAAA,EAAI,WAAU,8CACb,UAAA;AAAA,UAAA,gBAAA/B,EAACyV,IAAA,EAAM,WAAU,wDAAuD,UAAA,UAAM;AAAA,UAC9E,gBAAAzV,EAAC8E,IAAA,EAAO,SAAS+R,GAAS,iBAAiBK,EAAA,CAAqB;AAAA,QAAA,GAClE;AAAA,QAECL,KACC,gBAAA9U,EAAA2C,IAAA,EAEE,UAAA;AAAA,UAAA,gBAAA3C,EAAC,OAAA,EAAI,WAAU,8CACb,UAAA;AAAA,YAAA,gBAAA/B,EAACyV,IAAA,EAAM,WAAU,wDAAuD,UAAA,SAAK;AAAA,YAC7E,gBAAAzV;AAAA,cAAC2K;AAAA,cAAA;AAAA,gBACC,OAAOsB;AAAA,gBACP,UAAU,CAACjI,MAAqCgpB,EAAO,EAAE,OAAOhpB,EAAE,OAAO,OAAO;AAAA,gBAChF,gBAAA6G;AAAA,gBACA,aAAAC;AAAA,gBACA,YAAY;AAAA,cAAA;AAAA,YAAA;AAAA,UACd,GACF;AAAA,UAGA,gBAAA9K;AAAA,YAACgG;AAAA,YAAA;AAAA,cACC,OAAM;AAAA,cACN,OAAOuuB;AAAA,cACP,UAAU,CAAC3rB,MAAMokB,EAAO,EAAE,OAAOpkB,GAAG;AAAA,cACpC,KAAK;AAAA,cACL,KAAK;AAAA,cACL,MAAK;AAAA,YAAA;AAAA,UAAA;AAAA,UAIP,gBAAA5I;AAAA,YAACgG;AAAA,YAAA;AAAA,cACC,OAAM;AAAA,cACN,OAAO,KAAK,MAAM8R,IAAU,GAAG;AAAA,cAC/B,UAAU,CAAClP,MAAMokB,EAAO,EAAE,SAASpkB,IAAI,KAAK;AAAA,cAC5C,KAAK;AAAA,cACL,KAAK;AAAA,cACL,MAAK;AAAA,YAAA;AAAA,UAAA;AAAA,UAIP,gBAAA7G;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,WAAU;AAAA,cACV,SAAS,MAAMuyB,EAAgB,CAAChX,MAAS,CAACA,CAAI;AAAA,cAE7C,UAAA;AAAA,gBAAA+W,IAAe,SAAS;AAAA,gBAAO;AAAA,cAAA;AAAA,YAAA;AAAA,UAAA;AAAA,UAGjCA,KACC,gBAAAtyB,EAAA2C,IAAA,EAEE,UAAA;AAAA,YAAA,gBAAA3C,EAAC,OAAA,EAAI,WAAU,oCACb,UAAA;AAAA,cAAA,gBAAA/B,EAACyV,IAAA,EAAM,WAAU,wDAAuD,UAAA,YAAQ;AAAA,cAChF,gBAAAzV,EAAC,OAAA,EAAI,WAAU,wEACX,UAAA,CAAC,QAAQ,SAAS,QAAQ,EAAY,IAAI,CAAC20B,MAC3C,gBAAA30B;AAAA,gBAAC;AAAA,gBAAA;AAAA,kBAEC,WAAW,2GACTw0B,MAAYG,IACR,6CACA,sCACN;AAAA,kBACA,SAAS,MAAM3H,EAAO,EAAE,SAAS2H,GAAK;AAAA,kBAErC,UAAAA;AAAA,gBAAA;AAAA,gBARIA;AAAA,cAAA,CAUR,EAAA,CACH;AAAA,YAAA,GACF;AAAA,YAGA,gBAAA5yB,EAAC,OAAA,EAAI,WAAU,oCACb,UAAA;AAAA,cAAA,gBAAA/B,EAACyV,IAAA,EAAM,WAAU,wDAAuD,UAAA,aAAS;AAAA,cACjF,gBAAAzV,EAAC,OAAA,EAAI,WAAU,wEACX,UAAA,CAAC,SAAS,SAAS,OAAO,EAAY,IAAI,CAAC40B,MAC3C,gBAAA50B;AAAA,gBAAC;AAAA,gBAAA;AAAA,kBAEC,WAAW,2GACTy0B,MAAaG,IACT,6CACA,sCACN;AAAA,kBACA,SAAS,MAAM5H,EAAO,EAAE,UAAU4H,GAAM;AAAA,kBAEvC,UAAAA;AAAA,gBAAA;AAAA,gBARIA;AAAA,cAAA,CAUR,EAAA,CACH;AAAA,YAAA,EAAA,CACF;AAAA,UAAA,EAAA,CACF;AAAA,QAAA,EAAA,CAEJ;AAAA,MAAA,EAAA,CAEJ;AAAA,IAAA;AAAA,EAAA;AAGN,GAKMC,KAAkB;AAAA,EACtB,OAAO;AAAA,EACP,MAAM;AAAA,EACN,SAAS;AAAA,EACT,SAAS;AAAA,EACT,SAAS;AACX,GASaC,KAA0C,CAAC,EAAE,QAAAC,GAAQ,UAAA9uB,GAAU,gBAAA4E,GAAgB,aAAAC,QAAkB;AAC5G,QAAM+L,KAAUke,KAAA,gBAAAA,EAAQ,YAAW,IAC7B9oB,KAAQ8oB,KAAA,gBAAAA,EAAQ,UAASF,GAAgB,OACzCG,KAAOD,KAAA,gBAAAA,EAAQ,SAAQF,GAAgB,MACvCI,KAAUF,KAAA,gBAAAA,EAAQ,YAAWF,GAAgB,SAC7CK,KAAUH,KAAA,gBAAAA,EAAQ,YAAWF,GAAgB,SAC7C/c,KAAUid,KAAA,gBAAAA,EAAQ,YAAWF,GAAgB,SAE7C3d,IAAsBjQ;AAAA,IAC1B,CAACkQ,MAAwB;AACvB,MACElR,EADEkR,IACO,EAAE,SAAS,IAAM,OAAAlL,GAAO,MAAA+oB,GAAM,SAAAC,GAAS,SAAAC,GAAS,SAAApd,MAEhD,MAFyD;AAAA,IAItE;AAAA,IACA,CAAC7R,GAAUgG,GAAO+oB,GAAMC,GAASC,GAASpd,CAAO;AAAA,EAAA,GAG7CkV,IAAS/lB;AAAA,IACb,CAACytB,MAAiC;AAChC,MAAKK,KACL9uB,EAAS,EAAE,GAAG8uB,GAAQ,GAAGL,GAAO;AAAA,IAClC;AAAA,IACA,CAACK,GAAQ9uB,CAAQ;AAAA,EAAA;AAGnB,SACE,gBAAAjG;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,WAAU;AAAA,MACV,gBAAa;AAAA,MACb,2BAAuB;AAAA,MACvB,OAAO,EAAE,aAAa,QAAA;AAAA,MAEtB,UAAA,gBAAA+B,EAAC,OAAA,EAAI,WAAW8uB,IAEd,UAAA;AAAA,QAAA,gBAAA9uB,EAAC,OAAA,EAAI,WAAU,8CACb,UAAA;AAAA,UAAA,gBAAA/B,EAACyV,IAAA,EAAM,WAAU,wDAAuD,UAAA,UAAM;AAAA,4BAC7E3Q,IAAA,EAAO,SAAS+R,GAAS,iBAAiBK,GAAqB,eAAY,wBAAA,CAAwB;AAAA,QAAA,GACtG;AAAA,QAECL,KACC,gBAAA9U,EAAA2C,IAAA,EAEE,UAAA;AAAA,UAAA,gBAAA3C,EAAC,OAAA,EAAI,WAAU,8CACb,UAAA;AAAA,YAAA,gBAAA/B,EAACyV,IAAA,EAAM,WAAU,wDAAuD,UAAA,SAAK;AAAA,YAC7E,gBAAAzV;AAAA,cAAC2K;AAAA,cAAA;AAAA,gBACC,OAAOsB;AAAA,gBACP,UAAU,CAACjI,MAAqCgpB,EAAO,EAAE,OAAOhpB,EAAE,OAAO,OAAO;AAAA,gBAChF,gBAAA6G;AAAA,gBACA,aAAAC;AAAA,gBACA,YAAY;AAAA,cAAA;AAAA,YAAA;AAAA,UACd,GACF;AAAA,UAGA,gBAAA9K;AAAA,YAACgG;AAAA,YAAA;AAAA,cACC,OAAM;AAAA,cACN,OAAOgvB;AAAA,cACP,UAAU,CAAC,MAAMhI,EAAO,EAAE,MAAM,GAAG;AAAA,cACnC,KAAK;AAAA,cACL,KAAK;AAAA,cACL,MAAK;AAAA,YAAA;AAAA,UAAA;AAAA,UAIP,gBAAAhtB;AAAA,YAACgG;AAAA,YAAA;AAAA,cACC,OAAM;AAAA,cACN,OAAOivB;AAAA,cACP,UAAU,CAAC,MAAMjI,EAAO,EAAE,SAAS,GAAG;AAAA,cACtC,KAAK;AAAA,cACL,KAAK;AAAA,cACL,MAAK;AAAA,YAAA;AAAA,UAAA;AAAA,UAEP,gBAAAhtB;AAAA,YAACgG;AAAA,YAAA;AAAA,cACC,OAAM;AAAA,cACN,OAAOkvB;AAAA,cACP,UAAU,CAAC,MAAMlI,EAAO,EAAE,SAAS,GAAG;AAAA,cACtC,KAAK;AAAA,cACL,KAAK;AAAA,cACL,MAAK;AAAA,YAAA;AAAA,UAAA;AAAA,UAIP,gBAAAhtB;AAAA,YAACgG;AAAA,YAAA;AAAA,cACC,OAAM;AAAA,cACN,OAAO,KAAK,MAAM8R,IAAU,GAAG;AAAA,cAC/B,UAAU,CAAC,MAAMkV,EAAO,EAAE,SAAS,IAAI,KAAK;AAAA,cAC5C,KAAK;AAAA,cACL,KAAK;AAAA,cACL,MAAK;AAAA,YAAA;AAAA,UAAA;AAAA,QACP,EAAA,CACF;AAAA,MAAA,EAAA,CAEJ;AAAA,IAAA;AAAA,EAAA;AAGN,GAKMmI,KAAkE,CAAC,UAAU,GAAGC,EAAoB,GAY7FC,KAAgD,CAAC,EAAE,WAAAC,GAAW,UAAArvB,QACzE,gBAAAjG;AAAA,EAAC;AAAA,EAAA;AAAA,IACC,WAAU;AAAA,IACV,gBAAa;AAAA,IACb,2BAAuB;AAAA,IACvB,OAAO,EAAE,aAAa,QAAA;AAAA,IAEtB,4BAAC,OAAA,EAAI,WAAW6wB,IACd,UAAA,gBAAA9uB,EAAC,OAAA,EAAI,WAAU,oCACb,UAAA;AAAA,MAAA,gBAAA/B,EAACyV,IAAA,EAAM,WAAU,wDAAuD,UAAA,SAAK;AAAA,wBAC5E,OAAA,EAAI,WAAU,qFACZ,UAAA0f,GAAmB,IAAI,CAAC7J,MACvB,gBAAAtrB;AAAA,QAAC;AAAA,QAAA;AAAA,UAEC,mBAAiBsrB;AAAA,UACjB,gBAAcgK,MAAchK;AAAA,UAC5B,WAAW,2GACTgK,MAAchK,IACV,6CACA,sCACN;AAAA,UACA,SAAS,MAAMrlB,EAASqlB,CAAI;AAAA,UAE3B,UAAAA;AAAA,QAAA;AAAA,QAVIA;AAAA,MAAA,CAYR,EAAA,CACH;AAAA,IAAA,EAAA,CACF,EAAA,CACF;AAAA,EAAA;AACF,GAUWiK,KAAoD,CAAC,EAAE,SAAA9nB,GAAS,iBAAAS,QAC3E,gBAAAlO,EAACsvB,IAAA,EAAU,SAAA7hB,GAAkB,iBAAAS,GAAkC,GC/mCpDsnB,KAAsD,CAAC;AAAA,EAClE,WAAAC;AAAA,EACA,aAAAC;AAAA,EACA,gBAAAC;AAAA,EACA,gBAAAC;AACF,MACMH,MAAc,cAEd,gBAAA1zB,EAAC,OAAA,EAAI,WAAU,gFACb,UAAA;AAAA,EAAA,gBAAA/B,EAAC,QAAA,EAAK,WAAU,yEAAwE,UAAA,KAAC;AAAA,EACzF,gBAAAA;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,WAAU;AAAA,MACV,OAAO,EAAE,iBAAiB21B,EAAA;AAAA,IAAe;AAAA,EAAA;AAC3C,GACF,IAIAF,MAAc,eAEd,gBAAA1zB,EAAC,OAAA,EAAI,WAAU,gFACb,UAAA;AAAA,EAAA,gBAAA/B,EAACG,GAAA,EAAK,MAAK,yBAAwB,WAAU,0CAAyC;AAAA,EACtF,gBAAAH;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,WAAU;AAAA,MACV,OAAO,EAAE,YAAY41B,KAAkB,UAAA;AAAA,IAAU;AAAA,EAAA;AACnD,GACF,IAIA,OAAOF,KAAgB,WAClB,gBAAA11B,EAACG,GAAA,EAAK,MAAMu1B,GAAa,WAAU,0CAAyC,4BAG3E,UAAAA,EAAA,CAAY,GCtCXG,KAA8D,CAAC,EAAE,QAAA/pB,GAAQ,UAAA1K,QAElF,gBAAApB;AAAA,EAAC;AAAA,EAAA;AAAA,IACC,WAAU;AAAA,IACV,OAAO;AAAA,MACL,SAAS;AAAA,MACT,eAAe;AAAA,MACf,MAAM8L,IAAS,IAAI;AAAA,MACnB,WAAWA,IAAS,IAAI;AAAA,MACxB,YAAY;AAAA,IAAA;AAAA,IAGd,UAAA,gBAAA9L;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,WAAW8L,IAAS,wCAAwC;AAAA,QAC5D,OAAO;AAAA,UACL,MAAM;AAAA,UACN,SAAS;AAAA,UACT,eAAe;AAAA,UACf,WAAWA,IAAS,SAAS;AAAA,UAC7B,qBAAqB;AAAA,UACrB,yBAAyB;AAAA,UACzB,WAAWA,IAAS,kBAAkB;AAAA,UACtC,SAASA,IAAS,IAAI;AAAA,UACtB,YAAY;AAAA,QAAA;AAAA,QAGb,UAAA1K;AAAA,MAAA;AAAA,IAAA;AAAA,EACH;AAAA,GC7BO00B,KAAsD,CAAC,EAAE,QAAAhqB,GAAQ,UAAA1K,QAE1E,gBAAApB;AAAA,EAAC;AAAA,EAAA;AAAA,IACC,WAAU;AAAA,IACV,OAAO;AAAA,MACL,SAAS;AAAA,MACT,eAAe;AAAA,MACf,MAAM8L,IAAS,IAAI;AAAA,MACnB,WAAWA,IAAS,IAAI;AAAA,MACxB,YAAY;AAAA,IAAA;AAAA,IAGd,UAAA,gBAAA9L;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,WAAW8L,IAAS,wCAAwC;AAAA,QAC5D,OAAO;AAAA,UACL,MAAM;AAAA,UACN,WAAW;AAAA,UACX,WAAWA,IAAS,SAAY;AAAA,UAChC,qBAAqB;AAAA,UACrB,yBAAyB;AAAA,UACzB,WAAWA,IAAS,kBAAkB;AAAA,UACtC,SAASA,IAAS,IAAI;AAAA,UACtB,YAAY;AAAA,QAAA;AAAA,QAGb,UAAA1K;AAAA,MAAA;AAAA,IAAA;AAAA,EACH;AAAA,GC4BO20B,KAA8D,CAAC;AAAA,EAC1E,gBAAAC;AAAA,EACA,iBAAAC;AAAA,EACA,cAAAC;AAAA,EACA,WAAAC;AAAA,EACA,kBAAAC;AAAA,EACA,mBAAAC;AAAA;AAAA,EAEA,kBAAAC;AAAA,EACA,yBAAAC;AAAA,EACA,iBAAAC;AAAA,EACA,qBAAAC;AAAA,EACA,oBAAAC;AAAA,EACA,mBAAAC;AAAA,EACA,qBAAAC;AAAA,EACA,8BAAAC;AAAA,EACA,8BAAAC;AAAA,EACA,uBAAAC;AAAA,EACA,wBAAAC;AAAA,EACA,6BAAAC;AAAA,EACA,uBAAAC;AAAA,EACA,sBAAAC;AAAA,EACA,mBAAAC;AAAA,EACA,mBAAAC;AAAA,EACA,sBAAAC;AAAA,EACA,qBAAAC;AAAA,EACA,4BAAAC;AAAA,EACA,sBAAAC;AAAA;AAAA,EAEA,YAAAC;AAAA,EACA,mBAAAC;AAAA,EACA,kBAAAC;AAAA,EACA,eAAAC;AAAA,EACA,cAAAC;AAAA,EACA,aAAAC;AAAA,EACA,eAAAC;AAAA,EACA,wBAAAC;AAAA,EACA,wBAAAC;AAAA,EACA,iBAAAC;AAAA,EACA,kBAAAC;AAAA,EACA,uBAAAC;AAAA,EACA,iBAAAC;AAAA,EACA,gBAAAC;AAAA,EACA,aAAAC;AAAA,EACA,aAAAC;AAAA,EACA,gBAAAC;AAAA,EACA,eAAAC;AAAA,EACA,sBAAAC;AAAA,EACA,gBAAAC;AACF,MAEI,gBAAA92B;AAAA,EAAC;AAAA,EAAA;AAAA,IACC,WAAU;AAAA,IACV,OAAO;AAAA,MACL,SAAS;AAAA,MACT,eAAe;AAAA,MACf,MAAM;AAAA,MACN,WAAW;AAAA;AAAA,MACX,qBAAqB;AAAA,IAAA;AAAA,IAItB,UAAA;AAAA,MAAAs0B;AAAA,MAED,gBAAAr2B;AAAA,QAAC;AAAA,QAAA;AAAA,UACC,WAAU;AAAA,UACV,OACEo2B,MAAqB,OACjB;AAAA;AAAA,YAEE,QAAQA;AAAA,YACR,UAAU;AAAA,YACV,YAAY;AAAA,UAAA,IAEd;AAAA;AAAA,YAEE,SAAS;AAAA,YACT,kBAAkBF,KAAgB,CAACC,IAAY,QAAQ;AAAA,YACvD,YAAY;AAAA,UAAA;AAAA,UAIpB,UAAA,gBAAAn2B,EAAC,OAAA,EAAI,KAAKi2B,GAAkB,UAAAD,EAAA,CAAe;AAAA,QAAA;AAAA,MAAA;AAAA,MAI7C,gBAAAh2B,EAAC61B,IAAA,EAAsB,QAAQS,GAAmB,UAAAoB,IAAW;AAAA,MAG7D,gBAAA13B,EAAC61B,IAAA,EAAsB,QAAQU,GAA0B,UAAAoB,GAAkB;AAAA,MAG3E,gBAAA33B,EAAC61B,IAAA,EAAsB,QAAQW,GAAkB,UAAAoB,IAAiB;AAAA,MAGlE,gBAAA53B,EAAC61B,IAAA,EAAsB,QAAQY,GAAsB,UAAAoB,IAAc;AAAA,MAGnE,gBAAA73B,EAAC61B,IAAA,EAAsB,QAAQa,GAAqB,UAAAoB,GAAa;AAAA,MAGjE,gBAAA93B,EAAC61B,IAAA,EAAsB,QAAQc,GAAoB,UAAAoB,GAAY;AAAA,MAG/D,gBAAA/3B,EAAC61B,IAAA,EAAsB,QAAQe,GAAsB,UAAAoB,GAAc;AAAA,MAGnE,gBAAAh4B,EAAC61B,IAAA,EAAsB,QAAQgB,GAC5B,UAAAoB,IACH;AAAA,MAGA,gBAAAj4B,EAAC61B,IAAA,EAAsB,QAAQiB,GAC5B,UAAAoB,GACH;AAAA,MAGA,gBAAAl4B,EAAC61B,IAAA,EAAsB,QAAQkB,GAAwB,UAAAoB,IAAgB;AAAA,MAGvE,gBAAAn4B,EAAC61B,IAAA,EAAsB,QAAQmB,GAAyB,UAAAoB,IAAiB;AAAA,MAGzE,gBAAAp4B,EAAC61B,IAAA,EAAsB,QAAQoB,GAC5B,UAAAoB,GACH;AAAA,MAGA,gBAAAr4B,EAAC81B,IAAA,EAAkB,QAAQoB,GAAwB,UAAAoB,IAAgB;AAAA,MAGnE,gBAAAt4B,EAAC81B,IAAA,EAAkB,QAAQqB,GAAuB,UAAAoB,IAAe;AAAA,MAGjE,gBAAAv4B,EAAC61B,IAAA,EAAsB,QAAQuB,GAAoB,UAAAoB,IAAY;AAAA,MAG/D,gBAAAx4B,EAAC61B,IAAA,EAAsB,QAAQwB,GAAoB,UAAAoB,IAAY;AAAA,MAG/D,gBAAAz4B,EAAC61B,IAAA,EAAsB,QAAQyB,GAAuB,UAAAoB,IAAe;AAAA,MAGrE,gBAAA14B,EAAC61B,IAAA,EAAsB,QAAQ0B,GAAsB,UAAAoB,IAAc;AAAA,MAGnE,gBAAA34B,EAAC61B,IAAA,EAAsB,QAAQ2B,GAA6B,UAAAoB,IAAqB;AAAA,MAGjF,gBAAA54B,EAAC61B,IAAA,EAAsB,QAAQ4B,GAAuB,UAAAoB,GAAA,CAAe;AAAA,IAAA;AAAA,EAAA;AAAA,GCrM9DC,KAAsE,CAAC;AAAA,EAClF,iBAAAC;AAAA,EACA,eAAA7K;AAAA,EACA,YAAA8K;AAAA,EACA,OAAA51B;AAAA,EACA,UAAA6C;AACF,MACE,gBAAAjG;AAAA,EAAC;AAAA,EAAA;AAAA,IACC,WAAU;AAAA,IACV,OAAO;AAAA,MACL,UAAU;AAAA,MACV,KAAK,GAAG+4B,EAAgB,MAAM7K,IAAgB,CAAC;AAAA,MAC/C,MAAM,GAAG6K,EAAgB,IAAI;AAAA,MAC7B,WAAW;AAAA,MACX,SAAS;AAAA,MACT,WAAW;AAAA,MACX,cAAc;AAAA,MACd,QAAQ;AAAA,MACR,WAAW;AAAA,MACX,QAAQ;AAAA,MACR,OAAO,GAAGC,CAAU;AAAA,MACpB,WAAW;AAAA,IAAA;AAAA,IAGb,UAAA,gBAAAh5B,EAACgG,IAAA,EAAU,OAAM,UAAS,OAAA5C,GAAc,UAAA6C,GAAoB,KAAK,GAAG,KAAK,IAAI,MAAK,IAAA,CAAI;AAAA,EAAA;AACxF,GASWgzB,KAAwD,CAAC;AAAA,EACpE,iBAAAF;AAAA,EACA,eAAA7K;AAAA,EACA,SAAA+C;AACF,MACE,gBAAAjxB;AAAA,EAAC;AAAA,EAAA;AAAA,IACC,WAAU;AAAA,IACV,OAAO;AAAA,MACL,UAAU;AAAA,MACV,KAAK,GAAG+4B,EAAgB,MAAM7K,IAAgB,CAAC;AAAA,MAC/C,MAAM,GAAG6K,EAAgB,IAAI;AAAA,MAC7B,WAAW;AAAA,MACX,YAAY;AAAA,MACZ,QAAQ;AAAA,MACR,cAAc;AAAA,MACd,WAAW;AAAA,MACX,QAAQ;AAAA,IAAA;AAAA,IAGV,UAAA,gBAAA/4B,EAACgxB,MAAW,SAAAC,EAAA,CAAkB;AAAA,EAAA;AAChC,GAUWiI,KAAsD,CAAC;AAAA,EAClE,iBAAAH;AAAA,EACA,eAAA7K;AAAA,EACA,SAAAzgB;AAAA,EACA,iBAAAS;AACF,MACE,gBAAAlO;AAAA,EAAC;AAAA,EAAA;AAAA,IACC,WAAU;AAAA,IACV,OAAO;AAAA,MACL,UAAU;AAAA,MACV,KAAK,GAAG+4B,EAAgB,MAAM7K,IAAgB,CAAC;AAAA,MAC/C,MAAM,GAAG6K,EAAgB,IAAI;AAAA,MAC7B,WAAW;AAAA,MACX,YAAY;AAAA,MACZ,QAAQ;AAAA,MACR,cAAc;AAAA,MACd,WAAW;AAAA,MACX,QAAQ;AAAA,MACR,UAAU;AAAA,IAAA;AAAA,IAGZ,UAAA,gBAAA/4B,EAACsvB,IAAA,EAAU,SAAA7hB,GAAkB,iBAAAS,EAAA,CAAkC;AAAA,EAAA;AACjE,GChFIirB,KAAc,CAAC9wB,MACnB,OAAOA,KAAM,YAAYA,EAAE,SAAS,KAAKA,MAAM;AAQjD,SAAS+wB,GAAmB3zB,GAAiB4zB,GAAwB;;AAGnE,QAAM5F,IAAUhuB,EACb;AAKH,MAJIguB,KAAA,QAAAA,EAAQ,WAAW0F,GAAY1F,EAAO,KAAK,KAC7C4F,EAAI,IAAI5F,EAAO,KAAK,GAGlBhuB,aAAcyhB,IAAa;AAC7B,IAAIiS,GAAY1zB,EAAG,KAAK,KAAG4zB,EAAI,IAAI5zB,EAAG,KAAK;AAI3C,UAAM6zB,IAAY7zB,EAAwE;AAC1F,QAAI6zB,KAAA,QAAAA,EAAU;AACZ,iBAAWrN,KAAQqN,EAAS;AAC1B,QAAIH,IAAY30B,IAAAynB,EAAK,UAAL,gBAAAznB,EAAY,KAAK,KAAG60B,EAAI,IAAIpN,EAAK,MAAO,KAAM;AAGlE;AAAA,EACF;AAEA,MAAIxmB,aAAc2kB,IAAc;AAC9B,UAAMmP,IAAW9zB,EAAG,cAAc;AAClC,QAAI8zB,GAAU;AAEZ,UAAIA,EAAS,SAAS;AACpB,QAAIJ,GAAYI,EAAS,KAAK,KAAGF,EAAI,IAAIE,EAAS,KAAK;AAAA;AAEvD,mBAAWjG,KAAQiG,EAAS;AAC1B,UAAIJ,GAAY7F,EAAK,KAAK,KAAG+F,EAAI,IAAI/F,EAAK,KAAK;AAGnD;AAAA,IACF;AACA,UAAMZ,IAAOjtB,EAAG,cAAc;AAC9B,IAAI0zB,GAAYzG,CAAI,KAAG2G,EAAI,IAAI3G,CAAI;AACnC;AAAA,EACF;AAEA,MAAIjtB,aAAc4kB,IAAa;AAC7B,UAAM3c,IAAMjI,EAAmB;AAC/B,IAAIiI,EAAG,eAAeyrB,GAAYzrB,EAAG,SAAS,KAAG2rB,EAAI,IAAI3rB,EAAG,SAAS,GACjEA,EAAG,iBAAiByrB,GAAYzrB,EAAG,WAAW,KAAG2rB,EAAI,IAAI3rB,EAAG,WAAW;AAC3E;AAAA,EACF;AAEA,MAAIjI,aAAc4gB,IAAc;AAE9B,eAAWlH,KAAS1Z,EAAG;AACrB,MAAA2zB,GAAmBja,GAAOka,CAAG;AAE/B;AAAA,EACF;AAIF;AAWO,SAASG,GACdjf,GACA/B,GACa;AACb,QAAM6gB,wBAAU,IAAA;AAChB,aAAW5zB,KAAM8U,EAAU,CAAA6e,GAAmB3zB,GAAI4zB,CAAG;AACrD,MAAI7gB;AACF,eAAWihB,KAAMjhB,GAAW;AAC1B,YAAMkhB,IAAMD,EAAoC;AAChD,MAAIN,GAAYO,CAAE,KAAGL,EAAI,IAAIK,CAAE;AAAA,IACjC;AAEF,SAAOL;AACT;AAMA,MAAMM,yBAA0B,IAAA,GAC1BC,yBAA6B,IAAA;AAgBnC,SAASC,GAAcC,GAAmE;AACxF,MAAIA,EAAO,WAAW,EAAG,QAAO,EAAE,QAAQ,GAAG,QAAQ,GAAG,QAAQ,EAAA;AAChE,MAAIC,IAAO,KAAKC,IAAO,GAAGC,IAAO,KAAKC,IAAO,GAAGC,IAAO,KAAKC,IAAO;AACnE,aAAWtyB,KAAKgyB;AACd,IAAIhyB,EAAE,IAAIiyB,MAAMA,IAAOjyB,EAAE,IACrBA,EAAE,IAAIkyB,MAAMA,IAAOlyB,EAAE,IACrBA,EAAE,IAAImyB,MAAMA,IAAOnyB,EAAE,IACrBA,EAAE,IAAIoyB,MAAMA,IAAOpyB,EAAE,IACrBA,EAAE,IAAIqyB,MAAMA,IAAOryB,EAAE,IACrBA,EAAE,IAAIsyB,MAAMA,IAAOtyB,EAAE;AAE3B,SAAO,EAAE,QAAQkyB,IAAOD,GAAM,QAAQG,IAAOD,GAAM,QAAQG,IAAOD,EAAA;AACpE;AAEA,SAASE,GAAeC,GAA2B;AACjD,QAAM92B,IAAM,KAAK,IAAI82B,EAAI,QAAQA,EAAI,QAAQA,EAAI,MAAM;AACvD,SAAIA,EAAI,WAAW92B,IAAY,MAC3B82B,EAAI,WAAW92B,IAAY,MACxB;AACT;AAEA,SAAS+2B,GAAQD,GAAkB;AACjC,SAAO,KAAK,IAAIA,EAAI,QAAQA,EAAI,QAAQA,EAAI,MAAM;AACpD;AAEA,SAASE,GAASF,GAAsB;AACtC,QAAMG,IAAOJ,GAAeC,CAAG,GAGzBxO,IAASwO,EAAI,OAAO,MAAA,EAAQ,KAAK,CAAC/xB,GAAGW,MAAMX,EAAEkyB,CAAI,IAAIvxB,EAAEuxB,CAAI,CAAC,GAC5DC,IAAM5O,EAAO,UAAU,GACvB6O,IAAa7O,EAAO,MAAM,GAAG4O,CAAG,GAChCE,IAAc9O,EAAO,MAAM4O,CAAG;AACpC,SAAO;AAAA,IACL,EAAE,QAAQC,GAAY,GAAGd,GAAcc,CAAU,EAAA;AAAA,IACjD,EAAE,QAAQC,GAAa,GAAGf,GAAce,CAAW,EAAA;AAAA,EAAE;AAEzD;AAEA,SAASC,GAAaf,GAAoB;AACxC,MAAI3xB,IAAI,GAAGY,IAAI,GAAGG,IAAI;AACtB,aAAWpB,KAAKgyB;AACd,IAAA3xB,KAAKL,EAAE,GACPiB,KAAKjB,EAAE,GACPoB,KAAKpB,EAAE;AAET,QAAMW,IAAIqxB,EAAO;AACjB,SAAO;AAAA,IACL,GAAG,KAAK,MAAM3xB,IAAIM,CAAC;AAAA,IACnB,GAAG,KAAK,MAAMM,IAAIN,CAAC;AAAA,IACnB,GAAG,KAAK,MAAMS,IAAIT,CAAC;AAAA,EAAA;AAEvB;AAQA,SAASqyB,GAAehB,GAAeiB,GAA8B;AACnE,MAAIjB,EAAO,WAAW,EAAG,QAAO,CAAA;AAChC,QAAMkB,IAAe,CAAC,EAAE,QAAAlB,GAAQ,GAAGD,GAAcC,CAAM,GAAG;AAE1D,SAAOkB,EAAM,SAASD,KAAe;AAInC,QAAIE,IAAU,IACVC,IAAW;AACf,aAAS,IAAI,GAAG,IAAIF,EAAM,QAAQ,KAAK;AACrC,YAAMl0B,IAAOyzB,GAAQS,EAAM,CAAC,CAAC;AAC7B,MAAIl0B,IAAOo0B,KAAYF,EAAM,CAAC,EAAE,OAAO,UAAU,MAC/CE,IAAWp0B,GACXm0B,IAAU;AAAA,IAEd;AACA,QAAIA,MAAY,GAAI;AACpB,UAAME,IAASH,EAAMC,CAAO;AAC5B,IAAAD,EAAM,OAAOC,GAAS,CAAC,GACvBD,EAAM,KAAK,GAAGR,GAASW,CAAM,CAAC;AAAA,EAChC;AAEA,SAAOH;AACT;AA+BO,SAASI,GAAgB7yB,GAAQW,GAAgB;AACtD,QAAMmyB,KAAS9yB,EAAE,IAAIW,EAAE,KAAK,GACtBoyB,IAAK/yB,EAAE,IAAIW,EAAE,GACbqyB,IAAKhzB,EAAE,IAAIW,EAAE,GACbsyB,IAAKjzB,EAAE,IAAIW,EAAE;AACnB,SAAO,KAAK;AAAA,KACT,IAAImyB,IAAQ,OAAOC,IAAKA,IACzB,IAAIC,IAAKA,KACR,KAAK,MAAMF,KAAS,OAAOG,IAAKA;AAAA,EAAA;AAErC;AAyCO,SAASC,GACdC,GACAC,GACAC,GACO;AACP,MAAIF,EAAW,WAAW,KAAKC,KAAe,UAAU,CAAA;AACxD,QAAME,IAAgB,CAACH,EAAW,CAAC,CAAC,GAC9BI,IAAO,oBAAI,IAAY,CAAC,CAAC,CAAC;AAChC,SAAOD,EAAO,SAASF,KAAa;AAClC,QAAIV,IAAU,IACVc,IAAc;AAClB,aAASvzB,IAAI,GAAGA,IAAIkzB,EAAW,QAAQlzB,KAAK;AAC1C,UAAIszB,EAAK,IAAItzB,CAAC,EAAG;AACjB,UAAIwzB,IAAU;AACd,iBAAWl0B,KAAK+zB,GAAQ;AACtB,cAAMhzB,IAAIuyB,GAAgBM,EAAWlzB,CAAC,GAAGV,CAAC;AAC1C,QAAIe,IAAImzB,MAASA,IAAUnzB;AAAA,MAC7B;AACA,MAAImzB,IAAUD,MACZA,IAAcC,GACdf,IAAUzyB;AAAA,IAEd;AACA,QAAIyyB,MAAY,MAAMc,KAAeH,EAAW;AAChD,IAAAC,EAAO,KAAKH,EAAWT,CAAO,CAAC,GAC/Ba,EAAK,IAAIb,CAAO;AAAA,EAClB;AACA,SAAOY;AACT;AAEA,MAAMI,KAAQ,CAACxzB,MAAcA,EAAE,SAAS,EAAE,EAAE,SAAS,GAAG,GAAG;AAC3D,SAASyzB,GAAS7zB,GAAgB;AAChC,SAAO,IAAI4zB,GAAM5zB,EAAE,CAAC,CAAC,GAAG4zB,GAAM5zB,EAAE,CAAC,CAAC,GAAG4zB,GAAM5zB,EAAE,CAAC,CAAC;AACjD;AA4BA,eAAsB8zB,GACpBvkB,GACA+jB,IAAc,GACK;AACnB,MAAI,CAAC/jB,EAAU,QAAO,CAAA;AACtB,QAAMwkB,IAASzC,GAAoB,IAAI/hB,CAAQ;AAC/C,MAAIwkB,EAAQ,QAAOA;AACnB,QAAMC,IAAWzC,GAAuB,IAAIhiB,CAAQ;AACpD,MAAIykB,EAAU,QAAOA;AAErB,QAAMC,KAAW,YAA+B;AAC9C,QAAI;AACF,YAAMtS,IAAM,MAAMuS,GAAc3kB,CAAQ,GAClC4kB,IAAS,IASTC,KARS,OAAO,kBAAoB,MACtC,IAAI,gBAAgBD,GAAQA,CAAM,KACjC,MAAM;AACL,cAAMn0B,IAAI,SAAS,cAAc,QAAQ;AACzC,eAAAA,EAAE,QAAQm0B,GACVn0B,EAAE,SAASm0B,GACJn0B;AAAA,MACT,GAAA,GAED,WAAW,IAAI;AAIlB,UAAI,CAACo0B,EAAK,QAAO,CAAA;AACjB,MAAAA,EAAI,UAAUzS,GAAK,GAAG,GAAGwS,GAAQA,CAAM;AACvC,YAAM,EAAE,MAAAE,MAASD,EAAI,aAAa,GAAG,GAAGD,GAAQA,CAAM,GAEhD1C,IAAgB,CAAA;AACtB,eAAStxB,IAAI,GAAGA,IAAIk0B,EAAK,QAAQl0B,KAAK,GAAG;AAEvC,YADUk0B,EAAKl0B,IAAI,CAAC,IACZ,IAAK;AACb,cAAML,IAAIu0B,EAAKl0B,CAAC,GACVO,IAAI2zB,EAAKl0B,IAAI,CAAC,GACdU,IAAIwzB,EAAKl0B,IAAI,CAAC;AAEpB,QAAIL,IAAI,OAAOY,IAAI,OAAOG,IAAI,OAC9B4wB,EAAO,KAAK,EAAE,GAAA3xB,GAAG,GAAAY,GAAG,GAAAG,GAAG;AAAA,MACzB;AACA,UAAI4wB,EAAO,WAAW;AACpB,eAAAH,GAAoB,IAAI/hB,GAAU,EAAE,GAC7B,CAAA;AAST,YAAM+kB,IAAc,KAAK,IAAIhB,IAAc,GAAG,EAAE,GAC1CX,IAAQF,GAAehB,GAAQ6C,CAAW;AAGhD,MAAA3B,EAAM,KAAK,CAACzyB,GAAGW,MAAMA,EAAE,OAAO,SAASX,EAAE,OAAO,MAAM;AAEtD,YAAMmzB,IAAaV,EAAM,IAAI,CAACV,MAAQO,GAAaP,EAAI,MAAM,CAAC,GAexDzL,IAAM4M,GAAqBC,GAAYC,GAAa,EAAE,EAAE,IAAIO,EAAQ;AAE1E,aAAAvC,GAAoB,IAAI/hB,GAAUiX,CAAG,GAC9BA;AAAA,IACT,QAAQ;AAGN,aAAA8K,GAAoB,IAAI/hB,GAAU,EAAE,GAC7B,CAAA;AAAA,IACT,UAAA;AACE,MAAAgiB,GAAuB,OAAOhiB,CAAQ;AAAA,IACxC;AAAA,EACF,GAAA;AACA,SAAAgiB,GAAuB,IAAIhiB,GAAU0kB,CAAO,GACrCA;AACT;AAEA,SAASC,GAAcnlB,GAAwC;AAC7D,SAAO,IAAI,QAAQ,CAAC6S,GAASC,MAAW;AACtC,UAAMF,IAAM,IAAI,MAAA;AAEhB,IAAAA,EAAI,cAAc,aAClBA,EAAI,SAAS,MAAMC,EAAQD,CAAG,GAC9BA,EAAI,UAAU,MAAME,EAAO,IAAI,MAAM,yBAAyB9S,CAAG,EAAE,CAAC,GACpE4S,EAAI,MAAM5S;AAAA,EACZ,CAAC;AACH;AAQA,eAAsBwlB,GACpBriB,GACAohB,IAAc,GACK;AACnB,QAAMkB,IAAiB,CAAA,GACjBzgB,wBAAW,IAAA,GACX0gB,IAAQ,CAACr3B,MAAoB;AACjC,QAAIA,aAAcskB,IAAc;AAC9B,YAAM3S,IAAM3R,EAAG;AACf,MAAI2R,KAAO,CAACgF,EAAK,IAAIhF,CAAG,MACtBgF,EAAK,IAAIhF,CAAG,GACZylB,EAAK,KAAKzlB,CAAG;AAAA,IAEjB,WAAW3R,aAAc4gB;AACvB,iBAAWhe,KAAK5C,EAAG,SAAU,CAAAq3B,EAAMz0B,CAAC;AAAA,EAExC;AACA,aAAW5C,KAAM8U,EAAU,CAAAuiB,EAAMr3B,CAAE;AACnC,MAAIo3B,EAAK,WAAW,EAAG,QAAO,CAAA;AAE9B,QAAME,IAAW,MAAM,QAAQ;AAAA,IAC7BF,EAAK,IAAI,CAAC30B,MAAMi0B,GAAoBj0B,GAAGyzB,CAAW,CAAC;AAAA,EAAA,GAE/CtC,IAAgB,CAAA,GAChB2D,wBAAa,IAAA;AACnB,aAAWC,KAAWF;AACpB,eAAW10B,KAAK40B;AACd,MAAKD,EAAO,IAAI30B,CAAC,MACf20B,EAAO,IAAI30B,CAAC,GACZgxB,EAAI,KAAKhxB,CAAC;AAIhB,SAAOgxB;AACT;AC1aA,MAAMpf,KAASC,GAAa,oBAAoB,GAG1CgjB,KAAwB;AAG9B,SAASC,GAAiBC,GAAcC,GAA0B;AAChE,QAAMC,IAAUF,aAAe,QAAQA,EAAI,UAAU;AACrD,SAAI,CAACE,KAAW,4BAA4B,KAAKA,CAAO,IAAUD,IAC3DC;AACT;AA2NO,MAAMC,KAAwD,CAAC,EAAE,UAAAC,GAAU,GAAG79B,QAAY;AAC/F,QAAMkrB,IAAQ,gBAAA7qB,EAACy9B,IAAA,EAAyB,GAAG99B,EAAA,CAAO;AAIlD,SAAO69B,IAAW,gBAAAx9B,EAAC09B,IAAA,EAAuB,UAAAF,GAAqB,aAAM,IAA4B3S;AACnG,GAEM4S,KAA+E,CAAC;AAAA,EACpF,MAAAnS,IAAO;AAAA,EACP,oBAAApI;AAAA,EACA,eAAA3U;AAAA,EACA,uBAAAiE;AAAA,EACA,gBAAA3H,wBAAqB,IAAA;AAAA,EACrB,eAAAmY,IAAgB,OAAO;AAAA,EACvB,aAAa2a,IAAe,CAAA;AAAA,EAC5B,WAAAxa,IAAY;AAAA,EACZ,kBAAAG;AAAA,EACA,kBAAA7K;AAAA,EACA,sBAAAG;AAAA,EACA,UAAAglB;AAAA,EACA,aAAAC,IAAc;AAAA,EACd,qBAAAC;AAAA,EACA,sBAAAC;AAAA,EACA,2BAAAC;AAAA,EACA,kBAAAC;AAAA,EACA,0BAAAC;AAAA,EACA,kBAAA94B,IAAmB;AAAA,EACnB,mBAAA+4B,IAAoB;AAAA,EACpB,kBAAAC;AAAA,EACA,kBAAAC,IAAmB;AAAA,EACnB,0BAAAC;AAAA,EACA,uBAAAC;AAAA,EACA,UAAAhR;AACF,MAAM;;AAGJ,QAAM,EAAE,WAAAE,EAAA,IAAcC,GAAA,GAChB,EAAE,gBAAAlB,IAAgB,eAAAgS,EAAA,IAAkBC,GAAA,GACpC;AAAA,IACJ,mBAAmBC;AAAA,IACnB,sBAAsBC;AAAA,IACtB,sBAAAC;AAAA,IACA,YAAAC;AAAA,EAAA,IACEC,GAAA,GAGE;AAAA,IACJ,UAAAvkB;AAAA,IACA,aAAAoS;AAAA,IACA,iBAAA1G;AAAA,IACA,oBAAAC;AAAA,IACA,qBAAAC;AAAA,IACA,iBAAAsG;AAAA,IACA,WAAAjU;AAAA,IACA,iBAAAwN;AAAA,IACA,WAAAwH;AAAA,IACA,sBAAAuR;AAAA,IACA,sBAAAC;AAAA,IACA,mBAAAC;AAAA,IACA,uBAAAC;AAAA,IACA,kBAAAC;AAAA,EAAA,IACE/Y,GAAA,GAGE,EAAE,kBAAAgZ,EAAA,IAAqB1jB,GAAA,GAGvB2jB,IAAcvZ,GAAe,EAAE,iBAAAE,IAAiB,GAGhD,CAACsZ,GAAYC,CAAa,IAAIj0B,EAAmB,MAAM,GACvD,CAACk0B,GAAcC,EAAe,IAAIn0B,EAAuB,IAAI,GAC7D,CAACytB,GAAiB2G,EAAkB,IAAIp0B,EAA+C,IAAI,GAC3F,CAACq0B,IAAaC,EAAa,IAAIt0B,EAAkB,EAAK,GACtD,CAACkY,IAAqBqc,EAAsB,IAAIv0B,EAAkB,EAAK,GACvE,CAACw0B,EAAiB,IAAIx0B,EAAkB,EAAK,GAC7C,CAACy0B,IAAoBC,EAAqB,IAAI10B,EAAkB,EAAK,GACrE,CAAC20B,IAAuBC,EAAwB,IAAI50B,EAAkB,EAAK,GAG3E,CAAC8X,GAAe+c,EAAgB,IAAI70B,EAA8B,MACjEyyB,KACqD;AAAA,IACxD,cAAc,EAAE,MAAM,gBAAgB,MAAM,8BAA8B,OAAO,gBAAA;AAAA,IACjF,MAAM,EAAE,MAAM,QAAQ,MAAM,eAAe,OAAO,OAAA;AAAA,IAClD,UAAU,EAAE,MAAM,YAAY,MAAMj4B,GAAM,YAAY,OAAO,SAAA;AAAA,IAC7D,SAAS,EAAE,MAAM,WAAW,MAAM,gBAAgB,OAAO,eAAA;AAAA,IACzD,SAAS,EAAE,MAAM,WAAW,MAAM,mBAAmB,OAAO,UAAA;AAAA,EAAU,EAEpDi4B,CAAoB,KAAK,IAC9C,GAGK,CAACqC,IAAYC,EAAa,IAAI/0B,EAAkB,EAAK,GACrD,CAAC6qB,IAAWmK,EAAY,IAAIh1B,EAAkB,EAAK,GACnD,CAAC4qB,IAAcqK,EAAe,IAAIj1B,EAAkB,EAAK,GACzD,CAACk1B,IAAsBC,EAAuB,IAAIn1B,EAAkB,EAAK,GACzE,CAACo1B,IAAqBC,EAAsB,IAAIr1B,EAAwB,IAAI,GAC5E,CAAC8qB,IAAkBwK,EAAmB,IAAIt1B,EAAwB,IAAI,GACtE,CAACu1B,IAAmBC,EAAoB,IAAIx1B,EAAS,EAAE,OAAO,GAAG,QAAQ,GAAG,GAG5EuiB,KAAavoB,EAAuB,IAAI,GACxC2wB,KAAkB3wB,EAAuB,IAAI,GAC7Cy7B,KAAqBz7B,EAAe,CAAC,GACrC07B,KAAoB17B,EAAgB,EAAK,GACzC27B,KAAiB37B,EAAgB,EAAK,GACtC47B,KAAoB57B,EAA6C,IAAI,GACrE67B,KAAyB77B,EAA2B,MAAS,GAC7D87B,KAAyB97B,EAAsB,IAAI,GACnD+7B,KAAkC/7B,EAAOo5B,EAAwB,GACjE4C,KAAoBh8B,EAA2B,MAAS,GACxDi8B,KAAqBj8B,EAA2B,MAAS,GACzDk8B,KAAoBl8B,EAAgB,EAAK,GACzCm8B,KAAgBn8B,EAAgB,EAAK,GACrCo8B,KAAsBp8B,EAAO,CAAC,CAACy4B,CAAoB,GACnD4D,KAAoBr8B,EAAO,EAAK,GAChCs8B,KAAmBt8B,EAAO8d,CAAa,GACvCye,KAA0Bv8B,EAA6B,IAAI,GAC3Dw8B,KAA0Bx8B,EAAoC,MAAM;AAAA,EAAC,CAAC,GACtEy8B,KAA0Bz8B,EAA2B,MAAS,GAC9D08B,KAAoB18B,EAA4B,MAAS;AAG/D,EAAAm8B,GAAc,UAAU5C;AAGxB,QAAMtb,IAAuB2C,MAAsBD,GAC7ClD,KAAkBQ,KAAA,gBAAAA,EAAsB,IACxC0e,KAAmBhc,KAAA,gBAAAA,EAAiB,IACpCic,KAAqB3e,KAAA,gBAAAA,EAAsB,eAC3C,EAAE,WAAA4D,IAAW,mBAAA+B,IAAmB,uBAAAT,GAAA,IAA0B4W,GAC1D8C,KAAoB,CAAC,EAAElc,KAAmB,CAAC4Y,IAG3Cnb,IAAuBzc;AAAA,IAC3B,CAACgL,MAAkC;AACjC,UAAKgU;AACL,YAAIC,IAAoB;AAEtB,gBAAMI,IADeL,EACa,MAAA,GAC5BM,IAAaD,EAAa,SAAS,UAAU,CAACje,OAAMA,GAAE,OAAO6d,GAAmB,EAAE;AACxF,UAAIK,MAAe,OACjBD,EAAa,SAASC,CAAU,IAAItU,GACpCkU,GAAoBG,CAAY;AAAA,QAEpC;AACE,UAAAH,GAAoBlU,CAAc;AAAA,IAEtC;AAAA,IACA,CAACgU,GAAiBC,IAAoBC,EAAmB;AAAA,EAAA,GAIrDic,KAA2Bn7B;AAAA,IAC/B,CAAC7D,MAAkB;AACjB,UAAI,CAACmgB,KAAwBA,EAAqB,kBAAkB,QAAS;AAC7E,YAAMtR,IAAkBsR,EAAsC,MAAA;AAC9D,MAAAtR,EAAe,cAAc,eAAe7O,GAC5CsgB,EAAqBzR,CAAc;AAAA,IACrC;AAAA,IACA,CAACsR,GAAsBG,CAAoB;AAAA,EAAA,GAIvC,CAACjV,IAAoB4zB,EAAqB,IAAI/2B,EAAkB,EAAK,GACrE,CAACoD,IAAuB4zB,EAAwB,IAAIh3B,EAAwB,IAAI,GAIhFi3B,KAAcj9B,EAAOiV,CAAQ;AACnC,EAAAgoB,GAAY,UAAUhoB;AAEtB,QAAMioB,KAA0Bl9B,EAAO,EAAI;AAC3C,EAAAE,EAAU,OACRg9B,GAAwB,UAAU,IAC3B,MAAM;AACX,IAAAA,GAAwB,UAAU;AAAA,EACpC,IACC,CAAA,CAAE;AAOL,QAAMC,KAA4Bx7B;AAAA,IAChC,CAACy7B,GAAmBC,MAAyB;AAC3C,YAAMC,IAAe,CAACC,OAAyC;AAC7D,cAAM3hB,KAAU2hB,GAAS,MAAA;AACzB,eAAA3hB,GAAQ,WAAWyhB,GAEnBzhB,GAAQ,cAAc,IACtBA,GAAQ,eAAe,MACvBA,GAAQ,iBAAiB,CAAC4hB,OAAkB;AAE1C,gBAAMr9B,KAAKq9B;AACX,UAAAnW,GAAY,CAACoW,OAAiBA,GAAa,IAAI,CAACr6B,OAAOA,GAAE,OAAOjD,GAAG,KAAKA,KAAKiD,EAAE,CAAC;AAAA,QAClF,GACAwY,GAAQ,UAAUyhB,CAAY,GACvBzhB;AAAA,MACT,GAEM8hB,IAAkBT,GAAY,SAG9BU,KAAWD,EAAgB,KAAK,CAACh/B,OAAMA,GAAE,OAAO0+B,CAAS;AAC/D,UAAIO,IAAU;AACZ,YAAI,EAAEA,cAAoBlZ,IAAe;AACzC,QAAAgV,GAAqBkE,IAAUL,EAAaK,EAAQ,CAAC;AACrD;AAAA,MACF;AAGA,iBAAWx9B,MAAMu9B,GAAiB;AAChC,YAAI,EAAEv9B,cAAc4gB,IAAe;AACnC,cAAME,KAAa9gB,GAAG,SAAS,UAAU,CAAC4C,OAAMA,GAAE,OAAOq6B,CAAS;AAClE,YAAInc,OAAe,GAAI;AACvB,cAAMpH,KAAQ1Z,GAAG,SAAS8gB,EAAU;AACpC,YAAI,EAAEpH,cAAiB4K,IAAe;AACtC,cAAMzD,KAAe7gB,GAAG,MAAA;AACxB,QAAA6gB,GAAa,SAASC,EAAU,IAAIqc,EAAazjB,EAAK,GACtD4f,GAAqBt5B,IAAI6gB,EAAY;AACrC;AAAA,MACF;AAAA,IAEF;AAAA,IACA,CAACyY,IAAsBpS,EAAW;AAAA,EAAA,GAG9BuW,KAAyBj8B,EAAY,MAAM;AAC/C,QAAI,CAACm4B,KAAoB3wB,GAAoB;AAC7C,UAAMhB,IAAU8V;AAChB,QAAI,CAAC9V,KAAW,EAAEA,aAAmBsc,OAAiB,CAACtc,EAAQ,SAAU;AAIzE,UAAMi1B,IAAYj1B,EAAQ;AAE1B,IAAA40B,GAAsB,EAAI,GAC1BC,GAAyB,IAAI,GAE7BlD,EAAiB3xB,EAAQ,QAAQ,EAC9B,KAAK,CAACk1B,MAAiB;AACtB,MAAKH,GAAwB,WAC7BC,GAA0BC,GAAWC,CAAY;AAAA,IACnD,CAAC,EACA,MAAM,CAACvF,MAAiB;AAEvB,MADAnjB,GAAO,MAAM,8BAA8BmjB,CAAG,GACzCoF,GAAwB,WAC7BF,GAAyBnF,GAAiBC,GAAKF,EAAqB,CAAC;AAAA,IACvE,CAAC,EACA,QAAQ,MAAM;AACb,MAAIsF,GAAwB,WAASH,GAAsB,EAAK;AAAA,IAClE,CAAC;AAAA,EACL,GAAG,CAACjD,GAAkB3wB,IAAoB8U,GAAsBkf,EAAyB,CAAC;AAG1F,EAAAj9B,EAAU,MAAM;AACd,IAAA88B,GAAyB,IAAI;AAAA,EAC/B,GAAG,CAACvf,EAAe,CAAC;AAGpB,QAAMogB,KAAgCl8B;AAAA,IACpC,CAAC7D,MAAkB;AACjB,UAAI,CAACmgB,KAAwBA,EAAqB,kBAAkB,QAAS;AAC7E,YAAMtR,IAAkBsR,EAAsC,MAAA;AAC9D,MAAAtR,EAAe,cAAc,eAAe7O,GAC5CsgB,EAAqBzR,CAAc;AAAA,IACrC;AAAA,IACA,CAACsR,GAAsBG,CAAoB;AAAA,EAAA,GAGvC0f,KAA2Bn8B;AAAA,IAC/B,CAAC7D,MAAkB;AACjB,UAAI,CAACmgB,KAAwBA,EAAqB,kBAAkB,QAAS;AAC7E,YAAMtR,IAAkBsR,EAAsC,MAAA;AAC9D,MAAAtR,EAAe,cAAc,cAAc7O,GAC3CsgB,EAAqBzR,CAAc;AAAA,IACrC;AAAA,IACA,CAACsR,GAAsBG,CAAoB;AAAA,EAAA,GAGvC2f,KAAyBp8B;AAAA,IAC7B,CAAC7D,MAAkB;AACjB,UAAI,CAACmgB,KAAwBA,EAAqB,kBAAkB,QAAS;AAC7E,YAAMtR,IAAkBsR,EAAsC,MAAA;AAC9D,MAAAtR,EAAe,cAAc,QAAQ7O,GACrCsgB,EAAqBzR,CAAc;AAAA,IACrC;AAAA,IACA,CAACsR,GAAsBG,CAAoB;AAAA,EAAA,GAGvC4f,KAA0Br8B;AAAA,IAC9B,CAAC7D,MAAkB;AACjB,UAAI,CAACmgB,KAAwBA,EAAqB,kBAAkB,QAAS;AAC7E,YAAMtR,IAAkBsR,EAAsC,MAAA;AAC9D,MAAAtR,EAAe,cAAc,SAAS7O,GACtCsgB,EAAqBzR,CAAc;AAAA,IACrC;AAAA,IACA,CAACsR,GAAsBG,CAAoB;AAAA,EAAA,GAGvC6f,KAA+Bt8B;AAAA,IACnC,CAAC7D,MAAkB;AACjB,UAAI,CAACmgB,KAAwBA,EAAqB,kBAAkB,QAAS;AAC7E,YAAMtR,IAAkBsR,EAAsC,MAAA;AAC9D,MAAAtR,EAAe,cAAc,cAAc7O,GAC3CsgB,EAAqBzR,CAAc;AAAA,IACrC;AAAA,IACA,CAACsR,GAAsBG,CAAoB;AAAA,EAAA,GAGvC8f,KAA6Bv8B;AAAA,IACjC,CAACgF,MAAkB;AACjB,UAAI,CAACsX,KAAwBA,EAAqB,kBAAkB,QAAS;AAC7E,YAAMtR,IAAkBsR,EAAsC,MAAA;AAC9D,MAAAtR,EAAe,cAAc,YAAYhG,GAGzC,OAAOgG,EAAe,cAAc,MACpCyR,EAAqBzR,CAAc;AAAA,IACrC;AAAA,IACA,CAACsR,GAAsBG,CAAoB;AAAA,EAAA,GAGvC+f,KAAwBx8B;AAAA,IAC5B,CAACyrB,MAA2B;AAC1B,UAAI,CAACnP,KAAwBA,EAAqB,kBAAkB,QAAS;AAC7E,YAAMtR,IAAkBsR,EAAsC,MAAA;AAC9D,MAAImP,MAAS,OACX,OAAOzgB,EAAe,cAAc,OAEpCA,EAAe,cAAc,OAAOygB,GAEtChP,EAAqBzR,CAAc;AAAA,IACrC;AAAA,IACA,CAACsR,GAAsBG,CAAoB;AAAA,EAAA,GAOvC,EAAE,UAAAiK,IAAU,OAAO+V,GAAA,IAAmBnX,GAAA,GAGtCoX,KAAoB18B,EAAY,MAAM;AAC1C,IAAAk5B;AAAA,MAAiB,CAAC7iB,OAChBA,KAAA,gBAAAA,EAAM,UAAS,UACX,OACA,EAAE,MAAM,SAAS,MAAM,4CAA4C,OAAO,WAAA;AAAA,IAAW;AAAA,EAE7F,GAAG,CAAA,CAAE,GAECsmB,KAA2B38B,EAAY,MAAM;AACjD,IAAIi3B,IACFA,EAAA,IAEAiC;AAAA,MAAiB,CAAC7iB,OAChBA,KAAA,gBAAAA,EAAM,UAAS,iBACX,OACA,EAAE,MAAM,gBAAgB,MAAM,8BAA8B,OAAO,gBAAA;AAAA,IAAgB;AAAA,EAG7F,GAAG,CAAC4gB,CAAwB,CAAC,GAEvBlsB,KAAmB/K,EAAY,MAAM;AACzC,IAAIg3B,IACFA,EAAA,IAEAkC,GAAiB,CAAC7iB,OAAUA,KAAA,gBAAAA,EAAM,UAAS,SAAS,OAAO,EAAE,MAAM,QAAQ,MAAM,eAAe,OAAO,QAAS;AAAA,EAEpH,GAAG,CAAC2gB,CAAgB,CAAC,GAEf4F,KAAuB58B,EAAY,MAAM;AAC7C,IAAAk5B;AAAA,MAAiB,CAAC7iB,OAChBA,KAAA,gBAAAA,EAAM,UAAS,aAAa,OAAO,EAAE,MAAM,YAAY,MAAMxX,GAAM,YAAY,OAAO,SAAA;AAAA,IAAS;AAAA,EAEnG,GAAG,CAAA,CAAE,GAECg+B,KAAsB78B,EAAY,MAAM;AAC5C,IAAAk5B;AAAA,MAAiB,CAAC7iB,OAChBA,KAAA,gBAAAA,EAAM,UAAS,YAAY,OAAO,EAAE,MAAM,WAAW,MAAM,gBAAgB,OAAO,eAAA;AAAA,IAAe;AAAA,EAErG,GAAG,CAAA,CAAE,GAECymB,KAAqB98B,EAAY,MAAM;AAC3C,IAAAk5B;AAAA,MAAiB,CAAC7iB,OAChBA,KAAA,gBAAAA,EAAM,UAAS,WAAW,OAAO,EAAE,MAAM,UAAU,MAAM,sBAAsB,OAAO,SAAA;AAAA,IAAS;AAAA,EAEnG,GAAG,CAAA,CAAE,GAEC0mB,KAAuB/8B,EAAY,MAAM;AAC7C,IAAAk5B;AAAA,MAAiB,CAAC7iB,OAChBA,KAAA,gBAAAA,EAAM,UAAS,aAAa,OAAO,EAAE,MAAM,YAAY,MAAM,eAAe,OAAO,YAAA;AAAA,IAAY;AAAA,EAEnG,GAAG,CAAA,CAAE,GAOC2mB,KAAwBh9B;AAAA,IAC5B,CAAC+rB,MAAiB;AAChB,UAAI,CAACzP,EAAsB;AAC3B,YAAM7V,IAAK6V,EAAqB;AAChC,UAAI,CAAC7V,KAAMA,EAAG,UAAU,OAAW;AACnC,YAAMwT,IAAUqC,EAAqB,MAAA;AACpC,MAAArC,EAAQ,cAAoC,QAAQ8R,GACrDtP,EAAqBxC,CAAO;AAAA,IAC9B;AAAA,IACA,CAACqC,GAAsBG,CAAoB;AAAA,EAAA,GAKvCwgB,OACH1/B,KAAA+e,KAAA,gBAAAA,EAAsB,kBAAtB,gBAAA/e,GAAwE,UAAS,MAM9E2/B,MAAe5gB,KAAA,gBAAAA,EAAsB,mBAAkB,UACvD6gB,KAAuBD,KAAe9E,EAAY,gBAAgB,MAClEgF,KAAoBF,KAAe9E,EAAY,aAAa,MAE5DiF,KAAgCr9B,EAAY,MAAM;AACtD,IAAAk5B;AAAA,MAAiB,CAAC7iB,OAChBA,KAAA,gBAAAA,EAAM,UAAS,sBACX,OACA,EAAE,MAAM,qBAAqB,MAAM,8BAA8B,OAAO,gBAAA;AAAA,IAAgB;AAAA,EAEhG,GAAG,CAAA,CAAE,GAECinB,KAAgCt9B,EAAY,MAAM;AACtD,IAAAk5B;AAAA,MAAiB,CAAC7iB,OAChBA,KAAA,gBAAAA,EAAM,UAAS,sBACX,OACA,EAAE,MAAM,qBAAqB,MAAM,gBAAgB,OAAO,eAAA;AAAA,IAAe;AAAA,EAEjF,GAAG,CAAA,CAAE,GAECknB,KAAyBv9B,EAAY,MAAM;AAC/C,IAAAk5B;AAAA,MAAiB,CAAC7iB,OAChBA,KAAA,gBAAAA,EAAM,UAAS,eAAe,OAAO,EAAE,MAAM,cAAc,MAAM,kBAAkB,OAAO,QAAA;AAAA,IAAQ;AAAA,EAEtG,GAAG,CAAA,CAAE,GAECmnB,KAA0Bx9B,EAAY,MAAM;AAChD,IAAAk5B;AAAA,MAAiB,CAAC7iB,OAChBA,KAAA,gBAAAA,EAAM,UAAS,gBAAgB,OAAO,EAAE,MAAM,eAAe,MAAM,eAAe,OAAO,SAAA;AAAA,IAAS;AAAA,EAEtG,GAAG,CAAA,CAAE,GAEConB,KAA+Bz9B,EAAY,MAAM;AACrD,IAAAk5B;AAAA,MAAiB,CAAC7iB,OAChBA,KAAA,gBAAAA,EAAM,UAAS,qBACX,OACA,EAAE,MAAM,oBAAoB,MAAM,wBAAwB,OAAO,eAAA;AAAA,IAAe;AAAA,EAExF,GAAG,CAAA,CAAE,GAECqnB,KAAyB19B,EAAY,MAAM;AAC/C,IAAAk5B;AAAA,MAAiB,CAAC7iB,OAChBA,KAAA,gBAAAA,EAAM,UAAS,eAAe,OAAO,EAAE,MAAM,cAAc,MAAM,uBAAuB,OAAO,aAAA;AAAA,IAAa;AAAA,EAEhH,GAAG,CAAA,CAAE,GAECsnB,KAAwB39B,EAAY,MAAM;AAC9C,IAAAk5B;AAAA,MAAiB,CAAC7iB,OAChBA,KAAA,gBAAAA,EAAM,UAAS,cAAc,OAAO,EAAE,MAAM,aAAa,MAAMxX,GAAM,SAAS,OAAO,aAAA;AAAA,IAAa;AAAA,EAEtG,GAAG,CAAA,CAAE,GAEC++B,KAA0B59B,EAAY,MAAM;AAChD,IAAAk5B;AAAA,MAAiB,CAAC7iB,OAChBA,KAAA,gBAAAA,EAAM,UAAS,gBAAgB,OAAO,EAAE,MAAM,eAAe,MAAM,mBAAmB,OAAO,kBAAA;AAAA,IAAkB;AAAA,EAEnH,GAAG,CAAA,CAAE,GAECwnB,KAA8B79B,EAAY,MAAM;AACpD,IAAAk5B;AAAA,MAAiB,CAAC7iB,OAChBA,KAAA,gBAAAA,EAAM,UAAS,oBACX,OACA,EAAE,MAAM,mBAAmB,MAAM,gBAAgB,OAAO,mBAAA;AAAA,IAAmB;AAAA,EAEnF,GAAG,CAAA,CAAE,GAECynB,KAAwB99B,EAAY,MAAM;AAC9C,IAAAk5B;AAAA,MAAiB,CAAC7iB,OAChBA,KAAA,gBAAAA,EAAM,UAAS,cACX,OACA,EAAE,MAAM,aAAa,MAAM,wBAAwB,OAAO,aAAA;AAAA,IAAa;AAAA,EAE/E,GAAG,CAAA,CAAE,GAEC0nB,KAAqB/9B,EAAY,MAAM;AAC3C,IAAAk5B;AAAA,MAAiB,CAAC7iB,OAChBA,KAAA,gBAAAA,EAAM,UAAS,WACX,OACA,EAAE,MAAM,UAAU,MAAM,mBAAmB,OAAO,SAAA;AAAA,IAAS;AAAA,EAEnE,GAAG,CAAA,CAAE,GAEC2nB,KAAqBh+B,EAAY,MAAM;AAC3C,IAAAk5B;AAAA,MAAiB,CAAC7iB,OAChBA,KAAA,gBAAAA,EAAM,UAAS,WACX,OACA,EAAE,MAAM,UAAU,MAAM,mCAAmC,OAAO,SAAA;AAAA,IAAS;AAAA,EAEnF,GAAG,CAAA,CAAE,GAEC4nB,KAAwBj+B,EAAY,MAAM;AAC9C,IAAAk5B;AAAA,MAAiB,CAAC7iB,OAChBA,KAAA,gBAAAA,EAAM,UAAS,cACX,OACA,EAAE,MAAM,aAAa,MAAM,mCAAmC,OAAO,aAAA;AAAA,IAAa;AAAA,EAE1F,GAAG,CAAA,CAAE,GAEC6nB,KAA2Bl+B,EAAY,MAAM;AACjD,SAAImc,KAAA,gBAAAA,EAAe,UAAS,WAAUG,KAAA,gBAAAA,EAAsB,mBAAkB,SAAS;AACrF,YAAM6hB,IAAe7hB;AACrB,UAAI6hB,EAAa,YAAY;AAC3B,cAAMnzB,IAAiBmzB,EAAa,MAAA;AACpC,QAAAnzB,EAAe,aAAA,GACfyR,EAAqBzR,CAAc;AAAA,MACrC;AAAA,IACF;AACA,IAAAkuB,GAAiB,IAAI;AAAA,EACvB,GAAG,CAAC/c,GAAeG,GAAsBG,CAAoB,CAAC,GAGxD2hB,KAAoBp+B,EAAY,MAAM;AAC1C,QAAI,CAACgf,EAAiB;AACtB,UAAMqf,IAAM/qB,EAAS,UAAU,CAACvW,MAAMA,EAAE,OAAOiiB,EAAgB,EAAE;AACjE,QAAIqf,IAAM/qB,EAAS,SAAS,GAAG;AAC7B,YAAMgrB,IAAgBhrB,EAAS+qB,IAAM,CAAC;AACtC,MAAApG,GAAsBjZ,EAAgB,IAAIsf,EAAc,IAAI,OAAO;AAAA,IACrE;AAAA,EACF,GAAG,CAACtf,GAAiB1L,GAAU2kB,EAAqB,CAAC,GAE/CsG,KAAqBv+B,EAAY,MAAM;AAC3C,QAAI,CAACgf,EAAiB;AACtB,UAAMqf,IAAM/qB,EAAS,UAAU,CAACvW,MAAMA,EAAE,OAAOiiB,EAAgB,EAAE;AACjE,QAAIqf,IAAM,GAAG;AACX,YAAMC,IAAgBhrB,EAAS+qB,IAAM,CAAC;AACtC,MAAApG,GAAsBjZ,EAAgB,IAAIsf,EAAc,IAAI,QAAQ;AAAA,IACtE;AAAA,EACF,GAAG,CAACtf,GAAiB1L,GAAU2kB,EAAqB,CAAC,GAE/CuG,KAAsBx+B,EAAY,MAAM;AAC5C,UAAMy+B,IAAkBxf,MAAsBD;AAG9C,IAAKyf,MACL1G,GAAqB0G,CAAe,GACpClH,EAAc,IAAI;AAAA,EACpB,GAAG,CAACtY,IAAoBD,GAAiB+Y,IAAsBR,CAAa,CAAC,GAMvEmH,KAAmB1+B,EAAY,MAAM;AACzC,QAAI,CAACsc,EAAsB;AAC3B,UAAMyP,IAAOzP,EAAqB,MAAA;AAClC,IAAAyP,EAAK,SAAS,CAACzP,EAAqB,QACpCG,EAAqBsP,CAAI;AAAA,EAC3B,GAAG,CAACzP,GAAsBG,CAAoB,CAAC,GAEzCkiB,KAAuB3+B,EAAY,MAAM;AAC7C,QAAI,CAACgf,KAAmBA,EAAgB,kBAAkB,QAAS;AACnE,UAAM4f,IAAQ5f;AACd,QAAI,CAAC4f,EAAM,YAAYA,EAAM,SAAS,WAAW,EAAG;AAEpD,UAAMC,IAAarZ,EAAgB,wBAAwBoZ,EAAM,EAAE;AACnE,QAAI,CAACC,EAAY;AAEjB,UAAMC,IAAoBF,EAAM,SAAS,IAAI,CAAA1mB,MAAS;AACpD,YAAM6mB,KAAQ7mB,EAAM,MAAA;AACpB,aAAA6mB,GAAM,IAAI7mB,EAAM,IAAI0mB,EAAM,GAC1BG,GAAM,IAAI7mB,EAAM,IAAI0mB,EAAM,GACnBG;AAAA,IACT,CAAC;AAED,IAAAhH,GAAqB6G,CAAK,GAC1BE,EAAkB,QAAQ,CAAA5mB,MAAS8f,GAAkB9f,GAAO2mB,CAAU,CAAC,GAEvEtH,EAAcuH,EAAkB,SAAS,IAAIA,EAAkB,CAAC,EAAE,KAAK,IAAI;AAAA,EAC7E,GAAG,CAAC9f,GAAiBwG,GAAiBuS,IAAsBC,IAAmBT,CAAa,CAAC,GAGvFyH,KAAuBh/B;AAAA,IAC3B,CAAC7D,MAAkB;AACjB,UAAI,CAACmgB,EAAsB;AAC3B,YAAMtR,IAAiBsR,EAAqB,MAAA;AAC5C,MAAAtR,EAAe,WAAW7O,GAC1BsgB,EAAqBzR,CAAc;AAAA,IACrC;AAAA,IACA,CAACsR,GAAsBG,CAAoB;AAAA,EAAA,GAGvCwiB,KAAiBj/B,EAAY,MAAM;AACvC,QAAI,CAACsc,EAAsB;AAC3B,UAAMtR,IAAiBsR,EAAqB,MAAA;AAC5C,QAAI4iB,IAAc,KAAK,MAAMl0B,EAAe,WAAW,EAAE,IAAI,KAAK;AAClE,IAAAk0B,KAAgBA,IAAc,MAAO,OAAO,KACxCA,IAAc,QAChBA,KAAe,MAEjBl0B,EAAe,WAAWk0B,GAC1BziB,EAAqBzR,CAAc;AAAA,EACrC,GAAG,CAACsR,GAAsBG,CAAoB,CAAC,GAEzCtL,KAAsBnR;AAAA,IAC1B,CAAC7D,MAAkB;AACjB,UAAI,CAACmgB,EAAsB;AAC3B,YAAMtR,IAAiBsR,EAAqB,MAAA;AAC5C,MAAAtR,EAAe,UAAU7O,GACzBsgB,EAAqBzR,CAAc;AAAA,IACrC;AAAA,IACA,CAACsR,GAAsBG,CAAoB;AAAA,EAAA,GASvC,EAAE,eAAe0iB,GAAA,IAAyBC,GAAA,GAC1CC,KAAqBhhC,EAAO,EAAK,GAEjCihC,KAA0Bt/B;AAAA,IAC9B,CAAC4qB,MAAkC;AACjC,UAAI,GAACtO,KAAwBA,EAAqB,kBAAkB,UACpE;AAAA,YAAI2C,IAAoB;AACtB,gBAAMhF,IAAWqC,EAAsC,MAAA,GACjDijB,IAAaC,GAAqB5U,CAAW;AACnD,UAAI2U,IACFtlB,EAAQ,cAAc,cAAcslB,IAEpC,OAAOtlB,EAAQ,cAAc,aAE/BwC,EAAqBxC,CAAO;AAC5B;AAAA,QACF;AACA,QAAAklB;AAAA,UACE7iB,EAAqB;AAAA,UACrB,EAAE,aAAAsO,EAAA;AAAA,UACF,EAAE,UAAUyU,GAAmB,QAAA;AAAA,QAAQ,GAEzCA,GAAmB,UAAU;AAAA;AAAA,IAC/B;AAAA,IACA,CAAC/iB,GAAsB2C,IAAoBxC,GAAsB0iB,EAAoB;AAAA,EAAA,GAGjFM,KAA0Bz/B,EAAY,MAAM;AAChD,IAAAq/B,GAAmB,UAAU;AAAA,EAC/B,GAAG,CAAA,CAAE,GAECK,KAAyB1/B,EAAY,MAAM;AAE/C,IAAAq/B,GAAmB,UAAU,IAC7BC,GAAwB,EAAE,GAAGxU,IAAqB,GAClDuU,GAAmB,UAAU;AAAA,EAC/B,GAAG,CAACC,EAAuB,CAAC,GAGtBK,KAA8B3/B;AAAA,IAClC,CAACqkB,MAA0B;AACzB,UAAI,CAAC/H,EAAsB;AAC3B,YAAMtR,IAAiBsR,EAAqB,MAAA;AAC5C,MAAAtR,EAAe,YAAYqZ,GACtBrZ,EAAe,kBAClBA,EAAe,gBAAgB,EAAE,MAAM,IAAM,OAAO,QAAA,IAEtDyR,EAAqBzR,CAAc;AAAA,IACrC;AAAA,IACA,CAACsR,GAAsBG,CAAoB;AAAA,EAAA,GAGvCmjB,KAA8B5/B;AAAA,IAClC,CAACyrB,MAAkB;AACjB,UAAI,CAACnP,EAAsB;AAC3B,YAAMtR,IAAiBsR,EAAqB,MAAA,GACtCujB,IAAc70B,EAAe,cAAc,SAAS,SAAS,YAC7D80B,IAAW,EAAE,GAAG90B,EAAe,eAAe,MAAAygB,EAAA;AACpD,MAAAzgB,EAAe,gBAAgB80B,GAC/B90B,EAAe,YAAa80B,EAAS,QAAQA,EAAS,SAAUD,IAAc,UAC9EpjB,EAAqBzR,CAAc;AAAA,IACrC;AAAA,IACA,CAACsR,GAAsBG,CAAoB;AAAA,EAAA,GAGvCsjB,KAAgC//B;AAAA,IACpC,CAACwsB,MAAoB;AACnB,UAAI,CAAClQ,EAAsB;AAC3B,YAAMtR,IAAiBsR,EAAqB,MAAA,GACtCujB,IAAc70B,EAAe,cAAc,SAAS,SAAS,YAC7D80B,IAAW,EAAE,GAAG90B,EAAe,eAAe,QAAAwhB,EAAA;AACpD,MAAAxhB,EAAe,gBAAgB80B,GAC/B90B,EAAe,YAAa80B,EAAS,QAAQA,EAAS,SAAUD,IAAc,UAC9EpjB,EAAqBzR,CAAc;AAAA,IACrC;AAAA,IACA,CAACsR,GAAsBG,CAAoB;AAAA,EAAA,GAGvCujB,KAA+BhgC;AAAA,IACnC,CAACysB,MAA4B;AAC3B,UAAI,CAACnQ,EAAsB;AAC3B,YAAMtR,IAAiBsR,EAAqB,MAAA;AAC5C,MAAAtR,EAAe,gBAAgB,EAAE,GAAGA,EAAe,eAAe,OAAAyhB,EAAA,GAClEhQ,EAAqBzR,CAAc;AAAA,IACrC;AAAA,IACA,CAACsR,GAAsBG,CAAoB;AAAA,EAAA,GAIvCpK,KAA8BrS;AAAA,IAClC,CAACmQ,MAAgB;;AACf,UAAI,CAACmM,EAAsB;AAC3B,YAAMtR,IAAiBsR,EAAqB,MAAA;AAC5C,MAAKnM,IAGHnF,EAAe,iBAAiB;AAAA,QAC9B,SAAS;AAAA,QACT,OAAO;AAAA,QACP,aAAWzN,IAAAyN,EAAe,mBAAf,gBAAAzN,EAA+B,cAAa;AAAA,QACvD,YAAY4S;AAAA,QACZ,kBAAgBvJ,IAAAoE,EAAe,mBAAf,gBAAApE,EAA+B,mBAAkB;AAAA,MAAA,IAPnEoE,EAAe,iBAAiB,QAUlCyR,EAAqBzR,CAAc;AAAA,IACrC;AAAA,IACA,CAACsR,GAAsBG,CAAoB;AAAA,EAAA,GAGvCwjB,KAA8BjgC;AAAA,IAClC,CAACkgC,MAAgB;AACf,UAAI,CAAC5jB,EAAsB;AAC3B,YAAMtR,IAAiBsR,EAAqB,MAAA;AAC5C,MAAItR,EAAe,mBACjBA,EAAe,iBAAiB;AAAA,QAC9B,GAAGA,EAAe;AAAA,QAClB,gBAAgBk1B,IAAM;AAAA,MAAA,IAG1BzjB,EAAqBzR,CAAc;AAAA,IACrC;AAAA,IACA,CAACsR,GAAsBG,CAAoB;AAAA,EAAA,GAIvC0jB,KAA6BngC;AAAA,IACjC,CAACmQ,MAAgB;AACf,UAAI,CAACmM,EAAsB;AAC3B,YAAMtR,IAAiBsR,EAAqB,MAAA;AAC5C,UAAI,CAACnM;AAEH,QAAAnF,EAAe,SAASA,EAAe,SAAS,CAAA,GAAI,OAAO,CAAChJ,MAAsBA,EAAE,OAAO,kBAAkB;AAAA,WACxG;AAML,cAAMo+B,IAAkB,OAAO;AAAA,UAC7B,eAAe;AAAA,UACf,UAAUjwB;AAAA,UACV,GAAG;AAAA,UAAG,GAAG;AAAA,UAAG,UAAU;AAAA,UACtB,eAAe,EAAE,MAAM,SAAkB,OAAO,KAAmB,QAAQ,KAAmB,OAAO,GAAG,OAAO,GAAG,WAAW,GAAG,YAAY,GAAG,gBAAgB,IAAO,cAAc,IAAO,cAAc,EAAA;AAAA,QAAE;AAK7M,YAAI,mBAAmBnF,KAAkBA,EAAe,eAAe;AACrE,gBAAMvE,KAAKuE,EAAe;AAC1B,UAAAvE,GAAG,QAAQ,GACXA,GAAG,QAAQ,GACXA,GAAG,YAAY,GACfA,GAAG,aAAa;AAAA,QAClB;AAEA,cAAM45B,MAAYr1B,EAAe,SAAS,CAAA,GAAI,KAAK,CAAChJ,OAAsBA,GAAE,OAAO,kBAAkB;AACrG,YAAIq+B;AACF,UAAAA,GAAS,cAAcD,EAAA;AAAA,aAClB;AACL,gBAAME,KAAQt1B,EAAe,SAAS,CAAA;AACtC,UAAAs1B,GAAM,KAAK;AAAA,YACT,IAAI;AAAA,YACJ,MAAM;AAAA,YACN,aAAaF,EAAA;AAAA,YACb,SAAS;AAAA,YACT,UAAU;AAAA,UAAA,CACX,GACDp1B,EAAe,QAAQs1B;AAAA,QACzB;AAAA,MACF;AACA,MAAA7jB,EAAqBzR,CAAc;AAAA,IACrC;AAAA,IACA,CAACsR,GAAsBG,CAAoB;AAAA,EAAA,GAGvC8jB,KAA4BvgC;AAAA,IAChC,CAACkR,MAAoC;AACnC,UAAI,CAACoL,EAAsB;AAC3B,YAAMtR,IAAiBsR,EAAqB,MAAA,GACtCkkB,KAAQx1B,EAAe,SAAS,CAAA,GAAI,KAAK,CAAChJ,MAAsBA,EAAE,OAAO,kBAAkB;AACjG,MAAIw+B,MACFA,EAAK,OAAOtvB,GACZuL,EAAqBzR,CAAc;AAAA,IAEvC;AAAA,IACA,CAACsR,GAAsBG,CAAoB;AAAA,EAAA,GAGvCgkB,KAA+BzgC;AAAA,IACnC,CAACkgC,MAAgB;AACf,UAAI,CAAC5jB,EAAsB;AAC3B,YAAMtR,IAAiBsR,EAAqB,MAAA,GACtCkkB,KAAQx1B,EAAe,SAAS,CAAA,GAAI,KAAK,CAAChJ,MAAsBA,EAAE,OAAO,kBAAkB;AACjG,MAAIw+B,MACFA,EAAK,UAAUN,IAAM,KACrBzjB,EAAqBzR,CAAc;AAAA,IAEvC;AAAA,IACA,CAACsR,GAAsBG,CAAoB;AAAA,EAAA,GAGvCikB,KAAgC1gC;AAAA,IACpC,CAAC2gC,MAAiB;AAChB,UAAI,CAACrkB,EAAsB;AAC3B,YAAMtR,IAAiBsR,EAAqB,MAAA,GACtCkkB,KAAQx1B,EAAe,SAAS,CAAA,GAAI,KAAK,CAAChJ,MAAsBA,EAAE,OAAO,kBAAkB;AACjG,MAAIw+B,MACFA,EAAK,WAAWG,GAChBlkB,EAAqBzR,CAAc;AAAA,IAEvC;AAAA,IACA,CAACsR,GAAsBG,CAAoB;AAAA,EAAA,GAIvCmkB,KAAqB5gC;AAAA,IACzB,CAACwsB,MAAiE;AAChE,UAAI,CAAClQ,EAAsB;AAC3B,YAAMtR,IAAiBsR,EAAqB,MAAA;AAC5C,MAAAtR,EAAe,SAASwhB,GACxB/P,EAAqBzR,CAAc;AAAA,IACrC;AAAA,IACA,CAACsR,GAAsBG,CAAoB;AAAA,EAAA,GAIvCokB,KAAqB7gC;AAAA,IACzB,CAAC8tB,MAAqC;AACpC,UAAI,CAACxR,EAAsB;AAC3B,YAAMtR,IAAiBsR,EAAqB,MAAA;AAC5C,MAAAtR,EAAe,SAAS8iB,GACxBrR,EAAqBzR,CAAc;AAAA,IACrC;AAAA,IACA,CAACsR,GAAsBG,CAAoB;AAAA,EAAA,GAOvCqkB,KAAwB9gC;AAAA,IAC5B,CAACquB,MAA4C;AAC3C,UAAI,CAAC/R,EAAsB;AAC3B,YAAMtR,IAAiBsR,EAAqB,MAAA;AAC5C,MAAAtR,EAAe,YAAYqjB,MAAc,WAAW,SAAYA,GAChE5R,EAAqBzR,CAAc;AAAA,IACrC;AAAA,IACA,CAACsR,GAAsBG,CAAoB;AAAA,EAAA,GAIvCskB,KAAwB/gC;AAAA,IAC5B,CAACghC,MAAyB;AACxB,UAAI,CAAC1kB,KAAwBA,EAAqB,kBAAkB,QAAS;AAE7E,YAAMtR,IADesR,EACe,MAAA;AACpC,MAAAtR,EAAe,cAAc,YAAYg2B,GACzCvkB,EAAqBzR,CAAc,GACnCiuB,GAAyB,EAAK;AAAA,IAChC;AAAA,IACA,CAAC3c,GAAsBG,CAAoB;AAAA,EAAA,GAGvCwkB,KAA4BjhC,EAAY,MAAM;AAClD,IAAIuL,IACFA,EAAA,IAEA0tB,GAAyB,EAAI;AAAA,EAEjC,GAAG,CAAC1tB,CAAqB,CAAC;AAG1B,EAAAhN,EAAU,MAAM;AACd,IAAAs4B,KAAA,QAAAA,EAAsB1a,MAAkB,OACxC4a,KAAA,QAAAA;AAAA,OACG5a,KAAA,gBAAAA,EAAe,SAAoE;AAAA;AAAA,EAExF,GAAG,CAACA,GAAe0a,GAAqBE,CAAyB,CAAC,GAGlEx4B,EAAU,MAAM;AACd,UAAM2iC,KAAY/kB,KAAA,gBAAAA,EAAe,SAAQ;AACzC,IAAI+kB,MAAc/G,GAAuB,YACvCA,GAAuB,UAAU+G,GACjCxJ,GAA4BwJ,CAA8D;AAAA,EAE9F,GAAG,CAAC/kB,GAAeub,EAA2B,CAAC,GAG/Cn5B,EAAU,MAAM;AACd,UAAM4iC,IAAW/G,GAAgC,SAC3CgH,IAAc3J;AACpB,QAAI0J,MAAaC,GAGjB;AAAA,UAFAhH,GAAgC,UAAUgH,GAEtCD,MAAa,QAAQC,MAAgB,QAAQjlB,MAAkB,MAAM;AACvE,QAAAge,GAAuB,UAAU,MACjCjB,GAAiB,IAAI;AACrB;AAAA,MACF;AAEA,UAAIkI,MAAgB,SAAQjlB,KAAA,gBAAAA,EAAe,UAASilB,GAAa;AAyB/D,cAAM5jB,IAvBoE;AAAA,UACxE,OAAO,EAAE,MAAM,SAAS,MAAM,4CAA4C,OAAO,WAAA;AAAA,UACjF,MAAM,EAAE,MAAM,QAAQ,MAAM,eAAe,OAAO,OAAA;AAAA,UAClD,cAAc,EAAE,MAAM,gBAAgB,MAAM,8BAA8B,OAAO,gBAAA;AAAA,UACjF,UAAU,EAAE,MAAM,YAAY,MAAM3e,GAAM,YAAY,OAAO,SAAA;AAAA,UAC7D,SAAS,EAAE,MAAM,WAAW,MAAM,gBAAgB,OAAO,eAAA;AAAA,UACzD,QAAQ,EAAE,MAAM,UAAU,MAAM,sBAAsB,OAAO,SAAA;AAAA,UAC7D,UAAU,EAAE,MAAM,YAAY,MAAM,eAAe,OAAO,YAAA;AAAA,UAC1D,SAAS,EAAE,MAAM,WAAW,MAAM,mBAAmB,OAAO,UAAA;AAAA,UAC5D,mBAAmB,EAAE,MAAM,qBAAqB,MAAM,8BAA8B,OAAO,gBAAA;AAAA,UAC3F,mBAAmB,EAAE,MAAM,qBAAqB,MAAMA,GAAM,KAAK,OAAO,eAAA;AAAA,UACxE,YAAY,EAAE,MAAM,cAAc,MAAM,mBAAmB,OAAO,QAAA;AAAA,UAClE,aAAa,EAAE,MAAM,eAAe,MAAM,eAAe,OAAO,SAAA;AAAA,UAChE,kBAAkB,EAAE,MAAM,oBAAoB,MAAM,wBAAwB,OAAO,eAAA;AAAA,UACnF,YAAY,EAAE,MAAM,cAAc,MAAMA,GAAM,SAAS,OAAO,QAAA;AAAA,UAC9D,WAAW,EAAE,MAAM,aAAa,MAAMA,GAAM,SAAS,OAAO,QAAA;AAAA,UAC5D,QAAQ,EAAE,MAAM,UAAU,MAAM,mBAAmB,OAAO,SAAA;AAAA,UAC1D,QAAQ,EAAE,MAAM,UAAU,MAAM,mCAAmC,OAAO,SAAA;AAAA,UAC1E,WAAW,EAAE,MAAM,aAAa,MAAM,mCAAmC,OAAO,aAAA;AAAA,UAChF,aAAa,EAAE,MAAM,eAAe,MAAM,mBAAmB,OAAO,kBAAA;AAAA,UACpE,iBAAiB,EAAE,MAAM,mBAAmB,MAAM,gBAAgB,OAAO,mBAAA;AAAA,UACzE,WAAW,EAAE,MAAM,aAAa,MAAM,wBAAwB,OAAO,aAAA;AAAA,QAAa,EAExDuiC,CAAwB;AACpD,QAAI5jB,MACF2c,GAAuB,UAAUiH,GACjClI,GAAiB1b,CAAM;AAAA,MAE3B;AAAA;AAAA,EACF,GAAG,CAACia,IAA0Btb,CAAa,CAAC,GAG5C5d,EAAU,MAAM;AAQd,IAAAo5B,EANExb,MAAkB,QAClBoc,MAAiB,QACjBhc,MACAsc,MACAC,MACAT,MAAe,MACiB;AAAA,EACpC,GAAG,CAAClc,GAAeoc,GAAchc,IAAqBsc,IAAmBC,IAAoBT,GAAYV,CAAoB,CAAC,GAG9Hp5B,EAAU,MAAM;AACd,IAAIu4B,MACAgE,GAAwB,YAAY,UAAaA,GAAwB,YAAYE,MACvF9B,GAAiB,IAAI,GAEvB4B,GAAwB,UAAUE;AAAA,EACpC,GAAG,CAACA,IAAkBlE,CAAoB,CAAC,GAG3Cv4B,EAAU,MAAM;AACd,IAAI64B,KAAoBpY,MACtBqY,KAAA,QAAAA,EAA2B;AAAA,EAE/B,GAAG,CAACD,GAAkBpY,GAAiBqY,CAAwB,CAAC,GAGhE94B,EAAU,MAAM;AACd,UAAM8iC,KACJ/kB,KAAA,gBAAAA,EAAsB,mBAAkB,UAAWA,EAAsC,aAAa;AACxG,KAAIH,KAAA,gBAAAA,EAAe,UAAS,UAAU4e,GAAkB,YAAY,MAAQsG,MAAsB,MAChGnI,GAAiB,IAAI,GAEvB6B,GAAkB,UAAUsG;AAAA,EAC9B,GAAG,CAAC/kB,GAAsBH,KAAA,gBAAAA,EAAe,IAAI,CAAC,GAG9C5d,EAAU,MAAM;AACd,IAAAo8B,GAAiB,UAAUxe,GAC3Bye,GAAwB,UAAUte,KAAwB,MAC1Due,GAAwB,UAAUpe;AAAA,EACpC,CAAC,GAEDle,EAAU,MAAM;AACd,UAAM+iC,IAAY,WAAW,MAAM;AACjC,MAAA5G,GAAkB,UAAU;AAAA,IAC9B,GAAG,CAAC;AACJ,WAAO,MAAM;AAAE,mBAAa4G,CAAS;AAAA,IAAG;AAAA,EAC1C,GAAG,CAAA,CAAE,GAEL/iC,EAAU,MACD,MAAM;;AACX,QAAKm8B,GAAkB,WAClBD,GAAoB,aACrBl9B,IAAAo9B,GAAiB,YAAjB,gBAAAp9B,EAA0B,UAAS,QAAQ;AAC7C,YAAMiJ,IAAUo0B,GAAwB;AACxC,WAAIp0B,KAAA,gBAAAA,EAAS,mBAAkB,SAAS;AACtC,cAAM23B,IAAe33B;AACrB,YAAI23B,EAAa,YAAY;AAC3B,gBAAMnzB,IAAiBmzB,EAAa,MAAA;AACpC,UAAAnzB,EAAe,aAAA,GACf6vB,GAAwB,QAAQ7vB,CAAc;AAAA,QAChD;AAAA,MACF;AAAA,IACF;AAAA,EACF,GACC,CAAA,CAAE,GAGLzM,EAAU,MAAM;AACd,QAAIgjC,IAAgD,MAChDC,IAAoB;AACxB,UAAMC,IAAiB,GAEjBC,IAAkB,CAAC3kC,OAAkB;;AACzC,YAAMm3B,KAASn3B,GAAE;AACjB,OAAIQ,KAAAqpB,GAAW,YAAX,QAAArpB,GAAoB,SAAS22B,OAE/BA,GAAO,QAAQ,+BAA+B,KAC9CA,GAAO,QAAQ,sBAAsB,KACrCA,GAAO,QAAQ,iBAAiB,KAChCA,GAAO,QAAQ,kBAAkB,KACjCA,GAAO,QAAQ,aAAa,MAE9B8F,GAAe,UAAU,IACzBuH,IAAe,EAAE,GAAGxkC,GAAE,SAAS,GAAGA,GAAE,QAAA,GACpCykC,IAAoB;AAAA,IACtB,GAEMG,KAAkB,CAAC5kC,OAAkB;AACzC,UAAIwkC,KAAgB,CAACC,KAAqB,CAAChH,GAAc,SAAS;AAChE,cAAM77B,KAAS5B,GAAE,UAAUwkC,EAAa,GAClC3iC,KAAS7B,GAAE,UAAUwkC,EAAa;AAExC,QADiB,KAAK,KAAK5iC,KAASA,KAASC,KAASA,EAAM,IAC7C6iC,MACbD,IAAoB,IACpB7I,GAAc,EAAI;AAAA,MAEtB;AAAA,IACF,GAEMiJ,KAAgB,MAAM;AAC1B,MAAA5H,GAAe,UAAU,IACzBuH,IAAe,MACfC,IAAoB,IACpB7I,GAAc,EAAK;AAAA,IACrB;AAEA,kBAAO,iBAAiB,aAAa+I,CAAe,GACpD,OAAO,iBAAiB,aAAaC,EAAe,GACpD,OAAO,iBAAiB,WAAWC,EAAa,GACzC,MAAM;AACX,aAAO,oBAAoB,aAAaF,CAAe,GACvD,OAAO,oBAAoB,aAAaC,EAAe,GACvD,OAAO,oBAAoB,WAAWC,EAAa;AAAA,IACrD;AAAA,EACF,GAAG,CAAA,CAAE,GAGLrjC,EAAU,MAAM;AACd,QAAI,CAACqoB,GAAW,QAAS;AACzB,QAAI0a,IAA2B;AAE/B,UAAMjqB,IAAW,IAAI,eAAe,CAACC,MAAY;AAC/C,MAAIgqB,MAAc,QAAM,aAAaA,CAAS,GAC9CA,IAAY,OAAO,WAAW,MAAM;AAClC,mBAAW/pB,KAASD,GAAS;AAC3B,gBAAMuqB,KAAWtqB,EAAM,YAAY,OAC7BuqB,KAAYvqB,EAAM,YAAY;AACpC,UAAAsiB,GAAqB,CAACxjB,OAChBA,GAAK,UAAUwrB,MAAYxrB,GAAK,WAAWyrB,KAAkBzrB,KAC1D,EAAE,OAAOwrB,IAAU,QAAQC,GAAA,CACnC;AAAA,QACH;AAAA,MACF,GAAG,EAAE;AAAA,IACP,CAAC;AAED,WAAAzqB,EAAS,QAAQuP,GAAW,OAAO,GAC5B,MAAM;AACX,MAAAvP,EAAS,WAAA,GACLiqB,MAAc,QAAM,aAAaA,CAAS;AAAA,IAChD;AAAA,EACF,GAAG,CAACtiB,CAAe,CAAC,GAGpBzgB,EAAU,MAAM;;AAEd,QADI8lB,MAAS,cACT6K,GAAW;AAEf,UAAM6S,KAAmBxkC,IAAA0hB,MAAsBD,MAAtB,gBAAAzhB,EAAwC;AAGjE,QAFA28B,GAAuB,UAAU6H,GAE7B,CAAC/iB,GAAiB;AACpB,MAAAyZ,GAAmB,IAAI;AACvB;AAAA,IACF;AAEA,UAAMuJ,IAAwB,MAAM;;AAClC,UAAI;AACF,cAAMhb,OAAezpB,IAAAqpB,GAAW,YAAX,gBAAArpB,EAAoB,gBAAeq8B,GAAkB,SAAS,GAC7E3S,OAAgBrgB,KAAAggB,GAAW,YAAX,gBAAAhgB,GAAoB,iBAAgBgzB,GAAkB,UAAU,IAChFtS,KAASf,MAAA,gBAAAA,GAAW,SACpB0b,KAAoBhjB,MAAsBD,GAC1CrB,KAAgBskB,GAAkB,eAClCC,OAAgBr7B,KAAAo7B,GAAkB,mBAAlB,gBAAAp7B,GAAA,KAAAo7B,QAAwC;AAAA,UAC5D,GAAGA,GAAkB;AAAA,UACrB,GAAGA,GAAkB;AAAA,UACrB,QAAQtkB,MAAA,gBAAAA,GAAe,UAAoB;AAAA,UAC3C,SAASA,MAAA,gBAAAA,GAAe,WAAqB;AAAA,QAAA,GAGzCuJ,KAAiB1B,EAAgB,kBAAA,GACjC2B,MAAYD,MAAA,gBAAAA,GAAgB,MAAK,GACjCE,MAAYF,MAAA,gBAAAA,GAAgB,MAAK,GACjCG,OAAchE,MAAAlB,KAAApD,MAAA,gBAAAA,GAAiB,YAAjB,gBAAAoD,GAA0B,YAA1B,gBAAAkB,GAAA,KAAAlB,QAAyC;AAE7D,YAAIggB,IACAC,IACAC,IACAC;AAEJ,YAAIhb,IAAQ;AACV,gBAAMG,KAAaH,GAAO,sBAAA;AAC1B,UAAA6a,KAAiB1a,GAAW,QAAQya,GAAc,IAAI/a,MAAaE,IACnE+a,KAAiB3a,GAAW,OAAOya,GAAc,IAAI9a,MAAaC,IAClEgb,KAAqBH,GAAc,QAAQ7a,IAC3Cib,KAAsBJ,GAAc,SAAS7a;AAAA,QAC/C,WAAW1V;AACT,UAAAwwB,KAAiBxwB,EAAqB,QAAQuwB,GAAc,IAAI/a,MAAaE,IAC7E+a,KAAiBzwB,EAAqB,OAAOuwB,GAAc,IAAI9a,MAAaC,IAC5Egb,KAAqBH,GAAc,QAAQ7a,IAC3Cib,KAAsBJ,GAAc,SAAS7a;AAAA,aACxC;AACL,gBAAMkb,KAAkB,OAAO,aAAa,GACtCC,KAAkB,OAAO,cAAc;AAC7C,UAAAL,KAAiBI,KAAmBL,GAAc,QAAQ7a,KAAe,GACzE+a,KAAiBI,KAAmBN,GAAc,SAAS7a,KAAe,GAC1Egb,KAAqBH,GAAc,QAAQ7a,IAC3Cib,KAAsBJ,GAAc,SAAS7a;AAAA,QAC/C;AAEA,cAAMlC,KAAM,IACNsd,KAAaL,IACbM,KAAiBP,KAAiBE,KAAqB;AAE7D,YAAIza,KAAM6a,KAAaxb,KAAgB9B,IACnC0C,KAAO6a;AAEX,YAAI1b,KAAe,GAAG;AAEpB,gBAAMc,KAAUd,KAAe,IAAI,IAC7Be,KAAU,OAAO,aAAaf,KAAe,IAAI;AACvD,UAAAa,KAAO,KAAK,IAAIC,IAAS,KAAK,IAAIC,IAASF,EAAI,CAAC;AAAA,QAClD;AAEA,QAAID,KAAM,OACRA,KAAMwa,KAAiBE,KAAsBnd;AAG/C,cAAMwd,KAAS,OAAO,cAAc1b,KAAgB;AACpD,QAAAW,KAAM,KAAK,IAAIA,IAAK+a,EAAM,GAC1B/a,KAAM,KAAK,IAAI,IAAIA,EAAG,GAEtB6Q,GAAmB,EAAE,KAAA7Q,IAAK,MAAAC,IAAM,GAChC6R,GAAuBuI,GAAkB,EAAE;AAAA,MAC7C,SAASxsB,IAAO;AACd,QAAAzC,GAAO,MAAM,uCAAuCyC,EAAK,GACzDgjB,GAAmB,IAAI;AAAA,MACzB;AAAA,IACF;AAEA,WAAAuJ,EAAA,GACA,OAAO,iBAAiB,UAAUA,CAAqB,GAQvD,OAAO,iBAAiB,UAAUA,GAAuB,EAAE,SAAS,IAAM,SAAS,IAAM,GAClF,MAAM;AACX,aAAO,oBAAoB,UAAUA,CAAqB,GAC1D,OAAO,oBAAoB,UAAUA,GAAuB,EAAE,SAAS,IAAM;AAAA,IAC/E;AAAA,EACF,GAAG,CAAC3d,GAAMrF,GAAiBC,IAAoBsH,IAAWf,GAAiBzG,IAAiBpN,GAAsBioB,IAAmB1K,IAAW1I,CAAS,CAAC;AAG1J,QAAMvL,KAAmBgH,KAAoB,SAAS/B,IAChD0iB,KAAsB5iC;AAAA,IAC1B,CAACjD,MAAqCykB,GAAsBzkB,CAAwC;AAAA,IACpG,CAACykB,EAAqB;AAAA,EAAA,GAUlBqhB,KAAqB91B;AAAA,IACzB,MAAMwlB,GAAsBjf,GAAU/B,EAAS;AAAA,IAC/C,CAAC+B,GAAU/B,EAAS;AAAA,EAAA,GAGhBuxB,KAAuB/1B,GAAQ,MAAM;AACzC,UAAMqlB,IAAM,IAAI,IAAYyQ,EAAkB;AAC9C,eAAWzhC,KAAKwC,EAAgB,CAAAwuB,EAAI,IAAIhxB,CAAC;AACzC,WAAOgxB;AAAA,EACT,GAAG,CAACyQ,IAAoBj/B,CAAc,CAAC,GAEjCm/B,KAAoB,MAAM,KAAKD,EAAoB,EAAE,KAAA,EAAO,KAAK,GAAG,GACpEE,KAA4Bj2B;AAAA,IAChC,MAAM,MAAM,KAAK+1B,EAAoB;AAAA;AAAA,IAErC,CAACC,EAAiB;AAAA,EAAA,GASdE,KAAel2B,GAAQ,MAAM;AACjC,UAAM6oB,IAAiB,CAAA,GACjBzgB,wBAAW,IAAA,GACX+tB,IAAO,CAAC1kC,MAAsB;AAClC,UAAIA,aAAcskB;AAChB,QAAItkB,EAAG,YAAY,CAAC2W,EAAK,IAAI3W,EAAG,QAAQ,MACtC2W,EAAK,IAAI3W,EAAG,QAAQ,GACpBo3B,EAAK,KAAKp3B,EAAG,QAAQ;AAAA,eAEdA,aAAc4gB;AACvB,mBAAWhe,MAAK5C,EAAG,SAAU,CAAA0kC,EAAK9hC,EAAkB;AAAA,IAExD;AACA,eAAW5C,KAAM8U,EAAU,CAAA4vB,EAAK1kC,CAAE;AAClC,WAAAo3B,EAAK,KAAA,GACEA,EAAK,KAAK,GAAG;AAAA,EACtB,GAAG,CAACtiB,CAAQ,CAAC,GAEP,CAAC6vB,IAAwBC,EAAyB,IAAI/+B,EAAmB,CAAA,CAAE;AACjF,EAAA9F,EAAU,MAAM;AACd,QAAI,CAAC0kC,IAAc;AACjB,MAAAG,GAA0B,CAAA,CAAE;AAC5B;AAAA,IACF;AACA,QAAIC,IAAY;AAChB,WAAA1N,GAAmBriB,CAAQ,EAAE,KAAK,CAACgwB,MAAW;AAC5C,MAAKD,KAAWD,GAA0BE,CAAM;AAAA,IAClD,CAAC,GACM,MAAM;AACX,MAAAD,IAAY;AAAA,IACd;AAAA,EAKF,GAAG,CAACJ,EAAY,CAAC;AAGjB,QAAMM,KAAgBvjC,EAAY,CAACwjC,MAAgC;AACjE,QAAI5c,OAEDA,GAA6D,UAAU4c,GACpEA,IAAM;AACR,YAAM,EAAE,OAAAlW,GAAO,QAAAmW,MAAWD,EAAK,sBAAA;AAC/B,MAAIlW,IAAQ,KAAKmW,IAAS,KACxB5J,GAAqB,EAAE,OAAAvM,GAAO,QAAAmW,GAAQ;AAAA,IAE1C;AAAA,EAGJ,GAAG,CAAA,CAAE;AAGL,EAAAllC,EAAU,MAAM;AACd,UAAMmlC,IAAcnJ,GAAkB,SAChCoJ,IAAgB/L;AACtB,IAAI,CAAC8L,KAAeC,KAAiB7R,MACnCmI,GAAkB,UAAU,EAAE,GAAGnI,EAAA,IAE/B4R,KAAe,CAACC,MAClB1J,GAAkB,UAAU,OAE9BM,GAAkB,UAAU3C;AAAA,EAC9B,GAAG,CAACA,GAAY9F,CAAe,CAAC,GAGhCvzB,EAAU,MAAM;AACd,UAAMqlC,IAAiB7J,GAAkB,SACnC8J,IAAiBxJ,GAAkB;AAIzC,QAHAN,GAAkB,UAAUmB,IAC5Bb,GAAkB,UAAUW,IAExB,CAAC4I,KAAkB1I,IAAmB;AAExC,UADA5B,GAAgB,EAAI,GAChBjV,MAAS,YAAY;AACvB,QAAAmV,GAAwB,EAAK,GAC7BJ,GAAc,EAAI,GAClBC,GAAa,EAAK;AAClB,cAAMyK,IAAa,WAAW,MAAM;AAAE,UAAA1K,GAAc,EAAK;AAAA,QAAG,GAAG,GAAG;AAClE,eAAO,MAAM,aAAa0K,CAAU;AAAA,MACtC;AACA,MAAAtK,GAAwB,EAAI,GAC5BJ,GAAc,EAAK,GACnBC,GAAa,EAAK;AAClB;AAAA,IACF;AAEA,QAAIuK,KAAkB1I,MAAqB2I,MAAmB7I,MAAoBA,OAAqB,QAAW;AAChH,UAAI3W,MAAS,YAAY;AACvB,QAAA+U,GAAc,EAAK;AACnB;AAAA,MACF;AACA,MAAAI,GAAwB,EAAI,GAC5BJ,GAAc,EAAK,GACnBC,GAAa,EAAK;AAClB;AAAA,IACF;AAEA,QAAIuK,KAAkB,CAAC1I,IAAmB;AACxC,UAAItD,GAAY;AACd,QAAA0B,GAAgB,EAAK,GACrBF,GAAc,EAAK,GACnBC,GAAa,EAAK,GAClBG,GAAwB,EAAK;AAC7B;AAAA,MACF;AAEA,UAAInV,MAAS,YAAY;AAGvB,YAFAgV,GAAa,EAAI,GACjBD,GAAc,EAAK,GACfpK,GAAgB,SAAS;AAC3B,gBAAM+U,KAAgB/U,GAAgB,QAAQ;AAC9C,UAAA2K,GAAoBoK,EAAa,GACjC,sBAAsB,MAAM;AAAE,YAAApK,GAAoB,CAAC;AAAA,UAAG,CAAC;AAAA,QACzD;AACA,cAAMqK,IAAY,WAAW,MAAM;AACjC,UAAA1K,GAAgB,EAAK,GACrBD,GAAa,EAAK,GAClBM,GAAoB,IAAI;AAAA,QAC1B,GAAG,GAAG;AACN,eAAO,MAAM,aAAaqK,CAAS;AAAA,MACrC;AAEA,MAAA3K,GAAa,EAAI,GACjBD,GAAc,EAAK,GACnBI,GAAwB,EAAK;AAC7B,YAAMwK,IAAY,WAAW,MAAM;AACjC,QAAA1K,GAAgB,EAAK,GACrBD,GAAa,EAAK,GAClBZ,GAAmB,IAAI,GACvBiB,GAAuB,IAAI;AAAA,MAC7B,GAAG,GAAG;AACN,aAAO,MAAM,aAAasK,CAAS;AAAA,IACrC;AAAA,EAGF,GAAG,CAAC9I,IAAmBtD,GAAYoD,IAAkB3W,GAAM4W,EAAkB,CAAC,GAG9E18B,EAAU,MAAM;AACd,QAAIg7B,MAAwBzH,KAAmB2H,OAAwB3d,IAAiB;AACtF,MAAA0d,GAAwB,EAAK,GAC7BJ,GAAc,EAAI;AAClB,YAAM0K,IAAa,WAAW,MAAM;AAAE,QAAA1K,GAAc,EAAK;AAAA,MAAG,GAAG,GAAG;AAClE,aAAO,MAAM,aAAa0K,CAAU;AAAA,IACtC;AAAA,EAEF,GAAG,CAACvK,IAAsBzH,GAAiB2H,IAAqB3d,EAAe,CAAC,GAGhFmoB,GAAgB,MAAM;AACpB,QAAI5f,MAAS,WAAY;AACzB,UAAM8c,IAAW7G,GAAmB;AAGpC,QAFoB6G,MAAa,UAAalG,OAAuB,UAAakG,MAAalG,MAE5EnB,GAAmB,UAAU,KAAK3K,OAAqB,MAAM;AAC9E,YAAM+U,IAAcpK,GAAmB;AACvC,MAAAH,GAAoBuK,CAAW,GAC/B,sBAAsB,MAAM;AAC1B,8BAAsB,MAAM;AAC1B,cAAIlV,GAAgB,SAAS;AAC3B,kBAAM8S,IAAY9S,GAAgB,QAAQ;AAC1C,YAAA2K,GAAoBmI,CAAS,GAC7B,WAAW,MAAM;AAAE,cAAAnI,GAAoB,IAAI;AAAA,YAAG,GAAG,GAAG;AAAA,UACtD;AAAA,QACF,CAAC;AAAA,MACH,CAAC;AAAA,IACH;AAEA,IAAI3K,GAAgB,WAAWG,OAAqB,QAAQ,CAACgK,MAAc,CAACjK,OAC1E4K,GAAmB,UAAU9K,GAAgB,QAAQ,eAGvDsL,GAAmB,UAAUW;AAAA,EAC/B,GAAG,CAAC5W,GAAM4W,IAAoB9L,IAAkBgK,IAAYjK,EAAS,CAAC;AAGtE,QAAMiV,KAAep3B,GAAQ,MAAM;AACjC,UAAMq3B,IAAgBzN,IAAY,OAAOA,KAAa,WAAW,GAAGA,CAAQ,OAAOA,IAAY;AAE/F,QAAItS,MAAS;AACX,aAAO;AAAA,QACL,cAAcsS,IAAW,SAAS;AAAA,QAClC,YAAY;AAAA,QACZ,UAAU;AAAA,QACV,UAAUyN;AAAA,QACV,SAAS;AAAA,QACT,gBAAgB;AAAA,MAAA;AAIpB,UAAMlpC,IAAW++B,GAAkB,WAAWnI;AAC9C,WAAI52B,KAAY,CAACq+B,KACR;AAAA,MACL,KAAK,GAAGr+B,EAAS,GAAG;AAAA,MACpB,MAAM,GAAGA,EAAS,IAAI;AAAA,MACtB,UAAU;AAAA,MACV,WAAW;AAAA,MACX,cAAcy7B,IAAW,SAAS;AAAA,MAClC,YAAY;AAAA,MACZ,UAAUyN;AAAA,MACV,QAAQ;AAAA,IAAA,IAIL;AAAA,MACL,cAAczN,IAAW,SAAS;AAAA,MAClC,YAAY;AAAA,MACZ,UAAUyN;AAAA,MACV,UAAU;AAAA,MACV,KAAK;AAAA,MACL,MAAM;AAAA,MACN,QAAQ;AAAA,IAAA;AAAA,EAEZ,GAAG,CAAC/f,GAAMyN,GAAiByH,IAAsB5C,CAAQ,CAAC;AAK1D,MAAIpR,GAAe,SAAS;AAC1B,WACE,gBAAAxsB;AAAA,MAACstB;AAAA,MAAA;AAAA,QACC,MAAAhC;AAAA,QACA,sBAAA1S;AAAA,QACA,UAAA2U;AAAA,MAAA;AAAA,IAAA;AASN,QAAM+d,KACJ,gBAAAvpC,EAAA2C,IAAA,EAMG,UAAA;AAAA,IAAA46B,MAAe,UAAU/b,KACxB,gBAAAvjB;AAAA,MAACuqB;AAAA,MAAA;AAAA,QACC,SAAShH;AAAA,QACT,cAAcoiB;AAAA,QACd,kBAAkBpH;AAAA,MAAA;AAAA,IAAA;AAAA,IAQrBe,MAAe,UAAU/b,KAAwBoK,MAChD,gBAAA3tB;AAAA,MAACoS;AAAA,MAAA;AAAA,QACC,MAAK;AAAA,QACL,SAASuxB;AAAA,QACT,SAAQ;AAAA,QACR,SAAQvgB,KAAA,gBAAAA,EAAe,UAAS;AAAA,QAChC,eAAY;AAAA,MAAA;AAAA,IAAA;AAAA,IAKfkc,MAAe,WAAU/b,KAAA,gBAAAA,EAAsB,mBAAkB,WAChE,gBAAAvjB;AAAA,MAACiO;AAAA,MAAA;AAAA,QACC,SAASsV;AAAA,QACT,iBAAiBG;AAAA,QACjB,mBAAmB,CAAC,CAACwC,OAAsBD,KAAA,gBAAAA,EAAiB,mBAAkB;AAAA,QAC9E,WAAW2f;AAAA,QACX,eAAeP;AAAA,QACf,gBAAgBG;AAAA,QAChB,eAAAj3B;AAAA,QACA,oBAAoB6wB,IAAmB8D,KAAyB;AAAA,QAChE,oBAAAz0B;AAAA,QACA,uBAAAC;AAAA,QACA,UAAU+2B;AAAA,QACV,uBAAsBriB,KAAA,gBAAAA,EAAe,UAAS;AAAA,QAC9C,sBAAsBwgB;AAAA,QACtB,eAAcxgB,KAAA,gBAAAA,EAAe,UAAS;AAAA,QACtC,cAAcpR;AAAA,QACd,iBAAgBoR,KAAA,gBAAAA,EAAe,UAAS;AAAA,QACxC,gBAAgB2gB;AAAA,QAChB,mBAAkB3gB,KAAA,gBAAAA,EAAe,UAAS;AAAA,QAC1C,kBAAkBygB;AAAA,QAClB,kBAAiBzgB,KAAA,gBAAAA,EAAe,UAAS;AAAA,QACzC,iBAAiB0gB;AAAA,QACjB,iBAAgB1gB,KAAA,gBAAAA,EAAe,UAAS;AAAA,QACxC,gBAAgB4hB;AAAA,QAChB,iBAAgB5hB,KAAA,gBAAAA,EAAe,UAAS;AAAA,QACxC,gBAAgB6hB;AAAA,QAChB,oBAAmB7hB,KAAA,gBAAAA,EAAe,UAAS;AAAA,QAC3C,mBAAmB8hB;AAAA,QACnB,mBAAkB9hB,KAAA,gBAAAA,EAAe,UAAS;AAAA,QAC1C,kBAAkByhB;AAAA,QAClB,0BAAyBzhB,KAAA,gBAAAA,EAAe,UAAS;AAAA,QACjD,yBAAyB0hB;AAAA,QACzB,oBAAmB1hB,KAAA,gBAAAA,EAAe,UAAS;AAAA,QAC3C,mBAAmB2hB;AAAA,MAAA;AAAA,IAAA;AAAA,IAKtBzF,MAAe,WAAUrZ,KAAA,gBAAAA,EAAiB,mBAAkB,WAAW,CAACC,MACvE,gBAAAlmB;AAAA,MAACqvB;AAAA,MAAA;AAAA,QACC,SAASpJ;AAAA,QACT,mBAAkB7C,KAAA,gBAAAA,EAAe,UAAS;AAAA,QAC1C,kBAAkBygB;AAAA,QAClB,kBAAiBzgB,KAAA,gBAAAA,EAAe,UAAS;AAAA,QACzC,iBAAiB0gB;AAAA,QACjB,iBAAgB1gB,KAAA,gBAAAA,EAAe,UAAS;AAAA,QACxC,gBAAgB4hB;AAAA,QAChB,iBAAgB5hB,KAAA,gBAAAA,EAAe,UAAS;AAAA,QACxC,gBAAgB6hB;AAAA,QAChB,oBAAmB7hB,KAAA,gBAAAA,EAAe,UAAS;AAAA,QAC3C,mBAAmB8hB;AAAA,QACnB,mBAAkB9hB,KAAA,gBAAAA,EAAe,UAAS;AAAA,QAC1C,kBAAkByhB;AAAA,QAClB,0BAAyBzhB,KAAA,gBAAAA,EAAe,UAAS;AAAA,QACjD,yBAAyB0hB;AAAA,QACzB,oBAAmB1hB,KAAA,gBAAAA,EAAe,UAAS;AAAA,QAC3C,mBAAmB2hB;AAAA,QACnB,WAAWa;AAAA,MAAA;AAAA,IAAA;AAAA,IAKdtG,MAAe,WAAU/b,KAAA,gBAAAA,EAAsB,mBAAkB,WAChE,gBAAAvjB;AAAA,MAACuS;AAAA,MAAA;AAAA,QACC,SAASgR;AAAA,QACT,iBAAiBG;AAAA,QACjB,gBAAgBumB;AAAA,QAChB,aAAaG;AAAA,QACb,mBAAmB,CAAC,CAAClkB,OAAsBD,KAAA,gBAAAA,EAAiB,mBAAkB;AAAA,QAC9E,WAAW2f;AAAA,QACX,eAAeP;AAAA,QACf,gBAAgBG;AAAA,QAChB,uBAAuB0C;AAAA,QACvB,UAAUzC;AAAA,QACV,mBAAkBriB,KAAA,gBAAAA,EAAe,UAAS;AAAA,QAC1C,kBAAkBygB;AAAA,QAClB,uBAAsBzgB,KAAA,gBAAAA,EAAe,UAAS;AAAA,QAC9C,sBAAsBkhB;AAAA,QACtB,uBAAsBlhB,KAAA,gBAAAA,EAAe,UAAS;AAAA,QAC9C,sBAAsBmhB;AAAA,QACtB,gBAAenhB,KAAA,gBAAAA,EAAe,UAAS;AAAA,QACvC,eAAeohB;AAAA,QACf,iBAAgBphB,KAAA,gBAAAA,EAAe,UAAS;AAAA,QACxC,gBAAgBqhB;AAAA,QAChB,sBAAqBrhB,KAAA,gBAAAA,EAAe,UAAS;AAAA,QAC7C,qBAAqBshB;AAAA,QACrB,gBAAethB,KAAA,gBAAAA,EAAe,UAAS;AAAA,QACvC,eAAeuhB;AAAA,QACf,iBAAgBvhB,KAAA,gBAAAA,EAAe,UAAS;AAAA,QACxC,gBAAgB4hB;AAAA,QAChB,iBAAgB5hB,KAAA,gBAAAA,EAAe,UAAS;AAAA,QACxC,gBAAgB6hB;AAAA,QAChB,oBAAmB7hB,KAAA,gBAAAA,EAAe,UAAS;AAAA,QAC3C,mBAAmB8hB;AAAA,QACnB,mBAAkB9hB,KAAA,gBAAAA,EAAe,UAAS;AAAA,QAC1C,kBAAkByhB;AAAA,QAClB,0BAAyBzhB,KAAA,gBAAAA,EAAe,UAAS;AAAA,QACjD,yBAAyB0hB;AAAA,QACzB,oBAAmB1hB,KAAA,gBAAAA,EAAe,UAAS;AAAA,QAC3C,mBAAmB2hB;AAAA,MAAA;AAAA,IAAA;AAAA,IAKtBzF,MAAe,WAAU/b,KAAA,gBAAAA,EAAsB,mBAAkB,UAChE,gBAAAvjB;AAAA,MAACuU;AAAA,MAAA;AAAA,QACC,SAASgP;AAAA,QACT,iBAAiBG;AAAA,QACjB,eAAe2hB;AAAA,QACf,gBAAgBG;AAAA,MAAA;AAAA,IAAA;AAAA,IAKnBlG,MAAe,UACd/b,KACAA,EAAqB,kBAAkB,WACvCA,EAAqB,kBAAkB,WACvCA,EAAqB,kBAAkB,WACvCA,EAAqB,kBAAkB,UACrC,gBAAAvjB;AAAA,MAAC8iB;AAAA,MAAA;AAAA,QACC,SAASuc;AAAA,QACT,iBAAAtc;AAAA,QACA,eAAAC;AAAA,QACA,kBAAAd;AAAA,QACA,gBAAekB,KAAA,gBAAAA,EAAe,UAAS;AAAA,QACvC,eAAewhB;AAAA,QACf,oBAAA1hB;AAAA,QACA,iBAAgBE,KAAA,gBAAAA,EAAe,UAAS;AAAA,QACxC,gBAAgB4hB;AAAA,QAChB,iBAAgB5hB,KAAA,gBAAAA,EAAe,UAAS;AAAA,QACxC,gBAAgB6hB;AAAA,QAChB,oBAAmB7hB,KAAA,gBAAAA,EAAe,UAAS;AAAA,QAC3C,mBAAmB8hB;AAAA,QACnB,WAAA/hB;AAAA,QACA,eAAAC;AAAA,QACA,kBAAkBygB;AAAA,QAClB,iBAAiBC;AAAA,QACjB,kBAAkBE;AAAA,QAClB,mBAAkB5gB,KAAA,gBAAAA,EAAe,UAAS;AAAA,QAC1C,kBAAkByhB;AAAA,QAClB,0BAAyBzhB,KAAA,gBAAAA,EAAe,UAAS;AAAA,QACjD,yBAAyB0hB;AAAA,QACzB,oBAAmB1hB,KAAA,gBAAAA,EAAe,UAAS;AAAA,QAC3C,mBAAmB2hB;AAAA,QACnB,kBAAAzhB;AAAA,QACA,eAAe+hB;AAAA,QACf,gBAAgBG;AAAA,QAChB,UAAUC;AAAA,QACV,sBAAAliB;AAAA,QACA,UAAAhJ;AAAA,QACA,qBAAAiJ;AAAA,QACA,2BAA2Bqc;AAAA,QAC3B,sBAAAnc;AAAA,QACA,mBAAmB,CAAC,CAACwC,OAAsBD,KAAA,gBAAAA,EAAiB,mBAAkB;AAAA,QAC9E,WAAW2f;AAAA,QACX,mBAAmBpG,MAAiB;AAAA,QACpC,qBAAqB,CAAC1zB,MAAW2zB,GAAgB3zB,IAAS,eAAe,IAAI;AAAA,QAC7E,0BAA0Bk0B;AAAA,MAAA;AAAA,IAAA;AAAA,IAK/BV,MAAe,WACd,gBAAAv9B,EAAC,OAAA,EAAI,WAAU,oBACb,UAAA;AAAA,MAAA,gBAAA/B,EAACiN,IAAA,EAAW,SAAS,MAAMsyB,EAAc,MAAM,GAAG;AAAA,MAClD,gBAAAx9B,EAAC,OAAA,EAAI,WAAU,qBACb,UAAA;AAAA,QAAA,gBAAA/B;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,WAAU;AAAA,YACV,MAAK;AAAA,YACL,OAAOmnB;AAAA,YACP,UAAU,CAACnjB,MAAM;AAAE,cAAAykB,GAAsBzkB,CAAC;AAAA,YAAG;AAAA,UAAA;AAAA,QAAA;AAAA,QAE/C,gBAAAhE,EAAC,QAAA,EAAK,WAAU,oBAAoB,UAAAmnB,GAAA,CAAU;AAAA,MAAA,EAAA,CAChD;AAAA,IAAA,EAAA,CACF;AAAA,EAAA,GAEJ,GAIIokB,MAAehoB,KAAA,gBAAAA,EAAsB,mBAAkB,UAAWA,IAAwC,MAE1GyS,KAAiBE,KACrB,gBAAAl2B;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,KAAKwqC;AAAA,MACL,WAAU;AAAA,MACV,gBAAcjd;AAAA,MACd,aAAWjC;AAAA,MACX,aAAWsS,IAAW,KAAK;AAAA,MAC3B,oBAAkBC,IAAc,KAAK;AAAA,MACrC,uBAAqBza,IAAgB,KAAK;AAAA,MAC1C,2BAAuB;AAAA,MACvB,OAAO;AAAA,QACL,GAAGgoB;AAAA,QACH,SAASvM,IAAa,IAAI;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAO1B,eAAeA,KAAsBvT,MAAS,aAAlB,SAAwC;AAAA,QACpE,YAAY;AAAA,MAAA;AAAA,MAEd,iBAAe8U,KAAa,KAAK;AAAA,MACjC,gBAAcjK,KAAY,KAAK;AAAA,MAE/B,UAAA,gBAAAp0B,EAAC,OAAA,EAAI,WAAU,8BACb,UAAA;AAAA,QAAA,gBAAA/B,EAAC,SAAI,WAAU,8BAA6B,eAAaojB,IAAgB,KAAK,QAC3E,UAAAkoB,GAAA,CACH;AAAA,QACA,gBAAAtrC,EAAC,SAAI,WAAU,+BAA8B,gBAAcojB,IAAgB,KAAK,QAC7E,UAAAA,KACC,gBAAApjB;AAAA,UAACgF;AAAA,UAAA;AAAA,YACC,MACE,gBAAAhF;AAAA,cAACw1B;AAAA,cAAA;AAAA,gBACC,WAAWpS,EAAc;AAAA,gBACzB,aAAaA,EAAc;AAAA,gBAC3B,gBAAgBlB;AAAA,gBAChB,gBACEqpB,KACIj3B,IAAezG,KAAA09B,GAAa,kBAAb,gBAAA19B,GAA4B,OAAMC,KAAAy9B,GAAa,kBAAb,gBAAAz9B,GAA4B,SAAS,IACtF;AAAA,cAAA;AAAA,YAAA;AAAA,YAIV,OAAOsV,EAAc;AAAA,YACrB,SAAS+hB;AAAA,YACT,kBAAA//B;AAAA,UAAA;AAAA,QAAA,EACF,CAEJ;AAAA,MAAA,EAAA,CACF;AAAA,IAAA;AAAA,EAAA,IAEA,MAGEkxB,MAAmBlT,KAAA,gBAAAA,EAAe,UAAS,SAC3CmT,MAA0BnT,KAAA,gBAAAA,EAAe,UAAS,gBAClDoT,MAAkBpT,KAAA,gBAAAA,EAAe,UAAS,QAC1CqT,MAAsBrT,KAAA,gBAAAA,EAAe,UAAS,YAC9CsT,MAAqBtT,KAAA,gBAAAA,EAAe,UAAS,WAC7CuT,MAAoBvT,KAAA,gBAAAA,EAAe,UAAS,UAC5CwT,MAAsBxT,KAAA,gBAAAA,EAAe,UAAS,YAC9CyT,MAA+BzT,KAAA,gBAAAA,EAAe,UAAS,qBACvD0T,MAA+B1T,KAAA,gBAAAA,EAAe,UAAS,qBACvD2T,MAAwB3T,KAAA,gBAAAA,EAAe,UAAS,cAChD4T,MAAyB5T,KAAA,gBAAAA,EAAe,UAAS,eACjD6T,MAA8B7T,KAAA,gBAAAA,EAAe,UAAS,oBACtD8T,MAAwB9T,KAAA,gBAAAA,EAAe,UAAS,cAChD+T,MAAuB/T,KAAA,gBAAAA,EAAe,UAAS,aAC/CmU,MAAsBnU,KAAA,gBAAAA,EAAe,UAAS,eAC9CoU,MAA6BpU,KAAA,gBAAAA,EAAe,UAAS,mBACrDgU,MAAoBhU,KAAA,gBAAAA,EAAe,UAAS,UAC5CiU,MAAoBjU,KAAA,gBAAAA,EAAe,UAAS,UAC5CkU,MAAuBlU,KAAA,gBAAAA,EAAe,UAAS,aAC/CqU,MAAuBrU,KAAA,gBAAAA,EAAe,UAAS,aAG/CooB,MACJjoB,KAAA,gBAAAA,EAAsB,mBAAkB,aACnC6F,KAAA7F,EAAsC,kBAAtC,gBAAA6F,GAAqD,iBAAgB,GAEtE4f,MAAkBzlB,KAAA,gBAAAA,EAAsB,aAAY,GACpDkoB,MAAiBloB,KAAA,gBAAAA,EAAsB,YAAW,GAClDmoB,OAA2BphB,KAAAihB,MAAA,gBAAAA,GAAc,kBAAd,gBAAAjhB,GAA6B,iBAAgB,GACxEqhB,OAAsBC,KAAAL,MAAA,gBAAAA,GAAc,kBAAd,gBAAAK,GAA6B,gBAAe,GAClEC,OAAoBC,KAAAP,MAAA,gBAAAA,GAAc,kBAAd,gBAAAO,GAA6B,UAAS,GAC1DC,OAAqBC,KAAAT,MAAA,gBAAAA,GAAc,kBAAd,gBAAAS,GAA6B,WAAU,GAC5DC,OAA0BC,KAAAX,MAAA,gBAAAA,GAAc,kBAAd,gBAAAW,GAA6B,gBAAe,KACtEC,OAAwBC,KAAAb,MAAA,gBAAAA,GAAc,kBAAd,gBAAAa,GAA6B,cAAa,WAClEC,MAAmBC,KAAAf,MAAA,gBAAAA,GAAc,kBAAd,gBAAAe,GAA6B,MAChDC,OAAkBC,KAAAjpB,KAAA,gBAAAA,EAAsB,kBAAtB,gBAAAipB,GAAqC,SAAQ,IAC/DC,OAAoBC,KAAAnpB,KAAA,gBAAAA,EAAsB,kBAAtB,gBAAAmpB,GAAqC,WAAU,IACnEC,OAAqCC,KAAArpB,KAAA,gBAAAA,EAAsB,kBAAtB,gBAAAqpB,GAAqC,UAAS,SACnFC,MAAmCtpB,KAAA,gBAAAA,EAAsB,eAAc,SAAS,SAAS,YAGzFmU,KAAapB,MAAoB/S,sBAClCyN,IAAA,EAAW,SAAS0S,IAAgB,IACrC,MAEE/L,KAAoBpB,OAA2BhT,KAAA,gBAAAA,EAAsB,mBAAkB,UACzF,gBAAAvjB,EAAC+wB,IAAA,EAAkB,OAAOya,IAAqB,UAAUpJ,GAAA,CAA0B,IACnF,MAEExK,KAAmBpB,OAAmBjT,KAAA,gBAAAA,EAAsB,mBAAkB,UAChF,gBAAAvjB,EAACu1B,IAAA,EAAiB,SAAShS,GAAsC,iBAAiBG,EAAA,CAAsB,IACxG,MAEEmU,KAAgBpB,MAAuBlT,IACzC,gBAAAvjB,EAACkxB,IAAA,EAAc,OAAO8X,IAAiB,UAAU/C,IAAsB,YAAYC,GAAA,CAAgB,IACnG,MAEEpO,KAAepB,MAAsBnT,IACvC,gBAAAvjB,EAAC2xB,MAAa,OAAO8Z,IAAgB,UAAUrzB,GAAA,CAAqB,IACpE,MAEE00B,MACJvpB,KAAA,gBAAAA,EAAsB,mBAAkB,WACnCwpB,KAAAxpB,EAAsC,kBAAtC,gBAAAwpB,GAAqD,cACtD,QAEAhV,KAAcpB,OAAqBpT,KAAA,gBAAAA,EAAsB,mBAAkB,UAE3E,gBAAAvjB;AAAA,IAAC4xB;AAAA,IAAA;AAAA,MACC,aAAakb;AAAA,MACb,UAAUvG;AAAA,MACV,aAAaG;AAAA,MACb,SAASC;AAAA,IAAA;AAAA,EAAA,IAGb,MAME3O,KAAgBpB,KAEhB,gBAAA52B;AAAA,IAACoxB;AAAA,IAAA;AAAA,MACC,OAAOiO,EAAY;AAAA,MACnB,UAAUA,EAAY;AAAA,MACtB,YAAY6E;AAAA,MACZ,eAAeD;AAAA,MACf,oBAAoBG;AAAA,MACpB,uBAAuB/E,EAAY;AAAA,MACnC,iBAAiBgF;AAAA,MACjB,oBAAoBhF,EAAY;AAAA,IAAA;AAAA,EAAA,IAGpC,MAEEpH,KAAyBpB,MAAgC0U,KAC3D,gBAAAvrC,EAACmyB,MAAuB,OAAOuZ,IAA0B,UAAUvI,GAAA,CAA+B,IAClG,MAEEjL,KAAyBpB,MAAgCyU,KAC3D,gBAAAvrC,EAACoyB,MAAuB,OAAOuZ,IAAqB,UAAUvI,GAAA,CAA0B,IACxF,MAEEjL,KAAkBpB,MAAyBwU,KAC7C,gBAAAvrC,EAACqyB,MAAgB,OAAOwZ,IAAmB,UAAUxI,GAAA,CAAwB,IAC7E,MAEEjL,KAAmBpB,MAA0BuU,KAC/C,gBAAAvrC,EAACsyB,MAAiB,OAAOyZ,IAAoB,UAAUzI,GAAA,CAAyB,IAChF,MAEEjL,KAAwBpB,MAA+BsU,KACzD,gBAAAvrC,EAACuyB,MAAsB,OAAO0Z,IAAyB,UAAU1I,GAAA,CAA8B,IAC/F,MAEEjL,KAAkBpB,MAAyBqU,KAC7C,gBAAAvrC,EAACyyB,IAAA,EAAgB,OAAO0Z,IAAuB,UAAU3I,IAA4B,MAAM6I,IAAkB,cAAc5I,IAAuB,gBAAgBwG,IAA2B,aAAaG,IAAwB,IAClO,MAEE7R,KAAiBpB,MAAwB5T,IAC3C,gBAAAvjB,EAACuzB,IAAA,EAAe,OAAOrR,IAAkB,UAAU2nB,IAAqB,gBAAgBI,IAA2B,aAAaG,IAAwB,IACxJ,MAEEzR,KAAgBpB,MAAuBhU,IACzC,gBAAAvjB;AAAA,IAACwzB;AAAA,IAAA;AAAA,MACC,MAAMqZ;AAAA,MACN,MAAMN;AAAA,MACN,QAAQE;AAAA,MACR,OAAOE;AAAA,MACP,cAAc/F;AAAA,MACd,cAAcC;AAAA,MACd,gBAAgBG;AAAA,MAChB,eAAeC;AAAA,IAAA;AAAA,EAAA,IAEjB,MAEEzO,KAAcpB,MAAqB7T,IACrC,gBAAAvjB;AAAA,IAACo0B;AAAA,IAAA;AAAA,MACC,QAAQ7Q,EAAqB;AAAA,MAC7B,UAAUskB;AAAA,MACV,gBAAgBoC;AAAA,MAChB,aAAaG;AAAA,IAAA;AAAA,EAAA,IAEf,MAEE3R,KAAcpB,MAAqB9T,IACrC,gBAAAvjB;AAAA,IAAC80B;AAAA,IAAA;AAAA,MACC,QAAQvR,EAAqB;AAAA,MAC7B,UAAUukB;AAAA,MACV,gBAAgBmC;AAAA,MAChB,aAAaG;AAAA,IAAA;AAAA,EAAA,IAEf,MAEE1R,KAAiBpB,MAAwB/T,IAC3C,gBAAAvjB;AAAA,IAACq1B;AAAA,IAAA;AAAA,MACC,WACEtnB,GAAoBwV,EAAqB,SAAS,IAC9CA,EAAqB,YACrB;AAAA,MAEN,UAAUwkB;AAAA,IAAA;AAAA,EAAA,IAEZ,MAEEnP,KAAuBpB,MAA8BjU,IACvD,gBAAAvjB;AAAA,IAAC8zB;AAAA,IAAA;AAAA,MACC,cAAYkZ,KAAAzpB,EAAqB,mBAArB,gBAAAypB,GAAqC,eAAc;AAAA,MAC/D,SAAS,KAAK,SAAOC,KAAA1pB,EAAqB,mBAArB,gBAAA0pB,GAAqC,mBAAkB,OAAO,GAAG;AAAA,MACtF,iBAAiB3zB;AAAA,MACjB,iBAAiB4tB;AAAA,IAAA;AAAA,EAAA,IAEnB,MAEEgG,MAAYC,KAAA5pB,KAAA,gBAAAA,EAAsB,UAAtB,gBAAA4pB,GAA6B,KAAK,CAAClkC,MAAsBA,EAAE,OAAO,qBAC9E4vB,KAAiBpB,MAAwBlU,IAC3C,gBAAAvjB;AAAA,IAACg0B;AAAA,IAAA;AAAA,MACC,YAAWoZ,KAAAF,MAAA,gBAAAA,GAAW,gBAAX,gBAAAE,GAAkD,aAAY;AAAA,MACzE,WAAWF,MAAA,gBAAAA,GAAW,SAAsC;AAAA,MAC5D,SAAS,KAAK,QAAOA,MAAA,gBAAAA,GAAW,YAAW,KAAK,GAAG;AAAA,MACnD,WAAUA,MAAA,gBAAAA,GAAW,aAAY;AAAA,MACjC,eAAe9F;AAAA,MACf,kBAAkBI;AAAA,MAClB,iBAAiBE;AAAA,MACjB,kBAAkBC;AAAA,IAAA;AAAA,EAAA,IAEpB,MAGEtR,KACJ/K,MAAS,cAAc,CAACrF,KAAmB,CAACoY,IAC1CD,IACE,gBAAAp+B,EAAC,SAAI,WAAU,uBAAuB,UAAAo+B,EAAA,CAAiB,IACrDD,MAAsB,OACxB,gBAAAn+B;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,WAAU;AAAA,MACV,OAAO;AAAA,QACL,SAAS;AAAA,QACT,YAAY;AAAA,QACZ,gBAAgB;AAAA,QAChB,SAAS;AAAA,QACT,OAAO;AAAA,QACP,SAAS;AAAA,QACT,UAAU;AAAA,QACV,WAAW;AAAA,MAAA;AAAA,MAGZ,UAAAm+B;AAAA,IAAA;AAAA,EAAA,IAED,OACF,MAGAkP,KACJ/hB,MAAS,cAAc+S,KAAoB,CAACpY,KAAmBwG,EAAgB,kBAAA,IAC7E,gBAAA1qB,EAAC,OAAA,EAAI,WAAU,gDACb,UAAA;AAAA,IAAA,gBAAA/B;AAAA,MAACgF;AAAA,MAAA;AAAA,QACC,MAAK;AAAA,QACL,OAAM;AAAA,QACN,SAAS,MAAMs5B,KAAA,gBAAAA,EAA2B;AAAA,QAC1C,kBAAiB;AAAA,MAAA;AAAA,IAAA;AAAA,IAEnB,gBAAAt+B;AAAA,MAAC0W;AAAA,MAAA;AAAA,QACC,iBAAiB+V,EAAgB,kBAAA,EAAqB;AAAA,QACtD,UAAU,CAAC9V,MAAoB;AAC7B,gBAAM22B,IAAkB7gB,EAAgB,kBAAA;AACxC,UAAIhU,IACFA;AAAA,YACE60B,EAAgB;AAAA,YAChB,EAAE,iBAAiBA,EAAgB,gBAAA;AAAA,YACnC,EAAE,iBAAA32B,EAAA;AAAA,UAAgB,KAGpB8V,EAAgB,eAAe6gB,EAAgB,IAAI,EAAE,iBAAA32B,GAAiB,GACtEwoB,GAAA;AAAA,QAEJ;AAAA,MAAA;AAAA,IAAA;AAAA,IAEF,gBAAAn/B;AAAA,MAACyX;AAAA,MAAA;AAAA,QACC,WAAWgV,EAAgB,kBAAA,EAAqB;AAAA,QAChD,UAAU,CAAC/U,MAAc;AACvB,gBAAM41B,IAAkB7gB,EAAgB,kBAAA;AACxC,UAAIhU,IACFA;AAAA,YACE60B,EAAgB;AAAA,YAChB,EAAE,WAAWA,EAAgB,UAAA;AAAA,YAC7B,EAAE,WAAA51B,EAAA;AAAA,UAAU,KAGd+U,EAAgB,eAAe6gB,EAAgB,IAAI,EAAE,WAAA51B,GAAW,GAChEynB,GAAA;AAAA,QAEJ;AAAA,MAAA;AAAA,IAAA;AAAA,EACF,EAAA,CACF,IACE,MAGAoO,KACJjiB,MAAS,aACP,gBAAAtrB;AAAA,IAAC+1B;AAAA,IAAA;AAAA,MACC,gBAAAC;AAAA,MACA,iBAAAC;AAAA,MACA,cAAAC;AAAA,MACA,WAAAC;AAAA,MACA,kBAAAC;AAAA,MACA,mBAAmBiX,MAAuBhX;AAAA,MAC1C,kBAAAC;AAAA,MACA,yBAAAC;AAAA,MACA,iBAAAC;AAAA,MACA,qBAAAC;AAAA,MACA,oBAAAC;AAAA,MACA,mBAAAC;AAAA,MACA,qBAAAC;AAAA,MACA,8BAAAC;AAAA,MACA,8BAAAC;AAAA,MACA,uBAAAC;AAAA,MACA,wBAAAC;AAAA,MACA,6BAAAC;AAAA,MACA,uBAAAC;AAAA,MACA,sBAAAC;AAAA,MACA,mBAAAC;AAAA,MACA,mBAAAC;AAAA,MACA,sBAAAC;AAAA,MACA,qBAAAC;AAAA,MACA,4BAAAC;AAAA,MACA,sBAAAC;AAAA,MACA,mBAAAE;AAAA,MACA,kBAAAC;AAAA,MACA,eAAAC;AAAA,MACA,cAAAC;AAAA,MACA,aAAAC;AAAA,MACA,eAAAC;AAAA,MACA,wBAAAC;AAAA,MACA,wBAAAC;AAAA,MACA,iBAAAC;AAAA,MACA,kBAAAC;AAAA,MACA,uBAAAC;AAAA,MACA,iBAAAC;AAAA,MACA,gBAAAC;AAAA,MACA,aAAAC;AAAA,MACA,aAAAC;AAAA,MACA,gBAAAC;AAAA,MACA,eAAAC;AAAA,MACA,sBAAAC;AAAA,MACA,YAAAlB;AAAA,MACA,gBAAAmB;AAAA,IAAA;AAAA,EAAA,IAEA,MAGAG,KAAa6H,GAAkB,QAAQ,IAAI,KAAK,IAAIA,GAAkB,OAAO,GAAG,IAAI,KAEpF2M,KACJliB,MAAS,cAAciL,OAA2BhT,KAAA,gBAAAA,EAAsB,mBAAkB,WAAWwV,IACnG,gBAAA/4B;AAAA,IAAC84B;AAAA,IAAA;AAAA,MACC,iBAAAC;AAAA,MACA,eAAe8H,GAAkB,UAAU;AAAA,MAC3C,YAAA7H;AAAA,MACA,OAAOwS;AAAA,MACP,UAAUpJ;AAAA,IAAA;AAAA,EAAA,IAEV,MAEAqL,KACJniB,MAAS,cAAckL,OAAmBjT,KAAA,gBAAAA,EAAsB,mBAAkB,WAAWwV,IAC3F,gBAAA/4B;AAAA,IAACk5B;AAAA,IAAA;AAAA,MACC,iBAAAH;AAAA,MACA,eAAe8H,GAAkB,UAAU;AAAA,MAC3C,SAAStd;AAAA,MACT,iBAAiBG;AAAA,IAAA;AAAA,EAAA,IAEjB,MAEAgqB,KACJpiB,MAAS,cAAcgL,MAAoB/S,KAAwBwV,IACjE,gBAAA/4B;AAAA,IAACi5B;AAAA,IAAA;AAAA,MACC,iBAAAF;AAAA,MACA,eAAe8H,GAAkB,UAAU;AAAA,MAC3C,SAAS6C;AAAA,IAAA;AAAA,EAAA,IAET;AAMN,SACE,gBAAA3hC,EAAA2C,IAAA,EAEG,UAAA;AAAA,IAAA4mB,MAAS,cAAc,OAAO,WAAa,MACxC8D;AAAA,MACE,gBAAArtB,EAAA2C,IAAA,EACG,UAAA;AAAA,QAAAsxB;AAAA,QACAwX;AAAA,QACAC;AAAA,QACAC;AAAA,MAAA,GACH;AAAA,MACA,SAAS;AAAA,IAAA,IAEXH;AAAA,IAGHjiB,MAAS,cAAc,CAACrF,KAAmBwG,EAAgB,kBAAA,KAAuBhU,KACjF,gBAAAzY;AAAA,MAACsY;AAAA,MAAA;AAAA,QACC,UAAUmU,EAAgB,kBAAA;AAAA,QAC1B,WAAAjU;AAAA,QACA,kBAAkB,CAACW,MAAoB;AACrC,gBAAMm0B,IAAkB7gB,EAAgB,kBAAA;AACxC,UAAAhU;AAAA,YACE60B,EAAgB;AAAA,YAChB;AAAA,cACE,iBAAiBA,EAAgB;AAAA,cACjC,gBAAgBA,EAAgB;AAAA,cAChC,mBAAmBA,EAAgB;AAAA,cACnC,kBAAkBA,EAAgB;AAAA,YAAA;AAAA,YAEpC;AAAA,cACE,iBAAiBn0B,EAAgB;AAAA,cACjC,gBAAgBA,EAAgB;AAAA,cAChC,mBAAmBA,EAAgB;AAAA,cACnC,kBAAkBA,EAAgB;AAAA,YAAA;AAAA,UACpC;AAAA,QAEJ;AAAA,QACA,kBAAkB,CAAC2sB,GAAoB6H,MAAoB;AACzD,UAAAlhB,EAAgB,eAAeqZ,GAAY6H,CAAO,GAClDxO,GAAA;AAAA,QACF;AAAA,QACA,kBAAkB,CAAC2G,MAAuB;AACxC,UAAArZ,EAAgB,eAAeqZ,CAAU,GACzC3G,GAAA;AAAA,QACF;AAAA,QACA,sBAAAvmB;AAAA,MAAA;AAAA,IAAA;AAAA,IAKH,CAACpG,MAAyB+Q,KAAA,gBAAAA,EAAsB,mBAAkB,WACjE,gBAAAvjB;AAAA,MAAC4tC;AAAA,MAAA;AAAA,QACC,QAAQ3N;AAAA,QACR,SAAS,MAAMC,GAAyB,EAAK;AAAA,QAC7C,cAAc8H;AAAA,QACd,aAAczkB,EAAsC,cAAc;AAAA,MAAA;AAAA,IAAA;AAAA,EACpE,GAEJ;AAEJ;;;;;","x_google_ignoreList":[10]}
|
|
1
|
+
{"version":3,"file":"ContextualToolbars-CG5Gmv_i.js","sources":["../src/vendor/ui/primitives/checkbox.tsx","../src/vendor/ui/primitives/collapsible.tsx","../src/vendor/ui/primitives/popover.tsx","../src/vendor/ui/primitives/select.tsx","../src/vendor/ui/primitives/separator.tsx","../src/vendor/ui/primitives/slider.tsx","../src/vendor/ui/primitives/switch.tsx","../src/components/ui/collapsed-toolbar-header.tsx","../src/components/ui/SliderRow.tsx","../src/components/ui/PresetCarousel.tsx","../../../node_modules/.pnpm/react-colorful@5.7.0_react-dom@19.2.6_react@19.2.6__react@19.2.6/node_modules/react-colorful/dist/index.mjs","../src/components/ColorPickerDropdown.tsx","../src/components/BackButton.tsx","../src/utils/featureApplied.ts","../src/components/ImageToolbar.tsx","../src/presets/artboard-color-presets.ts","../src/components/ShapeToolbar.tsx","../src/components/PathToolbar.tsx","../src/components/BackgroundPickerDropdown.tsx","../src/components/ArtboardDistressPanel.tsx","../src/components/ArtboardImageMaskPanel.tsx","../src/components/ArtboardPropertiesToolbar.tsx","../src/utils/textUtils.ts","../src/components/FontBrowserDrawer.tsx","../src/components/TransformControlPanel.tsx","../src/components/TextEffectsDropdown.tsx","../src/components/MoreMenu.tsx","../src/components/text-toolbar/FontColorButton.tsx","../src/components/text-toolbar/BoldButton.tsx","../src/components/text-toolbar/ItalicButton.tsx","../src/components/text-toolbar/UnderlineButton.tsx","../src/components/text-toolbar/UppercaseButton.tsx","../src/components/text-toolbar/TextAlignButton.tsx","../src/components/text-toolbar/TextMoreMenu.tsx","../src/components/TextToolbar.tsx","../src/core/TransformConverter.ts","../src/hooks/useTextToolbar.ts","../src/hooks/useLayerPreview.ts","../src/components/LayerLeadingChip.tsx","../src/utils/alignDistribute.ts","../src/hooks/useAlignDistribute.ts","../src/components/toolbars/alignButtons.ts","../src/components/MultiSelectionToolbar.tsx","../src/components/toolbars/GroupElementToolbar.tsx","../src/components/CropPanel.tsx","../src/components/toolbars/SecondaryPanels.tsx","../src/components/toolbars/ExpandedPanelIcon.tsx","../src/components/toolbars/shared/SecondaryPanelWrapper.tsx","../src/components/toolbars/shared/ColorPanelWrapper.tsx","../src/components/toolbars/EmbeddedToolbarLayout.tsx","../src/components/toolbars/FloatingPanels.tsx","../src/utils/documentColors.ts","../src/components/ContextualToolbars.tsx"],"sourcesContent":["'use client';\n\nimport * as React from 'react';\nimport * as CheckboxPrimitive from '@radix-ui/react-checkbox';\nimport { Icon } from '@iconify/react';\nimport { cn } from '../lib/utils';\nimport { useSurface } from './surface';\n\ninterface CheckboxProps extends React.ComponentPropsWithoutRef<typeof CheckboxPrimitive.Root> {\n /** Visual variant - auto-detected from Surface context, or can be set explicitly */\n variant?: 'default' | 'filled';\n}\n\nconst Checkbox = React.forwardRef<React.ElementRef<typeof CheckboxPrimitive.Root>, CheckboxProps>(\n ({ className, checked, variant, ...props }, ref) => {\n // Auto-detect variant from Surface context\n const surface = useSurface();\n const effectiveVariant = variant ?? (surface.variant === 'default' ? 'filled' : 'default');\n\n return (\n <CheckboxPrimitive.Root\n ref={ref}\n className={cn(\n 'sc:peer sc:size-4 sc:shrink-0 sc:rounded sc:transition-colors sc:border-none',\n 'sc:focus-visible:outline-none',\n 'sc:disabled:cursor-not-allowed sc:disabled:opacity-50',\n // Variant styles - semantic: field on page vs field on surface\n effectiveVariant === 'default' && 'sc:bg-field sc:shadow-soft sc:dark:shadow-none',\n effectiveVariant === 'filled' && 'sc:bg-[var(--color-field-on-surface)]',\n 'sc:data-[state=checked]:bg-primary sc:data-[state=checked]:text-primary-foreground sc:data-[state=checked]:shadow-none',\n 'sc:data-[state=indeterminate]:bg-primary sc:data-[state=indeterminate]:text-primary-foreground sc:data-[state=indeterminate]:shadow-none',\n className\n )}\n checked={checked}\n {...props}\n >\n <CheckboxPrimitive.Indicator\n className={cn(\n 'sc:flex sc:items-center sc:justify-center sc:text-current',\n 'sc:data-[state=checked]:animate-in sc:data-[state=checked]:zoom-in-0 sc:data-[state=checked]:duration-300',\n 'sc:data-[state=indeterminate]:animate-in sc:data-[state=indeterminate]:zoom-in-0 sc:data-[state=indeterminate]:duration-150'\n )}\n >\n {checked === 'indeterminate' ? (\n <Icon icon=\"gravity-ui:minus\" className=\"sc:size-3\" />\n ) : (\n <Icon icon=\"gravity-ui:check\" className=\"sc:size-3\" />\n )}\n </CheckboxPrimitive.Indicator>\n </CheckboxPrimitive.Root>\n );\n }\n);\nCheckbox.displayName = CheckboxPrimitive.Root.displayName;\n\nexport { Checkbox };\n","'use client';\n\nimport * as React from 'react';\nimport * as CollapsiblePrimitive from '@radix-ui/react-collapsible';\nimport { cn } from '../lib/utils';\n\nconst CollapsibleRoot = React.forwardRef<\n React.ElementRef<typeof CollapsiblePrimitive.Root>,\n React.ComponentPropsWithoutRef<typeof CollapsiblePrimitive.Root>\n>(({ className, ...props }, ref) => (\n <CollapsiblePrimitive.Root\n ref={ref}\n className={cn(className)}\n {...props}\n />\n));\nCollapsibleRoot.displayName = 'Collapsible';\n\nconst CollapsibleTrigger = CollapsiblePrimitive.Trigger;\n\nconst CollapsibleContent = React.forwardRef<\n React.ElementRef<typeof CollapsiblePrimitive.Content>,\n React.ComponentPropsWithoutRef<typeof CollapsiblePrimitive.Content>\n>(({ className, ...props }, ref) => (\n <CollapsiblePrimitive.Content\n ref={ref}\n className={cn(\n 'sc:overflow-hidden sc:data-[state=closed]:animate-collapsible-up sc:data-[state=open]:animate-collapsible-down',\n className\n )}\n {...props}\n />\n));\nCollapsibleContent.displayName = 'CollapsibleContent';\n\nconst Collapsible = CollapsibleRoot;\n\n// Disclosure aliases (alternative naming)\nconst Disclosure = CollapsibleRoot;\nconst DisclosureTrigger = CollapsibleTrigger;\nconst DisclosureContent = CollapsibleContent;\n\nexport {\n Collapsible,\n CollapsibleTrigger,\n CollapsibleContent,\n CollapsibleRoot,\n Disclosure,\n DisclosureTrigger,\n DisclosureContent,\n};\n","'use client';\n\nimport * as React from 'react';\nimport * as PopoverPrimitive from '@radix-ui/react-popover';\nimport { cn } from '../lib/utils';\nimport { SurfaceContext } from './surface';\n\nconst PopoverRoot = PopoverPrimitive.Root;\n\nconst PopoverTrigger = PopoverPrimitive.Trigger;\n\nconst PopoverAnchor = PopoverPrimitive.Anchor;\n\ninterface PopoverContentProps extends React.ComponentPropsWithoutRef<typeof PopoverPrimitive.Content> {\n /** Preserve text selection when popover opens (useful for canvas/editor contexts) */\n preserveSelection?: boolean;\n /** Use maximum z-index to appear above fullscreen modals (for canvas/editor contexts) */\n maxZIndex?: boolean;\n}\n\nconst PopoverContent = React.forwardRef<\n React.ElementRef<typeof PopoverPrimitive.Content>,\n PopoverContentProps\n>(({ className, align = 'center', sideOffset = 4, preserveSelection, maxZIndex, children, style, ...props }, ref) => (\n <PopoverPrimitive.Portal>\n <SurfaceContext.Provider value={{ variant: 'default' }}>\n <PopoverPrimitive.Content\n ref={ref}\n align={align}\n sideOffset={sideOffset}\n data-preserve-selection={preserveSelection ? '' : undefined}\n className={cn(\n 'sc:z-dropdown sc:w-72 sc:overflow-hidden sc:rounded-tooltip sc:border-none sc:bg-popover sc:p-4 sc:text-popover-foreground sc:shadow-soft sc:outline-none',\n 'sc:data-[state=open]:animate-in sc:data-[state=closed]:animate-out',\n 'sc:data-[state=closed]:fade-out-0 sc:data-[state=open]:fade-in-0',\n 'sc:data-[state=closed]:zoom-out-95 sc:data-[state=open]:zoom-in-95',\n 'sc:data-[side=bottom]:slide-in-from-top-2 sc:data-[side=left]:slide-in-from-right-2',\n 'sc:data-[side=right]:slide-in-from-left-2 sc:data-[side=top]:slide-in-from-bottom-2',\n className\n )}\n style={maxZIndex ? { ...style, zIndex: 2147483647 } : style}\n {...props}\n >\n {children}\n </PopoverPrimitive.Content>\n </SurfaceContext.Provider>\n </PopoverPrimitive.Portal>\n));\nPopoverContent.displayName = PopoverPrimitive.Content.displayName;\n\ninterface PopoverProps {\n children: React.ReactNode;\n open?: boolean;\n onOpenChange?: (open: boolean) => void;\n defaultOpen?: boolean;\n modal?: boolean;\n}\n\nconst PopoverBase = ({ children, open, onOpenChange, ...props }: PopoverProps) => (\n <PopoverRoot open={open} onOpenChange={onOpenChange} {...props}>\n {children}\n </PopoverRoot>\n);\n\n// Compound component with subcomponents\nconst Popover = Object.assign(PopoverBase, {\n Trigger: PopoverTrigger,\n Content: PopoverContent,\n Anchor: PopoverAnchor,\n // HeroUI uses Dialog for the content wrapper - map to Content\n Dialog: React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(\n ({ children, className, ...props }, ref) => (\n <div ref={ref} className={className} {...props}>\n {children}\n </div>\n )\n ),\n});\n\nexport { Popover, PopoverTrigger, PopoverContent, PopoverAnchor, PopoverRoot };\n","'use client';\n\nimport * as React from 'react';\nimport * as SelectPrimitive from '@radix-ui/react-select';\nimport { Icon } from '@iconify/react';\nimport { cn } from '../lib/utils';\nimport { useSurface } from './surface';\n\nconst Select = SelectPrimitive.Root;\n\nconst SelectGroup = SelectPrimitive.Group;\n\nconst SelectValue = SelectPrimitive.Value;\n\ninterface SelectTriggerProps extends React.ComponentPropsWithoutRef<typeof SelectPrimitive.Trigger> {\n /** Visual variant - auto-detected from Surface context, or can be set explicitly */\n variant?: 'default' | 'filled';\n}\n\nconst SelectTrigger = React.forwardRef<React.ElementRef<typeof SelectPrimitive.Trigger>, SelectTriggerProps>(\n ({ className, children, variant, ...props }, ref) => {\n // Auto-detect variant from Surface context\n const surface = useSurface();\n const effectiveVariant = variant ?? (surface.variant === 'default' ? 'filled' : 'default');\n\n return (\n <SelectPrimitive.Trigger\n ref={ref}\n className={cn(\n 'sc:flex sc:h-9 sc:w-full sc:items-center sc:justify-between sc:gap-2 sc:rounded-input sc:px-2.5 sc:py-1.5 sc:text-sm sc:transition-colors',\n 'sc:text-foreground sc:border-none',\n 'sc:focus:ring-focus sc:focus:ring-2 sc:focus:outline-none',\n 'sc:disabled:cursor-not-allowed sc:disabled:opacity-50 sc:[&>span]:line-clamp-1',\n // Placeholder styling (Radix adds data-placeholder attribute to trigger)\n 'sc:data-[placeholder]:text-foreground/50',\n // Variant styles - semantic: field on page vs field on surface\n effectiveVariant === 'default' && 'sc:bg-field sc:shadow-soft sc:dark:shadow-none',\n effectiveVariant === 'filled' && 'sc:bg-[var(--color-field-on-surface)]',\n className\n )}\n {...props}\n >\n {children}\n <SelectPrimitive.Icon asChild>\n <Icon\n icon=\"gravity-ui:chevron-down\"\n className=\"sc:text-foreground/40 sc:size-4 sc:transition-transform sc:duration-200 sc:ease-out sc:[[data-state=open]>&]:rotate-180\"\n />\n </SelectPrimitive.Icon>\n </SelectPrimitive.Trigger>\n );\n }\n);\nSelectTrigger.displayName = SelectPrimitive.Trigger.displayName;\n\nconst SelectScrollUpButton = React.forwardRef<\n React.ElementRef<typeof SelectPrimitive.ScrollUpButton>,\n React.ComponentPropsWithoutRef<typeof SelectPrimitive.ScrollUpButton>\n>(({ className, ...props }, ref) => (\n <SelectPrimitive.ScrollUpButton\n ref={ref}\n className={cn('sc:flex sc:cursor-default sc:items-center sc:justify-center sc:py-1', className)}\n {...props}\n >\n <Icon icon=\"gravity-ui:chevron-up\" className=\"sc:size-4\" />\n </SelectPrimitive.ScrollUpButton>\n));\nSelectScrollUpButton.displayName = SelectPrimitive.ScrollUpButton.displayName;\n\nconst SelectScrollDownButton = React.forwardRef<\n React.ElementRef<typeof SelectPrimitive.ScrollDownButton>,\n React.ComponentPropsWithoutRef<typeof SelectPrimitive.ScrollDownButton>\n>(({ className, ...props }, ref) => (\n <SelectPrimitive.ScrollDownButton\n ref={ref}\n className={cn('sc:flex sc:cursor-default sc:items-center sc:justify-center sc:py-1', className)}\n {...props}\n >\n <Icon icon=\"gravity-ui:chevron-down\" className=\"sc:size-4\" />\n </SelectPrimitive.ScrollDownButton>\n));\nSelectScrollDownButton.displayName = SelectPrimitive.ScrollDownButton.displayName;\n\nconst SelectContent = React.forwardRef<\n React.ElementRef<typeof SelectPrimitive.Content>,\n React.ComponentPropsWithoutRef<typeof SelectPrimitive.Content>\n>(({ className, children, position = 'popper', ...props }, ref) => (\n <SelectPrimitive.Portal>\n <SelectPrimitive.Content\n ref={ref}\n className={cn(\n 'sc:z-dropdown sc:bg-popover sc:text-popover-foreground sc:shadow-soft sc:relative sc:min-w-[8rem] sc:overflow-hidden sc:rounded-tooltip sc:border-none sc:p-1',\n 'sc:data-[state=open]:animate-in sc:data-[state=closed]:animate-out sc:data-[state=closed]:fade-out-0 sc:data-[state=open]:fade-in-0',\n 'sc:data-[state=closed]:zoom-out-95 sc:data-[state=open]:zoom-in-95',\n 'sc:data-[side=bottom]:slide-in-from-top-2 sc:data-[side=left]:slide-in-from-right-2',\n 'sc:data-[side=right]:slide-in-from-left-2 sc:data-[side=top]:slide-in-from-bottom-2',\n position === 'popper' &&\n 'sc:data-[side=bottom]:translate-y-1 sc:data-[side=left]:-translate-x-1 sc:data-[side=right]:translate-x-1 sc:data-[side=top]:-translate-y-1',\n className\n )}\n position={position}\n {...props}\n >\n <SelectScrollUpButton />\n <SelectPrimitive.Viewport\n className={cn(position === 'popper' && 'sc:w-full sc:min-w-[var(--radix-select-trigger-width)]')}\n >\n {children}\n </SelectPrimitive.Viewport>\n <SelectScrollDownButton />\n </SelectPrimitive.Content>\n </SelectPrimitive.Portal>\n));\nSelectContent.displayName = SelectPrimitive.Content.displayName;\n\nconst SelectLabel = React.forwardRef<\n React.ElementRef<typeof SelectPrimitive.Label>,\n React.ComponentPropsWithoutRef<typeof SelectPrimitive.Label>\n>(({ className, ...props }, ref) => (\n <SelectPrimitive.Label\n ref={ref}\n className={cn('sc:text-muted-foreground sc:px-2 sc:py-1.5 sc:text-xs sc:font-label', className)}\n {...props}\n />\n));\nSelectLabel.displayName = SelectPrimitive.Label.displayName;\n\nconst SelectItem = React.forwardRef<\n React.ElementRef<typeof SelectPrimitive.Item>,\n React.ComponentPropsWithoutRef<typeof SelectPrimitive.Item>\n>(({ className, children, ...props }, ref) => (\n <SelectPrimitive.Item\n ref={ref}\n className={cn(\n 'sc:relative sc:flex sc:w-full sc:cursor-default sc:items-center sc:rounded-full sc:py-1 sc:pr-8 sc:pl-2 sc:text-sm sc:text-foreground sc:outline-none sc:select-none sc:font-body',\n 'sc:hover:bg-default/50 sc:focus:bg-default/50 sc:dark:hover:bg-white/5 sc:dark:focus:bg-white/5 sc:data-[disabled]:pointer-events-none sc:data-[disabled]:opacity-50',\n className\n )}\n {...props}\n >\n <span className=\"sc:absolute sc:right-2 sc:flex sc:h-3.5 sc:w-3.5 sc:items-center sc:justify-center\">\n <SelectPrimitive.ItemIndicator>\n <Icon icon=\"gravity-ui:check\" className=\"sc:size-4\" />\n </SelectPrimitive.ItemIndicator>\n </span>\n <SelectPrimitive.ItemText>{children}</SelectPrimitive.ItemText>\n </SelectPrimitive.Item>\n));\nSelectItem.displayName = SelectPrimitive.Item.displayName;\n\nconst SelectSeparator = React.forwardRef<\n React.ElementRef<typeof SelectPrimitive.Separator>,\n React.ComponentPropsWithoutRef<typeof SelectPrimitive.Separator>\n>(({ className, ...props }, ref) => (\n <SelectPrimitive.Separator ref={ref} className={cn('sc:bg-divider sc:mx-2 sc:my-1 sc:h-px', className)} {...props} />\n));\nSelectSeparator.displayName = SelectPrimitive.Separator.displayName;\n\nexport {\n Select,\n SelectGroup,\n SelectValue,\n SelectTrigger,\n SelectContent,\n SelectLabel,\n SelectItem,\n SelectSeparator,\n SelectScrollUpButton,\n SelectScrollDownButton,\n};\n","'use client';\n\nimport * as React from 'react';\nimport * as SeparatorPrimitive from '@radix-ui/react-separator';\nimport { cn } from '../lib/utils';\n\nconst Separator = React.forwardRef<\n React.ElementRef<typeof SeparatorPrimitive.Root>,\n React.ComponentPropsWithoutRef<typeof SeparatorPrimitive.Root>\n>(({ className, orientation = 'horizontal', decorative = true, ...props }, ref) => (\n <SeparatorPrimitive.Root\n ref={ref}\n decorative={decorative}\n orientation={orientation}\n className={cn(\n 'sc:shrink-0 sc:bg-divider',\n orientation === 'horizontal' ? 'sc:h-[1px] sc:w-full' : 'sc:h-full sc:w-[1px]',\n className\n )}\n {...props}\n />\n));\nSeparator.displayName = SeparatorPrimitive.Root.displayName;\n\nexport { Separator };\n","\"use client\";\n\n'use client';\n\nimport * as React from 'react';\nimport * as SliderPrimitive from '@radix-ui/react-slider';\nimport { cn } from '../lib/utils';\n\ninterface SliderProps\n extends Omit<\n React.ComponentPropsWithoutRef<typeof SliderPrimitive.Root>,\n 'value' | 'onValueChange'\n > {\n // Accepts both array and single number for convenience\n value?: number | number[];\n onValueChange?: (value: number[]) => void;\n onChangeEnd?: (value: number[]) => void;\n children?: React.ReactNode;\n}\n\n// Context for passing slider state to compound components\ninterface SliderContextValue {\n values: number[];\n min: number;\n max: number;\n}\nconst SliderContext = React.createContext<SliderContextValue | null>(null);\n\n// HeroUI-compatible compound components\nconst SliderTrack = React.forwardRef<HTMLSpanElement, React.HTMLAttributes<HTMLSpanElement>>(\n ({ className, children, ...props }, ref) => (\n <SliderPrimitive.Track\n ref={ref}\n className={cn('sc:relative sc:h-2 sc:w-full sc:grow sc:overflow-hidden sc:rounded-full sc:bg-muted', className)}\n {...props}\n >\n {children}\n </SliderPrimitive.Track>\n )\n);\nSliderTrack.displayName = 'SliderTrack';\n\nconst SliderThumb = React.forwardRef<HTMLSpanElement, React.HTMLAttributes<HTMLSpanElement>>(\n ({ className, ...props }, ref) => (\n <SliderPrimitive.Thumb\n ref={ref}\n // Base thumb size: h-6 w-6 (24px), touch devices can override via CSS to 32-36px\n className={cn(\n 'sc:relative sc:block sc:h-6 sc:w-6 sc:rounded-full sc:border-2 sc:border-primary sc:bg-background sc:ring-offset-background sc:transition-colors sc:focus-visible:outline-none sc:focus-visible:ring-2 sc:focus-visible:ring-focus sc:focus-visible:ring-offset-2 sc:disabled:pointer-events-none sc:disabled:opacity-50',\n className\n )}\n {...props}\n />\n )\n);\nSliderThumb.displayName = 'SliderThumb';\n\n// HeroUI Fill component - displays the filled range portion\nconst SliderFill = React.forwardRef<HTMLSpanElement, React.HTMLAttributes<HTMLSpanElement>>(\n ({ className, ...props }, ref) => (\n <SliderPrimitive.Range ref={ref} className={cn('sc:absolute sc:h-full sc:bg-primary', className)} {...props} />\n )\n);\nSliderFill.displayName = 'SliderFill';\n\n// HeroUI Output component - renders current value(s)\ninterface SliderOutputProps extends Omit<React.HTMLAttributes<HTMLSpanElement>, 'children'> {\n children?: React.ReactNode | ((props: { state: { values: number[] } }) => React.ReactNode);\n}\n\nconst SliderOutput = React.forwardRef<HTMLSpanElement, SliderOutputProps>(\n ({ className, children, ...props }, ref) => {\n const context = React.useContext(SliderContext);\n const values = context?.values ?? [0];\n\n return (\n <span ref={ref} className={cn('sc:text-sm sc:text-foreground/60', className)} {...props}>\n {typeof children === 'function'\n ? children({ state: { values } })\n : children ?? values.join(' - ')}\n </span>\n );\n }\n);\nSliderOutput.displayName = 'SliderOutput';\n\nconst SliderBase = React.forwardRef<React.ElementRef<typeof SliderPrimitive.Root>, SliderProps>(\n (\n {\n className,\n value,\n onValueChange,\n onChangeEnd,\n min = 0,\n max = 100,\n step = 1,\n children,\n ...props\n },\n ref\n ) => {\n // Normalize value to array (accepts both single number and array for convenience)\n const normalizedValue = value !== undefined ? (Array.isArray(value) ? value : [value]) : undefined;\n\n // Track internal value for context\n const [internalValue, setInternalValue] = React.useState(normalizedValue ?? [min]);\n\n // Track if we're currently dragging (for iOS body scroll prevention)\n const isDraggingRef = React.useRef(false);\n const touchMoveHandlerRef = React.useRef<((e: TouchEvent) => void) | null>(null);\n\n // Prevent scroll during drag - added to document on pointer down, removed on pointer up\n const preventScroll = React.useCallback((e: TouchEvent) => {\n if (isDraggingRef.current) {\n e.preventDefault();\n }\n }, []);\n\n const handleChange = (newValue: number[]) => {\n // Mark as actively dragging once value changes\n isDraggingRef.current = true;\n setInternalValue(newValue);\n onValueChange?.(newValue);\n };\n\n const handleChangeEnd = (newValue: number[]) => {\n isDraggingRef.current = false;\n onChangeEnd?.(newValue);\n };\n\n // Handle pointer down - add document-level touchmove prevention\n const handlePointerDown = React.useCallback(() => {\n // Add touchmove listener to document to intercept scroll during drag\n if (!touchMoveHandlerRef.current) {\n touchMoveHandlerRef.current = preventScroll;\n document.addEventListener('touchmove', preventScroll, { passive: false });\n }\n }, [preventScroll]);\n\n // Handle pointer up/cancel - remove document listener\n const handlePointerUp = React.useCallback(() => {\n isDraggingRef.current = false;\n if (touchMoveHandlerRef.current) {\n document.removeEventListener('touchmove', touchMoveHandlerRef.current);\n touchMoveHandlerRef.current = null;\n }\n }, []);\n\n // Cleanup on unmount\n React.useEffect(() => {\n return () => {\n if (touchMoveHandlerRef.current) {\n document.removeEventListener('touchmove', touchMoveHandlerRef.current);\n }\n };\n }, []);\n\n // Check if children are provided (compound pattern)\n const hasChildren = React.Children.count(children) > 0;\n\n // Determine number of thumbs based on value array length or defaultValue\n const thumbCount = normalizedValue?.length ?? props.defaultValue?.length ?? 1;\n\n // Context value for compound components\n const contextValue = React.useMemo(\n () => ({\n values: normalizedValue ?? internalValue,\n min,\n max,\n }),\n [normalizedValue, internalValue, min, max]\n );\n\n return (\n <SliderContext.Provider value={contextValue}>\n <SliderPrimitive.Root\n ref={ref}\n className={cn('sc:relative sc:flex sc:w-full sc:touch-none sc:select-none sc:items-center', className)}\n value={normalizedValue}\n onValueChange={handleChange}\n onValueCommit={handleChangeEnd}\n onPointerDown={handlePointerDown}\n onPointerUp={handlePointerUp}\n onPointerCancel={handlePointerUp}\n onLostPointerCapture={handlePointerUp}\n min={min}\n max={max}\n step={step}\n {...props}\n >\n {hasChildren ? (\n children\n ) : (\n <>\n <SliderPrimitive.Track className=\"sc:relative sc:h-2 sc:w-full sc:grow sc:overflow-hidden sc:rounded-full sc:bg-muted\">\n <SliderPrimitive.Range className=\"sc:absolute sc:h-full sc:bg-primary\" />\n </SliderPrimitive.Track>\n {Array.from({ length: thumbCount }).map((_, index) => (\n <SliderPrimitive.Thumb\n key={index}\n className=\"sc:relative sc:block sc:h-6 sc:w-6 sc:rounded-full sc:border-2 sc:border-primary sc:bg-background sc:ring-offset-background sc:transition-colors sc:focus-visible:outline-none sc:focus-visible:ring-2 sc:focus-visible:ring-focus sc:focus-visible:ring-offset-2 sc:disabled:pointer-events-none sc:disabled:opacity-50\"\n />\n ))}\n </>\n )}\n </SliderPrimitive.Root>\n </SliderContext.Provider>\n );\n }\n);\nSliderBase.displayName = SliderPrimitive.Root.displayName;\n\n// Compound component with sub-components\nconst Slider = Object.assign(SliderBase, {\n Track: SliderTrack,\n Thumb: SliderThumb,\n Fill: SliderFill,\n Output: SliderOutput,\n});\n\nexport { Slider, SliderTrack, SliderThumb, SliderFill, SliderOutput };\n","'use client';\n\nimport * as React from 'react';\nimport * as SwitchPrimitive from '@radix-ui/react-switch';\nimport { cn } from '../lib/utils';\n\nconst Switch = React.forwardRef<\n React.ElementRef<typeof SwitchPrimitive.Root>,\n React.ComponentPropsWithoutRef<typeof SwitchPrimitive.Root>\n>(({ className, ...props }, ref) => {\n return (\n <SwitchPrimitive.Root\n className={cn(\n 'sc:peer sc:inline-flex sc:h-7 sc:w-12 sc:md:h-5 sc:md:w-9 sc:shrink-0 sc:cursor-pointer sc:items-center sc:rounded-full sc:border-2 sc:border-transparent sc:shadow-sm sc:transition-colors',\n 'sc:focus-visible:outline-none sc:focus-visible:ring-2 sc:focus-visible:ring-focus sc:focus-visible:ring-offset-2 sc:focus-visible:ring-offset-background',\n 'sc:disabled:cursor-not-allowed sc:disabled:opacity-50',\n 'sc:data-[state=checked]:bg-primary sc:data-[state=unchecked]:bg-muted',\n className\n )}\n {...props}\n ref={ref}\n >\n <SwitchPrimitive.Thumb\n className={cn(\n 'sc:pointer-events-none sc:block sc:h-6 sc:w-6 sc:md:h-4 sc:md:w-4 sc:rounded-full sc:bg-background sc:shadow-lg sc:ring-0 sc:transition-transform',\n 'sc:data-[state=checked]:translate-x-5 sc:md:data-[state=checked]:translate-x-4 sc:data-[state=unchecked]:translate-x-0'\n )}\n />\n </SwitchPrimitive.Root>\n );\n }\n);\nSwitch.displayName = SwitchPrimitive.Root.displayName;\n\nexport { Switch };\n","/**\n * CollapsedToolbarHeader - Header shown when a toolbar panel is expanded\n *\n * Displays:\n * - Icon on the left (same as the button that opened the panel)\n * - Label text\n * - Close button on the far right\n *\n * Used for corner radius, effects, and other expandable panels.\n *\n * @example\n * <CollapsedToolbarHeader\n * icon=\"lucide:square-round-corner\"\n * label=\"Corner Radius\"\n * onClose={() => setIsOpen(false)}\n * />\n */\n\nimport React, { useRef, useEffect } from 'react';\nimport { Icon } from '@iconify/react';\nimport { cn } from '../../lib/utils';\nimport { icons } from './icons';\n\nexport interface CollapsedToolbarHeaderProps {\n /** Iconify icon string (e.g., \"lucide:square-round-corner\") or custom React node */\n icon: string | React.ReactNode;\n /** Label text to display */\n label: string;\n /** Callback when close button is clicked */\n onClose: () => void;\n /** Additional CSS classes */\n className?: string;\n /** Close button style: 'icon' shows X, 'done' shows Done button */\n closeButtonStyle?: 'icon' | 'done';\n}\n\nexport const CollapsedToolbarHeader: React.FC<CollapsedToolbarHeaderProps> = ({\n icon,\n label,\n onClose,\n className,\n closeButtonStyle = 'icon',\n}) => {\n // Block horizontal touch movement to prevent drawer/page from being dragged\n const containerRef = useRef<HTMLDivElement>(null);\n const touchStartPos = useRef({ x: 0, y: 0 });\n useEffect(() => {\n const el = containerRef.current;\n if (!el) return;\n\n const handleTouchStart = (e: TouchEvent) => {\n touchStartPos.current = {\n x: e.touches[0].clientX,\n y: e.touches[0].clientY,\n };\n };\n\n const handleTouchMove = (e: TouchEvent) => {\n const deltaX = Math.abs(e.touches[0].clientX - touchStartPos.current.x);\n const deltaY = Math.abs(e.touches[0].clientY - touchStartPos.current.y);\n\n // If horizontal movement is greater than vertical, prevent it\n if (deltaX > 10 && deltaX > deltaY) {\n e.preventDefault();\n }\n };\n\n el.addEventListener('touchstart', handleTouchStart, { passive: true });\n el.addEventListener('touchmove', handleTouchMove, { passive: false });\n\n return () => {\n el.removeEventListener('touchstart', handleTouchStart);\n el.removeEventListener('touchmove', handleTouchMove);\n };\n }, []);\n\n return (\n <div\n ref={containerRef}\n className={cn('sc:flex sc:w-full sc:items-center sc:justify-between', className)}\n style={{ touchAction: 'pan-y' }}\n >\n {/* Left side: Icon + Label */}\n <div className=\"sc:flex sc:items-center sc:gap-3 sc:md:gap-2\">\n {typeof icon === 'string' ? (\n <Icon icon={icon} className=\"sc:text-primary sc:size-7 sc:md:size-5\" />\n ) : (\n icon\n )}\n <span className=\"sc:text-foreground sc:text-lg sc:font-semibold sc:md:text-sm sc:md:font-medium\">{label}</span>\n </div>\n\n {/* Right side: Close button */}\n {closeButtonStyle === 'done' ? (\n <button\n onClick={onClose}\n className=\"sc:bg-primary sc:text-primary-foreground sc:rounded-xl sc:hover:bg-primary/90 sc:shadow-sm sc:px-8 sc:py-3.5 sc:text-xl sc:font-bold sc:transition-colors sc:md:rounded-button sc:md:shadow-none sc:md:px-4 sc:md:py-2 sc:md:text-sm sc:md:font-medium\"\n aria-label=\"Done\"\n >\n Done\n </button>\n ) : (\n <button\n onClick={onClose}\n className=\"sc:hover:bg-muted sc:text-foreground/70 sc:hover:text-foreground sc:flex sc:size-11 sc:items-center sc:justify-center sc:rounded-md sc:transition-colors sc:md:size-7\"\n aria-label=\"Close panel\"\n >\n <Icon icon={icons.close} className=\"sc:size-7 sc:md:size-4\" />\n </button>\n )}\n </div>\n );\n};\n\nCollapsedToolbarHeader.displayName = 'CollapsedToolbarHeader';\n","/**\n * SliderRow - Reusable slider component with label, optional input, and touch guard\n *\n * Used in secondary panels (corner radius, rotation, etc.) for consistent styling\n * and proper touch handling on mobile devices.\n *\n * @example\n * <SliderRow\n * label=\"Radius\"\n * value={50}\n * onChange={setValue}\n * min={0}\n * max={100}\n * unit=\"%\"\n * />\n */\n\nimport React, { useRef, useEffect } from 'react';\nimport { Slider } from '../../vendor/ui';\nimport { cn } from '../../lib/utils';\n\n/**\n * TouchGuard - Wraps interactive elements to prevent parent scroll from capturing touches\n *\n * Uses native event listeners with { passive: false } because:\n * 1. React's synthetic events can't properly preventDefault on touch events\n * 2. CSS touch-action: none is evaluated at gesture start on the ancestor chain,\n * so a parent with pan-y can still capture the gesture before child CSS applies\n * 3. Native listeners with passive: false intercept events before the browser decides to scroll\n */\nfunction TouchGuard({ children, className }: { children: React.ReactNode; className?: string }) {\n const ref = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n const el = ref.current;\n if (!el) return;\n\n const handleTouchStart = (e: TouchEvent) => {\n // Stop the event from reaching parent scroll containers\n e.stopPropagation();\n };\n\n const handleTouchMove = (e: TouchEvent) => {\n // Prevent default scroll behavior and stop propagation\n e.preventDefault();\n e.stopPropagation();\n };\n\n // Must use passive: false to allow preventDefault\n el.addEventListener('touchstart', handleTouchStart, { passive: false });\n el.addEventListener('touchmove', handleTouchMove, { passive: false });\n\n return () => {\n el.removeEventListener('touchstart', handleTouchStart);\n el.removeEventListener('touchmove', handleTouchMove);\n };\n }, []);\n\n return (\n <div ref={ref} className={className} style={{ touchAction: 'none' }}>\n {children}\n </div>\n );\n}\n\nexport interface SliderRowProps {\n /** Label displayed to the left of the slider */\n label: string;\n /** Current value */\n value: number;\n /** Callback when value changes */\n onChange: (value: number) => void;\n /**\n * Callback when a drag/keyboard interaction COMMITS (pointer released /\n * key released). Lets callers coalesce the per-tick onChange stream into\n * one undo step per gesture.\n */\n onChangeEnd?: (value: number) => void;\n /** Minimum value */\n min: number;\n /** Maximum value */\n max: number;\n /** Step increment (default: 1) */\n step?: number;\n /** Unit to display after value (e.g., \"%\", \"°\", \"px\") */\n unit?: string;\n /** Show number input field (default: false) */\n showInput?: boolean;\n /** Width of the number input (default: '56px') */\n inputWidth?: string;\n /** Additional class name for the container */\n className?: string;\n /** Layout variant: 'inline' (default) or 'stacked' */\n variant?: 'inline' | 'stacked';\n}\n\n/**\n * SliderRow - A labeled slider with optional input and value display\n */\nexport const SliderRow: React.FC<SliderRowProps> = ({\n label,\n value,\n onChange,\n onChangeEnd,\n min,\n max,\n step = 1,\n unit = '',\n showInput = false,\n inputWidth = '56px',\n className,\n variant = 'inline',\n}) => {\n const displayValue = Math.round(value);\n\n if (variant === 'stacked') {\n // Stacked layout: label/input on top, slider below\n return (\n <div className={cn('sc:flex sc:flex-col sc:gap-2.5 sc:md:gap-1.5', className)}>\n <div className=\"sc:flex sc:items-center sc:justify-between\">\n <span className=\"sc:text-foreground/60 sc:text-base sc:md:text-xs\">{label}</span>\n {showInput && (\n <input\n type=\"number\"\n value={displayValue}\n onChange={(e) => onChange(Math.max(min, Math.min(max, Number(e.target.value))))}\n min={min}\n max={max}\n aria-label={`${label} value`}\n className=\"sc:bg-transparent sc:text-foreground sc:w-14 sc:rounded-md sc:border-none sc:px-2.5 sc:py-2 sc:text-right sc:text-base sc:md:w-14 sc:md:rounded sc:md:px-1.5 sc:md:py-1 sc:md:text-[13px]\"\n style={{ width: inputWidth }}\n />\n )}\n </div>\n <TouchGuard>\n <Slider\n value={[value]}\n onValueChange={(val) => onChange(val[0])}\n onChangeEnd={onChangeEnd ? (val: number[]) => onChangeEnd(val[0]) : undefined}\n min={min}\n max={max}\n step={step}\n >\n <Slider.Track className=\"sc:bg-foreground/10 sc:h-2.5 sc:md:h-2\">\n <Slider.Fill className=\"sc:bg-primary\" />\n </Slider.Track>\n <Slider.Thumb className=\"sc:size-7 sc:md:size-6\" />\n </Slider>\n </TouchGuard>\n </div>\n );\n }\n\n // Inline layout: label, slider, value all in one row\n return (\n <div className={cn('sc:flex sc:items-center sc:gap-3', className)}>\n <span className=\"sc:text-foreground/70 sc:text-base sc:md:text-[13px] sc:whitespace-nowrap\">{label}</span>\n {showInput ? (\n <input\n type=\"number\"\n value={displayValue}\n onChange={(e) => onChange(Math.max(min, Math.min(max, Number(e.target.value))))}\n min={min}\n max={max}\n aria-label={`${label} value`}\n className=\"sc:bg-transparent sc:text-foreground sc:rounded-md sc:border-none sc:px-2 sc:py-2 sc:text-right sc:text-base sc:md:py-1.5 sc:md:text-[13px]\"\n style={{ width: inputWidth }}\n />\n ) : null}\n <TouchGuard className=\"sc:flex-1\">\n <Slider\n value={[value]}\n onValueChange={(val) => onChange(val[0])}\n onChangeEnd={onChangeEnd ? (val: number[]) => onChangeEnd(val[0]) : undefined}\n min={min}\n max={max}\n step={step}\n >\n <Slider.Track className=\"sc:bg-foreground/10 sc:h-2.5 sc:md:h-2\">\n <Slider.Fill className=\"sc:bg-primary\" />\n </Slider.Track>\n <Slider.Thumb className=\"sc:size-7 sc:md:size-6\" />\n </Slider>\n </TouchGuard>\n <span className=\"sc:text-foreground sc:text-base sc:md:text-[13px] sc:min-w-[44px] sc:md:min-w-[32px] sc:text-right\">\n {displayValue}{unit}\n </span>\n </div>\n );\n};\n\nexport default SliderRow;\n","/**\n * PresetCarousel - Reusable horizontal scrolling preset thumbnail carousel\n *\n * Features:\n * - Visual selection indicator (primary accent border + ring)\n * - Keyboard navigation (left/right arrow keys)\n * - Accessible focus management with roving tabindex\n * - Optional \"Off\" button as first item\n */\n\nimport React, { useRef, useCallback } from 'react';\n\nexport interface PresetItem {\n id: string;\n name: string;\n thumbnailUrl?: string;\n}\n\nexport interface PresetCarouselProps {\n /** Array of preset items to display */\n presets: PresetItem[];\n /** Currently selected preset ID, or empty string for \"Off\" */\n selectedId: string;\n /** Called when a preset is selected. Empty string means \"Off\". */\n onSelect: (id: string) => void;\n /** Show an \"Off\" button as the first item. Default: true */\n showOff?: boolean;\n /** Thumbnail size in pixels. Default: 40 */\n size?: number;\n /** Accessible label for the carousel */\n ariaLabel?: string;\n}\n\nconst SELECTED_CLASSES = 'sc:border-2 sc:border-primary sc:overflow-hidden';\nconst UNSELECTED_CLASSES = 'sc:border-2 sc:border-border-primary sc:hover:border-border-focus sc:overflow-hidden';\n\nexport const PresetCarousel: React.FC<PresetCarouselProps> = ({\n presets,\n selectedId,\n onSelect,\n showOff = true,\n size = 40,\n ariaLabel = 'Preset options',\n}) => {\n const containerRef = useRef<HTMLDivElement>(null);\n\n const scrollToItem = useCallback((button: HTMLButtonElement) => {\n button.scrollIntoView({ behavior: 'smooth', block: 'nearest', inline: 'nearest' });\n }, []);\n\n const handleKeyDown = useCallback(\n (e: React.KeyboardEvent<HTMLDivElement>) => {\n if (e.key !== 'ArrowLeft' && e.key !== 'ArrowRight') return;\n e.preventDefault();\n e.stopPropagation();\n\n const container = containerRef.current;\n if (!container) return;\n\n const buttons = Array.from(container.querySelectorAll<HTMLButtonElement>('button[data-preset-id]'));\n const focused = document.activeElement as HTMLButtonElement;\n let currentIndex = buttons.indexOf(focused);\n\n // If no button is focused, start from selected or first\n if (currentIndex === -1) {\n currentIndex = buttons.findIndex((btn) => btn.getAttribute('aria-selected') === 'true');\n if (currentIndex === -1) currentIndex = 0;\n }\n\n let nextIndex: number;\n if (e.key === 'ArrowRight') {\n nextIndex = currentIndex < buttons.length - 1 ? currentIndex + 1 : 0;\n } else {\n nextIndex = currentIndex > 0 ? currentIndex - 1 : buttons.length - 1;\n }\n\n const nextButton = buttons[nextIndex];\n nextButton.focus();\n scrollToItem(nextButton);\n\n // Also select the item on arrow navigation\n const presetId = nextButton.getAttribute('data-preset-id');\n if (presetId !== null) {\n onSelect(presetId);\n }\n },\n [scrollToItem, onSelect]\n );\n\n const isOffSelected = showOff && !selectedId;\n // Determine which item gets tabIndex 0 for initial Tab entry\n const hasSelection = showOff ? true : presets.some((p) => p.id === selectedId);\n\n return (\n <div\n ref={containerRef}\n className=\"sc:flex sc:gap-1.5 sc:overflow-x-auto sc:p-1 sc:-m-1\"\n style={{ flexWrap: 'nowrap' }}\n role=\"listbox\"\n aria-label={ariaLabel}\n onKeyDown={handleKeyDown}\n >\n {showOff && (\n <button\n data-preset-id=\"\"\n role=\"option\"\n aria-selected={isOffSelected}\n tabIndex={isOffSelected || (!hasSelection) ? 0 : -1}\n onClick={() => onSelect('')}\n className={`sc:shrink-0 sc:rounded-md sc:transition-all sc:flex sc:items-center sc:justify-center ${\n isOffSelected ? SELECTED_CLASSES : UNSELECTED_CLASSES\n }`}\n style={{ width: size, height: size }}\n title=\"None\"\n >\n <span className=\"sc:text-xs sc:text-muted-foreground\">Off</span>\n </button>\n )}\n {presets.map((preset, index) => {\n const isSelected = selectedId === preset.id;\n // First item gets tabIndex 0 if nothing else is selected (and no Off button)\n const isTabbable = isSelected || (!showOff && !hasSelection && index === 0);\n return (\n <button\n key={preset.id}\n data-preset-id={preset.id}\n role=\"option\"\n aria-selected={isSelected}\n tabIndex={isTabbable ? 0 : -1}\n onClick={() => onSelect(preset.id)}\n className={`sc:shrink-0 sc:rounded-md sc:transition-all ${\n isSelected ? SELECTED_CLASSES : UNSELECTED_CLASSES\n }`}\n style={{ width: size, height: size }}\n title={preset.name}\n >\n {preset.thumbnailUrl && (\n <img\n src={preset.thumbnailUrl}\n alt={preset.name}\n className=\"sc:w-full sc:h-full sc:object-cover\"\n loading=\"lazy\"\n />\n )}\n </button>\n );\n })}\n </div>\n );\n};\n","import e,{useRef as r,useMemo as n,useEffect as t,useState as o,useCallback as a,useLayoutEffect as l}from\"react\";function u(){return(u=Object.assign||function(e){for(var r=1;r<arguments.length;r++){var n=arguments[r];for(var t in n)Object.prototype.hasOwnProperty.call(n,t)&&(e[t]=n[t])}return e}).apply(this,arguments)}function c(e,r){if(null==e)return{};var n,t,o={},a=Object.keys(e);for(t=0;t<a.length;t++)r.indexOf(n=a[t])>=0||(o[n]=e[n]);return o}function i(e){var n=r(e),t=r(function(e){n.current&&n.current(e)});return n.current=e,t.current}var s=function(e,r,n){return void 0===r&&(r=0),void 0===n&&(n=1),e>n?n:e<r?r:e},f=function(e){return\"touches\"in e},v=function(e){return e&&e.ownerDocument.defaultView||self},d=function(e,r,n){var t=e.getBoundingClientRect(),o=f(r)?function(e,r){for(var n=0;n<e.length;n++)if(e[n].identifier===r)return e[n];return e[0]}(r.touches,n):r;return{left:s((o.pageX-(t.left+v(e).pageXOffset))/t.width),top:s((o.pageY-(t.top+v(e).pageYOffset))/t.height)}},h=function(e){!f(e)&&e.preventDefault()},g=e.memo(function(o){var a=o.onMove,l=o.onKey,s=o.onEnd,g=c(o,[\"onMove\",\"onKey\",\"onEnd\"]),m=r(null),p=i(a),b=i(l),_=i(s),E=r(null),C=r(!1),x=n(function(){var e=function(e){h(e),(f(e)?e.touches.length>0:e.buttons>0)&&m.current?p(d(m.current,e,E.current)):(n(!1),_())},r=function(){n(!1),_()};function n(n){var t=C.current,o=v(m.current),a=n?o.addEventListener:o.removeEventListener;a(t?\"touchmove\":\"mousemove\",e),a(t?\"touchend\":\"mouseup\",r)}return[function(e){var r=e.nativeEvent,t=m.current;if(t&&(h(r),!function(e,r){return r&&!f(e)}(r,C.current)&&t)){if(f(r)){C.current=!0;var o=r.changedTouches||[];o.length&&(E.current=o[0].identifier)}t.focus(),p(d(t,r,E.current)),n(!0)}},function(e){var r=e.which||e.keyCode;r<37||r>40||(e.preventDefault(),b({left:39===r?.05:37===r?-.05:0,top:40===r?.05:38===r?-.05:0}))},function(e){var r=e.which||e.keyCode;r>=37&&r<=40&&_()},n]},[b,p,_]),H=x[0],M=x[1],N=x[2],w=x[3];return t(function(){return w},[w]),e.createElement(\"div\",u({},g,{onTouchStart:H,onMouseDown:H,className:\"react-colorful__interactive\",ref:m,onKeyDown:M,onKeyUp:N,tabIndex:0,role:\"slider\"}))}),m=function(e){return e.filter(Boolean).join(\" \")},p=function(r){var n=r.color,t=r.left,o=r.top,a=void 0===o?.5:o,l=m([\"react-colorful__pointer\",r.className]);return e.createElement(\"div\",{className:l,style:{top:100*a+\"%\",left:100*t+\"%\"}},e.createElement(\"div\",{className:\"react-colorful__pointer-fill\",style:{backgroundColor:n}}))},b=function(e,r,n){return void 0===r&&(r=0),void 0===n&&(n=Math.pow(10,r)),Math.round(n*e)/n},_={grad:.9,turn:360,rad:360/(2*Math.PI)},E=function(e){return L(C(e))},C=function(e){return\"#\"===e[0]&&(e=e.substring(1)),e.length<6?{r:parseInt(e[0]+e[0],16),g:parseInt(e[1]+e[1],16),b:parseInt(e[2]+e[2],16),a:4===e.length?b(parseInt(e[3]+e[3],16)/255,2):1}:{r:parseInt(e.substring(0,2),16),g:parseInt(e.substring(2,4),16),b:parseInt(e.substring(4,6),16),a:8===e.length?b(parseInt(e.substring(6,8),16)/255,2):1}},x=function(e,r){return void 0===r&&(r=\"deg\"),Number(e)*(_[r]||1)},H=function(e){var r=/hsla?\\(?\\s*(-?\\d*\\.?\\d+)(deg|rad|grad|turn)?[,\\s]+(-?\\d*\\.?\\d+)%?[,\\s]+(-?\\d*\\.?\\d+)%?,?\\s*[/\\s]*(-?\\d*\\.?\\d+)?(%)?\\s*\\)?/i.exec(e);return r?N({h:x(r[1],r[2]),s:Number(r[3]),l:Number(r[4]),a:void 0===r[5]?1:Number(r[5])/(r[6]?100:1)}):{h:0,s:0,v:0,a:1}},M=H,N=function(e){var r=e.s,n=e.l;return{h:e.h,s:(r*=(n<50?n:100-n)/100)>0?2*r/(n+r)*100:0,v:n+r,a:e.a}},w=function(e){return D(I(e))},y=function(e){var r=e.s,n=e.v,t=e.a,o=(200-r)*n/100;return{h:b(e.h),s:b(o>0&&o<200?r*n/100/(o<=100?o:200-o)*100:0),l:b(o/2),a:b(t,2)}},q=function(e){var r=y(e);return\"hsl(\"+r.h+\", \"+r.s+\"%, \"+r.l+\"%)\"},k=function(e){var r=y(e);return\"hsla(\"+r.h+\", \"+r.s+\"%, \"+r.l+\"%, \"+r.a+\")\"},I=function(e){var r=e.h,n=e.s,t=e.v,o=e.a;r=r/360*6,n/=100,t/=100;var a=Math.floor(r),l=t*(1-n),u=t*(1-(r-a)*n),c=t*(1-(1-r+a)*n),i=a%6;return{r:b(255*[t,u,l,l,c,t][i]),g:b(255*[c,t,t,u,l,l][i]),b:b(255*[l,l,c,t,t,u][i]),a:b(o,2)}},O=function(e){var r=/hsva?\\(?\\s*(-?\\d*\\.?\\d+)(deg|rad|grad|turn)?[,\\s]+(-?\\d*\\.?\\d+)%?[,\\s]+(-?\\d*\\.?\\d+)%?,?\\s*[/\\s]*(-?\\d*\\.?\\d+)?(%)?\\s*\\)?/i.exec(e);return r?A({h:x(r[1],r[2]),s:Number(r[3]),v:Number(r[4]),a:void 0===r[5]?1:Number(r[5])/(r[6]?100:1)}):{h:0,s:0,v:0,a:1}},j=O,z=function(e){var r=/rgba?\\(?\\s*(-?\\d*\\.?\\d+)(%)?[,\\s]+(-?\\d*\\.?\\d+)(%)?[,\\s]+(-?\\d*\\.?\\d+)(%)?,?\\s*[/\\s]*(-?\\d*\\.?\\d+)?(%)?\\s*\\)?/i.exec(e);return r?L({r:Number(r[1])/(r[2]?100/255:1),g:Number(r[3])/(r[4]?100/255:1),b:Number(r[5])/(r[6]?100/255:1),a:void 0===r[7]?1:Number(r[7])/(r[8]?100:1)}):{h:0,s:0,v:0,a:1}},K=z,B=function(e){var r=e.toString(16);return r.length<2?\"0\"+r:r},D=function(e){var r=e.r,n=e.g,t=e.b,o=e.a,a=o<1?B(b(255*o)):\"\";return\"#\"+B(r)+B(n)+B(t)+a},L=function(e){var r=e.r,n=e.g,t=e.b,o=e.a,a=Math.max(r,n,t),l=a-Math.min(r,n,t),u=l?a===r?(n-t)/l:a===n?2+(t-r)/l:4+(r-n)/l:0;return{h:b(60*(u<0?u+6:u)),s:b(a?l/a*100:0),v:b(a/255*100),a:o}},A=function(e){return{h:b(e.h),s:b(e.s),v:b(e.v),a:b(e.a,2)}},S=e.memo(function(r){var n=r.hue,t=r.onChange,o=r.onChangeEnd,a=m([\"react-colorful__hue\",r.className]);return e.createElement(\"div\",{className:a},e.createElement(g,{onMove:function(e){t({h:360*e.left})},onKey:function(e){t({h:s(n+360*e.left,0,360)})},onEnd:o,\"aria-label\":\"Hue\",\"aria-valuenow\":b(n),\"aria-valuemax\":\"360\",\"aria-valuemin\":\"0\"},e.createElement(p,{className:\"react-colorful__hue-pointer\",left:n/360,color:q({h:n,s:100,v:100,a:1})})))}),T=e.memo(function(r){var n=r.hsva,t=r.onChange,o=r.onChangeEnd,a={backgroundColor:q({h:n.h,s:100,v:100,a:1})};return e.createElement(\"div\",{className:\"react-colorful__saturation\",style:a},e.createElement(g,{onMove:function(e){t({s:100*e.left,v:100-100*e.top})},onKey:function(e){t({s:s(n.s+100*e.left,0,100),v:s(n.v-100*e.top,0,100)})},onEnd:o,\"aria-label\":\"Color\",\"aria-valuetext\":\"Saturation \"+b(n.s)+\"%, Brightness \"+b(n.v)+\"%\"},e.createElement(p,{className:\"react-colorful__saturation-pointer\",top:1-n.v/100,left:n.s/100,color:q(n)})))}),F=function(e,r){if(e===r)return!0;for(var n in e)if(e[n]!==r[n])return!1;return!0},P=function(e,r){return e.replace(/\\s/g,\"\")===r.replace(/\\s/g,\"\")},X=function(e,r){return e.toLowerCase()===r.toLowerCase()||F(C(e),C(r))};function Y(e,n,l,u){var c=i(l),s=i(u),f=o(function(){return e.toHsva(n)}),v=f[0],d=f[1],h=r({color:n,hsva:v}),g=r(!1);t(function(){if(!e.equal(n,h.current.color)){var r=e.toHsva(n);h.current={hsva:r,color:n},d(r),g.current=!1}},[n,e]),t(function(){var r;F(v,h.current.hsva)||e.equal(r=e.fromHsva(v),h.current.color)||(h.current={hsva:v,color:r},c(r),g.current=!0)},[v,e,c]);var m=a(function(e){d(function(r){return Object.assign({},r,e)})},[]),p=a(function(){g.current&&(g.current=!1,s(h.current.color))},[s]);return[v,m,p]}var R,U=\"undefined\"!=typeof window?l:t,V=function(){return R||(\"undefined\"!=typeof __webpack_nonce__?__webpack_nonce__:void 0)},$=function(e){R=e},G=new Map,J=function(e){U(function(){var r=e.current?e.current.ownerDocument:document;if(void 0!==r&&!G.has(r)){var n=r.createElement(\"style\");n.innerHTML='.react-colorful{position:relative;display:flex;flex-direction:column;width:200px;height:200px;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;cursor:default}.react-colorful__saturation{position:relative;flex-grow:1;border-color:transparent;border-bottom:12px solid #000;border-radius:8px 8px 0 0;background-image:linear-gradient(0deg,#000,transparent),linear-gradient(90deg,#fff,hsla(0,0%,100%,0))}.react-colorful__alpha-gradient,.react-colorful__pointer-fill{content:\"\";position:absolute;left:0;top:0;right:0;bottom:0;pointer-events:none;border-radius:inherit}.react-colorful__alpha-gradient,.react-colorful__saturation{box-shadow:inset 0 0 0 1px rgba(0,0,0,.05)}.react-colorful__alpha,.react-colorful__hue{position:relative;height:24px}.react-colorful__hue{background:linear-gradient(90deg,red 0,#ff0 17%,#0f0 33%,#0ff 50%,#00f 67%,#f0f 83%,red)}.react-colorful__last-control{border-radius:0 0 8px 8px}.react-colorful__interactive{position:absolute;left:0;top:0;right:0;bottom:0;border-radius:inherit;outline:none;touch-action:none}.react-colorful__pointer{position:absolute;z-index:1;box-sizing:border-box;width:28px;height:28px;transform:translate(-50%,-50%);background-color:#fff;border:2px solid #fff;border-radius:50%;box-shadow:0 2px 4px rgba(0,0,0,.2)}.react-colorful__interactive:focus .react-colorful__pointer{transform:translate(-50%,-50%) scale(1.1)}.react-colorful__alpha,.react-colorful__alpha-pointer{background-color:#fff;background-image:url(\\'data:image/svg+xml;charset=utf-8,<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"16\" height=\"16\" fill-opacity=\".05\"><path d=\"M8 0h8v8H8zM0 8h8v8H0z\"/></svg>\\')}.react-colorful__saturation-pointer{z-index:3}.react-colorful__hue-pointer{z-index:2}',G.set(r,n);var t=V();t&&n.setAttribute(\"nonce\",t),r.head.appendChild(n)}},[])},Q=function(n){var t=n.className,o=n.colorModel,a=n.color,l=void 0===a?o.defaultColor:a,i=n.onChange,s=n.onChangeEnd,f=c(n,[\"className\",\"colorModel\",\"color\",\"onChange\",\"onChangeEnd\"]),v=r(null);J(v);var d=Y(o,l,i,s),h=d[0],g=d[1],p=d[2],b=m([\"react-colorful\",t]);return e.createElement(\"div\",u({},f,{ref:v,className:b}),e.createElement(T,{hsva:h,onChange:g,onChangeEnd:p}),e.createElement(S,{hue:h.h,onChange:g,onChangeEnd:p,className:\"react-colorful__last-control\"}))},W={defaultColor:\"000\",toHsva:E,fromHsva:function(e){return w({h:e.h,s:e.s,v:e.v,a:1})},equal:X},Z=function(r){return e.createElement(Q,u({},r,{colorModel:W}))},ee=function(r){var n=r.className,t=r.hsva,o=r.onChange,a=r.onChangeEnd,l={backgroundImage:\"linear-gradient(90deg, \"+k(Object.assign({},t,{a:0}))+\", \"+k(Object.assign({},t,{a:1}))+\")\"},u=m([\"react-colorful__alpha\",n]),c=b(100*t.a);return e.createElement(\"div\",{className:u},e.createElement(\"div\",{className:\"react-colorful__alpha-gradient\",style:l}),e.createElement(g,{onMove:function(e){o({a:e.left})},onKey:function(e){o({a:s(t.a+e.left)})},onEnd:a,\"aria-label\":\"Alpha\",\"aria-valuetext\":c+\"%\",\"aria-valuenow\":c,\"aria-valuemin\":\"0\",\"aria-valuemax\":\"100\"},e.createElement(p,{className:\"react-colorful__alpha-pointer\",left:t.a,color:k(t)})))},re=function(n){var t=n.className,o=n.colorModel,a=n.color,l=void 0===a?o.defaultColor:a,i=n.onChange,s=n.onChangeEnd,f=c(n,[\"className\",\"colorModel\",\"color\",\"onChange\",\"onChangeEnd\"]),v=r(null);J(v);var d=Y(o,l,i,s),h=d[0],g=d[1],p=d[2],b=m([\"react-colorful\",t]);return e.createElement(\"div\",u({},f,{ref:v,className:b}),e.createElement(T,{hsva:h,onChange:g,onChangeEnd:p}),e.createElement(S,{hue:h.h,onChange:g,onChangeEnd:p}),e.createElement(ee,{hsva:h,onChange:g,onChangeEnd:p,className:\"react-colorful__last-control\"}))},ne={defaultColor:\"0001\",toHsva:E,fromHsva:w,equal:X},te=function(r){return e.createElement(re,u({},r,{colorModel:ne}))},oe={defaultColor:{h:0,s:0,l:0,a:1},toHsva:N,fromHsva:y,equal:F},ae=function(r){return e.createElement(re,u({},r,{colorModel:oe}))},le={defaultColor:\"hsla(0, 0%, 0%, 1)\",toHsva:H,fromHsva:k,equal:P},ue=function(r){return e.createElement(re,u({},r,{colorModel:le}))},ce={defaultColor:{h:0,s:0,l:0},toHsva:function(e){return N({h:e.h,s:e.s,l:e.l,a:1})},fromHsva:function(e){return{h:(r=y(e)).h,s:r.s,l:r.l};var r},equal:F},ie=function(r){return e.createElement(Q,u({},r,{colorModel:ce}))},se={defaultColor:\"hsl(0, 0%, 0%)\",toHsva:M,fromHsva:q,equal:P},fe=function(r){return e.createElement(Q,u({},r,{colorModel:se}))},ve={defaultColor:{h:0,s:0,v:0,a:1},toHsva:function(e){return e},fromHsva:A,equal:F},de=function(r){return e.createElement(re,u({},r,{colorModel:ve}))},he={defaultColor:\"hsva(0, 0%, 0%, 1)\",toHsva:O,fromHsva:function(e){var r=A(e);return\"hsva(\"+r.h+\", \"+r.s+\"%, \"+r.v+\"%, \"+r.a+\")\"},equal:P},ge=function(r){return e.createElement(re,u({},r,{colorModel:he}))},me={defaultColor:{h:0,s:0,v:0},toHsva:function(e){return{h:e.h,s:e.s,v:e.v,a:1}},fromHsva:function(e){var r=A(e);return{h:r.h,s:r.s,v:r.v}},equal:F},pe=function(r){return e.createElement(Q,u({},r,{colorModel:me}))},be={defaultColor:\"hsv(0, 0%, 0%)\",toHsva:j,fromHsva:function(e){var r=A(e);return\"hsv(\"+r.h+\", \"+r.s+\"%, \"+r.v+\"%)\"},equal:P},_e=function(r){return e.createElement(Q,u({},r,{colorModel:be}))},Ee={defaultColor:{r:0,g:0,b:0,a:1},toHsva:L,fromHsva:I,equal:F},Ce=function(r){return e.createElement(re,u({},r,{colorModel:Ee}))},xe={defaultColor:\"rgba(0, 0, 0, 1)\",toHsva:z,fromHsva:function(e){var r=I(e);return\"rgba(\"+r.r+\", \"+r.g+\", \"+r.b+\", \"+r.a+\")\"},equal:P},He=function(r){return e.createElement(re,u({},r,{colorModel:xe}))},Me={defaultColor:{r:0,g:0,b:0},toHsva:function(e){return L({r:e.r,g:e.g,b:e.b,a:1})},fromHsva:function(e){return{r:(r=I(e)).r,g:r.g,b:r.b};var r},equal:F},Ne=function(r){return e.createElement(Q,u({},r,{colorModel:Me}))},we={defaultColor:\"rgb(0, 0, 0)\",toHsva:K,fromHsva:function(e){var r=I(e);return\"rgb(\"+r.r+\", \"+r.g+\", \"+r.b+\")\"},equal:P},ye=function(r){return e.createElement(Q,u({},r,{colorModel:we}))},qe=/^#?([0-9A-F]{3,8})$/i,ke=function(r){var n=r.color,l=void 0===n?\"\":n,s=r.onChange,f=r.onBlur,v=r.escape,d=r.validate,h=r.format,g=r.process,m=c(r,[\"color\",\"onChange\",\"onBlur\",\"escape\",\"validate\",\"format\",\"process\"]),p=o(function(){return v(l)}),b=p[0],_=p[1],E=i(s),C=i(f),x=a(function(e){var r=v(e.target.value);_(r),d(r)&&E(g?g(r):r)},[v,g,d,E]),H=a(function(e){d(e.target.value)||_(v(l)),C(e)},[l,v,d,C]);return t(function(){_(v(l))},[l,v]),e.createElement(\"input\",u({},m,{value:h?h(b):b,spellCheck:\"false\",onChange:x,onBlur:H}))},Ie=function(e){return\"#\"+e},Oe=function(r){var n=r.prefixed,t=r.alpha,o=c(r,[\"prefixed\",\"alpha\"]),l=a(function(e){return e.replace(/([^0-9A-F]+)/gi,\"\").substring(0,t?8:6)},[t]),i=a(function(e){return function(e,r){var n=qe.exec(e),t=n?n[1].length:0;return 3===t||6===t||!!r&&4===t||!!r&&8===t}(e,t)},[t]);return e.createElement(ke,u({},o,{escape:l,format:n?Ie:void 0,process:Ie,validate:i}))};export{te as HexAlphaColorPicker,Oe as HexColorInput,Z as HexColorPicker,ie as HslColorPicker,fe as HslStringColorPicker,ae as HslaColorPicker,ue as HslaStringColorPicker,pe as HsvColorPicker,_e as HsvStringColorPicker,de as HsvaColorPicker,ge as HsvaStringColorPicker,Ne as RgbColorPicker,ye as RgbStringColorPicker,Ce as RgbaColorPicker,He as RgbaStringColorPicker,$ as setNonce};\n//# sourceMappingURL=index.module.js.map\n","/**\n * ColorPickerDropdown - Custom color picker with dropdown\n * Uses react-colorful for a better UX than native browser picker\n */\n\nimport { useState, useEffect, memo, useRef } from 'react';\nimport { HexColorPicker } from 'react-colorful';\nimport { Button, Popover, PopoverTrigger, PopoverContent } from './ui';\n\nexport interface ColorPickerDropdownProps {\n value: string;\n onChange: (event: { target: { value: string } }) => void;\n /** Colours already in use elsewhere in the design (text, shapes,\n * paths, strokes, artboard background). Surfaced as the\n * \"Document colors\" row. */\n documentColors?: string[];\n /** Dominant colours sampled from image elements in the design.\n * Surfaced as a separate \"Image colors\" row so users can match\n * a colour from their artwork. Empty / omitted hides the row. */\n imageColors?: string[];\n icon?: React.ReactNode;\n showSquare?: boolean;\n allowTransparent?: boolean;\n isOpen?: boolean;\n onOpenChange?: (isOpen: boolean) => void;\n /** When true, renders the color picker content directly without a popover trigger button */\n embedded?: boolean;\n}\n\nconst ColorPickerDropdown = memo(({\n value,\n onChange,\n documentColors = [],\n imageColors = [],\n icon,\n showSquare = false,\n allowTransparent = false,\n isOpen: controlledIsOpen,\n onOpenChange: controlledOnOpenChange,\n embedded = false,\n}: ColorPickerDropdownProps) => {\n const [internalIsOpen, setInternalIsOpen] = useState(false);\n const [hexInput, setHexInput] = useState(value);\n const [localColor, setLocalColor] = useState(value);\n const lastUpdateTimeRef = useRef<number>(0);\n const pendingUpdateRef = useRef<NodeJS.Timeout | null>(null);\n const isDraggingRef = useRef<boolean>(false);\n\n // CRITICAL: Store onChange in a ref to avoid stale closure bug\n // When throttled updates fire via setTimeout, they need the LATEST onChange,\n // not the one captured when the timeout was created\n const onChangeRef = useRef(onChange);\n onChangeRef.current = onChange;\n\n // Use controlled state if provided, otherwise use internal state\n const isOpen = controlledIsOpen !== undefined ? controlledIsOpen : internalIsOpen;\n const setIsOpen = controlledOnOpenChange || setInternalIsOpen;\n\n // Sync local state with value prop - but ONLY when not actively dragging\n // This prevents jank from prop updates conflicting with local drag state\n useEffect(() => {\n if (!isDraggingRef.current && value !== 'transparent') {\n setHexInput(value);\n setLocalColor(value);\n }\n }, [value]);\n\n // Throttled color change - updates at max 60fps for smooth real-time feedback\n const handleColorChange = (color: string) => {\n // Mark as dragging to prevent prop sync from causing jank\n isDraggingRef.current = true;\n\n // Update local state immediately for smooth UI\n setLocalColor(color);\n setHexInput(color);\n\n const now = Date.now();\n const timeSinceLastUpdate = now - lastUpdateTimeRef.current;\n\n // Throttle: update max once every 16ms (~60fps) for smooth real-time updates\n if (timeSinceLastUpdate >= 16) {\n // Call immediately if enough time has passed\n // Use ref to always get latest onChange (avoids stale closure on mobile)\n onChangeRef.current({ target: { value: color } });\n lastUpdateTimeRef.current = now;\n\n // Clear any pending update\n if (pendingUpdateRef.current) {\n clearTimeout(pendingUpdateRef.current);\n pendingUpdateRef.current = null;\n }\n } else {\n // Schedule an update for the remaining throttle time\n if (pendingUpdateRef.current) {\n clearTimeout(pendingUpdateRef.current);\n }\n\n pendingUpdateRef.current = setTimeout(() => {\n // CRITICAL: Use ref to get latest onChange, not captured closure value\n // This fixes intermittent color update failures on mobile\n onChangeRef.current({ target: { value: color } });\n lastUpdateTimeRef.current = Date.now();\n pendingUpdateRef.current = null;\n // Clear dragging state after final update\n isDraggingRef.current = false;\n }, 16 - timeSinceLastUpdate);\n }\n };\n\n // Store localColor in a ref for the pointerup handler to access\n const localColorRef = useRef(localColor);\n localColorRef.current = localColor;\n\n // Clear dragging state when mouse/touch is released and flush any pending update\n useEffect(() => {\n const handlePointerUp = () => {\n // If there's a pending throttled update, cancel it and send immediately\n // This ensures the final color is always applied even if component re-renders\n if (pendingUpdateRef.current) {\n clearTimeout(pendingUpdateRef.current);\n pendingUpdateRef.current = null;\n // Send the final color using the latest refs\n onChangeRef.current({ target: { value: localColorRef.current } });\n }\n // Clear dragging state after a small delay\n setTimeout(() => {\n isDraggingRef.current = false;\n }, 50);\n };\n\n window.addEventListener('pointerup', handlePointerUp);\n window.addEventListener('pointercancel', handlePointerUp);\n\n return () => {\n window.removeEventListener('pointerup', handlePointerUp);\n window.removeEventListener('pointercancel', handlePointerUp);\n };\n }, []);\n\n // Cleanup timeout on unmount\n useEffect(() => {\n return () => {\n if (pendingUpdateRef.current) {\n clearTimeout(pendingUpdateRef.current);\n }\n };\n }, []);\n\n const handleHexInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {\n const input = e.target.value;\n setHexInput(input);\n\n // Validate hex color (with or without #)\n const hexPattern = /^#?([0-9A-Fa-f]{6}|[0-9A-Fa-f]{3})$/;\n const withHash = input.startsWith('#') ? input : `#${input}`;\n\n if (hexPattern.test(withHash)) {\n // Use ref to ensure we always call the latest onChange\n onChangeRef.current({ target: { value: withHash } });\n }\n };\n\n const handlePresetClick = (color: string) => {\n handleColorChange(color);\n };\n\n const handleTransparentClick = () => {\n // Use ref to ensure we always call the latest onChange\n onChangeRef.current({ target: { value: 'transparent' } });\n };\n\n const isTransparent = value === 'transparent';\n\n const buttonContent = showSquare ? (\n <div\n className={`sc:size-8 sc:md:size-6 sc:rounded-md sc:border sc:border-border-primary ${isTransparent ? 'transparent-pattern-small' : ''}`}\n style={isTransparent ? {} : { backgroundColor: value }}\n />\n ) : (\n <div className=\"sc:relative sc:flex sc:items-center sc:justify-center sc:h-5 sc:w-5\">\n {icon ? <span className=\"sc:flex sc:items-center sc:-translate-y-0.5\">{icon}</span> : <span className=\"sc:font-bold sc:text-lg sc:leading-none sc:-translate-y-0.5\">A</span>}\n <div\n className={`sc:absolute sc:bottom-0 sc:left-1/2 sc:-translate-x-1/2 sc:h-[3px] sc:w-4 sc:rounded-sm ${isTransparent ? 'transparent-pattern-small' : ''}`}\n style={isTransparent ? {} : { backgroundColor: value }}\n />\n </div>\n );\n\n const pickerContent = (\n <div className=\"sc:space-y-4 sc:min-w-[232px]\">\n {allowTransparent && (\n <Button\n variant=\"ghost\"\n className={`sc:flex sc:w-full sc:cursor-pointer sc:items-center sc:justify-start sc:gap-2 sc:rounded-lg ${isTransparent ? 'sc:bg-primary/10' : ''}`}\n onClick={handleTransparentClick}\n >\n <div className=\"transparent-pattern-small sc:h-6 sc:w-6 sc:rounded\" />\n <span className=\"sc:text-sm sc:font-medium\">Transparent</span>\n </Button>\n )}\n\n <div className=\"sc:w-[200px]\">\n <HexColorPicker color={isTransparent ? '#ffffff' : localColor} onChange={handleColorChange} />\n </div>\n\n <div className=\"sc:flex sc:items-center sc:gap-2\">\n <label htmlFor=\"hex-input\" className=\"sc:text-sm sc:font-medium sc:uppercase sc:text-foreground/60\">\n HEX\n </label>\n <input\n id=\"hex-input\"\n type=\"text\"\n className=\"sc:w-24 sc:rounded-lg sc:border sc:border-divider sc:bg-field sc:px-2 sc:py-1.5 sc:text-sm sc:text-foreground sc:focus:border-primary sc:focus:outline-none\"\n value={hexInput}\n onChange={handleHexInputChange}\n placeholder=\"#000000\"\n maxLength={7}\n />\n </div>\n\n {documentColors.length > 0 && (\n <div className=\"sc:flex sc:flex-col sc:gap-1.5\">\n <div className=\"sc:text-sm sc:font-medium sc:text-foreground/60\">Document colors</div>\n <div className=\"sc:grid sc:grid-cols-8 sc:gap-1\">\n {documentColors.map((color, index) => (\n <button\n key={index}\n className={`sc:h-6 sc:w-6 sc:cursor-pointer sc:rounded sc:border-2 sc:transition-all sc:duration-150 sc:hover:scale-110 ${color === value ? 'sc:border-primary' : 'sc:border-transparent'}`}\n style={{ backgroundColor: color }}\n onClick={() => handlePresetClick(color)}\n aria-label={color}\n />\n ))}\n </div>\n </div>\n )}\n\n {imageColors.length > 0 && (\n <div className=\"sc:flex sc:flex-col sc:gap-1.5\">\n <div className=\"sc:text-sm sc:font-medium sc:text-foreground/60\">Image colors</div>\n <div className=\"sc:grid sc:grid-cols-8 sc:gap-1\">\n {imageColors.map((color, index) => (\n <button\n key={`img-${index}`}\n className={`sc:h-6 sc:w-6 sc:cursor-pointer sc:rounded sc:border-2 sc:transition-all sc:duration-150 sc:hover:scale-110 ${color === value ? 'sc:border-primary' : 'sc:border-transparent'}`}\n style={{ backgroundColor: color }}\n onClick={() => handlePresetClick(color)}\n aria-label={color}\n />\n ))}\n </div>\n </div>\n )}\n </div>\n );\n\n // Embedded mode: render just the picker content without popover wrapper\n if (embedded) {\n return pickerContent;\n }\n\n return (\n <Popover open={isOpen} onOpenChange={setIsOpen}>\n <PopoverTrigger asChild>\n <button\n className={\n showSquare\n ? 'sc:flex sc:items-center sc:justify-center sc:bg-transparent sc:border-0 sc:p-0 sc:cursor-pointer sc:rounded-md sc:hover:opacity-80 sc:transition-opacity'\n : 'sc-toolbar-btn'\n }\n aria-label=\"Color Picker\"\n >\n {buttonContent}\n </button>\n </PopoverTrigger>\n <PopoverContent className=\"sc:w-auto\" maxZIndex>\n {pickerContent}\n </PopoverContent>\n </Popover>\n );\n});\n\nColorPickerDropdown.displayName = 'ColorPickerDropdown';\n\nexport default ColorPickerDropdown;\n","/**\n * BackButton - Reusable back button for toolbar menus\n */\n\nimport { Button, Tooltip, TooltipTrigger, TooltipContent, TooltipProvider } from './ui';\n\nconst BackIcon = () => (\n <svg\n width=\"20\"\n height=\"20\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n className=\"sc:shrink-0\"\n >\n <path d=\"M19 12H5M12 19l-7-7 7-7\" />\n </svg>\n);\n\nexport function BackButton({ onClick }: { onClick: () => void }) {\n return (\n <TooltipProvider delayDuration={300}>\n <Tooltip>\n <TooltipTrigger asChild>\n <Button\n variant=\"outline\"\n onClick={onClick}\n className=\"sc:mr-sm sc:border-r-border-primary sc:pr-md\"\n aria-label=\"Back\"\n >\n <BackIcon />\n </Button>\n </TooltipTrigger>\n <TooltipContent>Back</TooltipContent>\n </Tooltip>\n </TooltipProvider>\n );\n}\n\nexport default BackButton;\n","/**\n * featureApplied — derive boolean flags from a canvas element saying\n * \"this feature has a non-default value.\" Used by toolbar buttons to\n * paint the active/selected style not just when the panel is open\n * but also when the property has actually been applied to the\n * element. Lets users tell at a glance whether a layer is rotated /\n * has a stroke / has a knockout / etc.\n *\n * Default values match the element constructors: rotation=0,\n * opacity=1, borderRadius=0, fillOpacity=1, blendMode unset, no\n * masks, no stroke, no distress, no shadow.\n */\n\nimport type { BaseElement } from '../core/BaseElement.js';\nimport type { ImageAdjustments } from '../types/index.js';\nimport { isStandardBlendMode } from '../types/index.js';\nimport { isNeutralAdjustments } from '../core/image-adjustments.js';\n\nconst EPSILON = 0.001;\n\nexport interface FeatureAppliedFlags {\n rotation: boolean;\n opacity: boolean;\n stroke: boolean;\n knockout: boolean;\n distress: boolean;\n imageMask: boolean;\n /** Drop shadow enabled */\n shadow: boolean;\n /** Standard blend mode applied (multiply/screen/overlay/darken/lighten — NOT knockout/clip) */\n blendMode: boolean;\n /** Image: `transformData.borderRadius`. */\n cornerRadius: boolean;\n /** Image: `transformData.adjustments` (brightness/contrast/saturation non-neutral). */\n adjustments: boolean;\n /** Shape: `transformData.fillOpacity`. */\n shapeTransparency: boolean;\n /**\n * Text: non-default `letterSpacing` (≠ 0) or `lineHeight` (≠ 1.2 default).\n * Drives the font-size toolbar button's applied highlight, since both\n * controls live inside the Font Size panel.\n */\n typography: boolean;\n}\n\nexport function getFeatureApplied(element: BaseElement | null | undefined): FeatureAppliedFlags {\n if (!element) {\n return {\n rotation: false,\n opacity: false,\n stroke: false,\n knockout: false,\n distress: false,\n imageMask: false,\n shadow: false,\n blendMode: false,\n cornerRadius: false,\n adjustments: false,\n shapeTransparency: false,\n typography: false,\n };\n }\n\n const td = element.transformData as\n | { borderRadius?: number; fillOpacity?: number; adjustments?: ImageAdjustments }\n | undefined;\n\n // Text typography knobs (TextElement only; undefined elsewhere)\n const { letterSpacing, lineHeight } = element as unknown as {\n letterSpacing?: number;\n lineHeight?: number;\n };\n\n return {\n rotation: Math.abs(element.rotation ?? 0) > EPSILON,\n opacity: (element.opacity ?? 1) < 1 - EPSILON,\n stroke: element.stroke?.enabled === true,\n knockout: element.blendMode === 'knockout' || element.blendMode === 'clip',\n distress: element.distressEffect?.enabled === true,\n imageMask: !!element.masks && element.masks.length > 0,\n shadow: element.shadow?.enabled === true,\n blendMode: isStandardBlendMode(element.blendMode),\n cornerRadius: (td?.borderRadius ?? 0) > 0,\n adjustments: !isNeutralAdjustments(td?.adjustments),\n shapeTransparency: (td?.fillOpacity ?? 1) < 1 - EPSILON,\n typography:\n Math.abs(letterSpacing ?? 0) > EPSILON ||\n (lineHeight !== undefined && Math.abs(lineHeight - 1.2) > EPSILON),\n };\n}\n","/**\n * ImageToolbar - Toolbar for image-specific controls\n * Handles crop, flip, and border radius controls\n */\n\nimport React, { useState } from 'react';\nimport { Tooltip, TooltipTrigger, TooltipContent, ToolbarButton, Button, Popover, PopoverTrigger, PopoverContent } from './ui';\nimport { Icon } from '@iconify/react';\nimport { ImageElement } from '../core/ImageElement';\nimport { RotateLeftIcon } from './ui/custom-icons';\nimport { icons } from './ui/icons';\nimport { getFeatureApplied } from '../utils/featureApplied.js';\n\ninterface ImageToolbarProps {\n element: ImageElement;\n onElementUpdate: (element: ImageElement) => void;\n showUngroupButton?: boolean;\n onUngroup?: () => void;\n onMoveForward?: () => void;\n onMoveBackward?: () => void;\n onChangeImage?: () => void;\n /**\n * Remove-background action. Provided only when the host configured\n * `services.removeBackground` — unconfigured = no button (consistent with\n * the services contract used by the Image Browser tabs).\n */\n onRemoveBackground?: () => void;\n /** Background removal in flight — disables the button + shows a spinner */\n removingBackground?: boolean;\n /** Inline error from the last background-removal attempt */\n removeBackgroundError?: string | null;\n /** Callback when element should be deleted */\n onDelete?: () => void;\n /** Whether the corner radius panel is expanded */\n cornerRadiusExpanded?: boolean;\n /** Callback when corner radius panel should be toggled */\n onCornerRadiusToggle?: () => void;\n /** Whether the crop panel is expanded */\n cropExpanded?: boolean;\n /** Callback when crop panel should be toggled */\n onCropToggle?: () => void;\n /** Whether the adjust panel (brightness/contrast/saturation) is expanded */\n adjustExpanded?: boolean;\n /** Callback when adjust panel should be toggled */\n onAdjustToggle?: () => void;\n /** Whether the rotation panel is expanded */\n rotationExpanded?: boolean;\n /** Callback when rotation panel should be toggled */\n onRotationToggle?: () => void;\n /** Whether the opacity panel is expanded */\n opacityExpanded?: boolean;\n /** Callback when opacity panel should be toggled */\n onOpacityToggle?: () => void;\n /** Whether the stroke panel is expanded */\n strokeExpanded?: boolean;\n /** Callback when stroke panel should be toggled */\n onStrokeToggle?: () => void;\n /** Whether the shadow panel is expanded */\n shadowExpanded?: boolean;\n /** Callback when shadow panel should be toggled */\n onShadowToggle?: () => void;\n /** Whether the blend mode panel is expanded */\n blendModeExpanded?: boolean;\n /** Callback when blend mode panel should be toggled */\n onBlendModeToggle?: () => void;\n /** Whether the knockout panel is expanded */\n knockoutExpanded?: boolean;\n /** Callback when knockout panel should be toggled */\n onKnockoutToggle?: () => void;\n /** Whether the distress texture panel is expanded */\n distressTextureExpanded?: boolean;\n /** Callback when distress texture panel should be toggled */\n onDistressTextureToggle?: () => void;\n /** Whether the image mask panel is expanded */\n imageMaskExpanded?: boolean;\n /** Callback when image mask panel should be toggled */\n onImageMaskToggle?: () => void;\n}\n\nconst ImageToolbar: React.FC<ImageToolbarProps> = ({\n element,\n onElementUpdate,\n showUngroupButton = false,\n onUngroup,\n onMoveForward,\n onMoveBackward,\n onChangeImage,\n onRemoveBackground,\n removingBackground = false,\n removeBackgroundError = null,\n onDelete,\n cornerRadiusExpanded = false,\n onCornerRadiusToggle,\n cropExpanded = false,\n onCropToggle,\n adjustExpanded = false,\n onAdjustToggle,\n rotationExpanded = false,\n onRotationToggle,\n opacityExpanded = false,\n onOpacityToggle,\n strokeExpanded = false,\n onStrokeToggle,\n shadowExpanded = false,\n onShadowToggle,\n blendModeExpanded = false,\n onBlendModeToggle,\n knockoutExpanded = false,\n onKnockoutToggle,\n distressTextureExpanded = false,\n onDistressTextureToggle,\n imageMaskExpanded = false,\n onImageMaskToggle,\n}) => {\n const [moreMenuOpen, setMoreMenuOpen] = useState<boolean>(false);\n const [changeImageTooltipDisabled, setChangeImageTooltipDisabled] = useState(false);\n const [removeBgTooltipDisabled, setRemoveBgTooltipDisabled] = useState(false);\n const [cornerRadiusTooltipDisabled, setCornerRadiusTooltipDisabled] = useState(false);\n const [cropTooltipDisabled, setCropTooltipDisabled] = useState(false);\n const [adjustTooltipDisabled, setAdjustTooltipDisabled] = useState(false);\n const [rotationTooltipDisabled, setRotationTooltipDisabled] = useState(false);\n const [opacityTooltipDisabled, setOpacityTooltipDisabled] = useState(false);\n const [strokeTooltipDisabled, setStrokeTooltipDisabled] = useState(false);\n const [shadowTooltipDisabled, setShadowTooltipDisabled] = useState(false);\n const [blendModeTooltipDisabled, setBlendModeTooltipDisabled] = useState(false);\n const [knockoutTooltipDisabled, setKnockoutTooltipDisabled] = useState(false);\n const [distressTooltipDisabled, setDistressTooltipDisabled] = useState(false);\n const [imageMaskTooltipDisabled, setImageMaskTooltipDisabled] = useState(false);\n\n // Check if element is in crop mode\n const isCropping = element.isCropping;\n\n // Feature-applied flags — drive the \"selected\" highlight on the\n // toolbar buttons whose underlying property is set to a non-default\n // value. Combined with the panel-open flag below.\n const applied = getFeatureApplied(element);\n\n const handleCropToggle = () => {\n setCropTooltipDisabled(true);\n if (isCropping) {\n // Exit crop mode\n const updatedElement = element.clone();\n updatedElement.exitCropMode();\n onElementUpdate(updatedElement);\n } else {\n // Enter crop mode\n const updatedElement = element.clone();\n updatedElement.enterCropMode();\n onElementUpdate(updatedElement);\n }\n onCropToggle?.();\n };\n\n const handleFlipHorizontal = () => {\n const updatedElement = element.clone();\n updatedElement.transformData.flipHorizontal = !updatedElement.transformData.flipHorizontal;\n onElementUpdate(updatedElement);\n };\n\n const handleFlipVertical = () => {\n const updatedElement = element.clone();\n updatedElement.transformData.flipVertical = !updatedElement.transformData.flipVertical;\n onElementUpdate(updatedElement);\n };\n\n return (\n <div className=\"sc-toolbar-items\">\n {/* Change Image button */}\n {onChangeImage && (\n <ToolbarButton\n icon=\"lucide:image\"\n onClick={() => {\n setChangeImageTooltipDisabled(true);\n onChangeImage();\n }}\n onMouseLeave={() => setChangeImageTooltipDisabled(false)}\n tooltip=\"Change Image\"\n tooltipDisabled={changeImageTooltipDisabled}\n />\n )}\n\n {/* Remove Background button — one-shot service action, NOT a toggle\n (deliberately absent from getFeatureApplied). Rendered only when the\n host configured `services.removeBackground` (unconfigured = hidden);\n disabled with no crash when the element has no imageUrl yet. */}\n {onRemoveBackground && (\n <ToolbarButton\n icon={\n removingBackground ? (\n <Icon icon=\"eos-icons:loading\" className=\"sc:size-6 sc:md:size-5 sc:animate-spin\" />\n ) : (\n 'gravity-ui:magic-wand'\n )\n }\n onClick={() => {\n setRemoveBgTooltipDisabled(true);\n onRemoveBackground();\n }}\n onMouseLeave={() => setRemoveBgTooltipDisabled(false)}\n tooltip={removingBackground ? 'Removing…' : 'Remove Background'}\n tooltipDisabled={removeBgTooltipDisabled}\n disabled={removingBackground || !element.imageUrl}\n aria-label=\"Remove Background\"\n />\n )}\n\n {/* Inline error from the last background-removal attempt. Lives inside\n .toolbar-items so it wraps with the rest of the row (embed mode uses\n `display: contents` — all items wrap together). */}\n {onRemoveBackground && removeBackgroundError && (\n <span\n role=\"alert\"\n data-testid=\"toolbar-remove-bg-error\"\n className=\"sc:self-center sc:whitespace-nowrap sc:rounded-lg sc:border sc:border-danger sc:bg-danger/10 sc:px-2 sc:py-1 sc:text-xs sc:text-danger\"\n >\n {removeBackgroundError}\n </span>\n )}\n\n {/* Crop button */}\n <ToolbarButton\n icon=\"lucide:crop\"\n onClick={handleCropToggle}\n onMouseLeave={() => setCropTooltipDisabled(false)}\n tooltip={isCropping ? 'Exit Crop Mode' : 'Crop'}\n tooltipDisabled={cropTooltipDisabled || cropExpanded}\n active={isCropping || cropExpanded}\n />\n\n {/* Flip Horizontal button */}\n <ToolbarButton icon=\"lucide:flip-horizontal-2\" onClick={handleFlipHorizontal} tooltip=\"Flip Horizontal\" />\n\n {/* Flip Vertical button */}\n <ToolbarButton icon=\"lucide:flip-vertical-2\" onClick={handleFlipVertical} tooltip=\"Flip Vertical\" />\n\n {/* Adjust button — brightness/contrast/saturation panel. Tinted while\n the panel is open OR while non-neutral adjustments are applied\n (getFeatureApplied affordance, gotcha #21). */}\n {onAdjustToggle && (\n <ToolbarButton\n icon=\"gravity-ui:sliders\"\n onClick={() => {\n setAdjustTooltipDisabled(true);\n onAdjustToggle();\n }}\n onMouseLeave={() => setAdjustTooltipDisabled(false)}\n tooltip=\"Adjust\"\n tooltipDisabled={adjustTooltipDisabled || adjustExpanded}\n active={adjustExpanded || applied.adjustments}\n data-testid=\"toolbar-adjust\"\n aria-label=\"Adjust\"\n />\n )}\n\n {/* Rotate button - toggles rotation panel */}\n <ToolbarButton\n icon={<RotateLeftIcon size={20} className=\"sc:md:size-5\" />}\n onClick={() => {\n setRotationTooltipDisabled(true);\n onRotationToggle?.();\n }}\n onMouseLeave={() => setRotationTooltipDisabled(false)}\n tooltip=\"Rotate\"\n tooltipDisabled={rotationTooltipDisabled || rotationExpanded}\n active={rotationExpanded || applied.rotation}\n />\n\n {/* Transparency button - toggles transparency panel */}\n <ToolbarButton\n icon=\"lucide:blend\"\n onClick={() => {\n setOpacityTooltipDisabled(true);\n onOpacityToggle?.();\n }}\n onMouseLeave={() => setOpacityTooltipDisabled(false)}\n tooltip=\"Transparency\"\n tooltipDisabled={opacityTooltipDisabled || opacityExpanded}\n active={opacityExpanded || applied.opacity}\n />\n\n {/* Border radius control - toggle button for embedded panel */}\n <ToolbarButton\n icon=\"lucide:square-round-corner\"\n onClick={() => {\n setCornerRadiusTooltipDisabled(true);\n onCornerRadiusToggle?.();\n }}\n onMouseLeave={() => setCornerRadiusTooltipDisabled(false)}\n tooltip=\"Corner Radius\"\n tooltipDisabled={cornerRadiusTooltipDisabled || cornerRadiusExpanded}\n active={cornerRadiusExpanded || applied.cornerRadius}\n />\n\n {/* Knockout */}\n {onKnockoutToggle && (\n <ToolbarButton\n icon=\"lucide:scissors\"\n onClick={() => {\n setKnockoutTooltipDisabled(true);\n onKnockoutToggle();\n }}\n onMouseLeave={() => setKnockoutTooltipDisabled(false)}\n tooltip=\"Clip / Knockout\"\n tooltipDisabled={knockoutTooltipDisabled || knockoutExpanded}\n active={knockoutExpanded || applied.knockout}\n />\n )}\n\n {/* Distress Texture */}\n {onDistressTextureToggle && (\n <ToolbarButton\n icon=\"lucide:stamp\"\n onClick={() => {\n setDistressTooltipDisabled(true);\n onDistressTextureToggle();\n }}\n onMouseLeave={() => setDistressTooltipDisabled(false)}\n tooltip=\"Distress Texture\"\n tooltipDisabled={distressTooltipDisabled || distressTextureExpanded}\n active={distressTextureExpanded || applied.distress}\n />\n )}\n\n {/* Image Mask */}\n {onImageMaskToggle && (\n <ToolbarButton\n icon=\"lucide:venetian-mask\"\n onClick={() => {\n setImageMaskTooltipDisabled(true);\n onImageMaskToggle();\n }}\n onMouseLeave={() => setImageMaskTooltipDisabled(false)}\n tooltip=\"Image Mask\"\n tooltipDisabled={imageMaskTooltipDisabled || imageMaskExpanded}\n active={imageMaskExpanded || applied.imageMask}\n />\n )}\n\n {/* Stroke */}\n {onStrokeToggle && (\n <ToolbarButton\n icon=\"lucide:pen-line\"\n onClick={() => {\n setStrokeTooltipDisabled(true);\n onStrokeToggle();\n }}\n onMouseLeave={() => setStrokeTooltipDisabled(false)}\n tooltip=\"Stroke\"\n tooltipDisabled={strokeTooltipDisabled || strokeExpanded}\n active={strokeExpanded || applied.stroke}\n />\n )}\n\n {/* Shadow */}\n {onShadowToggle && (\n <ToolbarButton\n icon=\"gravity-ui:square-dashed-circle\"\n onClick={() => {\n setShadowTooltipDisabled(true);\n onShadowToggle();\n }}\n onMouseLeave={() => setShadowTooltipDisabled(false)}\n tooltip=\"Shadow\"\n tooltipDisabled={shadowTooltipDisabled || shadowExpanded}\n active={shadowExpanded || applied.shadow}\n />\n )}\n\n {/* Blend Mode */}\n {onBlendModeToggle && (\n <ToolbarButton\n icon=\"gravity-ui:circles-intersection\"\n onClick={() => {\n setBlendModeTooltipDisabled(true);\n onBlendModeToggle();\n }}\n onMouseLeave={() => setBlendModeTooltipDisabled(false)}\n tooltip=\"Blend Mode\"\n tooltipDisabled={blendModeTooltipDisabled || blendModeExpanded}\n active={blendModeExpanded || applied.blendMode}\n />\n )}\n\n {/* More Menu - overflow menu for additional options */}\n {(onMoveForward || onMoveBackward || onDelete) && (\n <Popover open={moreMenuOpen} onOpenChange={setMoreMenuOpen}>\n <PopoverTrigger asChild>\n <button className=\"sc-toolbar-btn\" aria-label=\"More options\">\n <Icon icon=\"lucide:ellipsis-vertical\" className=\"sc:size-6\" />\n </button>\n </PopoverTrigger>\n <PopoverContent align=\"end\" className=\"sc:w-auto sc:p-1\" maxZIndex>\n <div className=\"sc:flex sc:items-center sc:gap-1\">\n {onMoveForward && (\n <Tooltip delayDuration={300}>\n <TooltipTrigger asChild>\n <Button\n variant=\"ghost\"\n size=\"icon\"\n onClick={() => {\n onMoveForward();\n setMoreMenuOpen(false);\n }}\n aria-label=\"Move Forward\"\n >\n <Icon icon=\"hugeicons:layer-bring-forward\" className=\"sc:size-5\" />\n </Button>\n </TooltipTrigger>\n <TooltipContent>Move Forward</TooltipContent>\n </Tooltip>\n )}\n {onMoveBackward && (\n <Tooltip delayDuration={300}>\n <TooltipTrigger asChild>\n <Button\n variant=\"ghost\"\n size=\"icon\"\n onClick={() => {\n onMoveBackward();\n setMoreMenuOpen(false);\n }}\n aria-label=\"Move Backward\"\n >\n <Icon icon=\"hugeicons:layer-send-backward\" className=\"sc:size-5\" />\n </Button>\n </TooltipTrigger>\n <TooltipContent>Move Backward</TooltipContent>\n </Tooltip>\n )}\n {onDelete && (\n <Tooltip delayDuration={300}>\n <TooltipTrigger asChild>\n <Button\n variant=\"ghost\"\n size=\"icon\"\n onClick={() => {\n setMoreMenuOpen(false);\n onDelete();\n }}\n aria-label=\"Delete\"\n >\n <Icon icon={icons.trash} className=\"sc:size-5\" />\n </Button>\n </TooltipTrigger>\n <TooltipContent>Delete</TooltipContent>\n </Tooltip>\n )}\n </div>\n </PopoverContent>\n </Popover>\n )}\n\n {/* Ungroup button - shown when editing a child in a group */}\n {showUngroupButton && onUngroup && (\n <Tooltip delay={300}>\n <TooltipTrigger asChild>\n <Button variant=\"ghost\" size=\"sm\" onClick={onUngroup}>\n Ungroup\n </Button>\n </TooltipTrigger>\n <TooltipContent>Ungroup this group</TooltipContent>\n </Tooltip>\n )}\n </div>\n );\n};\n\nexport default ImageToolbar;\n","/**\n * Artboard Color Presets\n * A curated set of 10 background colors for artboards\n */\n\nexport interface ArtboardColor {\n id: string;\n name: string;\n color: string; // Hex color\n}\n\n/**\n * Artboard color presets\n * Includes a variety of colors for different design needs\n */\nexport const ARTBOARD_COLORS: ArtboardColor[] = [\n { id: 'white', name: 'White', color: '#FFFFFF' },\n { id: 'light-gray', name: 'Light Gray', color: '#E5E5E5' },\n { id: 'medium-gray', name: 'Medium Gray', color: '#999999' },\n { id: 'dark-gray', name: 'Dark Gray', color: '#333333' },\n { id: 'black', name: 'Black', color: '#000000' },\n { id: 'orange', name: 'Orange', color: '#FF8800' },\n { id: 'blue', name: 'Blue', color: '#0074D9' },\n { id: 'indigo', name: 'Indigo', color: '#4B0082' },\n { id: 'teal', name: 'Teal', color: '#39CCCC' },\n { id: 'coral', name: 'Coral', color: '#FF6B6B' },\n];\n\n/**\n * Get a random artboard color\n */\nexport function getRandomArtboardColor(): string {\n const randomIndex = Math.floor(Math.random() * ARTBOARD_COLORS.length);\n return ARTBOARD_COLORS[randomIndex].color;\n}\n\n/**\n * Find artboard color by hex value\n */\nexport function findArtboardColor(hexColor: string): ArtboardColor | undefined {\n return ARTBOARD_COLORS.find((c) => c.color.toLowerCase() === hexColor.toLowerCase());\n}\n","/**\n * ShapeToolbar - Toolbar for shape-specific controls\n * Handles shape type, fill color, opacity, and shape-specific parameters\n *\n * Uses callback props for secondary panels (like ImageToolbar) for better mobile UX\n */\n\nimport React, { useState, useMemo } from 'react';\nimport { Icon } from '@iconify/react';\nimport { Button, Popover, PopoverTrigger, PopoverContent, Tooltip, TooltipTrigger, TooltipContent, ToolbarButton, icons, RotateLeftIcon } from './ui';\nimport { ShapeElement } from '../core/ShapeElement';\nimport { getFeatureApplied } from '../utils/featureApplied.js';\n\nimport type { ShapeType } from '../types/index.js';\nimport { ARTBOARD_COLORS } from '../presets/artboard-color-presets.js';\nimport { shapeFillToCss } from '../core/shape-fill.js';\nimport ColorPickerDropdown from './ColorPickerDropdown.jsx';\n\ninterface ShapeToolbarProps {\n element: ShapeElement;\n onElementUpdate: (element: ShapeElement) => void;\n /**\n * Colours actually in use elsewhere in the design (text colours,\n * shape fills, strokes, paths, artboard background). Surfaced in\n * the colour picker so users can match an existing colour. Pass\n * `[]` (or omit) to fall back to the artboard-preset palette.\n */\n documentColors?: string[];\n /**\n * Dominant colours sampled from image elements in the design.\n * Surfaced as a separate \"Image colors\" row in the colour picker.\n */\n imageColors?: string[];\n showUngroupButton?: boolean;\n onUngroup?: () => void;\n onMoveForward?: () => void;\n onMoveBackward?: () => void;\n onOpenShapeTypeDrawer?: () => void;\n /** Callback when element should be deleted */\n onDelete?: () => void;\n /** Whether the rotation panel is expanded */\n rotationExpanded?: boolean;\n /** Callback when rotation panel should be toggled */\n onRotationToggle?: () => void;\n /** Whether the corner radius panel is expanded */\n cornerRadiusExpanded?: boolean;\n /** Callback when corner radius panel should be toggled */\n onCornerRadiusToggle?: () => void;\n /** Whether the transparency/opacity panel is expanded */\n transparencyExpanded?: boolean;\n /** Callback when transparency panel should be toggled */\n onTransparencyToggle?: () => void;\n /** Whether the sides panel is expanded (polygon) */\n sidesExpanded?: boolean;\n /** Callback when sides panel should be toggled */\n onSidesToggle?: () => void;\n /** Whether the points panel is expanded (star) */\n pointsExpanded?: boolean;\n /** Callback when points panel should be toggled */\n onPointsToggle?: () => void;\n /** Whether the inner radius panel is expanded (star) */\n innerRadiusExpanded?: boolean;\n /** Callback when inner radius panel should be toggled */\n onInnerRadiusToggle?: () => void;\n /** Whether the fill color panel is expanded */\n colorExpanded?: boolean;\n /** Callback when fill color panel should be toggled */\n onColorToggle?: () => void;\n /** Whether the stroke panel is expanded */\n strokeExpanded?: boolean;\n /** Callback when stroke panel should be toggled */\n onStrokeToggle?: () => void;\n /** Whether the shadow panel is expanded */\n shadowExpanded?: boolean;\n /** Callback when shadow panel should be toggled */\n onShadowToggle?: () => void;\n /** Whether the blend mode panel is expanded */\n blendModeExpanded?: boolean;\n /** Callback when blend mode panel should be toggled */\n onBlendModeToggle?: () => void;\n /** Whether the knockout panel is expanded */\n knockoutExpanded?: boolean;\n /** Callback when knockout panel should be toggled */\n onKnockoutToggle?: () => void;\n /** Whether the distress texture panel is expanded */\n distressTextureExpanded?: boolean;\n /** Callback when distress texture panel should be toggled */\n onDistressTextureToggle?: () => void;\n /** Whether the image mask panel is expanded */\n imageMaskExpanded?: boolean;\n /** Callback when image mask panel should be toggled */\n onImageMaskToggle?: () => void;\n}\n\nconst ShapeToolbar: React.FC<ShapeToolbarProps> = ({\n element,\n onElementUpdate,\n documentColors,\n imageColors,\n showUngroupButton = false,\n onUngroup,\n onMoveForward,\n onMoveBackward,\n onOpenShapeTypeDrawer,\n onDelete,\n rotationExpanded = false,\n onRotationToggle,\n cornerRadiusExpanded = false,\n onCornerRadiusToggle,\n transparencyExpanded = false,\n onTransparencyToggle,\n sidesExpanded = false,\n onSidesToggle,\n pointsExpanded = false,\n onPointsToggle,\n innerRadiusExpanded = false,\n onInnerRadiusToggle,\n colorExpanded = false,\n onColorToggle,\n strokeExpanded = false,\n onStrokeToggle,\n shadowExpanded = false,\n onShadowToggle,\n blendModeExpanded = false,\n onBlendModeToggle,\n knockoutExpanded = false,\n onKnockoutToggle,\n distressTextureExpanded = false,\n onDistressTextureToggle,\n imageMaskExpanded = false,\n onImageMaskToggle,\n}) => {\n const [moreMenuOpen, setMoreMenuOpen] = useState<boolean>(false);\n const [shapeTypeTooltipDisabled, setShapeTypeTooltipDisabled] = useState<boolean>(false);\n const [rotationTooltipDisabled, setRotationTooltipDisabled] = useState<boolean>(false);\n const [cornerRadiusTooltipDisabled, setCornerRadiusTooltipDisabled] = useState<boolean>(false);\n const [transparencyTooltipDisabled, setTransparencyTooltipDisabled] = useState<boolean>(false);\n const [sidesTooltipDisabled, setSidesTooltipDisabled] = useState<boolean>(false);\n const [pointsTooltipDisabled, setPointsTooltipDisabled] = useState<boolean>(false);\n const [innerRadiusTooltipDisabled, setInnerRadiusTooltipDisabled] = useState<boolean>(false);\n const [colorTooltipDisabled, setColorTooltipDisabled] = useState<boolean>(false);\n const [strokeTooltipDisabled, setStrokeTooltipDisabled] = useState<boolean>(false);\n const [shadowTooltipDisabled, setShadowTooltipDisabled] = useState<boolean>(false);\n const [blendModeTooltipDisabled, setBlendModeTooltipDisabled] = useState<boolean>(false);\n const [knockoutTooltipDisabled, setKnockoutTooltipDisabled] = useState<boolean>(false);\n const [distressTooltipDisabled, setDistressTooltipDisabled] = useState<boolean>(false);\n const [imageMaskTooltipDisabled, setImageMaskTooltipDisabled] = useState<boolean>(false);\n\n // Prefer colours from the active design (passed in by\n // ContextualToolbars) so users can match a colour they're already\n // using. Fall back to the artboard-preset palette only when the\n // design has no colours yet.\n const presetDocumentColors = useMemo(() => ARTBOARD_COLORS.map((c) => c.color), []);\n const effectiveDocumentColors = useMemo(() => {\n if (documentColors && documentColors.length > 0) return documentColors;\n return presetDocumentColors;\n }, [documentColors, presetDocumentColors]);\n\n // Feature-applied flags — drive the \"selected\" highlight on the\n // toolbar buttons whose underlying property has been set to a\n // non-default value.\n const applied = getFeatureApplied(element);\n\n const handleFillColorChange = (e: { target: { value: string } }) => {\n const updatedElement = element.clone();\n updatedElement.transformData.fillColor = e.target.value;\n // A rich `fill` wins over `fillColor` at render time — clear it so the\n // picked solid color is what actually renders.\n delete updatedElement.transformData.fill;\n onElementUpdate(updatedElement);\n };\n\n // Shape labels for the tooltip — the toolbar button itself uses\n // a generic \"shapes picker\" icon (icons.shapes) rather than the\n // current shape's outline. Showing the current shape made it look\n // like a static label, so users couldn't discover that tapping it\n // opens a picker. The label still names the current shape so the\n // hover tooltip (\"Change Shape (Star)\") gives context.\n const shapeTypeLabels: Record<ShapeType, string> = {\n rectangle: 'Rectangle',\n circle: 'Circle',\n ellipse: 'Ellipse',\n triangle: 'Triangle',\n polygon: 'Polygon',\n star: 'Star',\n line: 'Line',\n };\n\n const currentShapeType = element.transformData.shapeType;\n const currentLabel = shapeTypeLabels[currentShapeType] || 'Shape';\n\n return (\n <div className=\"sc-toolbar-items\">\n {/* Shape Type Button - Opens Drawer (picker affordance) */}\n {onOpenShapeTypeDrawer && (\n <ToolbarButton\n icon={icons.shapes}\n onClick={() => {\n setShapeTypeTooltipDisabled(true);\n onOpenShapeTypeDrawer();\n }}\n onMouseLeave={() => setShapeTypeTooltipDisabled(false)}\n tooltip={`Change Shape (${currentLabel})`}\n tooltipDisabled={shapeTypeTooltipDisabled}\n />\n )}\n\n {/* Fill Color Button - toggles secondary panel */}\n {onColorToggle ? (\n <Tooltip delay={300}>\n <TooltipTrigger asChild>\n <button\n className=\"sc-toolbar-btn\"\n onClick={() => {\n setColorTooltipDisabled(true);\n onColorToggle();\n }}\n onMouseLeave={() => setColorTooltipDisabled(false)}\n aria-label=\"Fill Color\"\n data-active={colorExpanded}\n >\n <div\n className=\"sc:h-6 sc:w-6 sc:rounded-md sc:border sc:border-border-primary\"\n style={{ background: shapeFillToCss(element.transformData.fill, element.transformData.fillColor) }}\n />\n </button>\n </TooltipTrigger>\n {!colorTooltipDisabled && !colorExpanded && <TooltipContent>Fill Color</TooltipContent>}\n </Tooltip>\n ) : (\n <Tooltip delay={300}>\n <TooltipTrigger asChild>\n <div>\n <ColorPickerDropdown\n value={element.transformData.fillColor || '#3b82f6'}\n onChange={handleFillColorChange}\n documentColors={effectiveDocumentColors}\n imageColors={imageColors}\n showSquare={true}\n />\n </div>\n </TooltipTrigger>\n <TooltipContent>Fill Color</TooltipContent>\n </Tooltip>\n )}\n\n {/* Border Radius (Rectangle only) - toggles secondary panel */}\n {element.transformData.shapeType === 'rectangle' && onCornerRadiusToggle && (\n <ToolbarButton\n icon=\"lucide:square-round-corner\"\n onClick={() => {\n setCornerRadiusTooltipDisabled(true);\n onCornerRadiusToggle();\n }}\n onMouseLeave={() => setCornerRadiusTooltipDisabled(false)}\n tooltip=\"Corner Radius\"\n tooltipDisabled={cornerRadiusTooltipDisabled || cornerRadiusExpanded}\n active={cornerRadiusExpanded || applied.cornerRadius}\n />\n )}\n\n {/* Sides (Polygon only) - toggles secondary panel */}\n {element.transformData.shapeType === 'polygon' && onSidesToggle && (\n <ToolbarButton\n icon=\"healthicons:polygon\"\n onClick={() => {\n setSidesTooltipDisabled(true);\n onSidesToggle();\n }}\n onMouseLeave={() => setSidesTooltipDisabled(false)}\n tooltip=\"Sides\"\n tooltipDisabled={sidesTooltipDisabled || sidesExpanded}\n active={sidesExpanded}\n />\n )}\n\n {/* Points (Star only) - toggles secondary panel */}\n {element.transformData.shapeType === 'star' && onPointsToggle && (\n <ToolbarButton\n icon=\"material-symbols:award-star-outline\"\n onClick={() => {\n setPointsTooltipDisabled(true);\n onPointsToggle();\n }}\n onMouseLeave={() => setPointsTooltipDisabled(false)}\n tooltip=\"Points\"\n tooltipDisabled={pointsTooltipDisabled || pointsExpanded}\n active={pointsExpanded}\n />\n )}\n\n {/* Inner Radius (Star only) - toggles secondary panel */}\n {element.transformData.shapeType === 'star' && onInnerRadiusToggle && (\n <ToolbarButton\n icon=\"lucide:circle-dashed\"\n onClick={() => {\n setInnerRadiusTooltipDisabled(true);\n onInnerRadiusToggle();\n }}\n onMouseLeave={() => setInnerRadiusTooltipDisabled(false)}\n tooltip=\"Inner Radius\"\n tooltipDisabled={innerRadiusTooltipDisabled || innerRadiusExpanded}\n active={innerRadiusExpanded}\n />\n )}\n\n {/* Transparency - toggles secondary panel */}\n {onTransparencyToggle && (\n <ToolbarButton\n icon=\"lucide:blend\"\n onClick={() => {\n setTransparencyTooltipDisabled(true);\n onTransparencyToggle();\n }}\n onMouseLeave={() => setTransparencyTooltipDisabled(false)}\n tooltip=\"Transparency\"\n tooltipDisabled={transparencyTooltipDisabled || transparencyExpanded}\n active={transparencyExpanded || applied.shapeTransparency}\n />\n )}\n\n {/* Rotate - toggles rotation panel */}\n {onRotationToggle && (\n <ToolbarButton\n icon={<RotateLeftIcon size={20} className=\"sc:md:size-5\" />}\n onClick={() => {\n setRotationTooltipDisabled(true);\n onRotationToggle();\n }}\n onMouseLeave={() => setRotationTooltipDisabled(false)}\n tooltip=\"Rotate\"\n tooltipDisabled={rotationTooltipDisabled || rotationExpanded}\n active={rotationExpanded || applied.rotation}\n />\n )}\n\n {/* Knockout */}\n {onKnockoutToggle && (\n <ToolbarButton\n icon=\"lucide:scissors\"\n onClick={() => {\n setKnockoutTooltipDisabled(true);\n onKnockoutToggle();\n }}\n onMouseLeave={() => setKnockoutTooltipDisabled(false)}\n tooltip=\"Clip / Knockout\"\n tooltipDisabled={knockoutTooltipDisabled || knockoutExpanded}\n active={knockoutExpanded || applied.knockout}\n />\n )}\n\n {/* Distress Texture */}\n {onDistressTextureToggle && (\n <ToolbarButton\n icon=\"lucide:stamp\"\n onClick={() => {\n setDistressTooltipDisabled(true);\n onDistressTextureToggle();\n }}\n onMouseLeave={() => setDistressTooltipDisabled(false)}\n tooltip=\"Distress Texture\"\n tooltipDisabled={distressTooltipDisabled || distressTextureExpanded}\n active={distressTextureExpanded || applied.distress}\n />\n )}\n\n {/* Image Mask */}\n {onImageMaskToggle && (\n <ToolbarButton\n icon=\"lucide:venetian-mask\"\n onClick={() => {\n setImageMaskTooltipDisabled(true);\n onImageMaskToggle();\n }}\n onMouseLeave={() => setImageMaskTooltipDisabled(false)}\n tooltip=\"Image Mask\"\n tooltipDisabled={imageMaskTooltipDisabled || imageMaskExpanded}\n active={imageMaskExpanded || applied.imageMask}\n />\n )}\n\n {/* Stroke */}\n {onStrokeToggle && (\n <ToolbarButton\n icon=\"lucide:pen-line\"\n onClick={() => {\n setStrokeTooltipDisabled(true);\n onStrokeToggle();\n }}\n onMouseLeave={() => setStrokeTooltipDisabled(false)}\n tooltip=\"Stroke\"\n tooltipDisabled={strokeTooltipDisabled || strokeExpanded}\n active={strokeExpanded || applied.stroke}\n />\n )}\n\n {/* Shadow */}\n {onShadowToggle && (\n <ToolbarButton\n icon=\"gravity-ui:square-dashed-circle\"\n onClick={() => {\n setShadowTooltipDisabled(true);\n onShadowToggle();\n }}\n onMouseLeave={() => setShadowTooltipDisabled(false)}\n tooltip=\"Shadow\"\n tooltipDisabled={shadowTooltipDisabled || shadowExpanded}\n active={shadowExpanded || applied.shadow}\n />\n )}\n\n {/* Blend Mode */}\n {onBlendModeToggle && (\n <ToolbarButton\n icon=\"gravity-ui:circles-intersection\"\n onClick={() => {\n setBlendModeTooltipDisabled(true);\n onBlendModeToggle();\n }}\n onMouseLeave={() => setBlendModeTooltipDisabled(false)}\n tooltip=\"Blend Mode\"\n tooltipDisabled={blendModeTooltipDisabled || blendModeExpanded}\n active={blendModeExpanded || applied.blendMode}\n />\n )}\n\n {/* More Menu - overflow menu for additional options */}\n {(onMoveForward || onMoveBackward || onDelete) && (\n <Popover open={moreMenuOpen} onOpenChange={setMoreMenuOpen}>\n <PopoverTrigger asChild>\n <button className=\"sc-toolbar-btn\" aria-label=\"More options\">\n <Icon icon=\"lucide:ellipsis-vertical\" className=\"sc:size-6\" />\n </button>\n </PopoverTrigger>\n <PopoverContent align=\"end\" className=\"sc:w-auto sc:p-1\" maxZIndex>\n <div className=\"sc:flex sc:items-center sc:gap-1\">\n {onMoveForward && (\n <Tooltip delayDuration={300}>\n <TooltipTrigger asChild>\n <Button\n variant=\"ghost\"\n size=\"icon\"\n onClick={() => {\n onMoveForward();\n setMoreMenuOpen(false);\n }}\n aria-label=\"Move Forward\"\n >\n <Icon icon=\"hugeicons:layer-bring-forward\" className=\"sc:size-5\" />\n </Button>\n </TooltipTrigger>\n <TooltipContent>Move Forward</TooltipContent>\n </Tooltip>\n )}\n {onMoveBackward && (\n <Tooltip delayDuration={300}>\n <TooltipTrigger asChild>\n <Button\n variant=\"ghost\"\n size=\"icon\"\n onClick={() => {\n onMoveBackward();\n setMoreMenuOpen(false);\n }}\n aria-label=\"Move Backward\"\n >\n <Icon icon=\"hugeicons:layer-send-backward\" className=\"sc:size-5\" />\n </Button>\n </TooltipTrigger>\n <TooltipContent>Move Backward</TooltipContent>\n </Tooltip>\n )}\n {onDelete && (\n <Tooltip delayDuration={300}>\n <TooltipTrigger asChild>\n <Button\n variant=\"ghost\"\n size=\"icon\"\n onClick={() => {\n setMoreMenuOpen(false);\n onDelete();\n }}\n aria-label=\"Delete\"\n >\n <Icon icon={icons.trash} className=\"sc:size-5\" />\n </Button>\n </TooltipTrigger>\n <TooltipContent>Delete</TooltipContent>\n </Tooltip>\n )}\n </div>\n </PopoverContent>\n </Popover>\n )}\n\n {/* Ungroup button - shown when editing a child in a group */}\n {showUngroupButton && onUngroup && (\n <Tooltip delay={300}>\n <TooltipTrigger asChild>\n <Button variant=\"ghost\" size=\"sm\" onClick={onUngroup}>\n Ungroup\n </Button>\n </TooltipTrigger>\n <TooltipContent>Ungroup this group</TooltipContent>\n </Tooltip>\n )}\n </div>\n );\n};\n\nexport default ShapeToolbar;\n","/**\n * PathToolbar - Toolbar for path-specific controls\n * Handles stroke color, width, fill properties, and path editing\n */\n\nimport React, { useState } from 'react';\nimport { Icon } from '@iconify/react';\nimport { Button, Popover, PopoverTrigger, PopoverContent, Slider, Tooltip, TooltipTrigger, TooltipContent, Label } from './ui';\nimport { PathElement } from '../core/PathElement';\nimport { ARTBOARD_COLORS } from '../presets/artboard-color-presets.js';\n\ninterface PathToolbarProps {\n element: PathElement;\n onElementUpdate: (element: PathElement) => void;\n onMoveForward?: () => void;\n onMoveBackward?: () => void;\n}\n\nconst PathToolbar: React.FC<PathToolbarProps> = ({ element, onElementUpdate, onMoveForward, onMoveBackward }) => {\n const [strokeColorOpen, setStrokeColorOpen] = useState<boolean>(false);\n const [fillColorOpen, setFillColorOpen] = useState<boolean>(false);\n const [strokeWidthOpen, setStrokeWidthOpen] = useState<boolean>(false);\n\n const handleStrokeColorChange = (color: string) => {\n const updatedElement = element.clone();\n updatedElement.transformData.strokeColor = color;\n onElementUpdate(updatedElement);\n setStrokeColorOpen(false);\n };\n\n const handleFillColorChange = (color: string) => {\n const updatedElement = element.clone();\n updatedElement.transformData.fillColor = color;\n onElementUpdate(updatedElement);\n setFillColorOpen(false);\n };\n\n const handleStrokeEnabledToggle = () => {\n const updatedElement = element.clone();\n updatedElement.transformData.strokeEnabled = !updatedElement.transformData.strokeEnabled;\n onElementUpdate(updatedElement);\n };\n\n const handleFillEnabledToggle = () => {\n const updatedElement = element.clone();\n updatedElement.transformData.fillEnabled = !updatedElement.transformData.fillEnabled;\n onElementUpdate(updatedElement);\n };\n\n const handleStrokeWidthChange = (value: number) => {\n const updatedElement = element.clone();\n updatedElement.transformData.strokeWidth = value;\n onElementUpdate(updatedElement);\n };\n\n const strokeColor = element.transformData.strokeColor || '#000000';\n const fillColor = element.transformData.fillColor || '#3b82f6';\n const strokeEnabled = element.transformData.strokeEnabled ?? true;\n const fillEnabled = element.transformData.fillEnabled ?? false;\n const strokeWidth = element.transformData.strokeWidth ?? 2;\n const isClosed = element.transformData.closed;\n const pointCount = element.transformData.points.length;\n\n return (\n <div className=\"sc:fixed sc:top-3xl sc:left-1/2 sc:-translate-x-1/2 sc:flex sc:items-center sc:gap-md sc:px-xl sc:py-md sc:bg-bg-primary sc:rounded-xl sc:shadow-md\" style={{ zIndex: 'var(--sc-z-dropdown)' }}>\n {/* Path Info */}\n <div className=\"sc:px-xl sc:text-base sc:text-text-muted sc:border-r sc:border-border-primary\">\n <span className=\"sc:font-semibold\">Path</span>\n <span className=\"sc:ml-md sc:text-text-placeholder\">\n {pointCount} {pointCount === 1 ? 'point' : 'points'}\n {isClosed && ' • Closed'}\n </span>\n </div>\n\n {/* Stroke Enabled Toggle */}\n <Tooltip delay={300}>\n <TooltipTrigger asChild>\n <Button\n variant={strokeEnabled ? 'default' : 'ghost'}\n onClick={handleStrokeEnabledToggle}\n className=\"sc:px-xl sc:text-base\"\n >\n Stroke\n </Button>\n </TooltipTrigger>\n <TooltipContent>{strokeEnabled ? 'Disable Stroke' : 'Enable Stroke'}</TooltipContent>\n </Tooltip>\n\n {/* Stroke Color Picker */}\n {strokeEnabled && (\n <Popover open={strokeColorOpen} onOpenChange={setStrokeColorOpen}>\n <PopoverTrigger asChild>\n <button\n className=\"sc:w-8 sc:h-8 sc:p-xs sc:rounded-md sc:border-2 sc:border-border-primary sc:cursor-pointer sc:transition-transform sc:hover:scale-105\"\n style={{ background: strokeColor }}\n title=\"Stroke Color\"\n />\n </PopoverTrigger>\n <PopoverContent align=\"start\" className=\"sc:p-0\">\n <div className=\"sc:bg-bg-primary sc:rounded-xl sc:shadow-lg sc:p-6 sc:min-w-[240px]\">\n <div className=\"sc:grid sc:grid-cols-6 sc:gap-sm sc:mb-md\">\n {ARTBOARD_COLORS.map((color) => (\n <Button\n key={color.color}\n onClick={() => handleStrokeColorChange(color.color)}\n aria-label={color.name}\n className={`sc:w-8 sc:h-8 sc:rounded-md sc:cursor-pointer sc:transition-all sc:min-h-0 sc:min-w-0 sc:p-0 ${\n strokeColor === color.color\n ? 'sc:border-2 sc:border-accent-primary sc:scale-110'\n : 'sc:border sc:border-border-primary sc:hover:scale-105'\n }`}\n style={{ background: color.color }}\n />\n ))}\n </div>\n <input\n type=\"color\"\n value={strokeColor}\n onChange={(e) => handleStrokeColorChange(e.target.value)}\n className=\"sc:w-full sc:h-8 sc:cursor-pointer sc:rounded-md sc:border sc:border-border-primary\"\n />\n </div>\n </PopoverContent>\n </Popover>\n )}\n\n {/* Stroke Width */}\n {strokeEnabled && (\n <Popover open={strokeWidthOpen} onOpenChange={setStrokeWidthOpen}>\n <PopoverTrigger asChild>\n <Button variant=\"ghost\" className=\"sc:px-xl sc:text-base\">\n {strokeWidth}px\n </Button>\n </PopoverTrigger>\n <PopoverContent align=\"start\" className=\"sc:p-0\">\n <div className=\"sc:bg-bg-primary sc:rounded-xl sc:shadow-lg sc:p-6 sc:min-w-[200px]\">\n <Slider\n value={[strokeWidth]}\n onValueChange={(val) => handleStrokeWidthChange(val[0])}\n min={1}\n max={20}\n step={0.5}\n className=\"slider-no-fill sc:w-full\"\n >\n <Label>Width (px)</Label>\n <Slider.Output />\n <Slider.Track />\n <Slider.Thumb />\n </Slider>\n </div>\n </PopoverContent>\n </Popover>\n )}\n\n <div className=\"sc:w-px sc:h-6 sc:bg-border-primary sc:mx-xs\" />\n\n {/* Fill Enabled Toggle */}\n <Tooltip delay={300}>\n <TooltipTrigger asChild>\n <Button\n variant={fillEnabled ? 'default' : 'ghost'}\n onClick={handleFillEnabledToggle}\n className=\"sc:px-xl sc:text-base\"\n >\n Fill\n </Button>\n </TooltipTrigger>\n <TooltipContent>{fillEnabled ? 'Disable Fill' : 'Enable Fill'}</TooltipContent>\n </Tooltip>\n\n {/* Fill Color Picker */}\n {fillEnabled && (\n <Popover open={fillColorOpen} onOpenChange={setFillColorOpen}>\n <PopoverTrigger asChild>\n <button\n className=\"sc:w-8 sc:h-8 sc:p-xs sc:rounded-md sc:border-2 sc:border-border-primary sc:cursor-pointer sc:transition-transform sc:hover:scale-105\"\n style={{ background: fillColor }}\n title=\"Fill Color\"\n />\n </PopoverTrigger>\n <PopoverContent align=\"start\" className=\"sc:p-0\">\n <div className=\"sc:bg-bg-primary sc:rounded-xl sc:shadow-lg sc:p-6 sc:min-w-[240px]\">\n <div className=\"sc:grid sc:grid-cols-6 sc:gap-sm sc:mb-md\">\n {ARTBOARD_COLORS.map((color) => (\n <Button\n key={color.color}\n onClick={() => handleFillColorChange(color.color)}\n aria-label={color.name}\n className={`sc:w-8 sc:h-8 sc:rounded-md sc:cursor-pointer sc:transition-all sc:min-h-0 sc:min-w-0 sc:p-0 ${\n fillColor === color.color\n ? 'sc:border-2 sc:border-accent-primary sc:scale-110'\n : 'sc:border sc:border-border-primary sc:hover:scale-105'\n }`}\n style={{ background: color.color }}\n />\n ))}\n </div>\n <input\n type=\"color\"\n value={fillColor}\n onChange={(e) => handleFillColorChange(e.target.value)}\n className=\"sc:w-full sc:h-8 sc:cursor-pointer sc:rounded-md sc:border sc:border-border-primary\"\n />\n </div>\n </PopoverContent>\n </Popover>\n )}\n\n <div className=\"sc:w-px sc:h-6 sc:bg-border-primary sc:mx-xs\" />\n\n {/* Layer Order Controls */}\n {onMoveForward && (\n <Tooltip delay={300}>\n <TooltipTrigger asChild>\n <Button variant=\"ghost\" onClick={onMoveForward}>\n <Icon icon=\"hugeicons:layer-bring-forward\" className=\"sc:size-[18px]\" />\n </Button>\n </TooltipTrigger>\n <TooltipContent>Move Forward</TooltipContent>\n </Tooltip>\n )}\n\n {onMoveBackward && (\n <Tooltip delay={300}>\n <TooltipTrigger asChild>\n <Button variant=\"ghost\" onClick={onMoveBackward}>\n <Icon icon=\"hugeicons:layer-send-backward\" className=\"sc:size-[18px]\" />\n </Button>\n </TooltipTrigger>\n <TooltipContent>Move Backward</TooltipContent>\n </Tooltip>\n )}\n </div>\n );\n};\n\nexport default PathToolbar;\n","/**\n * BackgroundPickerDropdown - Unified picker for artboard backgrounds\n * Supports color, texture, and gradient (future) backgrounds\n */\n\nimport { useState, useEffect, memo } from 'react';\nimport { HexColorPicker } from 'react-colorful';\nimport { Button, Popover, PopoverTrigger, PopoverContent, icons } from './ui';\nimport { Icon } from '@iconify/react';\nimport { TextureManager } from '../utils/TextureManager';\nimport type { ArtboardBackgroundType } from '../types/index';\n\nexport interface BackgroundPickerDropdownProps {\n backgroundType: ArtboardBackgroundType;\n backgroundColor: string;\n backgroundTexture?: string;\n onBackgroundTypeChange: (type: ArtboardBackgroundType) => void;\n onColorChange: (color: string) => void;\n onTextureChange: (textureId: string) => void;\n}\n\ntype BackgroundTab = 'color' | 'texture' | 'gradient';\n\nconst BackgroundPickerDropdown = memo(({\n backgroundType,\n backgroundColor,\n backgroundTexture,\n onBackgroundTypeChange,\n onColorChange,\n onTextureChange,\n}: BackgroundPickerDropdownProps) => {\n const [isOpen, setIsOpen] = useState(false);\n const [activeTab, setActiveTab] = useState<BackgroundTab>('color');\n const [hexInput, setHexInput] = useState(backgroundColor);\n\n // Sync active tab with background type\n useEffect(() => {\n if (backgroundType === 'texture') {\n setActiveTab('texture');\n } else {\n setActiveTab('color');\n }\n }, [backgroundType]);\n\n // Sync hex input with color prop\n useEffect(() => {\n if (backgroundColor !== 'transparent') {\n setHexInput(backgroundColor);\n }\n }, [backgroundColor]);\n\n const handleColorChange = (color: string) => {\n setHexInput(color);\n onColorChange(color);\n onBackgroundTypeChange('color');\n };\n\n const handleHexInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {\n const input = e.target.value;\n setHexInput(input);\n\n // Validate hex color (with or without #)\n const hexPattern = /^#?([0-9A-Fa-f]{6}|[0-9A-Fa-f]{3})$/;\n const withHash = input.startsWith('#') ? input : `#${input}`;\n\n if (hexPattern.test(withHash)) {\n onColorChange(withHash);\n onBackgroundTypeChange('color');\n }\n };\n\n const handleTransparentClick = () => {\n onColorChange('transparent');\n onBackgroundTypeChange('transparent');\n };\n\n const handleTextureClick = (textureId: string) => {\n onTextureChange(textureId);\n onBackgroundTypeChange('texture');\n };\n\n const handleTabChange = (tab: BackgroundTab) => {\n setActiveTab(tab);\n if (tab === 'color') {\n onBackgroundTypeChange(backgroundColor === 'transparent' ? 'transparent' : 'color');\n } else if (tab === 'texture') {\n if (!backgroundTexture) {\n // Set default texture if none is set\n const defaultTexture = TextureManager.getAllTextures()[0];\n if (defaultTexture) {\n onTextureChange(defaultTexture.id);\n }\n }\n onBackgroundTypeChange('texture');\n }\n };\n\n const isTransparent = backgroundColor === 'transparent';\n\n return (\n <Popover open={isOpen} onOpenChange={setIsOpen}>\n <PopoverTrigger asChild>\n <Button variant={isOpen ? 'default' : 'ghost'} aria-label=\"Background\">\n <Icon icon={icons.palette} className=\"sc:size-[18px]\" />\n </Button>\n </PopoverTrigger>\n <PopoverContent className=\"sc:w-auto sc:p-3\">\n <div className=\"sc:flex sc:min-w-[220px] sc:flex-col sc:gap-3\">\n {/* Tab selector */}\n <div className=\"sc:flex sc:gap-1 sc:border-b sc:border-divider sc:pb-3\">\n <Button\n variant=\"ghost\"\n size=\"sm\"\n className={`sc:flex-1 ${activeTab === 'color' ? 'sc:bg-primary sc:text-primary-foreground' : ''}`}\n onClick={() => handleTabChange('color')}\n >\n Color\n </Button>\n <Button\n variant=\"ghost\"\n size=\"sm\"\n className={`sc:flex-1 ${activeTab === 'texture' ? 'sc:bg-primary sc:text-primary-foreground' : ''}`}\n onClick={() => handleTabChange('texture')}\n >\n Texture\n </Button>\n <Button\n variant=\"ghost\"\n size=\"sm\"\n className=\"sc:flex-1 sc:cursor-not-allowed sc:opacity-50\"\n disabled\n aria-label=\"Gradient (Coming soon)\"\n >\n Gradient\n </Button>\n </div>\n\n {/* Color picker panel */}\n {activeTab === 'color' && (\n <div className=\"sc:flex sc:flex-col sc:gap-3\">\n <Button\n variant=\"ghost\"\n className={`sc:flex sc:w-full sc:cursor-pointer sc:items-center sc:justify-start sc:gap-2 sc:rounded-lg ${isTransparent ? 'sc:bg-primary/10' : ''}`}\n onClick={handleTransparentClick}\n >\n <div className=\"transparent-pattern-small sc:h-6 sc:w-6 sc:rounded\" />\n <span className=\"sc:text-sm sc:font-medium\">Transparent</span>\n </Button>\n\n <HexColorPicker color={isTransparent ? '#ffffff' : backgroundColor} onChange={handleColorChange} />\n\n <div className=\"sc:flex sc:items-center sc:gap-2\">\n <label htmlFor=\"bg-hex-input\" className=\"sc:text-sm sc:font-medium sc:uppercase sc:text-foreground/60\">\n HEX\n </label>\n <input\n id=\"bg-hex-input\"\n type=\"text\"\n className=\"sc:flex-1 sc:rounded-lg sc:border sc:border-divider sc:bg-field sc:px-2 sc:py-1.5 sc:text-sm sc:text-foreground sc:focus:border-primary sc:focus:outline-none\"\n value={hexInput}\n onChange={handleHexInputChange}\n placeholder=\"#000000\"\n maxLength={7}\n />\n </div>\n </div>\n )}\n\n {/* Texture picker panel */}\n {activeTab === 'texture' && (\n <div className=\"sc:flex sc:flex-col sc:gap-3\">\n <div className=\"sc:text-sm sc:font-medium sc:text-foreground/60\">Select a texture</div>\n <div className=\"sc:grid sc:grid-cols-4 sc:gap-1.5\">\n {TextureManager.getAllTextures().map((texture) => (\n <button\n key={texture.id}\n className={`sc:flex sc:items-center sc:justify-center sc:p-1 sc:rounded-lg sc:cursor-pointer sc:transition-all sc:border-2 ${\n backgroundTexture === texture.id\n ? 'sc:border-primary'\n : 'sc:border-transparent sc:hover:border-primary/50'\n }`}\n onClick={() => handleTextureClick(texture.id)}\n aria-label={texture.name}\n >\n <img src={texture.url} alt={texture.name} className=\"sc:w-full sc:h-full sc:rounded\" />\n </button>\n ))}\n </div>\n </div>\n )}\n\n {/* Gradient picker panel (future) */}\n {activeTab === 'gradient' && (\n <div className=\"sc:flex sc:flex-col sc:items-center sc:justify-center sc:gap-3 sc:py-8 sc:text-foreground/60\">\n <div className=\"sc:text-sm\">Gradient backgrounds</div>\n <div className=\"sc:text-xs\">Coming soon</div>\n </div>\n )}\n </div>\n </PopoverContent>\n </Popover>\n );\n});\n\nBackgroundPickerDropdown.displayName = 'BackgroundPickerDropdown';\n\nexport default BackgroundPickerDropdown;\n","/**\n * ArtboardDistressPanel - UI panel for artboard-level distress texture\n *\n * Allows applying a grayscale texture as an alpha mask over all elements\n * on the artboard. Dark areas knock out pixels, light areas preserve them.\n */\n\nimport React, { useCallback } from 'react';\nimport type { ArtboardDistressTexture } from '../types/index.js';\nimport { DISTRESS_TEXTURE_PRESETS, ensureBuiltinTexturesReady } from '../effects/distress-textures.js';\nimport { preloadTexture } from '../effects/DistressTextureCache.js';\nimport {\n Disclosure,\n DisclosureTrigger,\n DisclosureContent,\n Switch,\n Label,\n SliderRow,\n PresetCarousel,\n} from './ui';\nimport type { PresetItem } from './ui';\n\ninterface ArtboardDistressPanelProps {\n distressTexture?: ArtboardDistressTexture;\n onChange: (distressTexture: ArtboardDistressTexture | undefined) => void;\n}\n\nconst ArtboardDistressPanel = ({ distressTexture, onChange }: ArtboardDistressPanelProps) => {\n ensureBuiltinTexturesReady();\n\n const enabled = distressTexture?.enabled || false;\n const textureUrl = distressTexture?.textureUrl || '';\n const intensity = distressTexture?.intensity ?? 50;\n\n const presetItems: PresetItem[] = DISTRESS_TEXTURE_PRESETS.map((p) => ({ id: p.textureUrl, name: p.name, thumbnailUrl: p.thumbnailUrl }));\n\n const handleEnabledChange = (newEnabled: boolean) => {\n if (newEnabled) {\n const url = textureUrl || DISTRESS_TEXTURE_PRESETS[0].textureUrl;\n preloadTexture(url);\n onChange({\n enabled: true,\n textureUrl: url,\n intensity,\n });\n } else {\n onChange(undefined);\n }\n };\n\n const handleTextureSelect = useCallback(\n (id: string) => {\n preloadTexture(id);\n onChange({\n enabled: true,\n textureUrl: id,\n intensity,\n });\n },\n [onChange, intensity]\n );\n\n const handleIntensityChange = (value: number[]) => {\n if (!distressTexture) return;\n onChange({\n ...distressTexture,\n intensity: value[0],\n });\n };\n\n return (\n <Disclosure open={enabled} onOpenChange={handleEnabledChange} className=\"sc:mb-xl\">\n <DisclosureTrigger className=\"sc:w-full\">\n <div className=\"sc:flex sc:items-center sc:justify-between sc:w-full\">\n <Label>Distress Texture</Label>\n <Switch\n checked={enabled}\n onCheckedChange={handleEnabledChange}\n onClick={(e: React.MouseEvent) => e.stopPropagation()}\n />\n </div>\n </DisclosureTrigger>\n <DisclosureContent className=\"sc:flex sc:flex-col sc:gap-lg sc:py-lg\">\n <PresetCarousel\n presets={presetItems}\n selectedId={textureUrl}\n onSelect={handleTextureSelect}\n showOff={false}\n ariaLabel=\"Distress texture presets\"\n />\n\n {/* Intensity slider */}\n <SliderRow\n label=\"Intensity\"\n value={intensity}\n onChange={(v) => handleIntensityChange([v])}\n min={0}\n max={100}\n step={1}\n unit=\"%\"\n />\n </DisclosureContent>\n </Disclosure>\n );\n};\n\nexport default ArtboardDistressPanel;\n","/**\n * ArtboardImageMaskPanel - UI panel for artboard-level image mask\n *\n * Allows applying an image mask over all elements on the artboard.\n * Supports clip, alpha, and luma mask types with inversion and opacity.\n */\n\nimport React, { useCallback } from 'react';\nimport type { ArtboardImageMask } from '../types/index.js';\nimport { MASK_IMAGE_PRESETS, ensureMaskPresetsReady } from '../effects/mask-presets.js';\nimport {\n Disclosure,\n DisclosureTrigger,\n DisclosureContent,\n Switch,\n Label,\n SliderRow,\n Checkbox,\n PresetCarousel,\n} from './ui';\nimport type { PresetItem } from './ui';\n\ninterface ArtboardImageMaskPanelProps {\n imageMask?: ArtboardImageMask;\n onChange: (imageMask: ArtboardImageMask | undefined) => void;\n}\n\nconst ArtboardImageMaskPanel = ({ imageMask, onChange }: ArtboardImageMaskPanelProps) => {\n ensureMaskPresetsReady();\n\n const enabled = imageMask?.enabled || false;\n const imageUrl = imageMask?.imageUrl || '';\n const maskType = imageMask?.maskType || 'clip';\n const opacity = imageMask?.opacity ?? 100;\n const inverted = imageMask?.inverted ?? false;\n\n const presetItems: PresetItem[] = MASK_IMAGE_PRESETS.map((p) => ({ id: p.imageUrl, name: p.name, thumbnailUrl: p.thumbnailUrl }));\n\n const handleEnabledChange = (newEnabled: boolean) => {\n if (newEnabled) {\n const url = imageUrl || MASK_IMAGE_PRESETS[0].imageUrl;\n onChange({\n enabled: true,\n imageUrl: url,\n maskType,\n opacity,\n inverted,\n });\n } else {\n onChange(undefined);\n }\n };\n\n const handleImageSelect = useCallback(\n (id: string) => {\n onChange({\n enabled: true,\n imageUrl: id,\n maskType,\n opacity,\n inverted,\n });\n },\n [onChange, maskType, opacity, inverted]\n );\n\n const handleMaskTypeChange = (type: 'clip' | 'alpha' | 'luma') => {\n if (!imageMask) return;\n onChange({ ...imageMask, maskType: type });\n };\n\n const handleOpacityChange = (value: number[]) => {\n if (!imageMask) return;\n onChange({ ...imageMask, opacity: value[0] });\n };\n\n const handleInvertedChange = (checked: boolean) => {\n if (!imageMask) return;\n onChange({ ...imageMask, inverted: checked });\n };\n\n return (\n <Disclosure open={enabled} onOpenChange={handleEnabledChange} className=\"sc:mb-xl\">\n <DisclosureTrigger className=\"sc:w-full\">\n <div className=\"sc:flex sc:items-center sc:justify-between sc:w-full\">\n <Label>Image Mask</Label>\n <Switch\n checked={enabled}\n onCheckedChange={handleEnabledChange}\n onClick={(e: React.MouseEvent) => e.stopPropagation()}\n />\n </div>\n </DisclosureTrigger>\n <DisclosureContent className=\"sc:flex sc:flex-col sc:gap-lg sc:py-lg\">\n <PresetCarousel\n presets={presetItems}\n selectedId={imageUrl}\n onSelect={handleImageSelect}\n showOff={false}\n ariaLabel=\"Image mask presets\"\n />\n\n {/* Mask type selector */}\n <div className=\"sc:flex sc:items-center sc:gap-2\">\n <Label className=\"sc:text-sm\">Type</Label>\n <div className=\"sc:flex sc:rounded-md sc:border sc:border-divider sc:overflow-hidden\">\n {(['clip', 'alpha', 'luma'] as const).map((type) => (\n <button\n key={type}\n className={`sc:px-3 sc:py-1 sc:text-xs sc:capitalize sc:transition-colors ${\n maskType === type\n ? 'sc:bg-primary sc:text-primary-foreground'\n : 'sc:text-foreground sc:hover:bg-muted'\n }`}\n onClick={() => handleMaskTypeChange(type)}\n >\n {type}\n </button>\n ))}\n </div>\n </div>\n\n {/* Opacity slider */}\n <SliderRow\n label=\"Opacity\"\n value={opacity}\n onChange={(v) => handleOpacityChange([v])}\n min={0}\n max={100}\n step={1}\n unit=\"%\"\n />\n\n {/* Inverted checkbox */}\n <label className=\"sc:flex sc:items-center sc:gap-2 sc:text-sm sc:text-foreground\">\n <Checkbox checked={inverted} onCheckedChange={(v) => handleInvertedChange(v === true)} />\n Invert Mask\n </label>\n </DisclosureContent>\n </Disclosure>\n );\n};\n\nexport default ArtboardImageMaskPanel;\n","/**\n * ArtboardPropertiesToolbar - Contextual toolbar for editing artboard properties\n * Shows when an artboard is selected (instead of an element)\n */\n\nimport React, { useState, useRef, useEffect } from 'react';\nimport { Icon } from '@iconify/react';\nimport { Button, Switch, Popover, PopoverTrigger, PopoverContent, Label, Tooltip, TooltipTrigger, TooltipContent, Surface, Separator, icons } from './ui';\nimport { ArtboardElement } from '../core/ArtboardElement';\nimport BackgroundPickerDropdown from './BackgroundPickerDropdown';\nimport ArtboardDistressPanel from './ArtboardDistressPanel';\nimport ArtboardImageMaskPanel from './ArtboardImageMaskPanel';\nimport type { ArtboardBackgroundType, ArtboardDistressTexture, ArtboardImageMask } from '../types/index';\n\ninterface ArtboardPropertiesToolbarProps {\n artboard: ArtboardElement;\n artboards: ArtboardElement[];\n onArtboardUpdate: (artboard: ArtboardElement) => void;\n onRenameArtboard: (artboardId: string, newName: string) => void;\n onDeleteArtboard: (artboardId: string) => void;\n artboardScreenBounds?: {\n left: number;\n top: number;\n width: number;\n height: number;\n bottom: number;\n centerX: number;\n };\n}\n\nconst ArtboardPropertiesToolbar: React.FC<ArtboardPropertiesToolbarProps> = ({\n artboard,\n artboards,\n onArtboardUpdate,\n onRenameArtboard,\n onDeleteArtboard,\n artboardScreenBounds,\n}) => {\n const [isEditing, setIsEditing] = useState(false);\n const [editingName, setEditingName] = useState('');\n const [moreMenuOpen, setMoreMenuOpen] = useState(false);\n const inputRef = useRef<HTMLInputElement>(null);\n\n const handleBackgroundTypeChange = (type: ArtboardBackgroundType) => {\n const updatedArtboard = artboard.clone();\n updatedArtboard.backgroundType = type;\n onArtboardUpdate(updatedArtboard);\n };\n\n const handleColorChange = (color: string) => {\n const updatedArtboard = artboard.clone();\n updatedArtboard.backgroundColor = color;\n onArtboardUpdate(updatedArtboard);\n };\n\n const handleTextureChange = (textureId: string) => {\n const updatedArtboard = artboard.clone();\n updatedArtboard.backgroundTexture = textureId;\n onArtboardUpdate(updatedArtboard);\n };\n\n const handleExportBackgroundToggle = (checked: boolean) => {\n const updatedArtboard = artboard.clone();\n updatedArtboard.exportBackground = checked;\n onArtboardUpdate(updatedArtboard);\n };\n\n const handleDistressTextureChange = (distressTexture: ArtboardDistressTexture | undefined) => {\n const updatedArtboard = artboard.clone();\n updatedArtboard.distressTexture = distressTexture;\n onArtboardUpdate(updatedArtboard);\n };\n\n const handleImageMaskChange = (imageMask: ArtboardImageMask | undefined) => {\n const updatedArtboard = artboard.clone();\n updatedArtboard.imageMask = imageMask;\n onArtboardUpdate(updatedArtboard);\n };\n\n const handleStartEdit = () => {\n setIsEditing(true);\n setEditingName(artboard.name);\n };\n\n const handleSaveEdit = () => {\n if (editingName.trim()) {\n onRenameArtboard(artboard.id, editingName.trim());\n }\n setIsEditing(false);\n setEditingName('');\n };\n\n const handleCancelEdit = () => {\n setIsEditing(false);\n setEditingName('');\n };\n\n const handleKeyDown = (e: React.KeyboardEvent) => {\n if (e.key === 'Enter') {\n handleSaveEdit();\n } else if (e.key === 'Escape') {\n handleCancelEdit();\n }\n };\n\n const handleDelete = () => {\n if (artboards.length <= 1) {\n alert('Cannot delete the last artboard');\n return;\n }\n\n if (artboard.getElementCount() > 0) {\n if (!confirm(`Delete \"${artboard.name}\" with ${artboard.getElementCount()} element(s)?`)) {\n return;\n }\n }\n\n onDeleteArtboard(artboard.id);\n };\n\n // Focus input when editing starts\n useEffect(() => {\n if (isEditing && inputRef.current) {\n inputRef.current.focus();\n inputRef.current.select();\n }\n }, [isEditing]);\n\n return (\n <Surface\n className=\"sc:absolute sc:px-4 sc:py-2 sc:flex sc:items-center sc:gap-2 sc:shadow-lg sc:z-50 sc:rounded-full sc:bg-bg-primary sc:border sc:border-border-primary\"\n style={{\n left: '50%',\n top: artboardScreenBounds ? `${artboardScreenBounds.top - 68}px` : '32px',\n transform: 'translateX(-50%)',\n }}\n >\n {/* Artboard name with edit/delete controls */}\n {isEditing ? (\n <div className=\"sc:flex sc:items-center sc:gap-2\">\n <input\n ref={inputRef}\n type=\"text\"\n value={editingName}\n onChange={(e) => setEditingName(e.target.value)}\n onKeyDown={handleKeyDown}\n className=\"sc:px-3 sc:py-1 sc:border sc:border-border-primary sc:rounded-lg sc:text-base sc:text-text-primary sc:bg-bg-primary sc:outline-none sc:min-w-[120px] sc:transition-colors sc:focus:border-border-focus\"\n />\n <Tooltip delay={300}>\n <TooltipTrigger asChild>\n <Button variant=\"ghost\" onClick={handleSaveEdit} aria-label=\"Save\">\n <Icon icon={icons.check} className=\"sc:size-4\" />\n </Button>\n </TooltipTrigger>\n <TooltipContent>Save</TooltipContent>\n </Tooltip>\n <Tooltip delay={300}>\n <TooltipTrigger asChild>\n <Button variant=\"ghost\" onClick={handleCancelEdit} aria-label=\"Cancel\">\n <Icon icon={icons.close} className=\"sc:size-4\" />\n </Button>\n </TooltipTrigger>\n <TooltipContent>Cancel</TooltipContent>\n </Tooltip>\n </div>\n ) : (\n <div className=\"sc:flex sc:items-center sc:gap-2\">\n <span className=\"sc:text-xl sc:font-semibold sc:text-text-primary\">{artboard.name}</span>\n <Tooltip delay={300}>\n <TooltipTrigger asChild>\n <Button variant=\"ghost\" onClick={handleStartEdit} aria-label=\"Rename\">\n <Icon icon={icons.pencil} className=\"sc:size-4\" />\n </Button>\n </TooltipTrigger>\n <TooltipContent>Rename</TooltipContent>\n </Tooltip>\n <Tooltip delay={300}>\n <TooltipTrigger asChild>\n <Button variant=\"ghost\" onClick={handleDelete} disabled={artboards.length <= 1} aria-label=\"Delete\">\n <Icon icon={icons.trash} className=\"sc:size-4\" />\n </Button>\n </TooltipTrigger>\n <TooltipContent>Delete</TooltipContent>\n </Tooltip>\n </div>\n )}\n\n <Separator orientation=\"vertical\" className=\"sc:h-6\" />\n\n {/* Background picker */}\n <BackgroundPickerDropdown\n backgroundType={artboard.backgroundType}\n backgroundColor={artboard.backgroundColor}\n backgroundTexture={artboard.backgroundTexture}\n onBackgroundTypeChange={handleBackgroundTypeChange}\n onColorChange={handleColorChange}\n onTextureChange={handleTextureChange}\n />\n\n <Separator orientation=\"vertical\" className=\"sc:h-6\" />\n\n {/* Dimensions display */}\n <div className=\"sc:text-base sc:font-mono sc:text-text-muted sc:uppercase\">\n {Math.round(artboard.width)} × {Math.round(artboard.height)}\n </div>\n\n <Separator orientation=\"vertical\" className=\"sc:h-6\" />\n\n {/* More Menu - overflow menu for additional options */}\n <Popover open={moreMenuOpen} onOpenChange={setMoreMenuOpen}>\n <PopoverTrigger asChild>\n <Button variant={moreMenuOpen ? 'default' : 'ghost'} aria-label=\"More options\">\n <Icon icon={icons.menu} className=\"sc:size-6\" />\n </Button>\n </PopoverTrigger>\n <PopoverContent align=\"end\">\n <div className=\"sc:flex sc:flex-col sc:gap-2 sc:min-w-[240px]\">\n <div className=\"sc:flex sc:items-center sc:gap-3\">\n <Switch\n checked={artboard.exportBackground}\n onCheckedChange={handleExportBackgroundToggle}\n />\n <Label>Export Background</Label>\n </div>\n <Separator />\n <ArtboardDistressPanel\n distressTexture={artboard.distressTexture}\n onChange={handleDistressTextureChange}\n />\n <ArtboardImageMaskPanel\n imageMask={artboard.imageMask}\n onChange={handleImageMaskChange}\n />\n </div>\n </PopoverContent>\n </Popover>\n </Surface>\n );\n};\n\nexport default ArtboardPropertiesToolbar;\n","/**\n * Text utility functions\n */\n\n/**\n * Strip glyph characters from text for display purposes\n * Removes PUA (Private Use Area) characters used for alternate glyphs\n *\n * @param text - Text that may contain glyph characters\n * @returns Text with glyph characters removed\n */\nexport function stripGlyphs(text: string): string {\n // Remove PUA (Private Use Area) characters used for glyphs\n // PUA range: U+E000 to U+F8FF (standard), U+F0000 to U+FFFFD (supplementary)\n return Array.from(text)\n .filter((char) => {\n const cp = char.codePointAt(0);\n return !cp || cp < 0xf0000 || cp > 0xffffd;\n })\n .join('');\n}\n","/**\n * FontBrowserDrawer - Drawer for selecting font family with search and category filters\n * Refactored to use HeroUI design system\n */\n\nimport React, { useRef, useEffect, useState, useMemo, useSyncExternalStore } from 'react';\nimport { Icon } from '@iconify/react';\nimport { Input, Button, Tabs, Surface, Tooltip, TooltipTrigger, TooltipContent, TextField } from './ui';\nimport { Drawer } from './Drawer';\nimport { TSHIRT_FONTS, CATEGORY_LABELS, FontCategory, FontDefinition } from '../fonts/google-fonts.js';\nimport { UnifiedFontService } from '../utils/UnifiedFontService.js';\nimport {\n customFontRegistry,\n ensureCustomFontsLoaded,\n loadCustomFont,\n registerCustomFonts,\n type CustomFont,\n} from '../utils/custom-fonts.js';\nimport { useCanvasServices } from '../contexts/CanvasServicesContext.js';\nimport { isEditorError } from '../errors/editorError.js';\nimport { stripGlyphs } from '../utils/textUtils.js';\nimport { createLogger } from '../utils/logger.js';\n\nconst logger = createLogger('FontBrowserDrawer');\n\nexport interface FontBrowserDrawerProps {\n value: string;\n onChange: (event: { target: { value: string } }) => void;\n fontFamilies?: string[]; // Optional - uses TSHIRT_FONTS by default\n isOpen: boolean;\n onToggle: (open: boolean) => void;\n showLabel?: boolean;\n previewText?: string; // Text to preview in each font\n elements?: Array<Record<string, unknown>>; // Elements to extract fonts used in document\n}\n\nconst FontBrowserDrawer = ({\n value,\n onChange,\n fontFamilies: _fontFamilies,\n isOpen,\n onToggle,\n showLabel: _,\n previewText,\n elements,\n}: FontBrowserDrawerProps) => {\n const selectedFontRef = useRef<HTMLDivElement>(null);\n const [searchQuery, setSearchQuery] = useState('');\n const [selectedCategory, setSelectedCategory] = useState<FontCategory | 'all'>('all');\n const [fontsLoadedTrigger, setFontsLoadedTrigger] = useState(0); // Used to trigger re-render when fonts load\n const [displayMode, setDisplayMode] = useState<'both' | 'name' | 'preview'>('name'); // Three-way toggle: preview+name, name only, preview only\n const [cardSize, setCardSize] = useState<'small' | 'medium' | 'large'>('medium'); // Card size: small (1.0), medium (1.8), large (3.0)\n const [viewMode, setViewMode] = useState<'grid' | 'masonry'>('masonry'); // Toggle between grid and masonry layout\n const [loadedFonts, setLoadedFonts] = useState<Set<string>>(new Set()); // Track which fonts have been loaded\n const loadQueueRef = useRef<string[]>([]); // Queue of fonts to load\n const loadingRef = useRef(false); // Flag to prevent concurrent loading\n\n // === Custom (brand) fonts — \"Your fonts\" ===\n // The host-owned upload seam: `services.onFontUpload` receives the File,\n // stores it (the canvas never owns storage), and resolves { family, url }.\n // No callback → the upload affordance is NOT rendered (capability opt-in).\n const { onFontUpload } = useCanvasServices();\n const customFonts = useSyncExternalStore(\n customFontRegistry.subscribe,\n customFontRegistry.list,\n customFontRegistry.list\n );\n const fontFileInputRef = useRef<HTMLInputElement>(null);\n const [fontUploadBusy, setFontUploadBusy] = useState(false);\n const [fontUploadError, setFontUploadError] = useState<{ code?: string; message: string } | null>(\n null\n );\n\n // One picker entry per custom family (a family may register several\n // weight/style faces).\n const customFamilies = useMemo(() => {\n const seen = new Set<string>();\n const families: string[] = [];\n for (const font of customFonts) {\n const key = font.family.trim().toLowerCase();\n if (seen.has(key)) continue;\n seen.add(key);\n families.push(font.family);\n }\n return families;\n }, [customFonts]);\n\n // Families a custom font deterministically shadows out of the Google\n // sections below (see utils/custom-fonts.ts for the contract).\n const customFamilyKeys = useMemo(\n () => new Set(customFamilies.map((f) => f.trim().toLowerCase())),\n [customFamilies]\n );\n\n // Ensure registered custom fonts are activated while the drawer is open so\n // \"Your fonts\" previews render in their own face. Per-font failures stay\n // typed (E_FONT_LOAD_FAILED) and surface on the upload-error strip.\n useEffect(() => {\n if (!isOpen || customFonts.length === 0) return;\n void ensureCustomFontsLoaded(customFonts, {\n onLoadError: (error) => {\n logger.error('Custom font failed to load:', error);\n setFontUploadError({ code: error.code, message: error.message });\n },\n });\n }, [isOpen, customFonts]);\n\n const handleFontFileChange = async (e: React.ChangeEvent<HTMLInputElement>) => {\n const file = e.target.files?.[0];\n e.target.value = ''; // allow re-selecting the same file\n if (!file || !onFontUpload) return;\n\n setFontUploadBusy(true);\n setFontUploadError(null);\n try {\n const uploaded = await onFontUpload(file);\n const font: CustomFont = {\n family: uploaded.family,\n url: uploaded.url,\n ...(uploaded.weight !== undefined && { weight: uploaded.weight }),\n ...(uploaded.style !== undefined && { style: uploaded.style }),\n };\n // Load BEFORE registering: a font that can't load never enters the\n // design state (the wrong state stays unrepresentable). Throws the\n // typed E_FONT_LOAD_FAILED on a bad URL — no silent serif fallback.\n await loadCustomFont(font);\n registerCustomFonts([font]);\n // Immediately usable + selected.\n onChange({ target: { value: font.family } });\n setTimeout(() => onToggle(false), 0);\n } catch (error) {\n logger.error('Font upload failed:', error);\n setFontUploadError({\n code: isEditorError(error) ? error.code : undefined,\n message: error instanceof Error ? error.message : String(error),\n });\n } finally {\n setFontUploadBusy(false);\n }\n };\n\n const handleSelectCustom = (family: string) => {\n // Custom fonts never touch UnifiedFontService (no Google source may be\n // injected for a custom family) — the face is already activated by the\n // ensure effect above / the upload flow.\n onChange({ target: { value: family } });\n setTimeout(() => onToggle(false), 0);\n };\n\n // Convert size name to numeric scale value\n const getCardSizeScale = (size: 'small' | 'medium' | 'large'): number => {\n switch (size) {\n case 'small':\n return 1.0;\n case 'medium':\n return 1.8;\n case 'large':\n return 3.0;\n }\n };\n\n const cardSizeScale = getCardSizeScale(cardSize);\n\n // Inject font-preview CSS rule to ensure it overrides body font-family\n useEffect(() => {\n const styleId = 'font-preview-style';\n if (!document.getElementById(styleId)) {\n const style = document.createElement('style');\n style.id = styleId;\n style.textContent = '.font-preview { font-family: var(--font-preview) !important; }';\n document.head.appendChild(style);\n }\n }, []);\n\n // Fetch all fonts on mount\n useEffect(() => {\n if (!UnifiedFontService.isFontsLoaded()) {\n UnifiedFontService.initialize()\n .then(() => {\n setFontsLoadedTrigger((prev) => prev + 1); // Trigger re-render\n })\n .catch((error) => {\n logger.error('Failed to load fonts:', error);\n });\n }\n }, []);\n\n // Function to dynamically load a font for preview\n // Uses text= parameter to load only required glyphs (~99.9% smaller than full font)\n const loadFont = async (font: FontDefinition, forSelection: boolean = false) => {\n try {\n if (forSelection) {\n // Loading for actual selection - load full font\n await UnifiedFontService.loadFont(font);\n } else if (font.googleFont) {\n // Google Font preview - load only characters needed for preview text AND font name\n // This prevents iOS Safari memory crashes from loading full fonts\n // We need both: the preview text to display, and the font name for the label\n const textToLoad = previewText ? `${previewText}${font.name}` : font.name;\n UnifiedFontService.loadGoogleFontForPreview(font.name, textToLoad);\n } else {\n // System font - use regular loading\n await UnifiedFontService.loadFont(font);\n }\n // Update state immediately (no batching) to prevent accumulating 50+ fonts in one render\n setLoadedFonts((prev) => new Set(prev).add(font.name));\n } catch (error) {\n logger.error(`Failed to load font ${font.name}:`, error);\n }\n };\n\n // Load all queued fonts concurrently (no delays)\n useEffect(() => {\n const processQueue = async () => {\n if (loadingRef.current || loadQueueRef.current.length === 0) return;\n\n loadingRef.current = true;\n\n // Take all queued fonts and load them concurrently\n const fontsToLoad = [...loadQueueRef.current];\n loadQueueRef.current = [];\n\n const allFonts = UnifiedFontService.getAllFonts();\n\n // Load all fonts at once\n await Promise.all(\n fontsToLoad.map(async (fontName) => {\n const font = allFonts.find((f) => f.name === fontName);\n if (font && !loadedFonts.has(fontName)) {\n await loadFont(font);\n }\n })\n );\n\n loadingRef.current = false;\n };\n\n processQueue();\n }, [loadedFonts]);\n\n // Add font to load queue (called when font comes into view)\n const queueFontLoad = (fontName: string) => {\n // Check if already loaded or queued to avoid duplicates\n const alreadyLoaded = loadedFonts.has(fontName);\n const alreadyQueued = loadQueueRef.current.includes(fontName);\n\n if (!alreadyLoaded && !alreadyQueued) {\n loadQueueRef.current.push(fontName);\n // Trigger queue processing immediately if not already running\n if (!loadingRef.current && loadQueueRef.current.length === 1) {\n setLoadedFonts((prev) => new Set(prev)); // Trigger useEffect\n }\n }\n };\n\n // Focus search input when drawer opens\n useEffect(() => {\n if (isOpen) {\n // Scroll to selected font\n setTimeout(() => {\n if (selectedFontRef.current) {\n selectedFontRef.current.scrollIntoView({ behavior: 'smooth', block: 'center' });\n }\n }, 150);\n }\n // Reset filters and clear preview fonts when closing\n if (!isOpen) {\n setSearchQuery('');\n setSelectedCategory('all');\n // Clear preview font links from DOM to free memory (prevents iOS Safari crashes)\n UnifiedFontService.clearPreviewFonts();\n // Reset loaded fonts set so previews will load fresh next time\n setLoadedFonts(new Set());\n }\n }, [isOpen, value]);\n\n // Load the currently selected font so it displays correctly in the toolbar button\n // This needs to be the full font since it's actively being used\n useEffect(() => {\n if (value && !loadedFonts.has(value)) {\n const allFonts = UnifiedFontService.getAllFonts();\n const font = allFonts.find((f) => f.name === value);\n if (font) {\n loadFont(font, true); // forSelection=true to load full font\n }\n }\n }, [value, loadedFonts, fontsLoadedTrigger]);\n\n // When user starts searching, reset category to all\n useEffect(() => {\n if (searchQuery.trim()) {\n setSelectedCategory('all');\n }\n }, [searchQuery]);\n\n const handleSelect = async (family: string) => {\n // Load full font on selection (preview only loaded subset characters)\n const allFonts = UnifiedFontService.getAllFonts();\n const selectedFont = allFonts.find((f) => f.name === family);\n if (selectedFont) {\n try {\n // Load full font for actual use (forSelection=true)\n await loadFont(selectedFont, true);\n } catch (error) {\n logger.warn(`Failed to load font ${family}, will use fallback`);\n }\n }\n\n onChange({ target: { value: family } });\n // Small delay to allow tooltip to close properly before drawer closes\n setTimeout(() => onToggle(false), 0);\n };\n\n // Font Item Component - Memoized to prevent unnecessary re-renders\n const FontItem = React.memo(\n ({ font, isUsedInDocument = false }: { font: FontDefinition; isUsedInDocument?: boolean }) => {\n const fontItemRef = useRef<HTMLDivElement>(null);\n const isSelected = value === font.name;\n const isLoaded = loadedFonts.has(font.name);\n\n // Lazy load fonts when they come into view\n useEffect(() => {\n if (!fontItemRef.current) return;\n\n const observer = new IntersectionObserver(\n (entries) => {\n entries.forEach((entry) => {\n if (entry.isIntersecting && !isLoaded) {\n queueFontLoad(font.name);\n }\n });\n },\n { rootMargin: '600px' } // Load fonts before they come into view for smoother scrolling\n );\n\n observer.observe(fontItemRef.current);\n\n return () => observer.disconnect();\n }, [font.name, isLoaded]);\n\n // Determine what text to display based on mode\n let mainText = '';\n let showSecondaryLabel = false;\n\n if (displayMode === 'name') {\n mainText = font.name;\n showSecondaryLabel = false;\n } else if (displayMode === 'preview') {\n mainText = previewText || font.name;\n // Only show font name underneath in \"Used in Document\" section\n showSecondaryLabel = isUsedInDocument;\n } else {\n // displayMode === 'both'\n mainText = previewText || font.name;\n showSecondaryLabel = true;\n }\n\n // Check if we should show a tooltip (when displaying user text and not showing secondary label)\n const shouldShowTooltip = displayMode === 'preview' && !showSecondaryLabel;\n\n const surfaceContent = (\n <Surface\n ref={(el) => {\n // Assign to both refs: selectedFontRef for scrolling, fontItemRef for intersection observer\n if (isSelected && selectedFontRef) {\n selectedFontRef.current = el;\n }\n fontItemRef.current = el;\n }}\n className={`sc:relative sc:flex sc:cursor-pointer sc:flex-col sc:justify-center sc:rounded-lg sc:border-2 sc:text-left ${viewMode === 'masonry' ? 'sc:w-fit' : 'sc:min-w-0'} ${isSelected ? 'sc:border-accent' : 'sc:hover:border-muted sc:border-transparent'}`}\n onClick={shouldShowTooltip ? undefined : () => handleSelect(font.name)}\n role={shouldShowTooltip ? undefined : 'button'}\n aria-label={shouldShowTooltip ? undefined : `Select ${font.name} font`}\n tabIndex={shouldShowTooltip ? undefined : 0}\n onKeyDown={\n shouldShowTooltip\n ? undefined\n : (e) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n handleSelect(font.name);\n }\n }\n }\n style={{\n minHeight: `${showSecondaryLabel ? 48 * cardSizeScale : 36 * cardSizeScale}px`,\n padding: `${6 * cardSizeScale}px ${10 * cardSizeScale}px`,\n gap: `${2 * cardSizeScale}px`,\n }}\n >\n {/* Simple loading background - no animation for performance */}\n {!isLoaded && (\n <div\n className=\"sc:absolute sc:inset-0 sc:rounded-lg sc:bg-gray-100\"\n style={{\n opacity: 0.5,\n }}\n />\n )}\n\n <div\n className=\"sc-font-preview sc:text-foreground sc:overflow-hidden sc:leading-[1.1] sc:font-medium sc:text-ellipsis sc:whitespace-nowrap\"\n style={{\n '--font-preview': isLoaded ? `\"${font.name}\", sans-serif` : 'sans-serif',\n fontSize: `${15 * cardSizeScale}px`,\n opacity: isLoaded ? 1 : 0.4,\n } as React.CSSProperties}\n >\n {mainText}\n </div>\n {showSecondaryLabel && (\n <div\n className=\"sc:text-muted sc:overflow-hidden sc:font-sans sc:leading-[1.1] sc:font-normal sc:text-ellipsis sc:whitespace-nowrap\"\n style={{\n fontSize: `${7 * cardSizeScale}px`,\n opacity: isLoaded ? 1 : 0.4,\n }}\n >\n {font.name}\n </div>\n )}\n </Surface>\n );\n\n // Wrap with Tooltip if needed\n if (shouldShowTooltip) {\n return (\n <Tooltip key={font.name} delayDuration={200}>\n <TooltipTrigger asChild>\n <Button\n className=\"sc:m-0 sc:inline-block sc:h-auto sc:min-h-0 sc:border-0 sc:bg-transparent sc:p-0 sc:hover:bg-transparent\"\n style={{ width: viewMode === 'masonry' ? 'auto' : '100%' }}\n onClick={() => handleSelect(font.name)}\n aria-label={`Select ${font.name} font`}\n >\n <Surface\n ref={(el) => {\n // Assign to both refs: selectedFontRef for scrolling, fontItemRef for intersection observer\n if (isSelected && selectedFontRef) {\n selectedFontRef.current = el;\n }\n fontItemRef.current = el;\n }}\n className={`sc:relative sc:flex sc:cursor-pointer sc:flex-col sc:justify-center sc:rounded-lg sc:border-2 sc:text-left ${viewMode === 'masonry' ? 'sc:w-fit' : 'sc:min-w-0'} ${isSelected ? 'sc:border-accent' : 'sc:hover:border-muted sc:border-transparent'}`}\n style={{\n minHeight: `${showSecondaryLabel ? 48 * cardSizeScale : 36 * cardSizeScale}px`,\n padding: `${6 * cardSizeScale}px ${10 * cardSizeScale}px`,\n gap: `${2 * cardSizeScale}px`,\n }}\n >\n {/* Simple loading background - no animation for performance */}\n {!isLoaded && (\n <div\n className=\"sc:absolute sc:inset-0 sc:rounded-lg sc:bg-gray-100\"\n style={{\n opacity: 0.5,\n }}\n />\n )}\n\n <div\n className=\"sc-font-preview sc:text-foreground sc:overflow-hidden sc:leading-[1.1] sc:font-medium sc:text-ellipsis sc:whitespace-nowrap\"\n style={{\n '--font-preview': isLoaded ? `\"${font.name}\", sans-serif` : 'sans-serif',\n fontSize: `${15 * cardSizeScale}px`,\n opacity: isLoaded ? 1 : 0.4,\n } as React.CSSProperties}\n >\n {mainText}\n </div>\n {showSecondaryLabel && (\n <div\n className=\"sc:text-muted sc:overflow-hidden sc:font-sans sc:leading-[1.1] sc:font-normal sc:text-ellipsis sc:whitespace-nowrap\"\n style={{\n fontSize: `${7 * cardSizeScale}px`,\n opacity: isLoaded ? 1 : 0.4,\n }}\n >\n {font.name}\n </div>\n )}\n </Surface>\n </Button>\n </TooltipTrigger>\n <TooltipContent side=\"top\">\n <p>{font.name}</p>\n </TooltipContent>\n </Tooltip>\n );\n }\n\n return <React.Fragment key={font.name}>{surfaceContent}</React.Fragment>;\n },\n (prevProps, nextProps) => {\n // Custom comparison for memoization\n return prevProps.font.name === nextProps.font.name && prevProps.isUsedInDocument === nextProps.isUsedInDocument;\n }\n );\n\n // Extract fonts used in the document (excluding glyph-only elements)\n const fontsUsedInDocument = useMemo(() => {\n if (!elements) return new Set<string>();\n\n const usedFonts = new Set<string>();\n\n const addFontIfValid = (el: Record<string, unknown>) => {\n // Only add font if element has a fontFamily and non-glyph text\n const fontFamily = el.fontFamily as string | undefined;\n const text = el.text as string | undefined;\n if (fontFamily && text) {\n const cleanText = stripGlyphs(text);\n // Only add if there's actual text left after stripping glyphs\n if (cleanText.trim().length > 0) {\n usedFonts.add(fontFamily);\n }\n }\n };\n\n elements.forEach((el) => {\n addFontIfValid(el);\n\n // Check children for groups\n if (el.children && Array.isArray(el.children)) {\n (el.children as Record<string, unknown>[]).forEach((child) => {\n addFontIfValid(child);\n });\n }\n });\n\n return usedFonts;\n }, [elements]);\n\n // Organize fonts into sections\n const fontSections = useMemo(() => {\n // Get all fonts from UnifiedFontService (system + Google). A family\n // registered as a custom font deterministically SHADOWS its Google\n // namesake: the Google entry is hidden here and the custom one renders\n // under \"Your fonts\" instead (utils/custom-fonts.ts contract).\n const allFonts = (\n UnifiedFontService.isFontsLoaded() ? UnifiedFontService.getAllFonts() : TSHIRT_FONTS\n ) // Fallback to recommended fonts only if not loaded\n .filter((font) => !customFamilyKeys.has(font.name.trim().toLowerCase()));\n\n const recommendedNames = new Set(TSHIRT_FONTS.map((f) => f.name));\n\n // Extract \"Used in Document\" fonts first (only filter by search, not category)\n const usedFonts: FontDefinition[] = [];\n allFonts.forEach((font) => {\n if (fontsUsedInDocument.has(font.name)) {\n // Only apply search filter, not category filter\n if (searchQuery) {\n const query = searchQuery.toLowerCase();\n if (font.name.toLowerCase().includes(query)) {\n usedFonts.push(font);\n }\n } else {\n usedFonts.push(font);\n }\n }\n });\n\n // For remaining fonts, apply both category and search filters\n let remainingFonts = allFonts.filter((font) => !fontsUsedInDocument.has(font.name));\n\n // Filter by category\n if (selectedCategory !== 'all') {\n remainingFonts = remainingFonts.filter((font) => font.category === selectedCategory);\n }\n\n // Filter by search query\n if (searchQuery) {\n const query = searchQuery.toLowerCase();\n remainingFonts = remainingFonts.filter((font) => font.name.toLowerCase().includes(query));\n }\n\n // Separate remaining into recommended and other\n const recommendedFonts: FontDefinition[] = [];\n const otherFonts: FontDefinition[] = [];\n\n remainingFonts.forEach((font) => {\n if (recommendedNames.has(font.name)) {\n recommendedFonts.push(font);\n } else {\n otherFonts.push(font);\n }\n });\n\n // Sort each section alphabetically\n usedFonts.sort((a, b) => a.name.localeCompare(b.name));\n recommendedFonts.sort((a, b) => a.name.localeCompare(b.name));\n otherFonts.sort((a, b) => a.name.localeCompare(b.name));\n\n return { usedFonts, recommendedFonts, otherFonts };\n }, [searchQuery, selectedCategory, fontsLoadedTrigger, fontsUsedInDocument, customFamilyKeys]);\n\n // Render a font section - simple grid layout (all fonts same height, no masonry needed)\n const renderFontSection = (fonts: FontDefinition[], isUsedInDocument = false) => {\n if (viewMode === 'masonry') {\n // Flex wrap layout - simpler than true masonry since all items same height\n return (\n <div className=\"sc:flex sc:flex-wrap sc:content-start sc:items-start sc:gap-2 sc:px-4 sc:pb-4\">\n {fonts.map((font) => (\n <FontItem key={font.name} font={font} isUsedInDocument={isUsedInDocument} />\n ))}\n </div>\n );\n } else {\n // Grid layout - optimized for uniform height items\n return (\n <div\n className=\"sc:px-4 sc:pb-4\"\n style={{\n display: 'grid',\n gridTemplateColumns: `repeat(auto-fill, minmax(${140 * cardSizeScale}px, 1fr))`,\n gap: '8px',\n }}\n >\n {fonts.map((font) => (\n <FontItem key={font.name} font={font} isUsedInDocument={isUsedInDocument} />\n ))}\n </div>\n );\n }\n };\n\n // Get unique categories in order\n const categories: Array<FontCategory | 'all'> = [\n 'all',\n 'system',\n 'display',\n 'sans-serif',\n 'script',\n 'serif',\n 'slab-serif',\n 'vintage',\n 'decorative',\n 'monospace',\n ];\n\n return (\n <>\n {/*\n Fixed at 3× the standard toolbar button width so the contextual\n toolbar's button grid stays aligned regardless of font name\n length. Long names (e.g. \"Permanent Marker\", \"Architects\n Daughter\") truncate with ellipsis. The full name is still\n visible in the drawer once opened, and the tooltip shows it.\n */}\n <button\n onClick={() => onToggle(!isOpen)}\n className={`sc:h-11 sc:md:h-9 sc:w-[132px] sc:md:w-[108px] sc:flex sc:items-center sc:justify-center sc:px-2 sc:text-foreground sc:cursor-pointer sc:rounded-lg sc:border sc:border-transparent sc:text-base sc:font-medium sc:transition-all sc:hover:bg-black/5 sc:dark:hover:bg-white/5 ${isOpen ? 'sc:bg-black/10 sc:dark:bg-white/10' : 'sc:bg-transparent'}`}\n aria-label={isOpen ? 'Close font browser' : 'Open font browser'}\n title={value}\n >\n <span\n className=\"sc-font-preview sc:overflow-hidden sc:text-ellipsis sc:whitespace-nowrap sc:min-w-0\"\n style={{ '--font-preview': `\"${value}\", sans-serif`, fontWeight: 400 } as React.CSSProperties}\n >\n {value}\n </span>\n </button>\n\n <Drawer\n isOpen={isOpen}\n onClose={() => onToggle(false)}\n title=\"Fonts\"\n description=\"\"\n height=\"85vh\"\n placement=\"bottom\"\n showCloseButton={false}\n hideVisibleTitle={true}\n hideHandle={true}\n disableScrollWrapper={true}\n >\n {/* IMPORTANT: Wrapper pattern to avoid backdrop-filter compositing bugs */}\n {/* Outer wrapper: defines border-radius + overflow clipping */}\n {/* Inner element: no border-radius, just backdrop-filter */}\n {/* See docs/BACKDROP_FILTER_GOTCHAS.md for details */}\n <div className=\"sc:relative sc:flex-1 sc:overflow-hidden\">\n <div className=\"sc:h-full sc:bg-white\">\n {/* Inner scrollable container */}\n <div className=\"sc:h-full sc:overflow-y-auto\">\n {/* Search Input & Controls - Scrolls away */}\n <div className=\"sc:px-4 sc:pt-5\">\n <Surface className=\"sc:flex sc:gap-2\">\n <TextField className=\"sc:flex-1\" aria-label=\"Search fonts\">\n <Input\n type=\"text\"\n className=\"sc:rounded-2xl sc:pt-[10px] sc:pb-[9px]\"\n placeholder=\"Search fonts...\"\n value={searchQuery}\n onChange={(e) => setSearchQuery(e.target.value)}\n autoFocus\n aria-label=\"Search fonts\"\n />\n </TextField>\n\n <Tabs\n value={cardSize}\n onValueChange={(value) => setCardSize(value as 'small' | 'medium' | 'large')}\n >\n <Tabs.ListContainer>\n <Tabs.List aria-label=\"Card size\">\n <Tabs.Tab id=\"small\" className=\"sc:text-xs sc:font-semibold\" aria-label=\"Small card size\">\n A\n <Tabs.Indicator />\n </Tabs.Tab>\n <Tabs.Tab id=\"medium\" className=\"sc:text-base sc:font-semibold\" aria-label=\"Medium card size\">\n A\n <Tabs.Indicator />\n </Tabs.Tab>\n <Tabs.Tab id=\"large\" className=\"sc:text-xl sc:font-semibold\" aria-label=\"Large card size\">\n A\n <Tabs.Indicator />\n </Tabs.Tab>\n </Tabs.List>\n </Tabs.ListContainer>\n </Tabs>\n\n <Button\n variant=\"secondary\"\n onClick={() => {\n setDisplayMode((prev) => {\n if (prev === 'both') return 'name';\n if (prev === 'name') return 'preview';\n return 'both';\n });\n }}\n aria-label={\n displayMode === 'both'\n ? 'Show font name only'\n : displayMode === 'name'\n ? 'Show preview only'\n : 'Show preview with font name'\n }\n className=\"sc:h-10 sc:w-10 sc:p-0\"\n >\n {displayMode === 'both' ? (\n <Icon icon=\"lucide:credit-card\" className=\"sc:size-[22px]\" />\n ) : displayMode === 'name' ? (\n <Icon icon=\"lucide:type\" className=\"sc:size-[22px]\" />\n ) : (\n <Icon icon=\"lucide:text-cursor\" className=\"sc:size-[22px]\" />\n )}\n </Button>\n\n <Button\n variant=\"secondary\"\n onClick={() => setViewMode(viewMode === 'grid' ? 'masonry' : 'grid')}\n aria-label={viewMode === 'grid' ? 'Switch to masonry view' : 'Switch to grid view'}\n className=\"sc:h-10 sc:w-10 sc:p-0\"\n >\n {viewMode === 'grid' ? (\n <Icon icon=\"lucide:grid-2x2\" className=\"sc:size-[22px]\" />\n ) : (\n <Icon icon=\"lucide:grid-3x3\" className=\"sc:size-[22px]\" />\n )}\n </Button>\n </Surface>\n </div>\n\n {/* Category Filters - Sticky at top with blur and gradient */}\n <div className=\"sc:sticky sc:top-0 sc:z-20 sc:shrink-0\">\n {/* Gradient overlay - sticky with pills */}\n <div\n className=\"sc:pointer-events-none sc:absolute sc:top-0 sc:right-0 sc:left-0\"\n style={{\n height: '64px',\n background:\n 'linear-gradient(to bottom, var(--background) 0%, color-mix(in srgb, var(--background) 80%, transparent) 40%, transparent 100%)',\n zIndex: 16,\n }}\n />\n\n {/* Pills content */}\n <div className=\"sc:relative sc:z-20 sc:px-4 sc:py-4 sc:pt-3\">\n <div className=\"sc:flex sc:gap-2 sc:overflow-x-auto\">\n {categories.map((category) => {\n const label = category === 'all' ? 'All' : CATEGORY_LABELS[category as FontCategory];\n\n return (\n <Button\n key={category}\n size=\"sm\"\n variant={selectedCategory === category ? 'default' : 'secondary'}\n onClick={() => setSelectedCategory(category)}\n className={`sc:shrink-0 ${selectedCategory === category ? '' : 'sc:hover:brightness-95'}`}\n >\n {label}\n </Button>\n );\n })}\n </div>\n </div>\n </div>\n\n {/* Font List with Sections */}\n <div className=\"sc:flex-1\">\n {/* Your Fonts Section — custom (brand) fonts + the host-owned\n upload affordance. The whole section disappears when there\n are no custom fonts AND no `services.onFontUpload`. */}\n {(customFamilies.length > 0 || onFontUpload) && !searchQuery && (\n <div className=\"sc:shrink-0 sc:p-0\" data-sc-part=\"font-picker-your-fonts\">\n <div className=\"sc:text-muted sc:bg-white sc:px-4 sc:pt-2 sc:pb-2 sc:text-xs sc:font-bold sc:tracking-wider sc:uppercase\">\n Your Fonts\n </div>\n <div className=\"sc:flex sc:flex-wrap sc:content-start sc:items-center sc:gap-2 sc:px-4 sc:pb-4\">\n {customFamilies.map((family) => {\n const isSelected = value === family;\n return (\n <Surface\n key={family}\n data-sc-part=\"font-picker-custom-font\"\n data-family={family}\n className={`sc:relative sc:flex sc:w-fit sc:cursor-pointer sc:flex-col sc:justify-center sc:rounded-lg sc:border-2 sc:text-left ${isSelected ? 'sc:border-accent' : 'sc:hover:border-muted sc:border-transparent'}`}\n onClick={() => handleSelectCustom(family)}\n role=\"button\"\n aria-label={`Select ${family} font`}\n tabIndex={0}\n onKeyDown={(e) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n handleSelectCustom(family);\n }\n }}\n style={{\n minHeight: `${36 * cardSizeScale}px`,\n padding: `${6 * cardSizeScale}px ${10 * cardSizeScale}px`,\n }}\n >\n <div\n className=\"sc-font-preview sc:text-foreground sc:overflow-hidden sc:leading-[1.1] sc:font-medium sc:text-ellipsis sc:whitespace-nowrap\"\n style={{\n '--font-preview': `\"${family}\", sans-serif`,\n fontSize: `${15 * cardSizeScale}px`,\n } as React.CSSProperties}\n >\n {displayMode === 'name' ? family : previewText || family}\n </div>\n </Surface>\n );\n })}\n {onFontUpload && (\n <>\n <input\n ref={fontFileInputRef}\n type=\"file\"\n accept=\".woff2,.woff,.ttf,.otf,font/woff2,font/woff,font/ttf,font/otf\"\n className=\"sc:hidden\"\n data-sc-part=\"font-picker-upload-input\"\n data-testid=\"font-upload-input\"\n aria-label=\"Upload font file\"\n onChange={handleFontFileChange}\n />\n <Button\n variant=\"secondary\"\n data-sc-part=\"font-picker-upload\"\n data-testid=\"font-upload-button\"\n onClick={() => fontFileInputRef.current?.click()}\n disabled={fontUploadBusy}\n aria-label=\"Upload a font\"\n >\n <Icon icon=\"lucide:upload\" className=\"sc:size-4\" />\n {fontUploadBusy ? 'Uploading…' : 'Upload font'}\n </Button>\n </>\n )}\n </div>\n {fontUploadError && (\n <div\n className=\"sc:text-danger sc:px-4 sc:pb-3 sc:text-xs\"\n data-sc-part=\"font-picker-upload-error\"\n {...(fontUploadError.code && { 'data-sc-error-code': fontUploadError.code })}\n role=\"alert\"\n >\n {fontUploadError.message}\n </div>\n )}\n </div>\n )}\n\n {/* Used in Document Section */}\n {fontSections.usedFonts.length > 0 && (\n <div className=\"sc:shrink-0 sc:p-0\">\n <div className=\"sc:text-muted sc:bg-white sc:px-4 sc:pt-2 sc:pb-2 sc:text-xs sc:font-bold sc:tracking-wider sc:uppercase\">\n Used in Document\n </div>\n {renderFontSection(fontSections.usedFonts, true)}\n </div>\n )}\n\n {fontSections.recommendedFonts.length === 0 && fontSections.otherFonts.length === 0 ? (\n <div className=\"sc:text-muted sc:col-span-full sc:px-4 sc:py-8 sc:text-center sc:text-sm\">No fonts found</div>\n ) : (\n <>\n {/* Recommended Section */}\n {fontSections.recommendedFonts.length > 0 && (\n <div className=\"sc:p-0\">\n <div className=\"sc:text-muted sc:bg-white sc:px-4 sc:pt-2 sc:pb-2 sc:text-xs sc:font-bold sc:tracking-wider sc:uppercase\">\n Recommended\n </div>\n {renderFontSection(fontSections.recommendedFonts)}\n </div>\n )}\n\n {/* All Fonts Section */}\n {fontSections.otherFonts.length > 0 && (\n <div className=\"sc:p-0\">\n <div className=\"sc:text-muted sc:bg-white sc:px-4 sc:pt-4 sc:pb-2 sc:text-xs sc:font-bold sc:tracking-wider sc:uppercase\">\n All Fonts\n </div>\n {renderFontSection(fontSections.otherFonts)}\n </div>\n )}\n </>\n )}\n </div>\n </div>\n </div>\n </div>\n </Drawer>\n </>\n );\n};\n\nexport default FontBrowserDrawer;\n","/**\n * TransformControlPanel - Reusable component for transform-specific sliders\n * Eliminates duplication of slider control code across transforms\n *\n * Migrated to Shadcn/Radix:\n * - Switch\n * - Slider\n * - Label\n */\n\nimport React, { useState } from 'react';\nimport { TextElement } from '../core/TextElement';\nimport { ImageElement } from '../core/ImageElement';\nimport { ShapeElement } from '../core/ShapeElement';\nimport type { TransformControl } from '../types/index.js';\nimport { Switch, Slider, Label } from './ui';\nimport { createLogger } from '../utils/logger.js';\n\nconst logger = createLogger('TransformControlPanel');\n\ninterface TransformControlPanelProps {\n element: TextElement | ImageElement | ShapeElement;\n controls: TransformControl[];\n onUpdate: (element: TextElement | ImageElement | ShapeElement) => void;\n}\n\nexport const TransformControlPanel: React.FC<TransformControlPanelProps> = ({ element, controls, onUpdate }) => {\n // Track which slider is being dragged to show preview value\n const [draggingValues, setDraggingValues] = useState<Record<string, number>>({});\n\n return (\n <div className=\"sc:w-full sc:space-y-4\">\n {controls.map((control) => {\n // Get the stored value (internal representation)\n const storedValue =\n (element.transformData as Record<string, unknown>)[control.key] ?? control.defaultInternalValue ?? control.defaultValue;\n\n // Handle checkbox controls\n if (control.type === 'checkbox') {\n return (\n <div key={control.key} className=\"sc:flex sc:items-center sc:space-x-2\">\n <Switch\n id={`control-${control.key}`}\n checked={storedValue as boolean}\n onCheckedChange={(checked: boolean) => {\n const newElement = element.clone();\n (newElement.transformData as Record<string, unknown>)[control.key] = checked;\n onUpdate(newElement);\n }}\n />\n <Label htmlFor={`control-${control.key}`}>{control.label}</Label>\n </div>\n );\n }\n\n // Handle slider controls (default)\n // Safety check: ensure storedValue is a valid number\n const safeStoredValue = typeof storedValue === 'number' && !isNaN(storedValue)\n ? storedValue\n : (control.defaultInternalValue ?? 0);\n\n // Use preview value while dragging, otherwise use stored value\n const currentInternalValue = draggingValues[control.key] !== undefined\n ? draggingValues[control.key]\n : safeStoredValue;\n\n // Convert to slider position (0-100 scale for simplicity)\n const sliderValue = control.toSlider ? control.toSlider(currentInternalValue) : currentInternalValue;\n\n // Convert to display string\n const formatValue = (value: number): string => {\n // Note: value is the slider position, we need to convert back to stored value for display\n const internalValue = control.fromSlider ? control.fromSlider(value) : value;\n\n // Safety check: ensure internalValue is a number\n if (typeof internalValue !== 'number' || isNaN(internalValue)) {\n logger.warn('Invalid internalValue:', internalValue, 'for control:', control.key);\n return '0';\n }\n\n return control.toDisplay\n ? control.toDisplay(internalValue)\n : 'isPercentage' in control && control.isPercentage\n ? `${(internalValue * 100).toFixed(0)}%`\n : internalValue.toFixed(1);\n };\n\n return (\n <div key={control.key} className=\"sc:flex sc:flex-col sc:gap-sm\">\n <div className=\"sc:flex sc:justify-between\">\n <Label>{control.label}</Label>\n <span className=\"sc:text-sm sc:text-foreground/60\">{formatValue(sliderValue)}</span>\n </div>\n <Slider\n value={[sliderValue]}\n onValueChange={(val) => {\n // Update preview value while dragging\n const newSliderValue = val[0];\n const newInternalValue = control.fromSlider\n ? control.fromSlider(newSliderValue)\n : newSliderValue;\n setDraggingValues(prev => ({ ...prev, [control.key]: newInternalValue }));\n }}\n onChangeEnd={(val) => {\n // Only update element when drag ends\n const newSliderValue = val[0];\n const newElement = element.clone();\n (newElement.transformData as Record<string, unknown>)[control.key] = control.fromSlider\n ? control.fromSlider(newSliderValue)\n : newSliderValue;\n onUpdate(newElement);\n // Clear preview value\n setDraggingValues(prev => {\n const updated = { ...prev };\n delete updated[control.key];\n return updated;\n });\n }}\n min={0}\n max={100}\n step={control.step ?? 1}\n className=\"slider-no-fill\"\n />\n </div>\n );\n })}\n </div>\n );\n};\n\nexport default TransformControlPanel;\n","/**\n * TextEffectsDropdown - Dropdown for selecting and configuring text transforms\n * Shows currently selected transform and configuration controls\n */\n\nimport React, { useState } from 'react';\nimport { Popover, PopoverTrigger, PopoverContent, Select, SelectTrigger, SelectValue, SelectContent, SelectItem, Label, icons } from './ui';\nimport { Icon } from '@iconify/react';\nimport { TRANSFORM_TYPES, getTransformControls } from '../transforms/registry.js';\nimport { TransformControlPanel } from './TransformControlPanel.js';\nimport type { TransformType } from '../types/index.js';\nimport type { TextElement } from '../core/TextElement.js';\nimport type { ImageElement } from '../core/ImageElement.js';\nimport type { ShapeElement } from '../core/ShapeElement.js';\n\nexport interface TextEffectsDropdownProps {\n element: TextElement;\n onTransformTypeChange: (newType: TransformType) => void;\n onElementUpdate: (updatedElement: TextElement | ImageElement | ShapeElement) => void;\n isOpen?: boolean;\n onOpenChange?: (isOpen: boolean) => void;\n}\n\nexport const TextEffectsDropdown: React.FC<TextEffectsDropdownProps> = ({\n element,\n onTransformTypeChange,\n onElementUpdate,\n isOpen: controlledIsOpen,\n onOpenChange: controlledOnOpenChange,\n}) => {\n const [internalIsOpen, setInternalIsOpen] = useState(false);\n\n // Use controlled state if provided, otherwise use internal state\n const isOpen = controlledIsOpen !== undefined ? controlledIsOpen : internalIsOpen;\n const setIsOpen = controlledOnOpenChange || setInternalIsOpen;\n\n const currentTransformType = element.transformType;\n const controls = getTransformControls(currentTransformType);\n\n // Filter to only text transform types (exclude image, group, shape, path)\n const textTransformTypes = TRANSFORM_TYPES.filter(\n (t) => t.Component && t.id !== 'image' && t.id !== 'group' && t.id !== 'shape' && t.id !== 'path'\n );\n\n const handleTransformChange = (newType: string) => {\n if (newType !== currentTransformType) {\n onTransformTypeChange(newType as TransformType);\n }\n };\n\n return (\n <Popover open={isOpen} onOpenChange={setIsOpen}>\n <PopoverTrigger asChild>\n <button className=\"sc-toolbar-btn\" aria-label=\"Text Effects\">\n <Icon icon={icons.wand} className=\"sc:size-6\" />\n </button>\n </PopoverTrigger>\n <PopoverContent align=\"start\" className=\"sc:w-[280px] sc:p-0\" maxZIndex>\n <div className=\"sc:space-y-4 sc:p-6\">\n {/* Transform Type Select */}\n <div className=\"sc:space-y-2\">\n <Label>Text Effect</Label>\n <Select value={currentTransformType} onValueChange={handleTransformChange}>\n <SelectTrigger>\n <SelectValue placeholder=\"Select effect\" />\n </SelectTrigger>\n <SelectContent style={{ zIndex: 2147483647 }}>\n {textTransformTypes.map((transform) => (\n <SelectItem key={transform.id} value={transform.id}>\n {transform.label}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n\n {/* Transform Configuration Controls */}\n {controls.length > 0 && (\n <TransformControlPanel element={element} controls={controls} onUpdate={onElementUpdate} />\n )}\n </div>\n </PopoverContent>\n </Popover>\n );\n};\n\nexport default TextEffectsDropdown;\n","/**\n * MoreMenu - Overflow menu for toolbar items\n * Shows a \"...\" menu with items that don't fit or are always hidden\n */\n\nimport { useState } from 'react';\nimport { Button, Popover, PopoverTrigger, PopoverContent, Tooltip, TooltipTrigger, TooltipContent, icons } from './ui';\nimport { Icon } from '@iconify/react';\n\ninterface MoreMenuItem {\n label: string;\n icon: React.ReactNode;\n onClick: () => void;\n active?: boolean;\n}\n\ninterface MoreMenuProps {\n items: MoreMenuItem[];\n}\n\nconst MoreMenu = ({ items }: MoreMenuProps) => {\n const [showMenu, setShowMenu] = useState(false);\n\n return (\n <Popover open={showMenu} onOpenChange={setShowMenu}>\n <PopoverTrigger asChild>\n <button className=\"sc-toolbar-btn\" aria-label=\"More options\">\n <Icon icon={icons.moreHorizontal} className=\"sc:size-6\" />\n </button>\n </PopoverTrigger>\n <PopoverContent align=\"start\" className=\"sc:w-auto sc:p-1\" maxZIndex>\n <div className=\"sc:flex sc:items-center sc:gap-1\">\n {items.map((item, index) => (\n <Tooltip key={index} delay={300}>\n <TooltipTrigger asChild>\n <Button\n variant={item.active ? 'default' : 'ghost'}\n size=\"icon\"\n onClick={() => {\n item.onClick();\n setShowMenu(false);\n }}\n aria-label={item.label}\n >\n {item.icon}\n </Button>\n </TooltipTrigger>\n <TooltipContent>{item.label}</TooltipContent>\n </Tooltip>\n ))}\n </div>\n </PopoverContent>\n </Popover>\n );\n};\n\nexport default MoreMenu;\n","import { Tooltip, TooltipTrigger, TooltipContent } from '../ui';\n\nexport interface FontColorButtonProps {\n colorPickerValue: string;\n isActive: boolean;\n onClick: () => void;\n}\n\nexport function FontColorButton({ colorPickerValue, isActive, onClick }: FontColorButtonProps) {\n return (\n <Tooltip delay={300}>\n <TooltipTrigger asChild>\n <button\n className=\"sc-toolbar-btn\"\n onClick={onClick}\n aria-label=\"Font Color\"\n data-active={isActive}\n >\n <div className=\"sc:relative sc:flex sc:h-5 sc:w-5 sc:items-center sc:justify-center\">\n <span className=\"sc:-translate-y-0.5 sc:text-lg sc:leading-none sc:font-bold\">A</span>\n <div\n className=\"sc:absolute sc:bottom-0 sc:left-1/2 sc:h-[3px] sc:w-4 sc:-translate-x-1/2 sc:rounded-sm\"\n style={{ backgroundColor: colorPickerValue }}\n />\n </div>\n </button>\n </TooltipTrigger>\n {!isActive && <TooltipContent>Font Color</TooltipContent>}\n </Tooltip>\n );\n}\n","import { ToolbarButton, icons } from '../ui';\nimport type { UseTextToolbarReturn } from '../../hooks/useTextToolbar.js';\n\nexport interface BoldButtonProps {\n toolbar: UseTextToolbarReturn;\n}\n\nexport function BoldButton({ toolbar }: BoldButtonProps) {\n return (\n <ToolbarButton\n icon={icons.bold}\n onClick={toolbar.handleBoldToggle}\n active={toolbar.getEffectiveStyle().bold}\n tooltip=\"Bold\"\n />\n );\n}\n","import { ToolbarButton, icons } from '../ui';\nimport type { UseTextToolbarReturn } from '../../hooks/useTextToolbar.js';\n\nexport interface ItalicButtonProps {\n toolbar: UseTextToolbarReturn;\n}\n\nexport function ItalicButton({ toolbar }: ItalicButtonProps) {\n return (\n <ToolbarButton\n icon={icons.italic}\n onClick={toolbar.handleItalicToggle}\n active={toolbar.getEffectiveStyle().italic}\n tooltip=\"Italic\"\n />\n );\n}\n","import { ToolbarButton, icons } from '../ui';\nimport type { UseTextToolbarReturn } from '../../hooks/useTextToolbar.js';\n\nexport interface UnderlineButtonProps {\n toolbar: UseTextToolbarReturn;\n}\n\nexport function UnderlineButton({ toolbar }: UnderlineButtonProps) {\n return (\n <ToolbarButton\n icon={icons.underline}\n onClick={toolbar.handleUnderlineToggle}\n active={toolbar.getEffectiveStyle().underline}\n tooltip=\"Underline\"\n />\n );\n}\n","import { ToolbarButton } from '../ui';\nimport type { UseTextToolbarReturn } from '../../hooks/useTextToolbar.js';\n\nexport interface UppercaseButtonProps {\n toolbar: UseTextToolbarReturn;\n}\n\nexport function UppercaseButton({ toolbar }: UppercaseButtonProps) {\n return (\n <ToolbarButton\n icon=\"lucide:case-upper\"\n onClick={toolbar.handleLetterCaseToggle}\n active={toolbar.isLetterCaseActive()}\n tooltip=\"Uppercase\"\n />\n );\n}\n","import { ToolbarButton, icons } from '../ui';\nimport type { UseTextToolbarReturn } from '../../hooks/useTextToolbar.js';\n\nexport interface TextAlignButtonProps {\n toolbar: UseTextToolbarReturn;\n}\n\nexport function TextAlignButton({ toolbar }: TextAlignButtonProps) {\n const { textAlign, handleTextAlignToggle } = toolbar;\n const icon =\n textAlign === 'left' ? icons.alignLeft : textAlign === 'center' ? icons.alignCenter : icons.alignRight;\n\n return (\n <ToolbarButton\n icon={icon}\n onClick={handleTextAlignToggle}\n tooltip={`Align ${textAlign.charAt(0).toUpperCase() + textAlign.slice(1)}`}\n />\n );\n}\n","import { useState } from 'react';\nimport { Icon } from '@iconify/react';\nimport {\n Tooltip,\n TooltipTrigger,\n TooltipContent,\n Button,\n Popover,\n PopoverTrigger,\n PopoverContent,\n icons,\n} from '../ui';\n\nexport interface TextMoreMenuProps {\n onMoveForward: () => void;\n onMoveBackward: () => void;\n onDelete: () => void;\n onOpenChange?: (open: boolean) => void;\n}\n\nexport function TextMoreMenu({ onMoveForward, onMoveBackward, onDelete, onOpenChange }: TextMoreMenuProps) {\n const [isOpen, setIsOpen] = useState(false);\n\n const handleOpenChange = (open: boolean) => {\n setIsOpen(open);\n onOpenChange?.(open);\n };\n\n return (\n <Popover open={isOpen} onOpenChange={handleOpenChange}>\n <PopoverTrigger asChild>\n <button className=\"sc-toolbar-btn\" aria-label=\"More options\">\n <Icon icon=\"lucide:ellipsis-vertical\" className=\"sc:size-6\" />\n </button>\n </PopoverTrigger>\n <PopoverContent align=\"end\" className=\"sc:w-auto sc:p-1\" maxZIndex>\n <div className=\"sc:flex sc:items-center sc:gap-1\">\n <Tooltip delayDuration={300}>\n <TooltipTrigger asChild>\n <Button\n variant=\"ghost\"\n size=\"icon\"\n onClick={() => {\n onMoveForward();\n handleOpenChange(false);\n }}\n aria-label=\"Move Forward\"\n >\n <Icon icon=\"hugeicons:layer-bring-forward\" className=\"sc:size-5\" />\n </Button>\n </TooltipTrigger>\n <TooltipContent>Move Forward</TooltipContent>\n </Tooltip>\n <Tooltip delayDuration={300}>\n <TooltipTrigger asChild>\n <Button\n variant=\"ghost\"\n size=\"icon\"\n onClick={() => {\n onMoveBackward();\n handleOpenChange(false);\n }}\n aria-label=\"Move Backward\"\n >\n <Icon icon=\"hugeicons:layer-send-backward\" className=\"sc:size-5\" />\n </Button>\n </TooltipTrigger>\n <TooltipContent>Move Backward</TooltipContent>\n </Tooltip>\n <Tooltip delayDuration={300}>\n <TooltipTrigger asChild>\n <Button\n variant=\"ghost\"\n size=\"icon\"\n onClick={() => {\n handleOpenChange(false);\n onDelete();\n }}\n aria-label=\"Delete\"\n >\n <Icon icon={icons.trash} className=\"sc:size-5\" />\n </Button>\n </TooltipTrigger>\n <TooltipContent>Delete</TooltipContent>\n </Tooltip>\n </div>\n </PopoverContent>\n </Popover>\n );\n}\n","/**\n * TextToolbar - Composed text formatting toolbar using primitives.\n *\n * Replaces the inline text toolbar JSX from ContextualToolbars.\n * Accepts a `toolbar` prop (from useTextToolbar) so the parent can\n * share the same state with other panels (e.g. text color picker).\n *\n * For standalone usage, call useTextToolbar() in your component and\n * pass the result as the `toolbar` prop.\n */\n\nimport React, { useState } from 'react';\nimport FontBrowserDrawer from './FontBrowserDrawer.jsx';\nimport TextEffectsDropdown from './TextEffectsDropdown.jsx';\nimport MoreMenu from './MoreMenu.jsx';\nimport { FontColorButton } from './text-toolbar/FontColorButton.js';\nimport { BoldButton } from './text-toolbar/BoldButton.js';\nimport { ItalicButton } from './text-toolbar/ItalicButton.js';\nimport { UnderlineButton } from './text-toolbar/UnderlineButton.js';\nimport { UppercaseButton } from './text-toolbar/UppercaseButton.js';\nimport { TextAlignButton } from './text-toolbar/TextAlignButton.js';\nimport { TextMoreMenu } from './text-toolbar/TextMoreMenu.js';\nimport { ToolbarButton, RotateLeftIcon } from './ui';\nimport { FONT_FAMILIES } from '../constants.js';\nimport { getFeatureApplied } from '../utils/featureApplied.js';\nimport type { UseTextToolbarReturn } from '../hooks/useTextToolbar.js';\nimport type { EditorElement } from '../contexts/EditorContext.js';\nimport type { TextElement } from '../core/TextElement.js';\n\nexport interface TextToolbarProps {\n toolbar: UseTextToolbarReturn;\n stableElementId?: string;\n viewportWidth?: number;\n colorPickerValue: string;\n isColorActive: boolean;\n onColorToggle: () => void;\n onOpenGlyphBrowser?: () => void;\n hasGlyphs?: boolean;\n expandedPanel: { type: string } | null;\n onRotationToggle: () => void;\n onOpacityToggle: () => void;\n onFontSizeToggle: () => void;\n getMoreMenuItems?: () => Array<{ label: string; onClick: () => void; icon: React.ReactNode; active?: boolean }>;\n strokeExpanded?: boolean;\n onStrokeToggle?: () => void;\n shadowExpanded?: boolean;\n onShadowToggle?: () => void;\n blendModeExpanded?: boolean;\n onBlendModeToggle?: () => void;\n knockoutExpanded?: boolean;\n onKnockoutToggle?: () => void;\n distressTextureExpanded?: boolean;\n onDistressTextureToggle?: () => void;\n imageMaskExpanded?: boolean;\n onImageMaskToggle?: () => void;\n onMoveForward: () => void;\n onMoveBackward: () => void;\n onDelete: () => void;\n elementForProperties: EditorElement;\n elements: EditorElement[];\n isTransformMenuOpen: boolean;\n onTransformMenuOpenChange: (open: boolean) => void;\n elementUpdateHandler: (updatedElement: EditorElement) => void;\n showUngroupButton?: boolean;\n onUngroup?: () => void;\n isFontBrowserOpen?: boolean;\n onFontBrowserToggle: (isOpen: boolean) => void;\n onTextMoreMenuOpenChange?: (open: boolean) => void;\n}\n\nexport function TextToolbar({\n toolbar,\n stableElementId,\n viewportWidth = window.innerWidth,\n colorPickerValue,\n isColorActive,\n onColorToggle,\n onOpenGlyphBrowser,\n hasGlyphs = false,\n expandedPanel,\n onRotationToggle,\n onOpacityToggle,\n onFontSizeToggle,\n strokeExpanded = false,\n onStrokeToggle,\n shadowExpanded = false,\n onShadowToggle,\n blendModeExpanded = false,\n onBlendModeToggle,\n knockoutExpanded = false,\n onKnockoutToggle,\n distressTextureExpanded = false,\n onDistressTextureToggle,\n imageMaskExpanded = false,\n onImageMaskToggle,\n getMoreMenuItems,\n onMoveForward,\n onMoveBackward,\n onDelete,\n elementForProperties,\n elements,\n isTransformMenuOpen,\n onTransformMenuOpenChange,\n elementUpdateHandler,\n showUngroupButton = false,\n onUngroup,\n isFontBrowserOpen = false,\n onFontBrowserToggle,\n onTextMoreMenuOpenChange,\n}: TextToolbarProps) {\n // Tooltip disabled states (prevent flicker after click)\n const [strokeTooltipDisabled, setStrokeTooltipDisabled] = useState(false);\n const [glyphTooltipDisabled, setGlyphTooltipDisabled] = useState(false);\n const [rotationTooltipDisabled, setRotationTooltipDisabled] = useState(false);\n const [fontSizeTooltipDisabled, setFontSizeTooltipDisabled] = useState(false);\n\n // Feature-applied flags — drive the \"selected\" highlight on the\n // toolbar buttons whose underlying property has been set to a\n // non-default value.\n const applied = getFeatureApplied(elementForProperties);\n const [opacityTooltipDisabled, setOpacityTooltipDisabled] = useState(false);\n const [shadowTooltipDisabled, setShadowTooltipDisabled] = useState(false);\n const [blendModeTooltipDisabled, setBlendModeTooltipDisabled] = useState(false);\n const [knockoutTooltipDisabled, setKnockoutTooltipDisabled] = useState(false);\n const [distressTooltipDisabled, setDistressTooltipDisabled] = useState(false);\n const [imageMaskTooltipDisabled, setImageMaskTooltipDisabled] = useState(false);\n\n return (\n <div key={`text-toolbar-${stableElementId}`} className=\"sc-toolbar-items\">\n {/* Font Browser Drawer */}\n <FontBrowserDrawer\n value={toolbar.getEffectiveStyle().fontFamily || toolbar.fontFamily}\n onChange={(e: { target: { value: string } }) => toolbar.handleFontFamilyChange(e.target.value)}\n fontFamilies={FONT_FAMILIES}\n isOpen={isFontBrowserOpen}\n onToggle={onFontBrowserToggle}\n showLabel={viewportWidth > 700}\n previewText={'text' in elementForProperties ? (elementForProperties as { text: string }).text : undefined}\n elements={elements as unknown as Array<Record<string, unknown>>}\n />\n\n {/* Font Size — toolbar button using the standard \"Aa\" font-size\n icon. Tapping opens the secondary panel (slider + number\n input). Earlier this button rendered the current size as\n its label — but at 3 digits (\"148\") that broke the toolbar's\n uniform button-width grid. The current size still shows in\n the tooltip and inside the panel; the icon keeps the\n toolbar visually aligned with the rest of its buttons. */}\n <ToolbarButton\n icon=\"lucide:a-large-small\"\n onClick={() => {\n setFontSizeTooltipDisabled(true);\n onFontSizeToggle();\n }}\n onMouseLeave={() => setFontSizeTooltipDisabled(false)}\n tooltip={`Font Size · ${Math.round(toolbar.fontSize)}`}\n tooltipDisabled={fontSizeTooltipDisabled || expandedPanel?.type === 'fontSize'}\n active={expandedPanel?.type === 'fontSize' || applied.typography}\n />\n\n {/* Font Color */}\n <FontColorButton\n colorPickerValue={colorPickerValue}\n isActive={isColorActive}\n onClick={onColorToggle}\n />\n\n {/* Text formatting buttons */}\n <BoldButton toolbar={toolbar} />\n <ItalicButton toolbar={toolbar} />\n <UnderlineButton toolbar={toolbar} />\n <UppercaseButton toolbar={toolbar} />\n\n {/* Text Alignment */}\n <TextAlignButton toolbar={toolbar} />\n\n {/* Text Effects Dropdown */}\n <TextEffectsDropdown\n element={elementForProperties as TextElement}\n onTransformTypeChange={toolbar.handleTransformTypeChange}\n onElementUpdate={elementUpdateHandler}\n isOpen={isTransformMenuOpen}\n onOpenChange={onTransformMenuOpenChange}\n />\n\n {/* Stroke */}\n {onStrokeToggle && (\n <ToolbarButton\n icon=\"lucide:pen-line\"\n onClick={() => {\n setStrokeTooltipDisabled(true);\n onStrokeToggle();\n }}\n onMouseLeave={() => setStrokeTooltipDisabled(false)}\n tooltip=\"Stroke\"\n tooltipDisabled={strokeTooltipDisabled || strokeExpanded}\n active={strokeExpanded || applied.stroke}\n />\n )}\n\n {/* Rotation */}\n <ToolbarButton\n icon={<RotateLeftIcon size={20} className=\"sc:md:size-5\" />}\n onClick={() => {\n setRotationTooltipDisabled(true);\n onRotationToggle();\n }}\n onMouseLeave={() => setRotationTooltipDisabled(false)}\n tooltip=\"Rotate\"\n tooltipDisabled={rotationTooltipDisabled || expandedPanel?.type === 'rotation'}\n active={expandedPanel?.type === 'rotation' || applied.rotation}\n />\n\n {/* Transparency */}\n <ToolbarButton\n icon=\"lucide:blend\"\n onClick={() => {\n setOpacityTooltipDisabled(true);\n onOpacityToggle();\n }}\n onMouseLeave={() => setOpacityTooltipDisabled(false)}\n tooltip=\"Transparency\"\n tooltipDisabled={opacityTooltipDisabled || expandedPanel?.type === 'opacity'}\n active={expandedPanel?.type === 'opacity' || applied.opacity}\n />\n\n {/* Shadow */}\n {onShadowToggle && (\n <ToolbarButton\n icon=\"gravity-ui:square-dashed-circle\"\n onClick={() => {\n setShadowTooltipDisabled(true);\n onShadowToggle();\n }}\n onMouseLeave={() => setShadowTooltipDisabled(false)}\n tooltip=\"Shadow\"\n tooltipDisabled={shadowTooltipDisabled || shadowExpanded}\n active={shadowExpanded || applied.shadow}\n />\n )}\n\n {/* Blend Mode */}\n {onBlendModeToggle && (\n <ToolbarButton\n icon=\"gravity-ui:circles-intersection\"\n onClick={() => {\n setBlendModeTooltipDisabled(true);\n onBlendModeToggle();\n }}\n onMouseLeave={() => setBlendModeTooltipDisabled(false)}\n tooltip=\"Blend Mode\"\n tooltipDisabled={blendModeTooltipDisabled || blendModeExpanded}\n active={blendModeExpanded || applied.blendMode}\n />\n )}\n\n {/* Knockout */}\n {onKnockoutToggle && (\n <ToolbarButton\n icon=\"lucide:scissors\"\n onClick={() => {\n setKnockoutTooltipDisabled(true);\n onKnockoutToggle();\n }}\n onMouseLeave={() => setKnockoutTooltipDisabled(false)}\n tooltip=\"Clip / Knockout\"\n tooltipDisabled={knockoutTooltipDisabled || knockoutExpanded}\n active={knockoutExpanded || applied.knockout}\n />\n )}\n\n {/* Distress Texture */}\n {onDistressTextureToggle && (\n <ToolbarButton\n icon=\"lucide:stamp\"\n onClick={() => {\n setDistressTooltipDisabled(true);\n onDistressTextureToggle();\n }}\n onMouseLeave={() => setDistressTooltipDisabled(false)}\n tooltip=\"Distress Texture\"\n tooltipDisabled={distressTooltipDisabled || distressTextureExpanded}\n active={distressTextureExpanded || applied.distress}\n />\n )}\n\n {/* Image Mask */}\n {onImageMaskToggle && (\n <ToolbarButton\n icon=\"lucide:venetian-mask\"\n onClick={() => {\n setImageMaskTooltipDisabled(true);\n onImageMaskToggle();\n }}\n onMouseLeave={() => setImageMaskTooltipDisabled(false)}\n tooltip=\"Image Mask\"\n tooltipDisabled={imageMaskTooltipDisabled || imageMaskExpanded}\n active={imageMaskExpanded || applied.imageMask}\n />\n )}\n\n {/* Glyph Browser */}\n <ToolbarButton\n icon=\"lucide:flag\"\n onClick={() => {\n setGlyphTooltipDisabled(true);\n onOpenGlyphBrowser?.();\n }}\n onMouseLeave={() => setGlyphTooltipDisabled(false)}\n tooltip={hasGlyphs ? 'Browse All Glyphs' : 'No alternate glyphs available'}\n tooltipDisabled={glyphTooltipDisabled}\n disabled={!hasGlyphs}\n className={!hasGlyphs ? 'sc:opacity-50' : ''}\n />\n\n {/* More Menu - custom items passed via prop */}\n {getMoreMenuItems && <MoreMenu items={getMoreMenuItems()} />}\n\n {/* More Menu - layer order and delete */}\n <TextMoreMenu\n onMoveForward={onMoveForward}\n onMoveBackward={onMoveBackward}\n onDelete={onDelete}\n onOpenChange={onTextMoreMenuOpenChange}\n />\n\n {/* Ungroup button - shown when editing a child in a group */}\n {showUngroupButton && (\n <button className=\"sc-toolbar-btn\" onClick={onUngroup}>\n Ungroup\n </button>\n )}\n </div>\n );\n}\n","/**\n * TransformConverter - Utility for converting between transform types\n * Handles position and dimension adjustments when switching transforms\n */\n\nimport { WAVE_DEFAULTS, FLAG_DEFAULTS, ARCH_DEFAULTS, LEAN_DEFAULTS } from '../transforms/defaults.js';\nimport type { TextElement } from './TextElement.js';\nimport type { TransformType, Point } from '../types/index.js';\n\n/** Configuration result for a transform conversion */\ninterface TransformConfig {\n x: number;\n y: number;\n fontSize: number;\n transformData: Record<string, unknown>;\n}\n\n/**\n * Convert an element from one transform type to another\n * Maintains visual size and position during conversion\n *\n * @param sourceElement - Element to convert from\n * @param targetType - Target transform type id\n * @param TargetClass - Target transform class constructor\n * @returns New element with target transform type\n */\nexport function convertTransform(\n sourceElement: TextElement,\n targetType: TransformType,\n TargetClass: new (config: Record<string, unknown>) => TextElement\n): TextElement {\n // Get the current element's rotation anchor as the consistent reference point\n const rotationAnchor = sourceElement.getRotationAnchor();\n\n // Get the current effective fontSize to maintain visual size\n let currentEffectiveFontSize: number;\n if (sourceElement.transformType === 'circle' && 'getEffectiveFontSize' in sourceElement) {\n // Circle mode uses scale, so get effective font size\n currentEffectiveFontSize = (sourceElement as unknown as { getEffectiveFontSize: () => number }).getEffectiveFontSize();\n } else {\n currentEffectiveFontSize = sourceElement.fontSize;\n }\n\n // Calculate appropriate transformData based on target type\n const config = calculateTransformConfig(sourceElement, targetType, currentEffectiveFontSize, rotationAnchor);\n\n // Create new element with converted properties\n return new TargetClass({\n id: sourceElement.id,\n text: sourceElement.text,\n x: config.x,\n y: config.y,\n rotation: sourceElement.rotation,\n fontSize: config.fontSize,\n fontFamily: sourceElement.fontFamily,\n color: sourceElement.color,\n textAlign: sourceElement.textAlign,\n transformData: config.transformData,\n });\n}\n\n/**\n * Calculate configuration for target transform type\n * @private\n */\nfunction calculateTransformConfig(\n sourceElement: TextElement,\n targetType: TransformType,\n effectiveFontSize: number,\n rotationAnchor: Point\n): TransformConfig {\n let transformData: Record<string, unknown>;\n let x: number, y: number;\n const fontSize = effectiveFontSize;\n\n switch (targetType) {\n case 'circle':\n // For circle, maintain the visual size by calculating radius from current dimensions\n // Use the height as the primary dimension since it's consistent across transforms\n const textHeight = effectiveFontSize * 1.2;\n // Use text height as basis for circle radius\n const radius = textHeight * 2; // Reasonable default circle size\n transformData = { radius, scale: 1 };\n // Circle's (x, y) is its center, which matches rotation anchor\n x = rotationAnchor.x;\n y = rotationAnchor.y;\n break;\n\n case 'custom':\n // For custom, preserve the fontSize and calculate appropriate width\n // Measure the actual text to determine minimum required width\n const minWidth = 200;\n const estimatedTextWidth = effectiveFontSize * sourceElement.text.length * 0.6;\n const targetWidth = Math.max(estimatedTextWidth, minWidth);\n\n transformData = { width: targetWidth };\n // CustomTransform's (x, y) is top-left, but rotation anchor is center\n // So we need to calculate top-left from the center\n const targetHeight = effectiveFontSize * 1.2;\n x = rotationAnchor.x - targetWidth / 2;\n y = rotationAnchor.y - targetHeight / 2;\n break;\n\n case 'arch':\n // For arch, use reasonable width based on text size\n const archMinWidth = 200;\n const archEstimatedWidth = effectiveFontSize * sourceElement.text.length * 0.6;\n transformData = {\n width: Math.max(archEstimatedWidth, archMinWidth),\n archHeight: ARCH_DEFAULTS.archHeight,\n };\n // Arch's (x, y) is center, which matches rotation anchor\n x = rotationAnchor.x;\n y = rotationAnchor.y;\n break;\n\n case 'wave':\n // Wave transform config\n const waveMinWidth = 200;\n const waveEstimatedWidth = effectiveFontSize * sourceElement.text.length * 0.6;\n transformData = {\n width: Math.max(waveEstimatedWidth, waveMinWidth),\n amplitude: WAVE_DEFAULTS.amplitude,\n frequency: WAVE_DEFAULTS.frequency,\n };\n x = rotationAnchor.x;\n y = rotationAnchor.y;\n break;\n\n case 'flag':\n // Flag transform config\n const flagMinWidth = 200;\n const flagEstimatedWidth = effectiveFontSize * sourceElement.text.length * 0.6;\n transformData = {\n width: Math.max(flagEstimatedWidth, flagMinWidth),\n amplitude: FLAG_DEFAULTS.amplitude,\n frequency: FLAG_DEFAULTS.frequency,\n };\n x = rotationAnchor.x;\n y = rotationAnchor.y;\n break;\n\n case 'lean':\n // Lean transform config\n const leanMinWidth = 200;\n const leanEstimatedWidth = effectiveFontSize * sourceElement.text.length * 0.6;\n transformData = {\n width: Math.max(leanEstimatedWidth, leanMinWidth),\n leanAmount: LEAN_DEFAULTS.leanAmount,\n };\n x = rotationAnchor.x;\n y = rotationAnchor.y;\n break;\n\n default:\n // Fallback for unknown transform types\n transformData = { width: 200 };\n x = rotationAnchor.x;\n y = rotationAnchor.y;\n }\n\n return { x, y, fontSize, transformData };\n}\n\nexport default { convertTransform };\n","/**\n * useTextToolbar - Hook for text element formatting state and handlers.\n *\n * Extracts all text-specific toolbar logic (font size, color, family,\n * bold/italic/underline, letter case, text align, transform type) from\n * ContextualToolbars so it can be reused in composed toolbar layouts.\n *\n * Uses `useEditor()` internally — no need to pass element/elements as props.\n * The only external dependency is `canvasEditorRef` for character-level formatting.\n */\n\nimport { useState, useCallback, useEffect, useRef } from 'react';\nimport { useEditor } from '../contexts/EditorContext.js';\nimport type { EditorElement } from '../contexts/EditorContext.js';\nimport { TextElement } from '../core/TextElement.js';\nimport { GroupElement } from '../core/GroupElement.js';\nimport { getTransformById } from '../transforms/registry.js';\nimport { convertTransform } from '../core/TransformConverter.js';\nimport type { TransformType, TextAlign, CharacterStyle } from '../types/index.js';\nimport type { CanvasEditorHandle } from '../components/CanvasEditor.js';\nimport type { CircleTransform } from '../transforms/CircleTransform.js';\n\nexport interface UseTextToolbarOptions {\n canvasEditorRef?: React.RefObject<CanvasEditorHandle | null>;\n}\n\nexport interface UseTextToolbarReturn {\n // State\n fontSize: number;\n fontColor: string;\n fontFamily: string;\n textAlign: TextAlign;\n bold: boolean;\n italic: boolean;\n underline: boolean;\n letterCase: string;\n /** Letter-spacing in px per character (element-level default; 0 = none). */\n letterSpacing: number;\n /** Line-height multiplier (1.2 = the layout default). */\n lineHeight: number;\n\n // Handlers\n handleFontSizeChange: (size: number) => void;\n handleFontSizeIncrement: (delta: number) => void;\n /** Per-character aware (applies to the selection while editing text). */\n handleLetterSpacingChange: (spacing: number) => void;\n /** Element-level only (line layout is an element concern, not a span one). */\n handleLineHeightChange: (lineHeight: number) => void;\n handleFontFamilyChange: (family: string) => void;\n handleFontColorChange: (e: React.ChangeEvent<HTMLInputElement>) => void;\n handleBoldToggle: () => void;\n handleItalicToggle: () => void;\n handleUnderlineToggle: () => void;\n handleLetterCaseToggle: () => void;\n isLetterCaseActive: () => boolean;\n handleTextAlignToggle: () => void;\n\n // Rich text support\n getEffectiveStyle: () => CharacterStyle;\n\n // Transform type\n handleTransformTypeChange: (type: TransformType) => void;\n}\n\n/**\n * Hook for text element formatting state and handlers.\n *\n * Extracts all text-specific toolbar logic (font size, color, family,\n * bold/italic/underline, letter case, text align, transform type) so it\n * can be reused across different toolbar layouts.\n *\n * Uses `useEditor()` internally. Pass a `canvasEditorRef` to enable\n * character-level rich text formatting during text editing mode.\n *\n * @param options - Configuration options\n * @returns Text toolbar state and handler functions\n *\n * @example\n * ```tsx\n * function MyTextToolbar() {\n * const toolbar = useTextToolbar({ canvasEditorRef });\n *\n * return (\n * <div>\n * <button onClick={toolbar.handleBoldToggle}>\n * Bold: {toolbar.bold ? 'ON' : 'OFF'}\n * </button>\n * <input\n * type=\"number\"\n * value={toolbar.fontSize}\n * onChange={(e) => toolbar.handleFontSizeChange(Number(e.target.value))}\n * />\n * </div>\n * );\n * }\n * ```\n */\nexport function useTextToolbar(options: UseTextToolbarOptions = {}): UseTextToolbarReturn {\n const { canvasEditorRef } = options;\n\n const {\n selectedElement,\n activeChildElement,\n handleElementUpdate,\n } = useEditor();\n\n // Determine which element to show properties for\n const elementForProperties = activeChildElement || selectedElement;\n\n // Element update handler (handles group children)\n const elementUpdateHandler = useCallback(\n (updatedElement: EditorElement) => {\n if (!selectedElement) return;\n\n if (activeChildElement) {\n // Update child within group\n if (!(selectedElement instanceof GroupElement)) return;\n const updatedGroup = selectedElement.clone();\n const childIndex = updatedGroup.children.findIndex((c) => c.id === activeChildElement.id);\n if (childIndex !== -1) {\n updatedGroup.children[childIndex] = updatedElement as typeof updatedGroup.children[number];\n handleElementUpdate(updatedGroup);\n }\n } else {\n handleElementUpdate(updatedElement);\n }\n },\n [selectedElement, activeChildElement, handleElementUpdate]\n );\n\n // Track element ID to detect real selection changes\n const currentElementId = elementForProperties?.id;\n const prevElementIdRef = useRef<string | undefined>(undefined);\n\n // Local state for toolbar\n const [localFontSize, setLocalFontSize] = useState<number>(32);\n const [localFontColor, setLocalFontColor] = useState<string>('#333333');\n const [localFontFamily, setLocalFontFamily] = useState<string>('Arial');\n const [localTextAlign, setLocalTextAlign] = useState<TextAlign>('center');\n\n // Sync local state ONLY when element ID changes (selection change)\n useEffect(() => {\n if (currentElementId !== prevElementIdRef.current) {\n prevElementIdRef.current = currentElementId;\n\n if (elementForProperties && elementForProperties instanceof TextElement) {\n if (elementForProperties.transformType === 'circle' && 'getEffectiveFontSize' in elementForProperties) {\n setLocalFontSize(Math.round((elementForProperties as CircleTransform).getEffectiveFontSize()));\n } else if (elementForProperties.fontSize !== undefined) {\n setLocalFontSize(Math.round(elementForProperties.fontSize));\n }\n if (elementForProperties.color !== undefined) {\n setLocalFontColor(elementForProperties.color);\n }\n if (elementForProperties.fontFamily !== undefined) {\n setLocalFontFamily(elementForProperties.fontFamily);\n }\n setLocalTextAlign(elementForProperties.textAlign || 'center');\n }\n }\n }, [currentElementId, elementForProperties]);\n\n // Derived display values\n const fontSize = localFontSize;\n const fontColor = localFontColor;\n const fontFamily = localFontFamily;\n const textAlign = localTextAlign;\n\n // Element-level text style properties\n const textElement = elementForProperties instanceof TextElement ? elementForProperties : null;\n const letterSpacing = textElement?.letterSpacing ?? 0;\n const lineHeight = textElement?.lineHeight ?? 1.2;\n const bold = textElement?.bold ?? false;\n const italic = textElement?.italic ?? false;\n const underline = textElement?.underline ?? false;\n // letterCase is not declared in TextElement's type but is stored as a dynamic property at runtime\n const letterCase = (textElement as Record<string, unknown> | null)?.letterCase as string ?? 'none';\n\n // Commit handlers\n const setFontSizeValue = useCallback(\n (newSize: number) => {\n setLocalFontSize(newSize);\n if (!elementForProperties || !(elementForProperties instanceof TextElement)) return;\n\n const updatedElement = elementForProperties.clone();\n if (updatedElement.transformType === 'circle' && 'setEffectiveFontSize' in updatedElement) {\n (updatedElement as CircleTransform).setEffectiveFontSize(newSize);\n } else {\n updatedElement.setFontSize(newSize);\n }\n\n if (updatedElement.richText) {\n updatedElement.richText.clearStyleProperty('fontSize');\n }\n\n elementUpdateHandler(updatedElement);\n },\n [elementForProperties, elementUpdateHandler]\n );\n\n const updateFontFamily = useCallback(\n (newFamily: string) => {\n setLocalFontFamily(newFamily);\n if (!elementForProperties || !(elementForProperties instanceof TextElement)) return;\n\n const updatedElement = elementForProperties.clone();\n updatedElement.fontFamily = newFamily;\n\n if (updatedElement.richText) {\n updatedElement.richText.clearStyleProperty('fontFamily');\n }\n\n elementUpdateHandler(updatedElement);\n },\n [elementForProperties, elementUpdateHandler]\n );\n\n const updateFontColor = useCallback(\n (newColor: string) => {\n setLocalFontColor(newColor);\n if (!elementForProperties || !(elementForProperties instanceof TextElement)) return;\n\n const updatedElement = elementForProperties.clone();\n updatedElement.color = newColor;\n if (updatedElement.richText) {\n updatedElement.richText.clearStyleProperty('color');\n }\n elementUpdateHandler(updatedElement);\n },\n [elementForProperties, elementUpdateHandler]\n );\n\n const updateTextAlign = useCallback(\n (alignment: TextAlign) => {\n setLocalTextAlign(alignment);\n if (!elementForProperties || !(elementForProperties instanceof TextElement)) return;\n\n const updatedElement = elementForProperties.clone();\n updatedElement.textAlign = alignment;\n elementUpdateHandler(updatedElement);\n },\n [elementForProperties, elementUpdateHandler]\n );\n\n // Character-level aware handlers\n const handleFontSizeChange = useCallback(\n (newSize: number) => {\n if (canvasEditorRef?.current?.isEditingText()) {\n canvasEditorRef.current.applyTextFormatting({ fontSize: newSize });\n } else {\n setFontSizeValue(newSize);\n }\n },\n [setFontSizeValue, canvasEditorRef]\n );\n\n const handleFontSizeIncrement = useCallback(\n (delta: number) => {\n const newSize = fontSize + delta;\n if (newSize >= 8 && newSize <= 500) {\n handleFontSizeChange(newSize);\n }\n },\n [fontSize, handleFontSizeChange]\n );\n\n // Letter-spacing: per-character aware (mirror handleFontSizeChange).\n // Element-level set clears span-level overrides so the slider acts on the\n // whole element, same contract as font size.\n const handleLetterSpacingChange = useCallback(\n (newSpacing: number) => {\n if (canvasEditorRef?.current?.isEditingText()) {\n canvasEditorRef.current.applyTextFormatting({ letterSpacing: newSpacing });\n return;\n }\n if (!elementForProperties || !(elementForProperties instanceof TextElement)) return;\n\n const updatedElement = elementForProperties.clone();\n updatedElement.letterSpacing = newSpacing;\n if (updatedElement.richText) {\n updatedElement.richText.clearStyleProperty('letterSpacing');\n }\n elementUpdateHandler(updatedElement);\n },\n [elementForProperties, elementUpdateHandler, canvasEditorRef]\n );\n\n // Line-height: element-level only — a line's height is a property of the\n // line box, not of individual characters.\n const handleLineHeightChange = useCallback(\n (newLineHeight: number) => {\n if (!elementForProperties || !(elementForProperties instanceof TextElement)) return;\n\n const updatedElement = elementForProperties.clone();\n updatedElement.lineHeight = newLineHeight;\n elementUpdateHandler(updatedElement);\n },\n [elementForProperties, elementUpdateHandler]\n );\n\n const handleFontFamilyChange = useCallback(\n (newFamily: string) => {\n if (canvasEditorRef?.current?.isEditingText()) {\n canvasEditorRef.current.applyTextFormatting({ fontFamily: newFamily });\n } else {\n updateFontFamily(newFamily);\n }\n },\n [updateFontFamily, canvasEditorRef]\n );\n\n const handleFontColorChange = useCallback(\n (e: React.ChangeEvent<HTMLInputElement>) => {\n const newColor = e.target.value;\n const isEditing = canvasEditorRef?.current?.isEditingText();\n if (isEditing && canvasEditorRef?.current) {\n canvasEditorRef.current.applyTextFormatting({ color: newColor });\n } else {\n updateFontColor(newColor);\n }\n },\n [updateFontColor, canvasEditorRef]\n );\n\n const handleBoldToggle = useCallback(() => {\n if (canvasEditorRef?.current?.isEditingText()) {\n canvasEditorRef.current.toggleFormattingProperty('bold');\n } else {\n if (!elementForProperties || !(elementForProperties instanceof TextElement)) return;\n const updated = elementForProperties.clone();\n updated.bold = !bold;\n if (updated.richText) {\n updated.richText.clearStyleProperty('bold');\n }\n elementUpdateHandler(updated);\n }\n }, [bold, elementForProperties, elementUpdateHandler, canvasEditorRef]);\n\n const handleItalicToggle = useCallback(() => {\n if (canvasEditorRef?.current?.isEditingText()) {\n canvasEditorRef.current.toggleFormattingProperty('italic');\n } else {\n if (!elementForProperties || !(elementForProperties instanceof TextElement)) return;\n const updated = elementForProperties.clone();\n updated.italic = !italic;\n if (updated.richText) {\n updated.richText.clearStyleProperty('italic');\n }\n elementUpdateHandler(updated);\n }\n }, [italic, elementForProperties, elementUpdateHandler, canvasEditorRef]);\n\n const handleUnderlineToggle = useCallback(() => {\n if (canvasEditorRef?.current?.isEditingText()) {\n canvasEditorRef.current.toggleFormattingProperty('underline');\n } else {\n if (!elementForProperties || !(elementForProperties instanceof TextElement)) return;\n const updated = elementForProperties.clone();\n updated.underline = !underline;\n if (updated.richText) {\n updated.richText.clearStyleProperty('underline');\n }\n elementUpdateHandler(updated);\n }\n }, [underline, elementForProperties, elementUpdateHandler, canvasEditorRef]);\n\n const handleLetterCaseToggle = useCallback(() => {\n if (!elementForProperties) return;\n const newCase = letterCase === 'uppercase' ? 'none' : 'uppercase';\n const updated = elementForProperties.clone();\n // letterCase is not declared in TextElement's type but is stored as a dynamic property at runtime\n (updated as unknown as Record<string, unknown>).letterCase = newCase;\n elementUpdateHandler(updated);\n }, [letterCase, elementForProperties, elementUpdateHandler]);\n\n const isLetterCaseActive = useCallback(() => {\n return letterCase === 'uppercase';\n }, [letterCase]);\n\n const handleTextAlignToggle = useCallback(() => {\n const alignments: TextAlign[] = ['left', 'center', 'right'];\n const currentIndex = alignments.indexOf(textAlign);\n const nextAlign = alignments[(currentIndex + 1) % alignments.length];\n updateTextAlign(nextAlign);\n }, [textAlign, updateTextAlign]);\n\n // Get effective style (for rich text support)\n const getEffectiveStyle = useCallback((): CharacterStyle => {\n if (canvasEditorRef?.current?.isEditingText?.()) {\n const selectionStyle = canvasEditorRef.current.getSelectionStyle?.();\n if (selectionStyle) {\n return {\n fontFamily: selectionStyle.fontFamily ?? fontFamily,\n fontSize: selectionStyle.fontSize ?? fontSize,\n color: selectionStyle.color ?? fontColor,\n bold: selectionStyle.bold ?? bold,\n italic: selectionStyle.italic ?? italic,\n underline: selectionStyle.underline ?? underline,\n };\n }\n }\n return {\n fontFamily,\n fontSize,\n color: fontColor,\n bold,\n italic,\n underline,\n };\n }, [canvasEditorRef, fontFamily, fontSize, fontColor, bold, italic, underline]);\n\n // Transform type change handler\n const handleTransformTypeChange = useCallback(\n (newType: TransformType) => {\n if (!elementForProperties) return;\n\n const transformDef = getTransformById(newType);\n if (!transformDef?.Component) return;\n\n const updated = convertTransform(elementForProperties as TextElement, newType, transformDef.Component as unknown as new (config: Record<string, unknown>) => TextElement);\n elementUpdateHandler(updated);\n },\n [elementForProperties, elementUpdateHandler]\n );\n\n return {\n fontSize,\n fontColor,\n fontFamily,\n textAlign,\n bold,\n italic,\n underline,\n letterCase,\n letterSpacing,\n lineHeight,\n handleFontSizeChange,\n handleFontSizeIncrement,\n handleLetterSpacingChange,\n handleLineHeightChange,\n handleFontFamilyChange,\n handleFontColorChange,\n handleBoldToggle,\n handleItalicToggle,\n handleUnderlineToggle,\n handleLetterCaseToggle,\n isLetterCaseActive,\n handleTextAlignToggle,\n getEffectiveStyle,\n handleTransformTypeChange,\n };\n}\n","/**\n * useLayerPreview - Hook for generating element preview thumbnails\n *\n * Extracts the preview/thumbnail generation logic from LayersPanel's\n * LayerPreview component into a reusable hook. Handles async image loading\n * for ImageElements and synchronous preview generation for other element types.\n *\n * @example\n * ```tsx\n * function LayerThumbnail({ element }: { element: EditorElement }) {\n * const { previewUrl, isLoading } = useLayerPreview({\n * element,\n * size: 148,\n * backgroundColor: 'transparent',\n * });\n *\n * if (isLoading || !previewUrl) return <Spinner />;\n * return <img src={previewUrl} alt=\"\" />;\n * }\n * ```\n */\n\nimport { useState, useEffect, useRef } from 'react';\nimport { ImageElement } from '../core/ImageElement.js';\nimport { TextElement } from '../core/TextElement.js';\nimport { ShapeElement } from '../core/ShapeElement.js';\nimport { PathElement } from '../core/PathElement.js';\nimport { GroupElement } from '../core/GroupElement.js';\nimport { generateElementPreview } from '../utils/ElementPreviewRenderer.js';\nimport { createLogger } from '../utils/logger.js';\nimport type { EditorElement } from '../contexts/EditorContext.js';\n\nconst logger = createLogger('useLayerPreview');\n\nexport interface UseLayerPreviewOptions {\n /** The element to generate a preview for */\n element: EditorElement;\n /** Preview size in pixels (width and height). Default: 148 */\n size?: number;\n /** Background color for the preview. Default: 'transparent' */\n backgroundColor?: string;\n /** Whether preview generation is enabled. Default: true */\n enabled?: boolean;\n}\n\nexport interface UseLayerPreviewReturn {\n /** Data URL of the preview image, or null if not yet generated */\n previewUrl: string | null;\n /** Whether the preview is currently being generated */\n isLoading: boolean;\n}\n\n/**\n * Hook for generating element preview thumbnails.\n *\n * Handles image elements by waiting for the image to load before\n * generating the preview. For text, shape, path, and group elements,\n * the preview is generated synchronously.\n *\n * Automatically regenerates when visual properties change (position,\n * rotation, transform data, text content, image URL, etc.).\n *\n * Debounces regeneration with a 50ms delay to avoid excessive\n * canvas operations during rapid property changes.\n */\nexport function useLayerPreview(options: UseLayerPreviewOptions): UseLayerPreviewReturn {\n const { element, size = 148, backgroundColor = 'transparent', enabled = true } = options;\n\n const [previewUrl, setPreviewUrl] = useState<string | null>(null);\n const [isLoading, setIsLoading] = useState(false);\n const debounceRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n\n useEffect(() => {\n if (!enabled) {\n setPreviewUrl(null);\n setIsLoading(false);\n return;\n }\n\n let mounted = true;\n setIsLoading(true);\n\n // Clear any pending debounce\n if (debounceRef.current) {\n clearTimeout(debounceRef.current);\n }\n\n debounceRef.current = setTimeout(() => {\n const generatePreview = async () => {\n try {\n // For image elements, wait for the image to load first\n if (element instanceof ImageElement && element.imageUrl) {\n const img = new Image();\n img.crossOrigin = 'anonymous';\n\n await new Promise<void>((resolve, reject) => {\n img.onload = () => resolve();\n img.onerror = () => reject(new Error('Failed to load image'));\n img.src = element.imageUrl;\n });\n\n if (!mounted) return;\n }\n\n // Generate the preview\n const url = generateElementPreview(element, {\n width: size,\n height: size,\n padding: 8,\n backgroundColor,\n });\n\n if (mounted) {\n setPreviewUrl(url);\n setIsLoading(false);\n }\n } catch (error) {\n logger.warn('Failed to generate preview:', error);\n // Generate a fallback preview without the loaded image\n if (mounted) {\n const url = generateElementPreview(element, {\n width: size,\n height: size,\n padding: 8,\n backgroundColor,\n });\n setPreviewUrl(url);\n setIsLoading(false);\n }\n }\n };\n\n generatePreview();\n }, 50); // 50ms debounce\n\n return () => {\n mounted = false;\n if (debounceRef.current) {\n clearTimeout(debounceRef.current);\n }\n };\n }, [\n element.id,\n backgroundColor,\n size,\n enabled,\n // Re-generate preview when visual properties change\n element.x,\n element.y,\n element.rotation,\n // Reference comparison is sufficient — elements are cloned before modification\n element.transformData,\n element instanceof TextElement ? element.text : null,\n element instanceof TextElement ? element.fontSize : null,\n element instanceof TextElement ? element.fontFamily : null,\n element instanceof TextElement ? element.color : null,\n element instanceof ImageElement ? element.imageUrl : null,\n element instanceof ImageElement ? element.imageLoaded : null,\n element instanceof ImageElement ? element.isCropping : null,\n element instanceof ShapeElement ? element.transformData?.fillColor : null,\n element instanceof ShapeElement ? element.transformData?.fill : null,\n element instanceof PathElement ? element.transformData?.points?.length : null,\n element instanceof GroupElement ? element.children?.length : null,\n ]);\n\n return { previewUrl, isLoading };\n}\n","/**\n * LayerLeadingChip — leading slot for the contextual toolbar.\n *\n * Shows the selected element's thumbnail and a lock toggle, inline\n * with the rest of the toolbar buttons.\n *\n * The thumbnail uses `useLayerPreview` — the same hook the LayersPanel\n * uses to render real per-element previews via the canvas pipeline.\n * That way a star shape looks like a star, a rotated layer looks\n * rotated, and a masked / distressed layer reads accordingly. Earlier\n * versions used a hand-coded element-type-specific glyph (a square\n * for any shape, a single character for any text), which lied to the\n * user about what they had selected.\n *\n * The toolbar wrapper carries `data-preserve-selection` already, so\n * tapping the lock toggle won't trigger the document-level deselect\n * listener.\n *\n * The lock button uses `ToolbarButton` so it inherits the standard\n * toolbar sizing, the standard 20px icon, and the standard\n * `data-active='true'` \"selected\" styling.\n */\n\nimport { BaseElement } from '../core/BaseElement.js';\nimport { ToolbarButton } from './ui/toolbar-button.js';\nimport { useLayerPreview } from '../hooks/useLayerPreview.js';\nimport type { EditorElement } from '../contexts/EditorContext.js';\n\nexport function LayerLeadingChip({\n element,\n onToggleLock,\n onThumbnailClick,\n}: {\n element: BaseElement | null;\n onToggleLock: () => void;\n /** Optional click handler for the thumbnail. When provided, the\n * thumbnail becomes a button — typical use is to open the\n * \"Manage Layers\" drawer with the current layer focused. */\n onThumbnailClick?: () => void;\n}) {\n if (!element) return null;\n const locked = element.locked === true;\n return (\n <>\n <SelectionThumbnail\n element={element as EditorElement}\n onClick={onThumbnailClick}\n />\n <ToolbarButton\n icon={<LockIcon locked={locked} />}\n onClick={onToggleLock}\n active={locked}\n tooltip={locked ? 'Unlock layer' : 'Lock layer'}\n aria-label={locked ? 'Unlock layer' : 'Lock layer'}\n />\n </>\n );\n}\n\n// Outer cell is a button-sized slot for layout alignment with the\n// toolbar buttons. Inner thumbnail is icon-sized so it carries the\n// same visual weight as an icon. We render the actual preview from\n// `useLayerPreview` (already used by the LayersPanel) — for shapes\n// that means a star renders as a star, polygon as polygon, etc.\nfunction SelectionThumbnail({\n element,\n onClick,\n}: {\n element: EditorElement;\n onClick?: () => void;\n}) {\n // 64px source — small enough to be cheap to regenerate, big enough\n // that browser downscale to 20–24px stays sharp. Transparent bg\n // so the muted backdrop shows through the layer's empty space.\n const { previewUrl } = useLayerPreview({\n element,\n size: 64,\n backgroundColor: 'transparent',\n });\n\n const inner = (\n <span\n className=\"sc:size-6 sc:md:size-5 sc:rounded-md sc:shrink-0 sc:flex sc:items-center sc:justify-center sc:overflow-hidden\"\n style={{ background: 'var(--color-muted, rgba(120,120,120,0.18))' }}\n >\n {previewUrl ? (\n <img\n src={previewUrl}\n alt=\"\"\n style={{ width: '100%', height: '100%', objectFit: 'contain' }}\n />\n ) : null}\n </span>\n );\n\n // When a click handler is wired (e.g. open layers drawer), render\n // the cell as a button so it gets the standard hover affordance and\n // keyboard focus. Otherwise keep it as a plain decorative span.\n if (onClick) {\n return (\n <button\n type=\"button\"\n onClick={onClick}\n onPointerDown={(e) => e.stopPropagation()}\n onPointerUp={(e) => e.stopPropagation()}\n aria-label=\"Manage layers\"\n title=\"Manage layers\"\n className=\"sc:size-11 sc:md:size-9 sc:shrink-0 sc:flex sc:items-center sc:justify-center\"\n >\n {inner}\n </button>\n );\n }\n return (\n <span\n aria-hidden\n className=\"sc:size-11 sc:md:size-9 sc:shrink-0 sc:flex sc:items-center sc:justify-center\"\n >\n {inner}\n </span>\n );\n}\n\n// 20px lock icon (size-5) matches the other toolbar icons. Closed\n// shackle when locked, open shackle when unlocked. `currentColor`\n// so the data-active=true styling tints the icon too.\nfunction LockIcon({ locked }: { locked: boolean }) {\n return (\n <svg width=\"20\" height=\"20\" viewBox=\"0 0 20 20\" fill=\"none\" aria-hidden>\n <rect\n x=\"4\"\n y=\"9\"\n width=\"12\"\n height=\"8.5\"\n rx=\"1.6\"\n stroke=\"currentColor\"\n strokeWidth=\"1.6\"\n fill={locked ? 'currentColor' : 'none'}\n fillOpacity={locked ? 0.18 : 0}\n />\n {locked ? (\n <path\n d=\"M6.5 9V6.25a3.5 3.5 0 0 1 7 0V9\"\n stroke=\"currentColor\"\n strokeWidth=\"1.6\"\n strokeLinecap=\"round\"\n />\n ) : (\n <path\n d=\"M6.5 9V6.25a3.5 3.5 0 0 1 7 0\"\n stroke=\"currentColor\"\n strokeWidth=\"1.6\"\n strokeLinecap=\"round\"\n />\n )}\n </svg>\n );\n}\n","/**\n * alignDistribute - Pure geometry for explicit align / distribute commands.\n *\n * The snap system (`AlignmentSnapSystem`) draws guides WHILE dragging; this\n * module is the other half: explicit \"align left / center / distribute\"\n * commands applied to a selection in one shot.\n *\n * Everything here is pure — element bboxes in, new positions out. The caller\n * (see `useAlignDistribute`) owns selection semantics, locked-element\n * filtering, and applying the result through the command history so one undo\n * reverts the whole operation.\n *\n * Coordinate model (gotcha #19 in packages/canvas/CLAUDE.md): `bbox` is the\n * CONCEPTUAL `getBoundingBox()` rect (x/y = top-left of the rect transform\n * handles act on), while an element's own `x`/`y` is its position field —\n * for most elements the CENTER point, NOT the bbox top-left. To stay correct\n * for every element type we never assume where `x` sits inside the bbox:\n * we compute the delta that moves the bbox where it should go and shift the\n * position field by the same delta.\n */\n\nimport { EditorError } from '../errors/editorError.js';\nimport type { BoundingBox } from '../types/index.js';\n\n/** Minimum number of movable elements for a distribute operation. */\nexport const DISTRIBUTE_MIN_COUNT = 3;\n\n/** Minimum number of elements for aligning relative to the selection itself\n * (below this the caller should align relative to the artboard). */\nexport const ALIGN_SELECTION_MIN_COUNT = 2;\n\nexport type AlignMode = 'left' | 'center-h' | 'right' | 'top' | 'center-v' | 'bottom';\nexport type DistributeMode = 'horizontal' | 'vertical';\n\n/** Geometry of one alignable element. `x`/`y` is the element's position\n * field (center point for canvas elements); `bbox` its conceptual\n * `getBoundingBox()` rect in the same world coordinates. */\nexport interface AlignableItem {\n id: string;\n x: number;\n y: number;\n bbox: BoundingBox;\n}\n\n/** New value for an element's position field. */\nexport interface PositionUpdate {\n id: string;\n x: number;\n y: number;\n}\n\n/** Union of the items' bboxes. Returns null for an empty list. */\nexport function combinedBounds(items: readonly AlignableItem[]): BoundingBox | null {\n if (items.length === 0) return null;\n let minX = Infinity;\n let minY = Infinity;\n let maxX = -Infinity;\n let maxY = -Infinity;\n for (const item of items) {\n minX = Math.min(minX, item.bbox.x);\n minY = Math.min(minY, item.bbox.y);\n maxX = Math.max(maxX, item.bbox.x + item.bbox.width);\n maxY = Math.max(maxY, item.bbox.y + item.bbox.height);\n }\n return { x: minX, y: minY, width: maxX - minX, height: maxY - minY };\n}\n\n/**\n * Align every item's bbox to `frame` (the selection's combined bounds, or the\n * artboard rect for a single element). Returns position updates ONLY for\n * items that actually move, so callers can batch exactly the real changes.\n */\nexport function computeAlign(\n items: readonly AlignableItem[],\n mode: AlignMode,\n frame: BoundingBox\n): PositionUpdate[] {\n const updates: PositionUpdate[] = [];\n for (const item of items) {\n let dx = 0;\n let dy = 0;\n switch (mode) {\n case 'left':\n dx = frame.x - item.bbox.x;\n break;\n case 'center-h':\n dx = frame.x + frame.width / 2 - (item.bbox.x + item.bbox.width / 2);\n break;\n case 'right':\n dx = frame.x + frame.width - (item.bbox.x + item.bbox.width);\n break;\n case 'top':\n dy = frame.y - item.bbox.y;\n break;\n case 'center-v':\n dy = frame.y + frame.height / 2 - (item.bbox.y + item.bbox.height / 2);\n break;\n case 'bottom':\n dy = frame.y + frame.height - (item.bbox.y + item.bbox.height);\n break;\n }\n if (dx !== 0 || dy !== 0) {\n updates.push({ id: item.id, x: item.x + dx, y: item.y + dy });\n }\n }\n return updates;\n}\n\n/**\n * Distribute items along one axis with EQUAL GAPS between bbox edges. The\n * outermost items (first/last along the axis) stay put; everything between\n * is repositioned. Requires at least {@link DISTRIBUTE_MIN_COUNT} items —\n * with fewer there is nothing between the ends to distribute, so calling\n * this is a contradiction and throws (`E_DISTRIBUTE_MIN_THREE`), never a\n * silent no-op. UI callers must not render distribute affordances below the\n * threshold (see `useAlignDistribute().canDistribute`).\n */\nexport function computeDistribute(\n items: readonly AlignableItem[],\n mode: DistributeMode\n): PositionUpdate[] {\n if (items.length < DISTRIBUTE_MIN_COUNT) {\n throw new EditorError(\n 'E_DISTRIBUTE_MIN_THREE',\n `distribute ${mode} needs at least ${DISTRIBUTE_MIN_COUNT} movable elements, got ${items.length}. ` +\n `Gate the action on useAlignDistribute().canDistribute (or items.length >= DISTRIBUTE_MIN_COUNT) ` +\n `instead of calling computeDistribute below the threshold.`,\n { mode, count: items.length, min: DISTRIBUTE_MIN_COUNT }\n );\n }\n\n const horizontal = mode === 'horizontal';\n const sorted = [...items].sort((a, b) =>\n horizontal\n ? a.bbox.x + a.bbox.width / 2 - (b.bbox.x + b.bbox.width / 2)\n : a.bbox.y + a.bbox.height / 2 - (b.bbox.y + b.bbox.height / 2)\n );\n\n const first = sorted[0];\n const last = sorted[sorted.length - 1];\n const span = horizontal\n ? last.bbox.x + last.bbox.width - first.bbox.x\n : last.bbox.y + last.bbox.height - first.bbox.y;\n const totalSize = sorted.reduce(\n (sum, item) => sum + (horizontal ? item.bbox.width : item.bbox.height),\n 0\n );\n const gap = (span - totalSize) / (sorted.length - 1);\n\n const updates: PositionUpdate[] = [];\n let cursor = horizontal ? first.bbox.x : first.bbox.y;\n for (const item of sorted) {\n const current = horizontal ? item.bbox.x : item.bbox.y;\n const delta = cursor - current;\n if (delta !== 0) {\n updates.push({\n id: item.id,\n x: item.x + (horizontal ? delta : 0),\n y: item.y + (horizontal ? 0 : delta),\n });\n }\n cursor += (horizontal ? item.bbox.width : item.bbox.height) + gap;\n }\n return updates;\n}\n","/**\n * useAlignDistribute - Explicit align / distribute commands for the current\n * selection, applied as ONE undo step.\n *\n * Semantics:\n * - Targets are the multi-selection if active, otherwise the single selected\n * element.\n * - `locked` elements are excluded entirely — they neither move nor serve as\n * an alignment reference (lock gates manipulation, gotcha #20; align IS\n * manipulation, unlike select/delete).\n * - With ≥2 movable elements, align is relative to the selection's combined\n * bbox; with exactly 1, align is relative to the active artboard (\"center\n * on artboard\").\n * - Distribute needs ≥3 movable elements. Below the threshold the action is\n * unavailable (`canDistribute` is false — UI must not render the buttons);\n * calling `distribute()` anyway throws `E_DISTRIBUTE_MIN_THREE` from the\n * pure layer, never a silent no-op.\n * - All moves go through `executeCommandBatch` (clone-before-modify), so a\n * single undo reverts the whole align/distribute.\n */\n\nimport { useCallback, useMemo } from 'react';\nimport { useEditor } from '../contexts/EditorContext.js';\nimport type { EditorElement } from '../contexts/EditorContext.js';\nimport {\n combinedBounds,\n computeAlign,\n computeDistribute,\n ALIGN_SELECTION_MIN_COUNT,\n DISTRIBUTE_MIN_COUNT,\n type AlignMode,\n type AlignableItem,\n type DistributeMode,\n type PositionUpdate,\n} from '../utils/alignDistribute.js';\n\nexport type { AlignMode, DistributeMode } from '../utils/alignDistribute.js';\n\nexport interface UseAlignDistributeResult {\n /** Number of movable (selected, unlocked) elements. */\n movableCount: number;\n /** True when align commands have something to act on. */\n canAlign: boolean;\n /** True when distribute commands are available (≥3 movable elements).\n * UI must gate rendering of distribute affordances on this. */\n canDistribute: boolean;\n /** Align the movable selection. ≥2 elements: relative to the selection's\n * combined bbox; exactly 1: relative to the active artboard. */\n align: (mode: AlignMode) => void;\n /** Distribute the movable selection with equal gaps between bbox edges.\n * Throws `E_DISTRIBUTE_MIN_THREE` when `canDistribute` is false. */\n distribute: (mode: DistributeMode) => void;\n}\n\nexport function useAlignDistribute(): UseAlignDistributeResult {\n const { elements, multiSelection, selectedElement, artboardManager, executeCommandBatch, setElements } =\n useEditor();\n\n // Movable targets: the multi-selection (or single selection), minus locked\n // elements — lock gates manipulation (gotcha #20), and align moves things.\n const movableElements = useMemo(() => {\n const selected =\n multiSelection.length > 0\n ? elements.filter((el) => multiSelection.includes(el.id))\n : selectedElement\n ? [selectedElement]\n : [];\n return selected.filter((el) => !el.locked);\n }, [elements, multiSelection, selectedElement]);\n\n const applyUpdates = useCallback(\n (updates: PositionUpdate[]) => {\n if (updates.length === 0) return;\n const byId = new Map(movableElements.map((el) => [el.id, el]));\n const commands = updates.flatMap((update) => {\n const oldElement = byId.get(update.id);\n if (!oldElement) return [];\n // Clone-before-modify: the old reference stays untouched for undo.\n const newElement = oldElement.clone() as EditorElement;\n newElement.x = update.x;\n newElement.y = update.y;\n const replaceWith = (el: EditorElement) => {\n setElements((prev) => prev.map((s) => (s.id === el.id ? el : s)));\n };\n return [{ execute: () => replaceWith(newElement), undo: () => replaceWith(oldElement) }];\n });\n // One CompoundCommand on the active artboard → one undo step.\n executeCommandBatch(commands);\n },\n [movableElements, executeCommandBatch, setElements]\n );\n\n const align = useCallback(\n (mode: AlignMode) => {\n const items: AlignableItem[] = movableElements.map((el) => ({\n id: el.id,\n x: el.x,\n y: el.y,\n bbox: el.getBoundingBox(),\n }));\n let frame = items.length >= ALIGN_SELECTION_MIN_COUNT ? combinedBounds(items) : null;\n if (!frame) {\n // Single element (or selection bbox unavailable): align to artboard.\n const artboard = artboardManager.getActiveArtboard();\n if (!artboard) return;\n frame = { x: artboard.x, y: artboard.y, width: artboard.width, height: artboard.height };\n }\n applyUpdates(computeAlign(items, mode, frame));\n },\n [movableElements, artboardManager, applyUpdates]\n );\n\n const distribute = useCallback(\n (mode: DistributeMode) => {\n const items: AlignableItem[] = movableElements.map((el) => ({\n id: el.id,\n x: el.x,\n y: el.y,\n bbox: el.getBoundingBox(),\n }));\n // Below DISTRIBUTE_MIN_COUNT the pure layer throws E_DISTRIBUTE_MIN_THREE.\n applyUpdates(computeDistribute(items, mode));\n },\n [movableElements, applyUpdates]\n );\n\n return {\n movableCount: movableElements.length,\n canAlign: movableElements.length >= 1,\n canDistribute: movableElements.length >= DISTRIBUTE_MIN_COUNT,\n align,\n distribute,\n };\n}\n\nexport default useAlignDistribute;\n","/**\n * Shared align / distribute button definitions.\n *\n * One source of truth for the icon + label + mode of each alignment command,\n * consumed by BOTH alignment surfaces:\n * - `MultiSelectionToolbar` (≥2 selected: align relative to the selection)\n * - `AlignPanel` (single selection: align relative to the artboard)\n *\n * Keeping the defs in one module guarantees the two surfaces can't drift —\n * same icons, same labels, same `data-testid` vocabulary (`align-<mode>`).\n */\n\nimport type { AlignMode, DistributeMode } from '../../utils/alignDistribute.js';\n\nexport interface AlignButtonDef {\n mode: AlignMode;\n icon: string;\n label: string;\n}\n\nexport interface DistributeButtonDef {\n mode: DistributeMode;\n icon: string;\n label: string;\n}\n\nexport const ALIGN_BUTTONS: readonly AlignButtonDef[] = [\n { mode: 'left', icon: 'gravity-ui:objects-align-left', label: 'Align left' },\n { mode: 'center-h', icon: 'gravity-ui:objects-align-center-horizontal', label: 'Align horizontal centers' },\n { mode: 'right', icon: 'gravity-ui:objects-align-right', label: 'Align right' },\n { mode: 'top', icon: 'gravity-ui:objects-align-top', label: 'Align top' },\n { mode: 'center-v', icon: 'gravity-ui:objects-align-center-vertical', label: 'Align vertical centers' },\n { mode: 'bottom', icon: 'gravity-ui:objects-align-bottom', label: 'Align bottom' },\n] as const;\n\nexport const DISTRIBUTE_BUTTONS: readonly DistributeButtonDef[] = [\n { mode: 'horizontal', icon: 'gravity-ui:objects-align-justify-horizontal', label: 'Distribute horizontally' },\n { mode: 'vertical', icon: 'gravity-ui:objects-align-justify-vertical', label: 'Distribute vertically' },\n] as const;\n","/**\n * MultiSelectionToolbar - Contextual toolbar for multi-element selections.\n *\n * Rendered by `ContextualToolbars` whenever a multi-selection is active (the\n * per-element toolbars only handle single selections). Provides the explicit\n * align / distribute commands (`useAlignDistribute`):\n *\n * - Align buttons act relative to the selection's combined bbox (or the\n * artboard when only one movable element remains after locked filtering).\n * - Distribute buttons are NOT RENDERED below 3 movable elements — the wrong\n * state is unrepresentable in the UI (the pure layer additionally throws\n * `E_DISTRIBUTE_MIN_THREE` for programmatic misuse).\n * - Locked elements neither move nor act as a reference.\n *\n * Each command lands as ONE undo step (CompoundCommand batch).\n *\n * Floating mode portals to `document.body` and anchors above the selection's\n * combined bbox using the same screen mapping + resize/scroll listeners as\n * the single-selection toolbar (class-3 anchoring contract, ADR-0085 §5).\n */\n\nimport React, { useEffect, useMemo, useRef, useState } from 'react';\nimport { createPortal } from 'react-dom';\nimport { useEditor } from '../contexts/EditorContext.js';\nimport { useViewportContext } from '../contexts/ViewportContext.js';\nimport { useAlignDistribute } from '../hooks/useAlignDistribute.js';\nimport { combinedBounds, type AlignableItem } from '../utils/alignDistribute.js';\nimport { ALIGN_BUTTONS, DISTRIBUTE_BUTTONS } from './toolbars/alignButtons.js';\nimport { ToolbarButton } from './ui/index.js';\n\nexport interface MultiSelectionToolbarProps {\n /** Positioning mode — mirrors `ContextualToolbars`. */\n mode?: 'floating' | 'embedded';\n /** Artboard screen bounds fallback when no canvas ref is available. */\n artboardScreenBounds?: {\n left: number;\n top: number;\n width: number;\n height: number;\n bottom: number;\n centerX: number;\n };\n /** `data-sc-part` value for the toolbar root (Editor.* parts contract). */\n partAttr?: string;\n}\n\nexport const MultiSelectionToolbar: React.FC<MultiSelectionToolbarProps> = ({\n mode = 'floating',\n artboardScreenBounds,\n partAttr,\n}) => {\n const { elements, multiSelection, artboardManager, canvasRef, canvasEditorRef } = useEditor();\n const { panOffset } = useViewportContext();\n const { canAlign, canDistribute, align, distribute } = useAlignDistribute();\n\n const toolbarRef = useRef<HTMLDivElement>(null);\n const [position, setPosition] = useState<{ top: number; left: number } | null>(null);\n\n // Combined world-space bounds of the multi-selection (all selected\n // elements, locked included — the toolbar anchors to what the user sees).\n const selectionBounds = useMemo(() => {\n const items: AlignableItem[] = elements\n .filter((el) => multiSelection.includes(el.id))\n .map((el) => ({ id: el.id, x: el.x, y: el.y, bbox: el.getBoundingBox() }));\n return combinedBounds(items);\n }, [elements, multiSelection]);\n\n // ── Floating position: anchor above the selection bbox ─────────────────\n // Same screen mapping + resize/scroll listeners as the single-selection\n // toolbar in ContextualToolbars (capture-phase scroll for nested scrollers).\n useEffect(() => {\n if (mode !== 'floating') return;\n if (!selectionBounds) {\n setPosition(null);\n return;\n }\n\n const updatePosition = () => {\n const toolbarWidth = toolbarRef.current?.offsetWidth || 0;\n const toolbarHeight = toolbarRef.current?.offsetHeight || 48;\n const activeArtboard = artboardManager.getActiveArtboard();\n const artboardX = activeArtboard?.x || 0;\n const artboardY = activeArtboard?.y || 0;\n const currentZoom = canvasEditorRef?.current?.getZoom?.() || 1;\n const canvas = canvasRef?.current;\n\n let screenX: number;\n let screenY: number;\n if (canvas) {\n const canvasRect = canvas.getBoundingClientRect();\n screenX = canvasRect.left + (selectionBounds.x - artboardX) * currentZoom;\n screenY = canvasRect.top + (selectionBounds.y - artboardY) * currentZoom;\n } else if (artboardScreenBounds) {\n screenX = artboardScreenBounds.left + (selectionBounds.x - artboardX) * currentZoom;\n screenY = artboardScreenBounds.top + (selectionBounds.y - artboardY) * currentZoom;\n } else {\n screenX = window.innerWidth / 2 - (selectionBounds.width * currentZoom) / 2;\n screenY = window.innerHeight / 2 - (selectionBounds.height * currentZoom) / 2;\n }\n const screenWidth = selectionBounds.width * currentZoom;\n const screenHeight = selectionBounds.height * currentZoom;\n\n const gap = 12;\n let top = screenY - toolbarHeight - gap;\n let left = screenX + screenWidth / 2;\n\n if (toolbarWidth > 0) {\n const padding = 20;\n const minLeft = toolbarWidth / 2 + padding;\n const maxLeft = window.innerWidth - toolbarWidth / 2 - padding;\n left = Math.max(minLeft, Math.min(maxLeft, left));\n }\n if (top < 10) {\n top = screenY + screenHeight + gap;\n }\n top = Math.min(top, window.innerHeight - toolbarHeight - 10);\n top = Math.max(10, top);\n\n setPosition({ top, left });\n };\n\n updatePosition();\n window.addEventListener('resize', updatePosition);\n window.addEventListener('scroll', updatePosition, { passive: true, capture: true });\n return () => {\n window.removeEventListener('resize', updatePosition);\n window.removeEventListener('scroll', updatePosition, { capture: true });\n };\n }, [mode, selectionBounds, artboardManager, canvasRef, canvasEditorRef, artboardScreenBounds, panOffset]);\n\n if (!canAlign || multiSelection.length === 0) return null;\n\n const style: React.CSSProperties =\n mode === 'embedded'\n ? { borderRadius: '9999px', position: 'static', display: 'flex', justifyContent: 'flex-start' }\n : position\n ? {\n top: `${position.top}px`,\n left: `${position.left}px`,\n position: 'fixed',\n transform: 'translateX(-50%)',\n borderRadius: '9999px',\n zIndex: 'var(--sc-z-tooltip)' as React.CSSProperties['zIndex'],\n }\n : {\n borderRadius: '9999px',\n visibility: 'hidden',\n position: 'fixed',\n top: '-9999px',\n left: '-9999px',\n zIndex: 'var(--sc-z-tooltip)' as React.CSSProperties['zIndex'],\n };\n\n const content = (\n <div\n ref={toolbarRef}\n className=\"sc-toolbar\"\n data-sc-part={partAttr ?? 'multi-selection-toolbar'}\n data-testid=\"multi-selection-toolbar\"\n data-mode={mode}\n data-preserve-selection\n style={style}\n >\n <div className=\"sc-toolbar-items\">\n {ALIGN_BUTTONS.map(({ mode: alignMode, icon, label }) => (\n <ToolbarButton\n key={alignMode}\n icon={icon}\n onClick={() => align(alignMode)}\n tooltip={label}\n data-testid={`align-${alignMode}`}\n />\n ))}\n {/* Distribute needs ≥3 movable elements — below the threshold the\n buttons do not exist (no disabled state to mis-click), matching\n the E_DISTRIBUTE_MIN_THREE contract in the pure layer. */}\n {canDistribute &&\n DISTRIBUTE_BUTTONS.map(({ mode: distMode, icon, label }) => (\n <ToolbarButton\n key={distMode}\n icon={icon}\n onClick={() => distribute(distMode)}\n tooltip={label}\n data-testid={`distribute-${distMode}`}\n />\n ))}\n </div>\n </div>\n );\n\n return mode === 'floating' ? createPortal(content, document.body) : content;\n};\n\nexport default MultiSelectionToolbar;\n","/**\n * GroupElementToolbar - Toolbar for group element controls.\n *\n * Shows when a group element is selected (not when editing a child within it).\n * Provides stroke, rotation, transparency, and ungroup controls.\n */\n\nimport React, { useState } from 'react';\nimport {\n Tooltip,\n TooltipTrigger,\n TooltipContent,\n ToolbarButton,\n Button,\n RotateLeftIcon,\n} from '../ui/index.js';\nimport { getFeatureApplied } from '../../utils/featureApplied.js';\nimport type { GroupElement } from '../../core/GroupElement.js';\n\nexport interface GroupElementToolbarProps {\n /** The group element being edited — used to derive feature-applied\n * flags so the toolbar buttons highlight when a property is set. */\n element?: GroupElement;\n /** Whether the rotation panel is expanded */\n rotationExpanded?: boolean;\n /** Callback when rotation panel should be toggled */\n onRotationToggle: () => void;\n /** Whether the opacity panel is expanded */\n opacityExpanded?: boolean;\n /** Callback when opacity panel should be toggled */\n onOpacityToggle: () => void;\n /** Whether the stroke panel is expanded */\n strokeExpanded?: boolean;\n /** Callback when stroke panel should be toggled */\n onStrokeToggle?: () => void;\n /** Whether the shadow panel is expanded */\n shadowExpanded?: boolean;\n /** Callback when shadow panel should be toggled */\n onShadowToggle?: () => void;\n /** Whether the blend mode panel is expanded */\n blendModeExpanded?: boolean;\n /** Callback when blend mode panel should be toggled */\n onBlendModeToggle?: () => void;\n /** Whether the knockout panel is expanded */\n knockoutExpanded?: boolean;\n /** Callback when knockout panel should be toggled */\n onKnockoutToggle?: () => void;\n /** Whether the distress texture panel is expanded */\n distressTextureExpanded?: boolean;\n /** Callback when distress texture panel should be toggled */\n onDistressTextureToggle?: () => void;\n /** Whether the image mask panel is expanded */\n imageMaskExpanded?: boolean;\n /** Callback when image mask panel should be toggled */\n onImageMaskToggle?: () => void;\n /** Callback when the group should be ungrouped */\n onUngroup: () => void;\n}\n\nexport const GroupElementToolbar: React.FC<GroupElementToolbarProps> = ({\n element,\n rotationExpanded = false,\n onRotationToggle,\n opacityExpanded = false,\n onOpacityToggle,\n strokeExpanded = false,\n onStrokeToggle,\n shadowExpanded = false,\n onShadowToggle,\n blendModeExpanded = false,\n onBlendModeToggle,\n knockoutExpanded = false,\n onKnockoutToggle,\n distressTextureExpanded = false,\n onDistressTextureToggle,\n imageMaskExpanded = false,\n onImageMaskToggle,\n onUngroup,\n}) => {\n const [rotationTooltipDisabled, setRotationTooltipDisabled] = useState(false);\n const [opacityTooltipDisabled, setOpacityTooltipDisabled] = useState(false);\n const [strokeTooltipDisabled, setStrokeTooltipDisabled] = useState(false);\n const [shadowTooltipDisabled, setShadowTooltipDisabled] = useState(false);\n const [blendModeTooltipDisabled, setBlendModeTooltipDisabled] = useState(false);\n const [knockoutTooltipDisabled, setKnockoutTooltipDisabled] = useState(false);\n const [distressTooltipDisabled, setDistressTooltipDisabled] = useState(false);\n const [imageMaskTooltipDisabled, setImageMaskTooltipDisabled] = useState(false);\n\n // Feature-applied flags — drive the \"selected\" highlight on the\n // toolbar buttons whose underlying property has been set to a\n // non-default value on the group element.\n const applied = getFeatureApplied(element ?? null);\n\n return (\n <div className=\"sc-toolbar-items\">\n {/* Rotation */}\n <ToolbarButton\n icon={<RotateLeftIcon size={20} className=\"sc:md:size-5\" />}\n onClick={() => {\n setRotationTooltipDisabled(true);\n onRotationToggle();\n }}\n onMouseLeave={() => setRotationTooltipDisabled(false)}\n tooltip=\"Rotate\"\n tooltipDisabled={rotationTooltipDisabled || rotationExpanded}\n active={rotationExpanded || applied.rotation}\n />\n\n {/* Transparency */}\n <ToolbarButton\n icon=\"lucide:blend\"\n onClick={() => {\n setOpacityTooltipDisabled(true);\n onOpacityToggle();\n }}\n onMouseLeave={() => setOpacityTooltipDisabled(false)}\n tooltip=\"Transparency\"\n tooltipDisabled={opacityTooltipDisabled || opacityExpanded}\n active={opacityExpanded || applied.opacity}\n />\n\n {/* Stroke */}\n {onStrokeToggle && (\n <ToolbarButton\n icon=\"lucide:pen-line\"\n onClick={() => {\n setStrokeTooltipDisabled(true);\n onStrokeToggle();\n }}\n onMouseLeave={() => setStrokeTooltipDisabled(false)}\n tooltip=\"Stroke\"\n tooltipDisabled={strokeTooltipDisabled || strokeExpanded}\n active={strokeExpanded || applied.stroke}\n />\n )}\n\n {/* Shadow */}\n {onShadowToggle && (\n <ToolbarButton\n icon=\"gravity-ui:square-dashed-circle\"\n onClick={() => {\n setShadowTooltipDisabled(true);\n onShadowToggle();\n }}\n onMouseLeave={() => setShadowTooltipDisabled(false)}\n tooltip=\"Shadow\"\n tooltipDisabled={shadowTooltipDisabled || shadowExpanded}\n active={shadowExpanded || applied.shadow}\n />\n )}\n\n {/* Blend Mode */}\n {onBlendModeToggle && (\n <ToolbarButton\n icon=\"gravity-ui:circles-intersection\"\n onClick={() => {\n setBlendModeTooltipDisabled(true);\n onBlendModeToggle();\n }}\n onMouseLeave={() => setBlendModeTooltipDisabled(false)}\n tooltip=\"Blend Mode\"\n tooltipDisabled={blendModeTooltipDisabled || blendModeExpanded}\n active={blendModeExpanded || applied.blendMode}\n />\n )}\n\n {/* Knockout */}\n {onKnockoutToggle && (\n <ToolbarButton\n icon=\"lucide:scissors\"\n onClick={() => {\n setKnockoutTooltipDisabled(true);\n onKnockoutToggle();\n }}\n onMouseLeave={() => setKnockoutTooltipDisabled(false)}\n tooltip=\"Knockout\"\n tooltipDisabled={knockoutTooltipDisabled || knockoutExpanded}\n active={knockoutExpanded || applied.knockout}\n />\n )}\n\n {/* Distress Texture */}\n {onDistressTextureToggle && (\n <ToolbarButton\n icon=\"lucide:stamp\"\n onClick={() => {\n setDistressTooltipDisabled(true);\n onDistressTextureToggle();\n }}\n onMouseLeave={() => setDistressTooltipDisabled(false)}\n tooltip=\"Distress Texture\"\n tooltipDisabled={distressTooltipDisabled || distressTextureExpanded}\n active={distressTextureExpanded || applied.distress}\n />\n )}\n\n {/* Image Mask */}\n {onImageMaskToggle && (\n <ToolbarButton\n icon=\"lucide:venetian-mask\"\n onClick={() => {\n setImageMaskTooltipDisabled(true);\n onImageMaskToggle();\n }}\n onMouseLeave={() => setImageMaskTooltipDisabled(false)}\n tooltip=\"Image Mask\"\n tooltipDisabled={imageMaskTooltipDisabled || imageMaskExpanded}\n active={imageMaskExpanded || applied.imageMask}\n />\n )}\n\n <Tooltip delayDuration={300}>\n <TooltipTrigger asChild>\n <Button variant=\"ghost\" size=\"sm\" onClick={onUngroup}>\n Ungroup\n </Button>\n </TooltipTrigger>\n <TooltipContent>Ungroup this group</TooltipContent>\n </Tooltip>\n </div>\n );\n};\n\nexport default GroupElementToolbar;\n","/**\n * CropPanel - Reusable crop controls for image elements\n *\n * Can be used standalone in a drawer or embedded in the contextual toolbar.\n * Provides anchor point selection and width/height sliders.\n *\n * @example\n * // In a drawer\n * <Drawer open={cropDrawerOpen} onOpenChange={setCropDrawerOpen}>\n * <DrawerContent>\n * <CropPanel\n * element={selectedImageElement}\n * onElementUpdate={handleElementUpdate}\n * />\n * </DrawerContent>\n * </Drawer>\n */\n\nimport React, { useState, useCallback, useRef, useEffect } from 'react';\nimport { Slider } from './ui';\nimport { ImageElement } from '../core/ImageElement.js';\nimport { cn } from '../lib/utils.js';\n\n/**\n * TouchGuard - Wraps interactive elements to prevent parent scroll from capturing touches\n *\n * Uses native event listeners with { passive: false } because:\n * 1. React's synthetic events can't properly preventDefault on touch events\n * 2. CSS touch-action: none is evaluated at gesture start on the ancestor chain,\n * so a parent with pan-y can still capture the gesture before child CSS applies\n * 3. Native listeners with passive: false intercept events before the browser decides to scroll\n */\nfunction TouchGuard({ children, className }: { children: React.ReactNode; className?: string }) {\n const ref = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n const el = ref.current;\n if (!el) return;\n\n const handleTouchStart = (e: TouchEvent) => {\n // Stop the event from reaching parent scroll containers\n e.stopPropagation();\n };\n\n const handleTouchMove = (e: TouchEvent) => {\n // Prevent default scroll behavior and stop propagation\n e.preventDefault();\n e.stopPropagation();\n };\n\n // Must use passive: false to allow preventDefault\n el.addEventListener('touchstart', handleTouchStart, { passive: false });\n el.addEventListener('touchmove', handleTouchMove, { passive: false });\n\n return () => {\n el.removeEventListener('touchstart', handleTouchStart);\n el.removeEventListener('touchmove', handleTouchMove);\n };\n }, []);\n\n return (\n <div ref={ref} className={className} style={{ touchAction: 'none' }}>\n {children}\n </div>\n );\n}\n\ntype CropAnchor =\n | 'top-left'\n | 'top-center'\n | 'top-right'\n | 'middle-left'\n | 'center'\n | 'middle-right'\n | 'bottom-left'\n | 'bottom-center'\n | 'bottom-right';\n\nexport interface CropPanelProps {\n /** The image element to crop */\n element: ImageElement;\n /** Callback when element is updated */\n onElementUpdate: (element: ImageElement) => void;\n /** Optional class name for the container */\n className?: string;\n}\n\n/**\n * CropPanel - Controls for cropping image elements\n *\n * Provides:\n * - 3x3 anchor grid for selecting resize origin\n * - Width slider (10-100%)\n * - Height slider (10-100%)\n */\nexport const CropPanel: React.FC<CropPanelProps> = ({ element, onElementUpdate, className }) => {\n // Crop anchor point - determines where the crop resizes from\n const [cropAnchor, setCropAnchor] = useState<CropAnchor>('center');\n\n // Block horizontal touch movement to prevent drawer/page from being dragged\n const containerRef = useRef<HTMLDivElement>(null);\n const touchStartPos = useRef({ x: 0, y: 0 });\n useEffect(() => {\n const el = containerRef.current;\n if (!el) return;\n\n const handleTouchStart = (e: TouchEvent) => {\n touchStartPos.current = {\n x: e.touches[0].clientX,\n y: e.touches[0].clientY,\n };\n };\n\n const handleTouchMove = (e: TouchEvent) => {\n const deltaX = Math.abs(e.touches[0].clientX - touchStartPos.current.x);\n const deltaY = Math.abs(e.touches[0].clientY - touchStartPos.current.y);\n\n // If horizontal movement is greater than vertical, prevent it\n if (deltaX > 10 && deltaX > deltaY) {\n e.preventDefault();\n }\n };\n\n el.addEventListener('touchstart', handleTouchStart, { passive: true });\n el.addEventListener('touchmove', handleTouchMove, { passive: false });\n\n return () => {\n el.removeEventListener('touchstart', handleTouchStart);\n el.removeEventListener('touchmove', handleTouchMove);\n };\n }, []);\n\n // Get current crop values\n const currentCropWidth = element.transformData?.cropWidth || 1;\n const currentCropHeight = element.transformData?.cropHeight || 1;\n\n // Handle crop changes\n const handleCropChange = useCallback(\n (cropX: number, cropY: number, cropWidth: number, cropHeight: number) => {\n const updatedElement = element.clone();\n updatedElement.updateCrop(cropX, cropY, cropWidth, cropHeight, true);\n onElementUpdate(updatedElement);\n },\n [element, onElementUpdate]\n );\n\n const handleCropWidthChange = useCallback(\n (value: number, anchor: CropAnchor = cropAnchor) => {\n const oldWidth = element.transformData.cropWidth;\n const oldX = element.transformData.cropX;\n const widthDiff = value - oldWidth;\n\n let newX = oldX;\n // Adjust X based on horizontal anchor position\n if (anchor.includes('center')) {\n newX = oldX - widthDiff / 2;\n } else if (anchor.includes('right')) {\n newX = oldX - widthDiff;\n }\n\n // Clamp X to valid range\n newX = Math.max(0, Math.min(1 - value, newX));\n\n handleCropChange(newX, element.transformData.cropY, value, element.transformData.cropHeight);\n },\n [element, handleCropChange, cropAnchor]\n );\n\n const handleCropHeightChange = useCallback(\n (value: number, anchor: CropAnchor = cropAnchor) => {\n const oldHeight = element.transformData.cropHeight;\n const oldY = element.transformData.cropY;\n const heightDiff = value - oldHeight;\n\n let newY = oldY;\n // Adjust Y based on vertical anchor position\n if (anchor.includes('middle') || anchor === 'center') {\n newY = oldY - heightDiff / 2;\n } else if (anchor.includes('bottom')) {\n newY = oldY - heightDiff;\n }\n\n // Clamp Y to valid range\n newY = Math.max(0, Math.min(1 - value, newY));\n\n handleCropChange(element.transformData.cropX, newY, element.transformData.cropWidth, value);\n },\n [element, handleCropChange, cropAnchor]\n );\n\n // Anchor grid positions\n const anchorPositions: CropAnchor[] = [\n 'top-left',\n 'top-center',\n 'top-right',\n 'middle-left',\n 'center',\n 'middle-right',\n 'bottom-left',\n 'bottom-center',\n 'bottom-right',\n ];\n\n return (\n <div\n ref={containerRef}\n data-preserve-selection\n className={cn('sc:flex sc:min-h-0 sc:flex-1 sc:flex-col', className)}\n style={{ touchAction: 'pan-y' }}\n >\n <div className=\"sc:flex sc:flex-col sc:gap-5 sc:px-5 sc:pt-1 sc:pb-[calc(env(safe-area-inset-bottom,0px)+20px)] sc:md:gap-4 sc:md:px-4 sc:md:pt-0 sc:md:pb-[calc(env(safe-area-inset-bottom,0px)+16px)]\">\n {/* Main content: Anchor Grid + Sliders */}\n <div className=\"sc:flex sc:items-start sc:gap-6 sc:md:gap-5\">\n {/* Anchor Grid */}\n <div className=\"sc:flex sc:flex-col sc:gap-2\">\n <span className=\"sc:text-foreground/60 sc:text-sm sc:md:text-xs\">Anchor</span>\n <div className=\"sc:grid sc:grid-cols-3 sc:gap-0.5 sc:rounded-md sc:p-1\">\n {anchorPositions.map((pos) => (\n <button\n key={pos}\n onClick={() => setCropAnchor(pos)}\n className={cn(\n 'sc-crop-anchor-btn sc:size-8 sc:rounded-md sc:md:size-6 sc:md:rounded',\n cropAnchor === pos && 'sc-active'\n )}\n title={pos.replace('-', ' ')}\n >\n <div\n className={cn(\n 'sc-crop-anchor-dot sc:size-2 sc:md:size-1.5',\n cropAnchor === pos && 'sc-active sc:size-2.5 sc:md:size-2'\n )}\n />\n </button>\n ))}\n </div>\n </div>\n\n {/* Size Sliders */}\n <div className=\"sc:flex sc:flex-1 sc:flex-col sc:gap-4 sc:md:gap-3\">\n {/* Width Slider */}\n <div className=\"sc:flex sc:flex-col sc:gap-2.5 sc:md:gap-1.5\">\n <div className=\"sc:flex sc:items-center sc:justify-between\">\n <span className=\"sc:text-foreground/60 sc:text-sm sc:md:text-xs\">Width</span>\n <input\n type=\"number\"\n value={Math.round(currentCropWidth * 100)}\n onChange={(e) => handleCropWidthChange(Math.max(10, Math.min(100, Number(e.target.value))) / 100)}\n min={10}\n max={100}\n className=\"sc:bg-transparent sc:text-foreground sc:w-14 sc:rounded-md sc:border-none sc:px-2.5 sc:py-2 sc:text-right sc:text-base sc:md:w-14 sc:md:rounded sc:md:px-1.5 sc:md:py-1 sc:md:text-[13px]\"\n />\n </div>\n {/* TouchGuard prevents parent scroll from capturing slider touches */}\n <TouchGuard>\n <Slider\n value={[currentCropWidth * 100]}\n onValueChange={(val) => handleCropWidthChange(val[0] / 100)}\n min={10}\n max={100}\n step={1}\n >\n <Slider.Track className=\"sc:bg-foreground/10 sc:h-2\">\n <Slider.Fill className=\"sc:bg-primary\" />\n </Slider.Track>\n <Slider.Thumb />\n </Slider>\n </TouchGuard>\n </div>\n\n {/* Height Slider */}\n <div className=\"sc:flex sc:flex-col sc:gap-2.5 sc:md:gap-1.5\">\n <div className=\"sc:flex sc:items-center sc:justify-between\">\n <span className=\"sc:text-foreground/60 sc:text-sm sc:md:text-xs\">Height</span>\n <input\n type=\"number\"\n value={Math.round(currentCropHeight * 100)}\n onChange={(e) => handleCropHeightChange(Math.max(10, Math.min(100, Number(e.target.value))) / 100)}\n min={10}\n max={100}\n className=\"sc:bg-transparent sc:text-foreground sc:w-14 sc:rounded-md sc:border-none sc:px-2.5 sc:py-2 sc:text-right sc:text-base sc:md:w-14 sc:md:rounded sc:md:px-1.5 sc:md:py-1 sc:md:text-[13px]\"\n />\n </div>\n {/* TouchGuard prevents parent scroll from capturing slider touches */}\n <TouchGuard>\n <Slider\n value={[currentCropHeight * 100]}\n onValueChange={(val) => handleCropHeightChange(val[0] / 100)}\n min={10}\n max={100}\n step={1}\n >\n <Slider.Track className=\"sc:bg-foreground/10 sc:h-2\">\n <Slider.Fill className=\"sc:bg-primary\" />\n </Slider.Track>\n <Slider.Thumb />\n </Slider>\n </TouchGuard>\n </div>\n </div>\n </div>\n </div>\n </div>\n );\n};\n\nexport default CropPanel;\n","/**\n * SecondaryPanels - Panel content components for expanded toolbar panels.\n *\n * These are the content areas rendered below the collapsed toolbar header\n * when a secondary panel (corner radius, rotation, opacity, etc.) is expanded.\n */\n\nimport React, { useCallback, useState } from 'react';\nimport { SliderRow, ToolbarButton, Button, Checkbox, Label, icons, PresetCarousel, Switch } from '../ui/index.js';\nimport type { PresetItem } from '../ui/index.js';\nimport ColorPickerDropdown from '../ColorPickerDropdown.jsx';\nimport CropPanel from '../CropPanel.jsx';\nimport type { ImageElement } from '../../core/ImageElement.js';\nimport type { StrokeConfig, CompositingScope, ImageAdjustments, ShapeFill, ShadowConfig, StandardBlendMode } from '../../types/index.js';\nimport { STANDARD_BLEND_MODES } from '../../types/index.js';\nimport { NEUTRAL_ADJUSTMENTS, isNeutralAdjustments } from '../../core/image-adjustments.js';\nimport { DISTRESS_TEXTURE_PRESETS, ensureBuiltinTexturesReady } from '../../effects/distress-textures.js';\nimport { preloadTexture } from '../../effects/DistressTextureCache.js';\nimport { MASK_IMAGE_PRESETS, ensureMaskPresetsReady } from '../../effects/mask-presets.js';\nimport type { AlignMode } from '../../utils/alignDistribute.js';\nimport { ALIGN_BUTTONS } from './alignButtons.js';\n\n// ── Shared panel body styling ───────────────────────────────────────────────\nconst PANEL_BODY_CLASSES =\n 'sc:flex sc:flex-col sc:gap-5 sc:px-5 sc:pt-4 sc:pb-4 sc:md:gap-4 sc:md:px-4 sc:md:pt-3 sc:md:pb-3';\n\nconst COLOR_PANEL_BODY_CLASSES =\n 'sc:flex sc:flex-col sc:gap-5 sc:px-5 sc:pt-4 sc:pb-[calc(env(safe-area-inset-bottom,0px)+20px)] sc:md:gap-4 sc:md:px-4 sc:md:pt-2 sc:md:pb-[calc(env(safe-area-inset-bottom,0px)+16px)]';\n\n// ── Corner Radius Panel (Image) ─────────────────────────────────────────────\n\nexport interface CornerRadiusPanelProps {\n value: number;\n onChange: (value: number) => void;\n}\n\nexport const CornerRadiusPanel: React.FC<CornerRadiusPanelProps> = ({ value, onChange }) => (\n <div\n className=\"corner-radius-panel sc:flex sc:flex-col\"\n data-preserve-selection\n style={{ touchAction: 'pan-y' }}\n >\n <div className={PANEL_BODY_CLASSES}>\n <SliderRow label=\"Radius\" value={value} onChange={onChange} min={0} max={50} unit=\"%\" />\n </div>\n </div>\n);\n\n// ── Align Panel (single selection → artboard) ───────────────────────────────\n\nexport interface AlignPanelProps {\n /** Apply one alignment command. For a single selection\n * `useAlignDistribute` aligns relative to the active artboard. */\n onAlign: (mode: AlignMode) => void;\n}\n\n/**\n * Position panel for a SINGLE selected element — the six align commands,\n * relative to the artboard (\"center on artboard\"). Multi-selections get the\n * same buttons inline in `MultiSelectionToolbar`, relative to the selection\n * bbox; both surfaces share `ALIGN_BUTTONS` so they cannot drift.\n */\nexport const AlignPanel: React.FC<AlignPanelProps> = ({ onAlign }) => (\n <div className=\"align-panel sc:flex sc:flex-col\" data-preserve-selection style={{ touchAction: 'pan-y' }}>\n <div className={PANEL_BODY_CLASSES}>\n <div className=\"sc:flex sc:items-center sc:justify-center sc:gap-1\">\n {ALIGN_BUTTONS.map(({ mode, icon, label }) => (\n <ToolbarButton\n key={mode}\n icon={icon}\n onClick={() => onAlign(mode)}\n tooltip={label}\n data-testid={`align-${mode}`}\n />\n ))}\n </div>\n </div>\n </div>\n);\n\n// ── Rotation Panel ──────────────────────────────────────────────────────────\n\nexport interface RotationPanelProps {\n value: number;\n onChange: (value: number) => void;\n onRotate90: () => void;\n}\n\nexport const RotationPanel: React.FC<RotationPanelProps> = ({ value, onChange, onRotate90 }) => (\n <div\n className=\"rotation-panel sc:flex sc:flex-col\"\n data-preserve-selection\n style={{ touchAction: 'pan-y' }}\n >\n <div className={PANEL_BODY_CLASSES}>\n <div className=\"sc:flex sc:items-end sc:gap-3\">\n <SliderRow\n label=\"Rotation\"\n value={value}\n onChange={onChange}\n min={-180}\n max={180}\n unit=\"°\"\n showInput\n inputWidth=\"56px\"\n variant=\"stacked\"\n className=\"sc:flex-1\"\n />\n {/* 90 Degree Button */}\n <div className=\"sc:pb-0.5\">\n <ToolbarButton icon={icons.rotateCcwSquare} onClick={onRotate90} tooltip=\"Rotate 90° CCW\" />\n </div>\n </div>\n </div>\n </div>\n);\n\n// ── Font Size Panel ─────────────────────────────────────────────────────────\n\nexport interface FontSizePanelProps {\n value: number;\n onChange: (value: number) => void;\n /** Current text-box width. When null/undefined the width slider is\n * hidden (e.g. element type doesn't expose a width on transformData). */\n widthValue?: number | null;\n /** Called when the width slider moves. */\n onWidthChange?: (value: number) => void;\n /** Letter-spacing in px (extra advance per character). When\n * null/undefined the slider is hidden (curved transforms — they lay\n * glyphs along a path and intentionally ignore letter-spacing). */\n letterSpacingValue?: number | null;\n /** Called when the letter-spacing slider moves. */\n onLetterSpacingChange?: (value: number) => void;\n /** Line-height multiplier (lineSpacing = fontSize × value). When\n * null/undefined the slider is hidden (curved transforms). */\n lineHeightValue?: number | null;\n /** Called when the line-height slider moves. */\n onLineHeightChange?: (value: number) => void;\n}\n\n// Font size panel — slider + number input. Replaces the older +/-\n// stepper which moved in 1px steps (too small to be useful) and\n// stretched the toolbar to fit a long number. Min/max give plenty\n// of headroom: 8 (smallest legible) → 256 (very large display\n// type). Step 1 because the input lets users dial precisely; the\n// slider handles coarse motion.\n//\n// Width slider sits directly under the font size slider — same\n// section because both control the layout of the text element. The\n// width slider operates on the text-box width (`transformData.width`)\n// which drives line-wrapping for custom text and the bounding box\n// for transformed text (wave, arch, etc.).\n// Letter-spacing and line-height sit in the same panel, directly under the\n// font size slider — they're the other two \"every editor has these\" type\n// knobs. Letter-spacing is in world-space px per character (CSS model);\n// line-height is a multiplier of fontSize (1.2 = the layout default).\n// Both apply to straight ('custom') text only — pass null to hide them for\n// curved transforms, which intentionally ignore these properties.\nexport const FontSizePanel: React.FC<FontSizePanelProps> = ({\n value,\n onChange,\n widthValue,\n onWidthChange,\n letterSpacingValue,\n onLetterSpacingChange,\n lineHeightValue,\n onLineHeightChange,\n}) => (\n <div\n className=\"font-size-panel sc:flex sc:flex-col\"\n data-preserve-selection\n data-sc-part=\"font-size-panel\"\n style={{ touchAction: 'pan-y' }}\n >\n <div className={PANEL_BODY_CLASSES}>\n <SliderRow\n label=\"Font Size\"\n value={Math.round(value)}\n onChange={onChange}\n min={8}\n max={256}\n step={1}\n unit=\"px\"\n showInput\n inputWidth=\"64px\"\n />\n {letterSpacingValue != null && onLetterSpacingChange && (\n <div data-sc-part=\"letter-spacing-control\">\n <SliderRow\n label=\"Letter Spacing\"\n value={letterSpacingValue}\n onChange={onLetterSpacingChange}\n min={-20}\n max={100}\n step={1}\n unit=\"px\"\n showInput\n inputWidth=\"64px\"\n />\n </div>\n )}\n {lineHeightValue != null && onLineHeightChange && (\n <div data-sc-part=\"line-height-control\">\n <SliderRow\n label=\"Line Height\"\n value={lineHeightValue}\n onChange={onLineHeightChange}\n min={0.5}\n max={3}\n step={0.1}\n unit=\"×\"\n showInput\n inputWidth=\"64px\"\n />\n </div>\n )}\n {widthValue != null && onWidthChange && (\n <SliderRow\n label=\"Width\"\n value={Math.round(widthValue)}\n onChange={onWidthChange}\n min={50}\n max={4000}\n step={1}\n unit=\"px\"\n showInput\n inputWidth=\"64px\"\n />\n )}\n </div>\n </div>\n);\n\n// ── Opacity Panel ───────────────────────────────────────────────────────────\n\nexport interface OpacityPanelProps {\n /** Opacity value 0-1 */\n value: number;\n /** Called with 0-1 range */\n onChange: (value: number) => void;\n}\n\nexport const OpacityPanel: React.FC<OpacityPanelProps> = ({ value, onChange }) => (\n <div\n className=\"opacity-panel sc:flex sc:flex-col\"\n data-preserve-selection\n style={{ touchAction: 'pan-y' }}\n >\n <div className={PANEL_BODY_CLASSES}>\n <SliderRow\n label=\"Opacity\"\n value={Math.round(value * 100)}\n onChange={(v) => onChange(v / 100)}\n min={0}\n max={100}\n unit=\"%\"\n />\n </div>\n </div>\n);\n\n// ── Adjust Panel (Image brightness / contrast / saturation) ─────────────────\n\nexport interface AdjustPanelProps {\n /** Current adjustments — undefined means neutral (all 1). */\n adjustments: ImageAdjustments | undefined;\n /** Called with the FULL next adjustments value on every slider tick. */\n onChange: (adjustments: ImageAdjustments) => void;\n /** Called when a slider gesture commits (pointer release) — breaks the undo-coalescing run. */\n onChangeEnd?: () => void;\n /** Reset all three channels to neutral (one undo step). */\n onReset: () => void;\n}\n\n/**\n * Brightness / contrast / saturation sliders for image elements.\n * Values are multipliers (1 = neutral) shown as 0–200%; the neutral detent is\n * 100%. Reset clears the adjustments back to neutral in a single undo step.\n */\nexport const AdjustPanel: React.FC<AdjustPanelProps> = ({ adjustments, onChange, onChangeEnd, onReset }) => {\n const current: ImageAdjustments = adjustments ?? { ...NEUTRAL_ADJUSTMENTS };\n const isNeutral = isNeutralAdjustments(adjustments);\n\n const channelRow = (label: string, channel: keyof ImageAdjustments) => (\n <div data-testid={`adjust-${channel}`}>\n <SliderRow\n label={label}\n value={Math.round(current[channel] * 100)}\n onChange={(v) => onChange({ ...current, [channel]: v / 100 })}\n onChangeEnd={onChangeEnd ? () => onChangeEnd() : undefined}\n min={0}\n max={200}\n unit=\"%\"\n />\n </div>\n );\n\n return (\n <div\n className=\"adjust-panel sc:flex sc:flex-col\"\n data-preserve-selection\n data-testid=\"adjust-panel\"\n style={{ touchAction: 'pan-y' }}\n >\n <div className={PANEL_BODY_CLASSES}>\n {channelRow('Brightness', 'brightness')}\n {channelRow('Contrast', 'contrast')}\n {channelRow('Saturation', 'saturation')}\n <div className=\"sc:flex sc:justify-end\">\n <Button\n variant=\"ghost\"\n size=\"sm\"\n onClick={onReset}\n disabled={isNeutral}\n data-testid=\"adjust-reset\"\n aria-label=\"Reset adjustments\"\n >\n Reset\n </Button>\n </div>\n </div>\n </div>\n );\n};\n\n// ── Shape Corner Radius Panel ───────────────────────────────────────────────\n\nexport interface ShapeCornerRadiusPanelProps {\n value: number;\n onChange: (value: number) => void;\n}\n\nexport const ShapeCornerRadiusPanel: React.FC<ShapeCornerRadiusPanelProps> = ({ value, onChange }) => (\n <div\n className=\"shape-corner-radius-panel sc:flex sc:flex-col\"\n data-preserve-selection\n style={{ touchAction: 'pan-y' }}\n >\n <div className={PANEL_BODY_CLASSES}>\n <SliderRow label=\"Radius\" value={value} onChange={onChange} min={0} max={50} unit=\"%\" />\n </div>\n </div>\n);\n\n// ── Shape Transparency Panel ────────────────────────────────────────────────\n\nexport interface ShapeTransparencyPanelProps {\n /** Fill opacity 0-1 */\n value: number;\n /** Called with 0-1 range */\n onChange: (value: number) => void;\n}\n\nexport const ShapeTransparencyPanel: React.FC<ShapeTransparencyPanelProps> = ({ value, onChange }) => (\n <div\n className=\"shape-transparency-panel sc:flex sc:flex-col\"\n data-preserve-selection\n style={{ touchAction: 'pan-y' }}\n >\n <div className={PANEL_BODY_CLASSES}>\n <SliderRow\n label=\"Opacity\"\n value={Math.round(value * 100)}\n onChange={(val) => onChange(val / 100)}\n min={0}\n max={100}\n unit=\"%\"\n />\n </div>\n </div>\n);\n\n// ── Shape Sides Panel (Polygon) ─────────────────────────────────────────────\n\nexport interface ShapeSidesPanelProps {\n value: number;\n onChange: (value: number) => void;\n}\n\nexport const ShapeSidesPanel: React.FC<ShapeSidesPanelProps> = ({ value, onChange }) => (\n <div\n className=\"shape-sides-panel sc:flex sc:flex-col\"\n data-preserve-selection\n style={{ touchAction: 'pan-y' }}\n >\n <div className={PANEL_BODY_CLASSES}>\n <SliderRow label=\"Sides\" value={value} onChange={onChange} min={3} max={20} />\n </div>\n </div>\n);\n\n// ── Shape Points Panel (Star) ───────────────────────────────────────────────\n\nexport interface ShapePointsPanelProps {\n value: number;\n onChange: (value: number) => void;\n}\n\nexport const ShapePointsPanel: React.FC<ShapePointsPanelProps> = ({ value, onChange }) => (\n <div\n className=\"shape-points-panel sc:flex sc:flex-col\"\n data-preserve-selection\n style={{ touchAction: 'pan-y' }}\n >\n <div className={PANEL_BODY_CLASSES}>\n <SliderRow label=\"Points\" value={value} onChange={onChange} min={3} max={20} />\n </div>\n </div>\n);\n\n// ── Shape Inner Radius Panel (Star) ─────────────────────────────────────────\n\nexport interface ShapeInnerRadiusPanelProps {\n /** Inner radius 0-1 */\n value: number;\n /** Called with 0-1 range */\n onChange: (value: number) => void;\n}\n\nexport const ShapeInnerRadiusPanel: React.FC<ShapeInnerRadiusPanelProps> = ({ value, onChange }) => (\n <div\n className=\"shape-inner-radius-panel sc:flex sc:flex-col\"\n data-preserve-selection\n style={{ touchAction: 'pan-y' }}\n >\n <div className={PANEL_BODY_CLASSES}>\n <SliderRow\n label=\"Inner Radius\"\n value={Math.round(value * 100)}\n onChange={(val) => onChange(val / 100)}\n min={10}\n max={90}\n unit=\"%\"\n />\n </div>\n </div>\n);\n\n// ── Shape Fill Color Panel ──────────────────────────────────────────────────\n\ntype ShapeFillMode = 'solid' | 'linear' | 'radial';\n\nexport interface ShapeColorPanelProps {\n /** Current solid fill color (legacy `fillColor`). */\n value: string;\n /** Solid color change — the host also clears any gradient `fill` (fill wins at render time). */\n onChange: (color: string) => void;\n /** Current rich fill (solid or gradient), if any. */\n fill?: ShapeFill;\n /** Rich fill change; `null` switches back to the solid `fillColor` path. */\n onFillChange?: (fill: ShapeFill | null) => void;\n documentColors: string[];\n imageColors?: string[];\n}\n\nconst FILL_MODE_LABELS: Record<ShapeFillMode, string> = {\n solid: 'Solid',\n linear: 'Linear',\n radial: 'Radial',\n};\n\nexport const ShapeColorPanel: React.FC<ShapeColorPanelProps> = ({\n value,\n onChange,\n fill,\n onFillChange,\n documentColors,\n imageColors,\n}) => {\n const mode: ShapeFillMode = fill?.type === 'linear' || fill?.type === 'radial' ? fill.type : 'solid';\n const gradient = fill?.type === 'linear' || fill?.type === 'radial' ? fill : null;\n const [activeStop, setActiveStop] = useState(0);\n\n const handleModeChange = useCallback(\n (next: ShapeFillMode) => {\n if (next === mode || !onFillChange) return;\n if (next === 'solid') {\n // Collapse to the first stop's color via the solid path (the host\n // clears `fill` on solid color writes).\n onChange(gradient?.stops[0]?.color ?? value);\n return;\n }\n // Keep stops when toggling linear <-> radial; otherwise seed a simple\n // two-stop ramp from the current solid color.\n const stops = gradient\n ? gradient.stops.map((s) => ({ ...s }))\n : [\n { offset: 0, color: value },\n { offset: 1, color: '#ffffff' },\n ];\n onFillChange(\n next === 'linear'\n ? { type: 'linear', angle: gradient?.type === 'linear' ? gradient.angle : 180, stops }\n : { type: 'radial', stops },\n );\n setActiveStop(0);\n },\n [mode, gradient, value, onChange, onFillChange],\n );\n\n const handleStopColorChange = useCallback(\n (color: string) => {\n if (!gradient || !onFillChange) return;\n const stops = gradient.stops.map((s, i) => (i === activeStop ? { ...s, color } : { ...s }));\n onFillChange(\n gradient.type === 'linear' ? { type: 'linear', angle: gradient.angle, stops } : { type: 'radial', stops },\n );\n },\n [gradient, activeStop, onFillChange],\n );\n\n const handleAngleChange = useCallback(\n (angle: number) => {\n if (gradient?.type !== 'linear' || !onFillChange) return;\n onFillChange({ type: 'linear', angle, stops: gradient.stops.map((s) => ({ ...s })) });\n },\n [gradient, onFillChange],\n );\n\n const activeColor = gradient ? (gradient.stops[activeStop]?.color ?? value) : value;\n\n return (\n <div\n className=\"shape-color-panel sc:flex sc:flex-col\"\n data-preserve-selection\n style={{ touchAction: 'pan-y' }}\n >\n <div className={COLOR_PANEL_BODY_CLASSES}>\n {/* Fill mode: Solid / Linear / Radial */}\n {onFillChange && (\n <div className=\"sc:flex sc:items-center sc:gap-3\">\n <Label className=\"sc:text-base sc:md:text-sm sc:font-medium\">Fill</Label>\n <div className=\"sc:flex sc:rounded-md sc:border sc:border-divider sc:overflow-hidden\">\n {(['solid', 'linear', 'radial'] as const).map((m) => (\n <button\n key={m}\n className={`sc:px-4 sc:py-2.5 sc:text-base sc:md:px-3 sc:md:py-1.5 sc:md:text-sm sc:transition-colors ${mode === m ? 'sc:bg-primary sc:text-primary-foreground' : 'sc:text-foreground sc:hover:bg-muted'}`}\n onClick={() => handleModeChange(m)}\n aria-pressed={mode === m}\n >\n {FILL_MODE_LABELS[m]}\n </button>\n ))}\n </div>\n </div>\n )}\n\n {/* Gradient controls: stop swatches + angle (linear only) */}\n {gradient && (\n <>\n <div className=\"sc:flex sc:items-center sc:gap-3\">\n <Label className=\"sc:text-base sc:md:text-sm sc:font-medium\">Stops</Label>\n <div className=\"sc:flex sc:items-center sc:gap-2\">\n {gradient.stops.map((stop, i) => (\n <button\n key={i}\n className={`sc:h-8 sc:w-8 sc:rounded-md sc:border-2 sc:transition-colors ${i === activeStop ? 'sc:border-primary' : 'sc:border-divider'}`}\n style={{ backgroundColor: stop.color }}\n onClick={() => setActiveStop(i)}\n aria-label={`Edit gradient stop ${i + 1}`}\n aria-pressed={i === activeStop}\n />\n ))}\n </div>\n </div>\n {gradient.type === 'linear' && (\n <SliderRow\n label=\"Angle\"\n value={Math.round(gradient.angle)}\n onChange={handleAngleChange}\n min={0}\n max={360}\n unit=\"°\"\n />\n )}\n </>\n )}\n\n <ColorPickerDropdown\n value={activeColor}\n onChange={(e: { target: { value: string } }) =>\n gradient ? handleStopColorChange(e.target.value) : onChange(e.target.value)\n }\n documentColors={documentColors}\n imageColors={imageColors}\n showSquare={true}\n embedded={true}\n />\n </div>\n </div>\n );\n};\n\n// ── Text Color Panel ────────────────────────────────────────────────────────\n\nexport interface TextColorPanelProps {\n value: string;\n onChange: (e: { target: { value: string } }) => void;\n documentColors: string[];\n imageColors?: string[];\n}\n\nexport const TextColorPanel: React.FC<TextColorPanelProps> = ({ value, onChange, documentColors, imageColors }) => (\n <div\n className=\"sc-text-color-panel sc:flex sc:flex-col\"\n data-preserve-selection\n style={{ touchAction: 'pan-y' }}\n >\n <div className={COLOR_PANEL_BODY_CLASSES}>\n <ColorPickerDropdown value={value} onChange={onChange} documentColors={documentColors} imageColors={imageColors} embedded={true} />\n </div>\n </div>\n);\n\n// ── Compositing Panel (Clip / Knockout) ─────────────────────────────────────\n\nexport type CompositingMode = 'clip' | 'knockout';\n\nexport interface CompositingPanelProps {\n mode: CompositingMode;\n fill: boolean;\n stroke: boolean;\n scope: CompositingScope;\n onModeChange: (mode: CompositingMode) => void;\n onFillChange: (fill: boolean) => void;\n onStrokeChange: (stroke: boolean) => void;\n onScopeChange: (scope: CompositingScope) => void;\n}\n\nexport const CompositingPanel: React.FC<CompositingPanelProps> = ({\n mode,\n fill,\n stroke,\n scope,\n onModeChange,\n onFillChange,\n onStrokeChange,\n onScopeChange,\n}) => (\n <div\n className=\"knockout-panel sc:flex sc:flex-col\"\n data-preserve-selection\n style={{ touchAction: 'pan-y' }}\n >\n <div className={PANEL_BODY_CLASSES}>\n {/* Mode selector: Clip / Knockout */}\n <div className=\"sc:flex sc:items-center sc:gap-3\">\n <Label className=\"sc:text-base sc:md:text-sm sc:font-medium\">Mode</Label>\n <div className=\"sc:flex sc:rounded-md sc:border sc:border-divider sc:overflow-hidden\">\n <button\n className={`sc:px-4 sc:py-2.5 sc:text-base sc:md:px-3 sc:md:py-1.5 sc:md:text-sm sc:transition-colors ${mode === 'clip' ? 'sc:bg-primary sc:text-primary-foreground' : 'sc:text-foreground sc:hover:bg-muted'}`}\n onClick={() => onModeChange('clip')}\n >\n Clip\n </button>\n <button\n className={`sc:px-4 sc:py-2.5 sc:text-base sc:md:px-3 sc:md:py-1.5 sc:md:text-sm sc:transition-colors ${mode === 'knockout' ? 'sc:bg-primary sc:text-primary-foreground' : 'sc:text-foreground sc:hover:bg-muted'}`}\n onClick={() => onModeChange('knockout')}\n >\n Knockout\n </button>\n </div>\n </div>\n\n {/* Fill / Stroke checkboxes */}\n <div className=\"sc:flex sc:items-center sc:gap-5\">\n <label className=\"sc:flex sc:items-center sc:gap-2 sc:text-base sc:md:text-sm sc:text-foreground\">\n <Checkbox checked={fill} onCheckedChange={(v) => onFillChange(v === true)} />\n Fill\n </label>\n <label className=\"sc:flex sc:items-center sc:gap-2 sc:text-base sc:md:text-sm sc:text-foreground\">\n <Checkbox checked={stroke} onCheckedChange={(v) => onStrokeChange(v === true)} />\n Stroke\n </label>\n </div>\n\n {/* Scope selector */}\n <div className=\"sc:flex sc:items-center sc:gap-3\">\n <Label className=\"sc:text-base sc:md:text-sm sc:font-medium\">Scope</Label>\n <div className=\"sc:flex sc:rounded-md sc:border sc:border-divider sc:overflow-hidden\">\n <button\n className={`sc:px-4 sc:py-2.5 sc:text-base sc:md:px-3 sc:md:py-1.5 sc:md:text-sm sc:transition-colors ${scope === 'group' ? 'sc:bg-primary sc:text-primary-foreground' : 'sc:text-foreground sc:hover:bg-muted'}`}\n onClick={() => onScopeChange('group')}\n >\n Group\n </button>\n <button\n className={`sc:px-4 sc:py-2.5 sc:text-base sc:md:px-3 sc:md:py-1.5 sc:md:text-sm sc:transition-colors ${scope === 'artboard' ? 'sc:bg-primary sc:text-primary-foreground' : 'sc:text-foreground sc:hover:bg-muted'}`}\n onClick={() => onScopeChange('artboard')}\n >\n Artboard\n </button>\n </div>\n </div>\n </div>\n </div>\n);\n\n/** @deprecated Use CompositingPanel instead */\nexport type KnockoutPanelProps = CompositingPanelProps;\n/** @deprecated Use CompositingPanel instead */\nexport const KnockoutPanel = CompositingPanel;\n\n// ── Distress Texture Panel ──────────────────────────────────────────────────\n\nexport interface DistressTexturePanelProps {\n textureUrl: string;\n /** Opacity 0-100 (percentage) */\n opacity: number;\n onTextureChange: (url: string) => void;\n onOpacityChange: (pct: number) => void;\n}\n\nexport const DistressTexturePanel: React.FC<DistressTexturePanelProps> = ({\n textureUrl,\n opacity,\n onTextureChange,\n onOpacityChange,\n}) => {\n // Call synchronously so thumbnailUrls are populated before we read them\n ensureBuiltinTexturesReady();\n\n const presetItems: PresetItem[] = DISTRESS_TEXTURE_PRESETS.map((p) => ({ id: p.textureUrl, name: p.name, thumbnailUrl: p.thumbnailUrl }));\n\n const handleSelect = useCallback(\n (id: string) => {\n if (id) preloadTexture(id);\n onTextureChange(id);\n },\n [onTextureChange]\n );\n\n return (\n <div\n className=\"distress-texture-panel sc:flex sc:flex-col\"\n data-preserve-selection\n style={{ touchAction: 'pan-y' }}\n >\n <div className={PANEL_BODY_CLASSES}>\n <PresetCarousel\n presets={presetItems}\n selectedId={textureUrl}\n onSelect={handleSelect}\n ariaLabel=\"Distress texture presets\"\n />\n\n {/* Opacity slider */}\n <SliderRow\n label=\"Opacity\"\n value={opacity}\n onChange={onOpacityChange}\n min={0}\n max={100}\n unit=\"%\"\n />\n </div>\n </div>\n );\n};\n\n// ── Image Mask Panel ────────────────────────────────────────────────────\n\nexport interface ImageMaskPanelProps {\n imageUrl: string;\n maskType: 'clip' | 'alpha' | 'luma';\n opacity: number; // 0-100\n inverted: boolean;\n onImageChange: (url: string) => void;\n onMaskTypeChange: (type: 'clip' | 'alpha' | 'luma') => void;\n onOpacityChange: (pct: number) => void;\n onInvertedChange: (inverted: boolean) => void;\n}\n\nexport const ImageMaskPanel: React.FC<ImageMaskPanelProps> = ({\n imageUrl,\n maskType,\n opacity,\n inverted,\n onImageChange,\n onMaskTypeChange,\n onOpacityChange,\n onInvertedChange,\n}) => {\n // Call synchronously so thumbnailUrls are populated before we read them\n ensureMaskPresetsReady();\n\n const presetItems: PresetItem[] = MASK_IMAGE_PRESETS.map((p) => ({ id: p.imageUrl, name: p.name, thumbnailUrl: p.thumbnailUrl }));\n\n return (\n <div\n className=\"image-mask-panel sc:flex sc:flex-col\"\n data-preserve-selection\n style={{ touchAction: 'pan-y' }}\n >\n <div className={PANEL_BODY_CLASSES}>\n <PresetCarousel\n presets={presetItems}\n selectedId={imageUrl}\n onSelect={onImageChange}\n ariaLabel=\"Image mask presets\"\n />\n\n {/* Mask type row */}\n <div className=\"sc:flex sc:items-center sc:gap-2\">\n <Label className=\"sc:text-base sc:md:text-sm sc:font-medium\">Type</Label>\n <div className=\"sc:flex sc:rounded-md sc:border sc:border-divider sc:overflow-hidden\">\n {(['clip', 'alpha', 'luma'] as const).map((type) => (\n <button\n key={type}\n className={`sc:px-4 sc:py-2.5 sc:text-base sc:md:px-3 sc:md:py-1.5 sc:md:text-sm sc:capitalize sc:transition-colors ${\n maskType === type\n ? 'sc:bg-primary sc:text-primary-foreground'\n : 'sc:text-foreground sc:hover:bg-muted'\n }`}\n onClick={() => onMaskTypeChange(type)}\n >\n {type}\n </button>\n ))}\n </div>\n </div>\n\n {/* Opacity slider */}\n <SliderRow\n label=\"Opacity\"\n value={opacity}\n onChange={onOpacityChange}\n min={0}\n max={100}\n unit=\"%\"\n />\n\n {/* Inverted checkbox */}\n <label className=\"sc:flex sc:items-center sc:gap-2 sc:text-base sc:md:text-sm sc:text-foreground\">\n <Checkbox checked={inverted} onCheckedChange={(v) => onInvertedChange(v === true)} />\n Invert Mask\n </label>\n </div>\n </div>\n );\n};\n\n// ── Stroke Panel ────────────────────────────────────────────────────────────\n\nexport interface StrokePanelProps {\n stroke?: StrokeConfig;\n onChange: (stroke: StrokeConfig | undefined) => void;\n documentColors?: string[];\n imageColors?: string[];\n}\n\nexport const StrokePanel: React.FC<StrokePanelProps> = ({ stroke, onChange, documentColors, imageColors }) => {\n const [showAdvanced, setShowAdvanced] = useState(false);\n\n const enabled = stroke?.enabled ?? false;\n const color = stroke?.color ?? '#000000';\n const width = stroke?.width ?? 5;\n const opacity = stroke?.opacity ?? 1;\n const lineCap = stroke?.lineCap ?? 'butt';\n const lineJoin = stroke?.lineJoin ?? 'miter';\n\n const handleEnabledChange = useCallback(\n (newEnabled: boolean) => {\n if (newEnabled) {\n onChange({ enabled: true, color, width, lineCap, lineJoin, opacity });\n } else {\n onChange(undefined);\n }\n },\n [onChange, color, width, lineCap, lineJoin, opacity]\n );\n\n const update = useCallback(\n (patch: Partial<StrokeConfig>) => {\n if (!stroke) return;\n onChange({ ...stroke, ...patch });\n },\n [stroke, onChange]\n );\n\n return (\n <div\n className=\"stroke-panel sc:flex sc:flex-col\"\n data-preserve-selection\n style={{ touchAction: 'pan-y' }}\n >\n <div className={PANEL_BODY_CLASSES}>\n {/* Enable/disable toggle */}\n <div className=\"sc:flex sc:items-center sc:justify-between\">\n <Label className=\"sc:text-foreground/70 sc:text-base sc:md:text-[13px]\">Stroke</Label>\n <Switch checked={enabled} onCheckedChange={handleEnabledChange} />\n </div>\n\n {enabled && (\n <>\n {/* Color picker */}\n <div className=\"sc:flex sc:items-center sc:justify-between\">\n <Label className=\"sc:text-foreground/70 sc:text-base sc:md:text-[13px]\">Color</Label>\n <ColorPickerDropdown\n value={color}\n onChange={(e: { target: { value: string } }) => update({ color: e.target.value })}\n documentColors={documentColors}\n imageColors={imageColors}\n showSquare={true}\n />\n </div>\n\n {/* Width slider */}\n <SliderRow\n label=\"Width\"\n value={width}\n onChange={(v) => update({ width: v })}\n min={1}\n max={50}\n unit=\"px\"\n />\n\n {/* Opacity slider */}\n <SliderRow\n label=\"Opacity\"\n value={Math.round(opacity * 100)}\n onChange={(v) => update({ opacity: v / 100 })}\n min={0}\n max={100}\n unit=\"%\"\n />\n\n {/* Advanced toggle */}\n <button\n className=\"sc:flex sc:items-center sc:gap-1 sc:text-base sc:md:text-sm sc:text-muted-foreground sc:hover:text-foreground sc:transition-colors sc:py-1.5 sc:md:py-0\"\n onClick={() => setShowAdvanced((prev) => !prev)}\n >\n {showAdvanced ? 'Hide' : 'Show'} Advanced\n </button>\n\n {showAdvanced && (\n <>\n {/* Line Cap */}\n <div className=\"sc:flex sc:items-center sc:gap-3\">\n <Label className=\"sc:text-foreground/70 sc:text-base sc:md:text-[13px]\">Line Cap</Label>\n <div className=\"sc:flex sc:rounded-md sc:border sc:border-divider sc:overflow-hidden\">\n {(['butt', 'round', 'square'] as const).map((cap) => (\n <button\n key={cap}\n className={`sc:px-4 sc:py-2.5 sc:text-base sc:md:px-3 sc:md:py-1.5 sc:md:text-sm sc:capitalize sc:transition-colors ${\n lineCap === cap\n ? 'sc:bg-primary sc:text-primary-foreground'\n : 'sc:text-foreground sc:hover:bg-muted'\n }`}\n onClick={() => update({ lineCap: cap })}\n >\n {cap}\n </button>\n ))}\n </div>\n </div>\n\n {/* Line Join */}\n <div className=\"sc:flex sc:items-center sc:gap-3\">\n <Label className=\"sc:text-foreground/70 sc:text-base sc:md:text-[13px]\">Line Join</Label>\n <div className=\"sc:flex sc:rounded-md sc:border sc:border-divider sc:overflow-hidden\">\n {(['miter', 'round', 'bevel'] as const).map((join) => (\n <button\n key={join}\n className={`sc:px-4 sc:py-2.5 sc:text-base sc:md:px-3 sc:md:py-1.5 sc:md:text-sm sc:capitalize sc:transition-colors ${\n lineJoin === join\n ? 'sc:bg-primary sc:text-primary-foreground'\n : 'sc:text-foreground sc:hover:bg-muted'\n }`}\n onClick={() => update({ lineJoin: join })}\n >\n {join}\n </button>\n ))}\n </div>\n </div>\n </>\n )}\n </>\n )}\n </div>\n </div>\n );\n};\n\n// ── Shadow Panel ────────────────────────────────────────────────────────────\n\n/** Defaults used when the shadow is first enabled (world-space px). */\nconst SHADOW_DEFAULTS = {\n color: '#000000',\n blur: 8,\n offsetX: 4,\n offsetY: 4,\n opacity: 0.5,\n} as const;\n\nexport interface ShadowPanelProps {\n shadow?: ShadowConfig;\n onChange: (shadow: ShadowConfig | undefined) => void;\n documentColors?: string[];\n imageColors?: string[];\n}\n\nexport const ShadowPanel: React.FC<ShadowPanelProps> = ({ shadow, onChange, documentColors, imageColors }) => {\n const enabled = shadow?.enabled ?? false;\n const color = shadow?.color ?? SHADOW_DEFAULTS.color;\n const blur = shadow?.blur ?? SHADOW_DEFAULTS.blur;\n const offsetX = shadow?.offsetX ?? SHADOW_DEFAULTS.offsetX;\n const offsetY = shadow?.offsetY ?? SHADOW_DEFAULTS.offsetY;\n const opacity = shadow?.opacity ?? SHADOW_DEFAULTS.opacity;\n\n const handleEnabledChange = useCallback(\n (newEnabled: boolean) => {\n if (newEnabled) {\n onChange({ enabled: true, color, blur, offsetX, offsetY, opacity });\n } else {\n onChange(undefined);\n }\n },\n [onChange, color, blur, offsetX, offsetY, opacity]\n );\n\n const update = useCallback(\n (patch: Partial<ShadowConfig>) => {\n if (!shadow) return;\n onChange({ ...shadow, ...patch });\n },\n [shadow, onChange]\n );\n\n return (\n <div\n className=\"shadow-panel sc:flex sc:flex-col\"\n data-sc-part=\"shadow-panel\"\n data-preserve-selection\n style={{ touchAction: 'pan-y' }}\n >\n <div className={PANEL_BODY_CLASSES}>\n {/* Enable/disable toggle */}\n <div className=\"sc:flex sc:items-center sc:justify-between\">\n <Label className=\"sc:text-foreground/70 sc:text-base sc:md:text-[13px]\">Shadow</Label>\n <Switch checked={enabled} onCheckedChange={handleEnabledChange} data-testid=\"shadow-enabled-switch\" />\n </div>\n\n {enabled && (\n <>\n {/* Color picker */}\n <div className=\"sc:flex sc:items-center sc:justify-between\">\n <Label className=\"sc:text-foreground/70 sc:text-base sc:md:text-[13px]\">Color</Label>\n <ColorPickerDropdown\n value={color}\n onChange={(e: { target: { value: string } }) => update({ color: e.target.value })}\n documentColors={documentColors}\n imageColors={imageColors}\n showSquare={true}\n />\n </div>\n\n {/* Blur slider */}\n <SliderRow\n label=\"Blur\"\n value={blur}\n onChange={(v) => update({ blur: v })}\n min={0}\n max={100}\n unit=\"px\"\n />\n\n {/* Offset sliders */}\n <SliderRow\n label=\"Offset X\"\n value={offsetX}\n onChange={(v) => update({ offsetX: v })}\n min={-100}\n max={100}\n unit=\"px\"\n />\n <SliderRow\n label=\"Offset Y\"\n value={offsetY}\n onChange={(v) => update({ offsetY: v })}\n min={-100}\n max={100}\n unit=\"px\"\n />\n\n {/* Opacity slider */}\n <SliderRow\n label=\"Opacity\"\n value={Math.round(opacity * 100)}\n onChange={(v) => update({ opacity: v / 100 })}\n min={0}\n max={100}\n unit=\"%\"\n />\n </>\n )}\n </div>\n </div>\n );\n};\n\n// ── Blend Mode Panel ────────────────────────────────────────────────────────\n\n/** 'normal' plus the standard blend modes, in display order. */\nconst BLEND_MODE_OPTIONS: ReadonlyArray<'normal' | StandardBlendMode> = ['normal', ...STANDARD_BLEND_MODES];\n\nexport interface BlendModePanelProps {\n /**\n * Current standard blend mode. 'normal' covers unset, 'normal', and the\n * knockout/clip compositing modes (which are controlled by the Clip /\n * Knockout panel, not here — picking a mode here replaces them).\n */\n blendMode: 'normal' | StandardBlendMode;\n onChange: (blendMode: 'normal' | StandardBlendMode) => void;\n}\n\nexport const BlendModePanel: React.FC<BlendModePanelProps> = ({ blendMode, onChange }) => (\n <div\n className=\"blend-mode-panel sc:flex sc:flex-col\"\n data-sc-part=\"blend-mode-panel\"\n data-preserve-selection\n style={{ touchAction: 'pan-y' }}\n >\n <div className={PANEL_BODY_CLASSES}>\n <div className=\"sc:flex sc:items-center sc:gap-3\">\n <Label className=\"sc:text-foreground/70 sc:text-base sc:md:text-[13px]\">Blend</Label>\n <div className=\"sc:flex sc:flex-wrap sc:rounded-md sc:border sc:border-divider sc:overflow-hidden\">\n {BLEND_MODE_OPTIONS.map((mode) => (\n <button\n key={mode}\n data-blend-mode={mode}\n aria-pressed={blendMode === mode}\n className={`sc:px-4 sc:py-2.5 sc:text-base sc:md:px-3 sc:md:py-1.5 sc:md:text-sm sc:capitalize sc:transition-colors ${\n blendMode === mode\n ? 'sc:bg-primary sc:text-primary-foreground'\n : 'sc:text-foreground sc:hover:bg-muted'\n }`}\n onClick={() => onChange(mode)}\n >\n {mode}\n </button>\n ))}\n </div>\n </div>\n </div>\n </div>\n);\n\n// ── Crop Panel Content ──────────────────────────────────────────────────────\n\nexport interface CropPanelContentProps {\n element: ImageElement;\n onElementUpdate: (element: ImageElement) => void;\n}\n\nexport const CropPanelContent: React.FC<CropPanelContentProps> = ({ element, onElementUpdate }) => (\n <CropPanel element={element} onElementUpdate={onElementUpdate} />\n);\n","/**\n * ExpandedPanelIcon - Renders the icon for the collapsed toolbar header\n * when a secondary panel is expanded.\n *\n * Special rendering for text color (shows \"A\" with color underline)\n * and shape color (shows fill icon with color underline).\n */\n\nimport React from 'react';\nimport { Icon } from '@iconify/react';\n\nexport interface ExpandedPanelIconProps {\n /** The type of expanded panel */\n panelType: string;\n /** The default icon from the panel config (used for non-special types) */\n defaultIcon: string | React.ReactNode;\n /** Current text color value (for textColor type) */\n textColorValue?: string;\n /** Current shape fill color value (for shapeColor type) */\n shapeFillColor?: string;\n}\n\nexport const ExpandedPanelIcon: React.FC<ExpandedPanelIconProps> = ({\n panelType,\n defaultIcon,\n textColorValue,\n shapeFillColor,\n}) => {\n if (panelType === 'textColor') {\n return (\n <div className=\"sc:relative sc:flex sc:size-6 sc:items-center sc:justify-center sc:md:size-5\">\n <span className=\"sc:text-primary sc:text-xl sc:leading-none sc:font-bold sc:md:text-lg\">A</span>\n <div\n className=\"sc:absolute sc:bottom-0 sc:left-1/2 sc:h-[3px] sc:w-4 sc:-translate-x-1/2 sc:rounded-sm\"\n style={{ backgroundColor: textColorValue }}\n />\n </div>\n );\n }\n\n if (panelType === 'shapeColor') {\n return (\n <div className=\"sc:relative sc:flex sc:size-6 sc:items-center sc:justify-center sc:md:size-5\">\n <Icon icon=\"mdi:format-color-fill\" className=\"sc:text-primary sc:size-5 sc:md:size-4\" />\n <div\n className=\"sc:absolute sc:-bottom-0.5 sc:left-1/2 sc:h-[3px] sc:w-4 sc:-translate-x-1/2 sc:rounded-sm\"\n style={{ background: shapeFillColor || '#3b82f6' }}\n />\n </div>\n );\n }\n\n if (typeof defaultIcon === 'string') {\n return <Icon icon={defaultIcon} className=\"sc:text-primary sc:size-6 sc:md:size-5\" />;\n }\n\n return <>{defaultIcon}</>;\n};\n\nexport default ExpandedPanelIcon;\n","/**\n * SecondaryPanelWrapper - Animated wrapper for secondary toolbar panels.\n *\n * Provides consistent expand/collapse animation for secondary panels\n * (corner radius, crop, rotation, opacity, shape panels, color panels).\n *\n * Used in embedded mode to wrap each panel with flex + transition styling.\n */\n\nimport React from 'react';\n\nexport interface SecondaryPanelWrapperProps {\n /** Whether this panel is currently open/expanded */\n isOpen: boolean;\n /** The panel content to render inside the wrapper */\n children: React.ReactNode;\n}\n\nexport const SecondaryPanelWrapper: React.FC<SecondaryPanelWrapperProps> = ({ isOpen, children }) => {\n return (\n <div\n className=\"sc-secondary-toolbar-panel-wrapper\"\n style={{\n display: 'flex',\n flexDirection: 'column',\n flex: isOpen ? 1 : 0,\n minHeight: isOpen ? 0 : undefined,\n transition: 'flex 300ms cubic-bezier(0.32, 0.72, 0, 1)',\n }}\n >\n <div\n className={isOpen ? 'sc-secondary-panel-scroll-container' : ''}\n style={{\n flex: 1,\n display: 'flex',\n flexDirection: 'column',\n overflowY: isOpen ? 'auto' : 'hidden',\n overscrollBehaviorY: 'contain',\n WebkitOverflowScrolling: 'touch',\n transform: isOpen ? 'translateY(0)' : 'translateY(100%)',\n opacity: isOpen ? 1 : 0,\n transition: 'transform 300ms cubic-bezier(0.32, 0.72, 0, 1), opacity 200ms ease-out',\n }}\n >\n {children}\n </div>\n </div>\n );\n};\n\nexport default SecondaryPanelWrapper;\n","/**\n * ColorPanelWrapper - Animated wrapper for color picker secondary panels.\n *\n * Similar to SecondaryPanelWrapper but with minHeight: 0 on the inner\n * scroll container for proper color picker layout.\n */\n\nimport React from 'react';\n\nexport interface ColorPanelWrapperProps {\n /** Whether this panel is currently open/expanded */\n isOpen: boolean;\n /** The panel content to render inside the wrapper */\n children: React.ReactNode;\n}\n\nexport const ColorPanelWrapper: React.FC<ColorPanelWrapperProps> = ({ isOpen, children }) => {\n return (\n <div\n className=\"sc-secondary-toolbar-panel-wrapper\"\n style={{\n display: 'flex',\n flexDirection: 'column',\n flex: isOpen ? 1 : 0,\n minHeight: isOpen ? 0 : undefined,\n transition: 'flex 300ms cubic-bezier(0.32, 0.72, 0, 1)',\n }}\n >\n <div\n className={isOpen ? 'sc-secondary-panel-scroll-container' : ''}\n style={{\n flex: 1,\n minHeight: 0,\n overflowY: isOpen ? undefined : 'hidden',\n overscrollBehaviorY: 'contain',\n WebkitOverflowScrolling: 'touch',\n transform: isOpen ? 'translateY(0)' : 'translateY(100%)',\n opacity: isOpen ? 1 : 0,\n transition: 'transform 300ms cubic-bezier(0.32, 0.72, 0, 1), opacity 200ms ease-out',\n }}\n >\n {children}\n </div>\n </div>\n );\n};\n\nexport default ColorPanelWrapper;\n","/**\n * EmbeddedToolbarLayout - Layout wrapper for embedded mode toolbar.\n *\n * Manages the height animation container, secondary panel wrappers,\n * and empty state display for embedded mode.\n */\n\nimport React from 'react';\nimport { SecondaryPanelWrapper } from './shared/SecondaryPanelWrapper.js';\nimport { ColorPanelWrapper } from './shared/ColorPanelWrapper.js';\n\nexport interface EmbeddedToolbarLayoutProps {\n /** The toolbar content (collapsed header + regular buttons) */\n toolbarContent: React.ReactNode;\n /** Inner content ref for height measurement */\n innerContentRef: React.RefObject<HTMLDivElement | null>;\n /** Whether the toolbar should be rendered */\n shouldRender: boolean;\n /** Whether exit animation is playing */\n isExiting: boolean;\n /** Explicit transition height (null = use CSS Grid) */\n transitionHeight: number | null;\n /** Empty state message content */\n emptyStateContent: React.ReactNode;\n\n // Panel open states\n isAlignPanelOpen: boolean;\n isCornerRadiusPanelOpen: boolean;\n isCropPanelOpen: boolean;\n isRotationPanelOpen: boolean;\n isOpacityPanelOpen: boolean;\n isAdjustPanelOpen: boolean;\n isFontSizePanelOpen: boolean;\n isShapeCornerRadiusPanelOpen: boolean;\n isShapeTransparencyPanelOpen: boolean;\n isShapeSidesPanelOpen: boolean;\n isShapePointsPanelOpen: boolean;\n isShapeInnerRadiusPanelOpen: boolean;\n isShapeColorPanelOpen: boolean;\n isTextColorPanelOpen: boolean;\n isStrokePanelOpen: boolean;\n isShadowPanelOpen: boolean;\n isBlendModePanelOpen: boolean;\n isKnockoutPanelOpen: boolean;\n isDistressTexturePanelOpen: boolean;\n isImageMaskPanelOpen: boolean;\n\n // Panel content\n alignPanel: React.ReactNode;\n cornerRadiusPanel: React.ReactNode;\n cropPanelContent: React.ReactNode;\n rotationPanel: React.ReactNode;\n opacityPanel: React.ReactNode;\n adjustPanel: React.ReactNode;\n fontSizePanel: React.ReactNode;\n shapeCornerRadiusPanel: React.ReactNode;\n shapeTransparencyPanel: React.ReactNode;\n shapeSidesPanel: React.ReactNode;\n shapePointsPanel: React.ReactNode;\n shapeInnerRadiusPanel: React.ReactNode;\n shapeColorPanel: React.ReactNode;\n textColorPanel: React.ReactNode;\n strokePanel: React.ReactNode;\n shadowPanel: React.ReactNode;\n blendModePanel: React.ReactNode;\n knockoutPanel: React.ReactNode;\n distressTexturePanel: React.ReactNode;\n imageMaskPanel: React.ReactNode;\n}\n\nexport const EmbeddedToolbarLayout: React.FC<EmbeddedToolbarLayoutProps> = ({\n toolbarContent,\n innerContentRef,\n shouldRender,\n isExiting,\n transitionHeight,\n emptyStateContent,\n // Panel open states\n isAlignPanelOpen,\n isCornerRadiusPanelOpen,\n isCropPanelOpen,\n isRotationPanelOpen,\n isOpacityPanelOpen,\n isAdjustPanelOpen,\n isFontSizePanelOpen,\n isShapeCornerRadiusPanelOpen,\n isShapeTransparencyPanelOpen,\n isShapeSidesPanelOpen,\n isShapePointsPanelOpen,\n isShapeInnerRadiusPanelOpen,\n isShapeColorPanelOpen,\n isTextColorPanelOpen,\n isStrokePanelOpen,\n isShadowPanelOpen,\n isBlendModePanelOpen,\n isKnockoutPanelOpen,\n isDistressTexturePanelOpen,\n isImageMaskPanelOpen,\n // Panel content\n alignPanel,\n cornerRadiusPanel,\n cropPanelContent,\n rotationPanel,\n opacityPanel,\n adjustPanel,\n fontSizePanel,\n shapeCornerRadiusPanel,\n shapeTransparencyPanel,\n shapeSidesPanel,\n shapePointsPanel,\n shapeInnerRadiusPanel,\n shapeColorPanel,\n textColorPanel,\n strokePanel,\n shadowPanel,\n blendModePanel,\n knockoutPanel,\n distressTexturePanel,\n imageMaskPanel,\n}) => {\n return (\n <div\n className=\"toolbar-embedded-wrapper\"\n style={{\n display: 'flex',\n flexDirection: 'column',\n flex: 1,\n minHeight: 0, // Critical: allows flex children to shrink and enables nested scrolling\n overscrollBehaviorY: 'contain',\n }}\n >\n {/* Empty state when no element selected */}\n {emptyStateContent}\n\n <div\n className=\"toolbar-height-wrapper\"\n style={\n transitionHeight !== null\n ? {\n // During type transitions: use explicit height for direct height-to-height animation\n height: transitionHeight,\n overflow: 'hidden',\n transition: 'height 200ms cubic-bezier(0.22, 1, 0.36, 1)',\n }\n : {\n // Normal show/hide: use CSS Grid for 0fr/1fr animation\n display: 'grid',\n gridTemplateRows: shouldRender && !isExiting ? '1fr' : '0fr',\n transition: 'grid-template-rows 200ms cubic-bezier(0.22, 1, 0.36, 1)',\n }\n }\n >\n <div ref={innerContentRef}>{toolbarContent}</div>\n </div>\n\n {/* Align panel (single selection → artboard) */}\n <SecondaryPanelWrapper isOpen={isAlignPanelOpen}>{alignPanel}</SecondaryPanelWrapper>\n\n {/* Corner radius panel */}\n <SecondaryPanelWrapper isOpen={isCornerRadiusPanelOpen}>{cornerRadiusPanel}</SecondaryPanelWrapper>\n\n {/* Crop panel */}\n <SecondaryPanelWrapper isOpen={isCropPanelOpen}>{cropPanelContent}</SecondaryPanelWrapper>\n\n {/* Rotation panel */}\n <SecondaryPanelWrapper isOpen={isRotationPanelOpen}>{rotationPanel}</SecondaryPanelWrapper>\n\n {/* Opacity panel */}\n <SecondaryPanelWrapper isOpen={isOpacityPanelOpen}>{opacityPanel}</SecondaryPanelWrapper>\n\n {/* Adjust panel (image brightness/contrast/saturation) */}\n <SecondaryPanelWrapper isOpen={isAdjustPanelOpen}>{adjustPanel}</SecondaryPanelWrapper>\n\n {/* Font size panel */}\n <SecondaryPanelWrapper isOpen={isFontSizePanelOpen}>{fontSizePanel}</SecondaryPanelWrapper>\n\n {/* Shape corner radius panel */}\n <SecondaryPanelWrapper isOpen={isShapeCornerRadiusPanelOpen}>\n {shapeCornerRadiusPanel}\n </SecondaryPanelWrapper>\n\n {/* Shape transparency panel */}\n <SecondaryPanelWrapper isOpen={isShapeTransparencyPanelOpen}>\n {shapeTransparencyPanel}\n </SecondaryPanelWrapper>\n\n {/* Shape sides panel (polygon) */}\n <SecondaryPanelWrapper isOpen={isShapeSidesPanelOpen}>{shapeSidesPanel}</SecondaryPanelWrapper>\n\n {/* Shape points panel (star) */}\n <SecondaryPanelWrapper isOpen={isShapePointsPanelOpen}>{shapePointsPanel}</SecondaryPanelWrapper>\n\n {/* Shape inner radius panel (star) */}\n <SecondaryPanelWrapper isOpen={isShapeInnerRadiusPanelOpen}>\n {shapeInnerRadiusPanel}\n </SecondaryPanelWrapper>\n\n {/* Shape fill color panel */}\n <ColorPanelWrapper isOpen={isShapeColorPanelOpen}>{shapeColorPanel}</ColorPanelWrapper>\n\n {/* Text font color panel */}\n <ColorPanelWrapper isOpen={isTextColorPanelOpen}>{textColorPanel}</ColorPanelWrapper>\n\n {/* Stroke panel */}\n <SecondaryPanelWrapper isOpen={isStrokePanelOpen}>{strokePanel}</SecondaryPanelWrapper>\n\n {/* Shadow panel */}\n <SecondaryPanelWrapper isOpen={isShadowPanelOpen}>{shadowPanel}</SecondaryPanelWrapper>\n\n {/* Blend mode panel */}\n <SecondaryPanelWrapper isOpen={isBlendModePanelOpen}>{blendModePanel}</SecondaryPanelWrapper>\n\n {/* Knockout panel */}\n <SecondaryPanelWrapper isOpen={isKnockoutPanelOpen}>{knockoutPanel}</SecondaryPanelWrapper>\n\n {/* Distress texture panel */}\n <SecondaryPanelWrapper isOpen={isDistressTexturePanelOpen}>{distressTexturePanel}</SecondaryPanelWrapper>\n\n {/* Image mask panel */}\n <SecondaryPanelWrapper isOpen={isImageMaskPanelOpen}>{imageMaskPanel}</SecondaryPanelWrapper>\n </div>\n );\n};\n\nexport default EmbeddedToolbarLayout;\n","/**\n * FloatingPanels - Secondary panels rendered in floating mode.\n *\n * These panels appear below the floating toolbar in a portal,\n * positioned relative to the toolbar's screen position.\n */\n\nimport React from 'react';\nimport { SliderRow } from '../ui/index.js';\nimport CropPanel from '../CropPanel.jsx';\nimport type { ImageElement } from '../../core/ImageElement.js';\nimport type { AlignMode } from '../../utils/alignDistribute.js';\nimport { AlignPanel } from './SecondaryPanels.js';\n\nexport interface FloatingCornerRadiusPanelProps {\n toolbarPosition: { top: number; left: number };\n toolbarHeight: number;\n panelWidth: number;\n value: number;\n onChange: (value: number) => void;\n}\n\nexport const FloatingCornerRadiusPanel: React.FC<FloatingCornerRadiusPanelProps> = ({\n toolbarPosition,\n toolbarHeight,\n panelWidth,\n value,\n onChange,\n}) => (\n <div\n className=\"corner-radius-panel\"\n style={{\n position: 'fixed',\n top: `${toolbarPosition.top + toolbarHeight + 8}px`,\n left: `${toolbarPosition.left}px`,\n transform: 'translateX(-50%)',\n padding: '12px 24px',\n marginTop: '-12px',\n borderRadius: 0,\n border: '1px solid var(--divider)',\n boxShadow: '0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1)',\n zIndex: 'var(--sc-z-tooltip)',\n width: `${panelWidth}px`,\n boxSizing: 'border-box',\n }}\n >\n <SliderRow label=\"Radius\" value={value} onChange={onChange} min={0} max={50} unit=\"%\" />\n </div>\n);\n\nexport interface FloatingAlignPanelProps {\n toolbarPosition: { top: number; left: number };\n toolbarHeight: number;\n onAlign: (mode: AlignMode) => void;\n}\n\nexport const FloatingAlignPanel: React.FC<FloatingAlignPanelProps> = ({\n toolbarPosition,\n toolbarHeight,\n onAlign,\n}) => (\n <div\n className=\"sc-align-panel\"\n style={{\n position: 'fixed',\n top: `${toolbarPosition.top + toolbarHeight + 8}px`,\n left: `${toolbarPosition.left}px`,\n transform: 'translateX(-50%)',\n background: 'var(--background)',\n border: '1px solid var(--divider)',\n borderRadius: '12px',\n boxShadow: '0 4px 12px 0 rgb(0 0 0 / 0.15)',\n zIndex: 'var(--sc-z-tooltip)' as React.CSSProperties['zIndex'],\n }}\n >\n <AlignPanel onAlign={onAlign} />\n </div>\n);\n\nexport interface FloatingCropPanelProps {\n toolbarPosition: { top: number; left: number };\n toolbarHeight: number;\n element: ImageElement;\n onElementUpdate: (element: ImageElement) => void;\n}\n\nexport const FloatingCropPanel: React.FC<FloatingCropPanelProps> = ({\n toolbarPosition,\n toolbarHeight,\n element,\n onElementUpdate,\n}) => (\n <div\n className=\"sc-crop-panel\"\n style={{\n position: 'fixed',\n top: `${toolbarPosition.top + toolbarHeight + 8}px`,\n left: `${toolbarPosition.left}px`,\n transform: 'translateX(-50%)',\n background: 'var(--background)',\n border: '1px solid var(--divider)',\n borderRadius: '12px',\n boxShadow: '0 4px 12px 0 rgb(0 0 0 / 0.15)',\n zIndex: 'var(--sc-z-tooltip)',\n minWidth: '300px',\n }}\n >\n <CropPanel element={element} onElementUpdate={onElementUpdate} />\n </div>\n);\n","/**\n * documentColors — collect every colour actually in use in a design.\n *\n * Surfaced in the colour-picker dropdowns (\"Document colors\" /\n * \"Image colors\" rows) so users can match a colour they're already\n * using elsewhere in the artwork instead of eyeballing it.\n *\n * Two kinds of colours are exposed:\n *\n * - **Vector colours** (`collectDocumentColors`) — text colours,\n * rich-text span colours, shape fills, path fills, path strokes,\n * element-level stroke colours, and artboard background. Cheap,\n * synchronous read off the data model.\n *\n * - **Image colours** (`extractImagePalette` / `collectImageColors`) —\n * a small dominant-colour palette per image element. Async, requires\n * pixel access (the image must be CORS-loaded — see CLAUDE.md\n * \"CORS Cache Poisoning\"). Cached by URL.\n */\n\nimport type { BaseElement } from '../core/BaseElement.js';\nimport { TextElement } from '../core/TextElement.js';\nimport { ShapeElement } from '../core/ShapeElement.js';\nimport { ImageElement } from '../core/ImageElement.js';\nimport { GroupElement } from '../core/GroupElement.js';\nimport { PathElement } from '../core/PathElement.js';\nimport type { ArtboardElement } from '../core/ArtboardElement.js';\n\nconst isPaintable = (c: unknown): c is string =>\n typeof c === 'string' && c.length > 0 && c !== 'transparent';\n\n/**\n * Walk one element and push every paint colour it carries into `out`.\n * Recurses into group children. Element-level stroke is only counted\n * when `stroke.enabled === true` so disabled-but-configured strokes\n * don't pollute the palette.\n */\nfunction collectFromElement(el: BaseElement, out: Set<string>): void {\n // Element-level stroke (StrokeConfig) — applies to text, image,\n // shape, group, path uniformly.\n const stroke = (el as { stroke?: { enabled?: boolean; color?: string } })\n .stroke;\n if (stroke?.enabled && isPaintable(stroke.color)) {\n out.add(stroke.color);\n }\n\n if (el instanceof TextElement) {\n if (isPaintable(el.color)) out.add(el.color);\n // Rich-text span colours — each per-character span can override\n // the element default. Skip undefined (means \"inherit element\n // colour\" — already added above).\n const richText = (el as { richText?: { spans?: Array<{ style?: { color?: string } }> } }).richText;\n if (richText?.spans) {\n for (const span of richText.spans) {\n if (isPaintable(span.style?.color)) out.add(span.style!.color!);\n }\n }\n return;\n }\n\n if (el instanceof ShapeElement) {\n const richFill = el.transformData.fill;\n if (richFill) {\n // Rich fill wins over fillColor at render time — collect what paints.\n if (richFill.type === 'solid') {\n if (isPaintable(richFill.color)) out.add(richFill.color);\n } else {\n for (const stop of richFill.stops) {\n if (isPaintable(stop.color)) out.add(stop.color);\n }\n }\n return;\n }\n const fill = el.transformData.fillColor;\n if (isPaintable(fill)) out.add(fill);\n return;\n }\n\n if (el instanceof PathElement) {\n const td = (el as PathElement).transformData;\n if (td.fillEnabled && isPaintable(td.fillColor)) out.add(td.fillColor);\n if (td.strokeEnabled && isPaintable(td.strokeColor)) out.add(td.strokeColor);\n return;\n }\n\n if (el instanceof GroupElement) {\n // Group itself doesn't paint — children do. Recurse.\n for (const child of el.children) {\n collectFromElement(child, out);\n }\n return;\n }\n\n // ImageElement contributes via image-palette extraction, not vector\n // colours.\n}\n\n/**\n * Collect every vector colour in the design. Synchronous.\n *\n * @param elements - Top-level elements (groups recurse internally)\n * @param artboards - Optional. When provided, `backgroundColor` from\n * each artboard is included (real exported background; the UI-only\n * `previewBackgroundColor` is intentionally skipped — it's the\n * shirt-colour preview, not part of the artwork).\n */\nexport function collectDocumentColors(\n elements: ReadonlyArray<BaseElement>,\n artboards?: ReadonlyArray<ArtboardElement>\n): Set<string> {\n const out = new Set<string>();\n for (const el of elements) collectFromElement(el, out);\n if (artboards) {\n for (const ab of artboards) {\n const bg = (ab as { backgroundColor?: string }).backgroundColor;\n if (isPaintable(bg)) out.add(bg);\n }\n }\n return out;\n}\n\n// ============================================================================\n// Image palette extraction\n// ============================================================================\n\nconst IMAGE_PALETTE_CACHE = new Map<string, string[]>();\nconst IMAGE_PALETTE_INFLIGHT = new Map<string, Promise<string[]>>();\n\ntype RGB = { r: number; g: number; b: number };\n\n/**\n * Median cut box — a region of RGB space holding some pixels plus\n * the per-channel ranges (cached so we can pick the longest axis\n * cheaply when deciding which axis to split next).\n */\ntype Box = {\n pixels: RGB[];\n rRange: number;\n gRange: number;\n bRange: number;\n};\n\nfunction computeRanges(pixels: RGB[]): { rRange: number; gRange: number; bRange: number } {\n if (pixels.length === 0) return { rRange: 0, gRange: 0, bRange: 0 };\n let rMin = 255, rMax = 0, gMin = 255, gMax = 0, bMin = 255, bMax = 0;\n for (const p of pixels) {\n if (p.r < rMin) rMin = p.r;\n if (p.r > rMax) rMax = p.r;\n if (p.g < gMin) gMin = p.g;\n if (p.g > gMax) gMax = p.g;\n if (p.b < bMin) bMin = p.b;\n if (p.b > bMax) bMax = p.b;\n }\n return { rRange: rMax - rMin, gRange: gMax - gMin, bRange: bMax - bMin };\n}\n\nfunction boxLongestAxis(box: Box): 'r' | 'g' | 'b' {\n const max = Math.max(box.rRange, box.gRange, box.bRange);\n if (box.rRange === max) return 'r';\n if (box.gRange === max) return 'g';\n return 'b';\n}\n\nfunction boxSize(box: Box): number {\n return Math.max(box.rRange, box.gRange, box.bRange);\n}\n\nfunction splitBox(box: Box): [Box, Box] {\n const axis = boxLongestAxis(box);\n // Sort by the longest axis so the median split actually balances\n // pixel count across the most-spread channel.\n const sorted = box.pixels.slice().sort((a, b) => a[axis] - b[axis]);\n const mid = sorted.length >> 1;\n const leftPixels = sorted.slice(0, mid);\n const rightPixels = sorted.slice(mid);\n return [\n { pixels: leftPixels, ...computeRanges(leftPixels) },\n { pixels: rightPixels, ...computeRanges(rightPixels) },\n ];\n}\n\nfunction averageColor(pixels: RGB[]): RGB {\n let r = 0, g = 0, b = 0;\n for (const p of pixels) {\n r += p.r;\n g += p.g;\n b += p.b;\n }\n const n = pixels.length;\n return {\n r: Math.round(r / n),\n g: Math.round(g / n),\n b: Math.round(b / n),\n };\n}\n\n/**\n * Median-cut quantisation, internal Box-returning variant. Recursively\n * splits the colour-space box with the largest spread until we reach\n * `targetBuckets`. Boxes are returned so callers that need the per-box\n * pixel population (e.g. for sorting before dedupe) can read it.\n */\nfunction medianCutBoxes(pixels: RGB[], targetBuckets: number): Box[] {\n if (pixels.length === 0) return [];\n const boxes: Box[] = [{ pixels, ...computeRanges(pixels) }];\n\n while (boxes.length < targetBuckets) {\n // Always split the box with the largest single-axis spread —\n // that's where we'll get the most colour diversity from one\n // additional bucket.\n let bestIdx = -1;\n let bestSize = 0;\n for (let i = 0; i < boxes.length; i++) {\n const size = boxSize(boxes[i]);\n if (size > bestSize && boxes[i].pixels.length >= 2) {\n bestSize = size;\n bestIdx = i;\n }\n }\n if (bestIdx === -1) break; // every remaining box is unsplittable\n const target = boxes[bestIdx];\n boxes.splice(bestIdx, 1);\n boxes.push(...splitBox(target));\n }\n\n return boxes;\n}\n\n/**\n * Median-cut quantisation. Returns the average colour of each box.\n *\n * Why this beats a frequency histogram for our use case: a frequency\n * histogram returns the most-populated buckets, which means a smooth\n * gradient (sunset reds spread across many adjacent buckets) loses\n * to a flat region (solid black sky) even when the gradient is the\n * visually salient subject. Median cut splits by *spread* in colour\n * space, so red, orange, and yellow each get their own bucket.\n *\n * @internal exported for tests\n */\nexport function medianCut(pixels: RGB[], targetBuckets: number): RGB[] {\n return medianCutBoxes(pixels, targetBuckets).map((box) => averageColor(box.pixels));\n}\n\n/**\n * Redmean ΔE — a cheap perceptual-distance approximation. Pure\n * Euclidean RGB distance treats (50,0,0) vs (0,0,50) as identical,\n * which is wrong because the eye is more sensitive to green than red\n * or blue. Redmean weights each channel by the average of the two\n * reds, which biases the metric toward perceived difference at low\n * cost. See https://www.compuphase.com/cmetric.htm.\n *\n * Returned distance is roughly comparable to a CIE-76 ΔE: ~25 means\n * \"noticeably different,\" ~50+ means \"obviously different.\"\n *\n * @internal exported for tests\n */\nexport function redmeanDistance(a: RGB, b: RGB): number {\n const rMean = (a.r + b.r) / 2;\n const dr = a.r - b.r;\n const dg = a.g - b.g;\n const db = a.b - b.b;\n return Math.sqrt(\n (2 + rMean / 256) * dr * dr +\n 4 * dg * dg +\n (2 + (255 - rMean) / 256) * db * db\n );\n}\n\n/**\n * Drop palette entries that are visually indistinguishable from one\n * we already kept. Walks in input order, so callers should pre-sort\n * by importance (we sort by population — bigger boxes first — so\n * the most-prominent shade in a \"near-duplicate\" cluster wins).\n *\n * @internal exported for tests\n */\nexport function dedupeByPerceptualDistance(\n palette: RGB[],\n threshold: number\n): RGB[] {\n const out: RGB[] = [];\n for (const c of palette) {\n let dup = false;\n for (const kept of out) {\n if (redmeanDistance(c, kept) <= threshold) {\n dup = true;\n break;\n }\n }\n if (!dup) out.push(c);\n }\n return out;\n}\n\n/**\n * Pick a diverse palette from a population-sorted candidate list via\n * furthest-point sampling. The first candidate is taken as the anchor\n * (most populous). Each subsequent pick maximises the minimum redmean\n * distance to every already-picked colour, so the row spans the image's\n * actual colour variation instead of N shades of whatever hue dominates.\n *\n * Candidates closer than `threshold` to an already-picked colour are\n * skipped — that's the dedupe step folded into the same pass. Stops\n * when there are no further candidates above the threshold.\n *\n * @internal exported for tests\n */\nexport function furthestPointPalette(\n candidates: RGB[],\n paletteSize: number,\n threshold: number\n): RGB[] {\n if (candidates.length === 0 || paletteSize <= 0) return [];\n const picked: RGB[] = [candidates[0]];\n const used = new Set<number>([0]);\n while (picked.length < paletteSize) {\n let bestIdx = -1;\n let bestMinDist = -1;\n for (let i = 1; i < candidates.length; i++) {\n if (used.has(i)) continue;\n let minDist = Infinity;\n for (const p of picked) {\n const d = redmeanDistance(candidates[i], p);\n if (d < minDist) minDist = d;\n }\n if (minDist > bestMinDist) {\n bestMinDist = minDist;\n bestIdx = i;\n }\n }\n if (bestIdx === -1 || bestMinDist <= threshold) break;\n picked.push(candidates[bestIdx]);\n used.add(bestIdx);\n }\n return picked;\n}\n\nconst toHex = (n: number) => n.toString(16).padStart(2, '0');\nfunction rgbToHex(c: RGB): string {\n return `#${toHex(c.r)}${toHex(c.g)}${toHex(c.b)}`;\n}\n\n/**\n * Extract up to `paletteSize` dominant colours from an image URL.\n *\n * Implementation:\n * 1. Draw the image into a small offscreen canvas (48×48). Smaller\n * than the source, but enough resolution for dominant colours\n * and *much* faster than walking the full image.\n * 2. Sample every pixel; skip fully-transparent and near-white\n * (background swamps the palette and isn't useful for matching).\n * 3. Run median cut to produce ~2× the requested palette size\n * (gives dedupe headroom).\n * 4. Sort by box population so visually-prominent shades come first\n * within near-duplicate clusters.\n * 5. Drop near-duplicates by redmean-weighted ΔE — without this\n * step a photo with a big black region returns 3 indistinguishable\n * blacks instead of black + the actual subject colours.\n * 6. Truncate to `paletteSize`.\n *\n * Cached per URL in module-scope (cache survives component unmount;\n * wiped on hard reload).\n *\n * Requires `crossOrigin=\"anonymous\"` on the source image. If the\n * image is CORS-tainted, `getImageData` throws and we cache an empty\n * array. Per CLAUDE.md \"CORS Cache Poisoning\" all canvas images\n * already set this.\n */\nexport async function extractImagePalette(\n imageUrl: string,\n paletteSize = 5\n): Promise<string[]> {\n if (!imageUrl) return [];\n const cached = IMAGE_PALETTE_CACHE.get(imageUrl);\n if (cached) return cached;\n const inflight = IMAGE_PALETTE_INFLIGHT.get(imageUrl);\n if (inflight) return inflight;\n\n const promise = (async (): Promise<string[]> => {\n try {\n const img = await loadCorsImage(imageUrl);\n const SAMPLE = 48; // 48×48 = 2304 pixels — plenty for dominant colours.\n const canvas = typeof OffscreenCanvas !== 'undefined'\n ? new OffscreenCanvas(SAMPLE, SAMPLE)\n : (() => {\n const c = document.createElement('canvas');\n c.width = SAMPLE;\n c.height = SAMPLE;\n return c;\n })();\n const ctx = (canvas as HTMLCanvasElement | OffscreenCanvas)\n .getContext('2d') as\n | CanvasRenderingContext2D\n | OffscreenCanvasRenderingContext2D\n | null;\n if (!ctx) return [];\n ctx.drawImage(img, 0, 0, SAMPLE, SAMPLE);\n const { data } = ctx.getImageData(0, 0, SAMPLE, SAMPLE);\n\n const pixels: RGB[] = [];\n for (let i = 0; i < data.length; i += 4) {\n const a = data[i + 3];\n if (a < 128) continue; // skip transparent\n const r = data[i];\n const g = data[i + 1];\n const b = data[i + 2];\n // Skip near-white pixels — typical background.\n if (r > 240 && g > 240 && b > 240) continue;\n pixels.push({ r, g, b });\n }\n if (pixels.length === 0) {\n IMAGE_PALETTE_CACHE.set(imageUrl, []);\n return [];\n }\n\n // Over-extract aggressively so diversity selection has lots of\n // candidates to choose from. Without this, photos dominated by\n // one hue (e.g. green leaves) fill every box with a slight\n // variant of that hue and a visually-prominent minority colour\n // (gold accents on a green background) never makes it into the\n // candidate pool.\n const overExtract = Math.max(paletteSize * 4, 16);\n const boxes = medianCutBoxes(pixels, overExtract);\n // Sort by population so the biggest cluster's average wins\n // as our anchor for furthest-point sampling.\n boxes.sort((a, b) => b.pixels.length - a.pixels.length);\n\n const candidates = boxes.map((box) => averageColor(box.pixels));\n // Furthest-point sampling: pick the most populous colour as the\n // anchor, then each subsequent pick is the candidate with the\n // largest minimum redmean distance to everything already picked.\n // This serves two goals at once — drops perceptually-indistinct\n // near-duplicates (via the threshold cutoff) AND surfaces\n // visually-salient minority colours that pure population-sort\n // would push out of the top-N slice. Threshold tuned against\n // the sunset failure case: (8,8,8) and (24,24,24) sit ~48\n // redmean apart and should collapse into one swatch.\n // Tradeoff: subtle gradients (deep-red vs red, ~33 apart)\n // collapse — but for a \"match a colour in your design\" picker\n // that's the right call. Five obviously-different swatches beats\n // five shades-of-the-same-thing, AND gold on a green photo\n // actually appears in the row.\n const top = furthestPointPalette(candidates, paletteSize, 50).map(rgbToHex);\n\n IMAGE_PALETTE_CACHE.set(imageUrl, top);\n return top;\n } catch {\n // CORS taint, decode failure, etc. Cache empty result so we\n // don't re-attempt every render.\n IMAGE_PALETTE_CACHE.set(imageUrl, []);\n return [];\n } finally {\n IMAGE_PALETTE_INFLIGHT.delete(imageUrl);\n }\n })();\n IMAGE_PALETTE_INFLIGHT.set(imageUrl, promise);\n return promise;\n}\n\nfunction loadCorsImage(url: string): Promise<HTMLImageElement> {\n return new Promise((resolve, reject) => {\n const img = new Image();\n // CORS attr MUST be set before src — see CLAUDE.md gotcha #13.\n img.crossOrigin = 'anonymous';\n img.onload = () => resolve(img);\n img.onerror = () => reject(new Error(`Failed to load image: ${url}`));\n img.src = url;\n });\n}\n\n/**\n * Walk every ImageElement (recursing into groups), pull the unique\n * URLs, extract a small palette per image, and return the deduped\n * union. Order is \"first image first, top-N per image\" so the row\n * has predictable colours. Returns [] if no images.\n */\nexport async function collectImageColors(\n elements: ReadonlyArray<BaseElement>,\n paletteSize = 5\n): Promise<string[]> {\n const urls: string[] = [];\n const seen = new Set<string>();\n const visit = (el: BaseElement) => {\n if (el instanceof ImageElement) {\n const url = el.imageUrl;\n if (url && !seen.has(url)) {\n seen.add(url);\n urls.push(url);\n }\n } else if (el instanceof GroupElement) {\n for (const c of el.children) visit(c);\n }\n };\n for (const el of elements) visit(el);\n if (urls.length === 0) return [];\n\n const palettes = await Promise.all(\n urls.map((u) => extractImagePalette(u, paletteSize))\n );\n const out: string[] = [];\n const dedupe = new Set<string>();\n for (const palette of palettes) {\n for (const c of palette) {\n if (!dedupe.has(c)) {\n dedupe.add(c);\n out.push(c);\n }\n }\n }\n return out;\n}\n\n/**\n * Test-only: clear the in-memory palette caches so unit tests start\n * from a known state.\n * @internal\n */\nexport function _resetImagePaletteCache(): void {\n IMAGE_PALETTE_CACHE.clear();\n IMAGE_PALETTE_INFLIGHT.clear();\n}\n","/**\n * ContextualToolbars - Renders the appropriate toolbar for the selected element type.\n *\n * Dispatches to element-specific toolbars (text, image, shape, path, artboard)\n * based on the current selection in `EditorContext`. Also manages expanded\n * sub-panels (crop, corner radius, effects, rotation) and floating overlays.\n *\n * Place anywhere inside an `EditorProvider` -- it reads selection state from context.\n *\n * @example\n * ```tsx\n * <EditorProvider>\n * <Canvas />\n * <ContextualToolbars />\n * </EditorProvider>\n * ```\n */\n\nimport React, { useState, useCallback, useEffect, useLayoutEffect, useRef, useMemo } from 'react';\nimport { createPortal } from 'react-dom';\nimport { useEditor } from '../contexts/EditorContext.js';\nimport { useViewportContext } from '../contexts/ViewportContext.js';\nimport { useSelectionContext } from '../contexts/SelectionContext.js';\nimport { useToolStateContext } from '../contexts/ToolStateContext.js';\nimport {\n CanvasServicesProvider,\n useCanvasServices,\n type CanvasServices,\n} from '../contexts/CanvasServicesContext.js';\nimport BackButton from './BackButton.jsx';\nimport ImageToolbar from './ImageToolbar.jsx';\nimport ShapeToolbar from './ShapeToolbar.jsx';\nimport ShapeTypeDrawer from './ShapeTypeDrawer.jsx';\nimport PathToolbar from './PathToolbar.jsx';\nimport ArtboardPropertiesToolbar from './ArtboardPropertiesToolbar.jsx';\nimport { TextToolbar } from './TextToolbar.js';\nimport { useTextToolbar } from '../hooks/useTextToolbar.js';\nimport { useCommands } from '../hooks/useCommands.js';\nimport { NEUTRAL_ADJUSTMENTS, normalizeAdjustments } from '../core/image-adjustments.js';\nimport type { EditorElement } from '../contexts/EditorContext.js';\nimport { ImageElement } from '../core/ImageElement.js';\nimport { GroupElement } from '../core/GroupElement.js';\nimport { ShapeElement } from '../core/ShapeElement.js';\nimport { PathElement } from '../core/PathElement.js';\nimport { CollapsedToolbarHeader, ToolbarButton, icons } from './ui';\nimport { LayerLeadingChip } from './LayerLeadingChip.js';\nimport { MultiSelectionToolbar } from './MultiSelectionToolbar.js';\nimport { useAlignDistribute } from '../hooks/useAlignDistribute.js';\nimport {\n GroupElementToolbar,\n ExpandedPanelIcon,\n EmbeddedToolbarLayout,\n FloatingAlignPanel,\n FloatingCornerRadiusPanel,\n FloatingCropPanel,\n AlignPanel,\n CornerRadiusPanel,\n RotationPanel,\n OpacityPanel,\n AdjustPanel,\n FontSizePanel,\n ShapeCornerRadiusPanel,\n ShapeTransparencyPanel,\n ShapeSidesPanel,\n ShapePointsPanel,\n ShapeInnerRadiusPanel,\n ShapeColorPanel,\n TextColorPanel,\n CompositingPanel,\n StrokePanel,\n ShadowPanel,\n BlendModePanel,\n CropPanelContent,\n DistressTexturePanel,\n ImageMaskPanel,\n} from './toolbars/index.js';\nimport type { CompositingMode } from './toolbars/SecondaryPanels.js';\nimport type { CompositingScope, ImageAdjustments, ShapeFill, ShadowConfig, StandardBlendMode } from '../types/index.js';\nimport { isStandardBlendMode } from '../types/index.js';\nimport { shapeFillToCss } from '../core/shape-fill.js';\nimport ArtboardDistressPanel from './ArtboardDistressPanel.jsx';\nimport ArtboardImageMaskPanel from './ArtboardImageMaskPanel.jsx';\nimport { createLogger } from '../utils/logger.js';\nimport { collectDocumentColors, collectImageColors } from '../utils/documentColors.js';\n\nconst logger = createLogger('ContextualToolbars');\n\n// User-facing failure copy. NEVER mention configuration internals here.\nconst REMOVE_BG_UNAVAILABLE = 'Background removal is temporarily unavailable.';\n\n/** Keep host-provided error copy, but never surface configuration internals. */\nfunction safeErrorMessage(err: unknown, fallback: string): string {\n const message = err instanceof Error ? err.message : '';\n if (!message || /VITE_|NEXT_PUBLIC_|\\.env/i.test(message)) return fallback;\n return message;\n}\n\ntype MenuType = 'root' | 'transforms' | 'align' | 'color';\ntype DropdownType = 'fontSize' | 'fontFamily' | null;\n\n/** Panel configuration for collapsed header */\ntype ExpandedPanelConfig = {\n type:\n | 'align'\n | 'cornerRadius'\n | 'effects'\n | 'crop'\n | 'rotation'\n | 'opacity'\n | 'adjust'\n | 'fontSize'\n | 'shapeCornerRadius'\n | 'shapeTransparency'\n | 'shapeSides'\n | 'shapePoints'\n | 'shapeInnerRadius'\n | 'shapeColor'\n | 'textColor'\n | 'stroke'\n | 'shadow'\n | 'blendMode'\n | 'compositing'\n | 'distressTexture'\n | 'imageMask';\n icon: string | React.ReactNode;\n label: string;\n} | null;\n\nexport interface ContextualToolbarsProps {\n /**\n * Positioning mode for the toolbar\n * - 'floating': Positioned relative to selected element (default)\n * - 'embedded': Static positioning for embedding in a container\n */\n mode?: 'floating' | 'embedded';\n\n /**\n * @deprecated Effects panel drawer has been replaced by inline secondary panels.\n * Stroke, masks, distress, and knockout are now accessible directly from the toolbar.\n */\n onOpenEffectsPanel?: () => void;\n\n /**\n * Callback when glyph browser should be opened\n */\n onOpenGlyphBrowser?: () => void;\n\n /**\n * Callback when image should be changed\n */\n onChangeImage?: () => void;\n\n /**\n * Callback when shape type drawer should be opened\n */\n onOpenShapeTypeDrawer?: () => void;\n\n /**\n * Document colors for color picker\n */\n documentColors?: Set<string>;\n\n /**\n * Current viewport width for responsive behavior\n */\n viewportWidth?: number;\n\n /**\n * Responsive breakpoints for layout\n * - full: All controls visible (default: 1024)\n * - compact: Some controls in overflow menu (default: 768)\n * - minimal: Only essential controls, rest in overflow (default: 480)\n */\n breakpoints?: {\n full?: number;\n compact?: number;\n minimal?: number;\n };\n\n /**\n * Whether element has glyphs available\n */\n hasGlyphs?: boolean;\n\n /**\n * Callback to get more menu items for text elements\n */\n getMoreMenuItems?: () => Array<{ label: string; onClick: () => void; icon: React.ReactNode; active?: boolean }>;\n\n /**\n * Callback when artboard is updated\n */\n onArtboardUpdate?: (artboardId: string, oldProps: Record<string, unknown>, newProps: Record<string, unknown>) => void;\n\n /**\n * Artboard screen bounds for positioning toolbars\n */\n artboardScreenBounds?: {\n left: number;\n top: number;\n width: number;\n height: number;\n bottom: number;\n centerX: number;\n };\n\n /**\n * Maximum width for the toolbar. When set, enables flex-wrap for multi-row layout.\n * Can be a number (pixels) or a CSS string (e.g., '100%', '400px').\n */\n maxWidth?: number | string;\n\n /**\n * When true, removes the toolbar background, border, and shadow for a transparent look.\n * Useful when embedding in a custom UI where you want only the controls visible.\n */\n transparent?: boolean;\n\n /**\n * Callback when a secondary panel is expanded or collapsed.\n * Useful for styling the container as a bottom drawer when panels are visible.\n */\n onPanelExpandChange?: (expanded: boolean) => void;\n\n /**\n * Default expanded panel type. Used to open a specific panel on mount.\n * Useful when rendering in a drawer that needs to show a specific panel.\n */\n defaultExpandedPanel?: 'cornerRadius' | 'effects' | 'crop' | 'rotation' | null;\n\n /**\n * Callback when expanded panel changes, passing the panel type.\n * Useful for tracking which specific panel is expanded.\n */\n onExpandedPanelTypeChange?: (panelType: 'cornerRadius' | 'effects' | 'crop' | 'rotation' | null) => void;\n\n /**\n * Callback when crop drawer should be opened.\n * When provided, clicking the crop button will call this instead of showing inline panel.\n * Use this to render the crop controls in a drawer in the parent component.\n */\n onOpenCropDrawer?: () => void;\n\n /**\n * Callback when corner radius drawer should be opened.\n * When provided, clicking the corner radius button will call this instead of showing inline panel.\n * Use this to render the corner radius controls in a drawer in the parent component.\n */\n onOpenCornerRadiusDrawer?: () => void;\n\n /**\n * Style for the close button in expanded panel headers.\n * - 'icon': Shows X icon (default)\n * - 'done': Shows \"Done\" text button\n */\n closeButtonStyle?: 'icon' | 'done';\n\n /**\n * Message to display when no element is selected (embedded mode only).\n * Set to null to hide the empty state completely.\n * Default: \"Tap an element to select and edit\"\n */\n emptyStateMessage?: string | null;\n\n /**\n * Custom content to render when no element is selected (embedded mode only).\n * Replaces the default emptyStateMessage text. Use for live mockup previews, etc.\n */\n emptyStateRender?: React.ReactNode;\n\n /**\n * When true and no element is selected, shows artboard distress panel\n * in the empty state slot (embedded mode only).\n */\n editArtboardMode?: boolean;\n\n /**\n * Called when artboard edit mode should change (e.g. dismissed by selecting\n * an element or clicking the \"Done\" button).\n */\n onEditArtboardModeChange?: (active: boolean) => void;\n\n /**\n * Called when the leading layer thumbnail in the toolbar is clicked.\n * Typical wiring: open the host app's \"Manage Layers\" drawer with\n * the currently-selected layer focused. The selected layer is\n * already tracked by EditorContext so the drawer's `LayersPanel`\n * will highlight the right row automatically.\n *\n * When omitted, the thumbnail is non-interactive (just a visual\n * indicator of the selection).\n */\n onLayerThumbnailClick?: () => void;\n\n /**\n * Privileged-service wiring (background removal, image search / AI\n * generation proxy URLs or providers). Needed when this toolbar is mounted\n * OUTSIDE `SnowconeCanvas` (e.g. a host app with its own chrome via\n * `externalProvider`) — the canvas-internal `CanvasServicesProvider` can't\n * reach it there. When the toolbar renders inside `SnowconeCanvas`, omit\n * this and the ambient context applies; passing it explicitly wins either way.\n */\n services?: CanvasServices;\n\n /**\n * `data-sc-part` value for the toolbar root (the Editor.* parts contract,\n * ADR-0085 §5 — the class-3 floating toolbar is themable and selectable via\n * `data-sc-part` even though the host doesn't position it). Set by the\n * canvas's built-in floating mount; omitted everywhere else.\n * @internal\n */\n partAttr?: string;\n}\n\nexport const ContextualToolbars: React.FC<ContextualToolbarsProps> = ({ services, ...props }) => {\n const inner = <ContextualToolbarsInner {...props} />;\n // Only wrap when the prop is present — an unconditional wrapper with\n // `services={undefined}` would clobber the ambient context from\n // `SnowconeCanvas` with empty services and hide every service-gated control.\n return services ? <CanvasServicesProvider services={services}>{inner}</CanvasServicesProvider> : inner;\n};\n\nconst ContextualToolbarsInner: React.FC<Omit<ContextualToolbarsProps, 'services'>> = ({\n mode = 'floating',\n onOpenGlyphBrowser,\n onChangeImage,\n onOpenShapeTypeDrawer,\n documentColors = new Set(),\n viewportWidth = window.innerWidth,\n breakpoints: _breakpoints = {},\n hasGlyphs = false,\n getMoreMenuItems,\n onArtboardUpdate,\n artboardScreenBounds,\n maxWidth,\n transparent = false,\n onPanelExpandChange,\n defaultExpandedPanel,\n onExpandedPanelTypeChange,\n onOpenCropDrawer,\n onOpenCornerRadiusDrawer,\n closeButtonStyle = 'icon',\n emptyStateMessage = 'Tap an element to select and edit',\n emptyStateRender,\n editArtboardMode = false,\n onEditArtboardModeChange,\n onLayerThumbnailClick,\n partAttr,\n}) => {\n // ── Focused sub-contexts ────────────────────────────────────────────────\n // Use sub-context hooks to avoid re-renders from unrelated state changes.\n const { panOffset } = useViewportContext();\n const { multiSelection, setSelectedId } = useSelectionContext();\n const {\n expandedPanelType: contextExpandedPanelType,\n setExpandedPanelType: setContextExpandedPanelType,\n setIsToolbarMenuOpen,\n isRotating,\n } = useToolStateContext();\n\n // ── Editor context (core state not available in sub-contexts) ──────────\n const {\n elements,\n setElements,\n selectedElement,\n activeChildElement,\n handleElementUpdate,\n artboardManager,\n artboards,\n canvasEditorRef,\n canvasRef,\n executeElementUpdate,\n executeRemoveElement,\n executeAddElement,\n executeReorderElement,\n refreshArtboards,\n } = useEditor();\n\n // ── Privileged services (background removal) ────────────────────────────\n const { removeBackground } = useCanvasServices();\n\n // ── Text toolbar hook ───────────────────────────────────────────────────\n const textToolbar = useTextToolbar({ canvasEditorRef });\n\n // ── Local state ─────────────────────────────────────────────────────────\n const [activeMenu, setActiveMenu] = useState<MenuType>('root');\n const [openDropdown, setOpenDropdown] = useState<DropdownType>(null);\n const [toolbarPosition, setToolbarPosition] = useState<{ top: number; left: number } | null>(null);\n const [_isDragging, setIsDragging] = useState<boolean>(false);\n const [isTransformMenuOpen, setIsTransformMenuOpen] = useState<boolean>(false);\n const [isColorPickerOpen] = useState<boolean>(false);\n const [isTextMoreMenuOpen, setIsTextMoreMenuOpen] = useState<boolean>(false);\n const [isShapeTypeDrawerOpen, setIsShapeTypeDrawerOpen] = useState<boolean>(false);\n\n // ── Expanded panel state ────────────────────────────────────────────────\n const [expandedPanel, setExpandedPanel] = useState<ExpandedPanelConfig>(() => {\n if (!defaultExpandedPanel) return null;\n const panelConfigs: Record<string, ExpandedPanelConfig> = {\n cornerRadius: { type: 'cornerRadius', icon: 'lucide:square-round-corner', label: 'Corner Radius' },\n crop: { type: 'crop', icon: 'lucide:crop', label: 'Crop' },\n rotation: { type: 'rotation', icon: icons.rotateLeft, label: 'Rotate' },\n opacity: { type: 'opacity', icon: 'lucide:blend', label: 'Transparency' },\n effects: { type: 'effects', icon: 'lucide:sparkles', label: 'Effects' },\n };\n return panelConfigs[defaultExpandedPanel] || null;\n });\n\n // ── Animation states ────────────────────────────────────────────────────\n const [isEntering, setIsEntering] = useState<boolean>(false);\n const [isExiting, setIsExiting] = useState<boolean>(false);\n const [shouldRender, setShouldRender] = useState<boolean>(false);\n const [isWaitingForPosition, setIsWaitingForPosition] = useState<boolean>(false);\n const [positionedElementId, setPositionedElementId] = useState<string | null>(null);\n const [transitionHeight, setTransitionHeight] = useState<number | null>(null);\n const [toolbarDimensions, setToolbarDimensions] = useState({ width: 0, height: 0 });\n\n // ── Refs ────────────────────────────────────────────────────────────────\n const toolbarRef = useRef<HTMLDivElement>(null);\n const innerContentRef = useRef<HTMLDivElement>(null);\n const lastKnownHeightRef = useRef<number>(0);\n const prevShouldShowRef = useRef<boolean>(false);\n const isMouseDownRef = useRef<boolean>(false);\n const frozenPositionRef = useRef<{ top: number; left: number } | null>(null);\n const lastElementRotationRef = useRef<number | undefined>(undefined);\n const lastSyncedToContextRef = useRef<string | null>(null);\n const prevContextExpandedPanelTypeRef = useRef(contextExpandedPanelType);\n const prevSelectedIdRef = useRef<string | undefined>(undefined);\n const prevElementTypeRef = useRef<string | undefined>(undefined);\n const prevIsRotatingRef = useRef<boolean>(false);\n const isRotatingRef = useRef<boolean>(false);\n const isDrawerModeAtMount = useRef(!!defaultExpandedPanel);\n const isFullyMountedRef = useRef(false);\n const expandedPanelRef = useRef(expandedPanel);\n const elementForPropertiesRef = useRef<EditorElement | null>(null);\n const elementUpdateHandlerRef = useRef<(el: EditorElement) => void>(() => {});\n const prevStableSelectedIdRef = useRef<string | undefined>(undefined);\n const prevIsCroppingRef = useRef<boolean | undefined>(undefined);\n\n // Keep isRotatingRef current on every render so stale-closure handlers can read it\n isRotatingRef.current = isRotating;\n\n // ── Derived state ───────────────────────────────────────────────────────\n const elementForProperties = activeChildElement || selectedElement;\n const stableElementId = elementForProperties?.id;\n const stableSelectedId = selectedElement?.id;\n const currentElementType = elementForProperties?.transformType;\n const { fontColor, getEffectiveStyle, handleFontColorChange } = textToolbar;\n const shouldShowToolbar = !!(selectedElement && !isRotating);\n\n // ── Element update handler ──────────────────────────────────────────────\n const elementUpdateHandler = useCallback(\n (updatedElement: EditorElement) => {\n if (!selectedElement) return;\n if (activeChildElement) {\n const groupElement = selectedElement as GroupElement;\n const updatedGroup = groupElement.clone() as GroupElement;\n const childIndex = updatedGroup.children.findIndex((c) => c.id === activeChildElement.id);\n if (childIndex !== -1) {\n updatedGroup.children[childIndex] = updatedElement;\n handleElementUpdate(updatedGroup);\n }\n } else {\n handleElementUpdate(updatedElement);\n }\n },\n [selectedElement, activeChildElement, handleElementUpdate]\n );\n\n // ── Image border radius handler ────────────────────────────────────────\n const handleBorderRadiusChange = useCallback(\n (value: number) => {\n if (!elementForProperties || elementForProperties.transformType !== 'image') return;\n const updatedElement = (elementForProperties as ImageElement).clone();\n updatedElement.transformData.borderRadius = value;\n elementUpdateHandler(updatedElement);\n },\n [elementForProperties, elementUpdateHandler]\n );\n\n // ── Remove background (one-shot service action) ────────────────────────\n const [removingBackground, setRemovingBackground] = useState<boolean>(false);\n const [removeBackgroundError, setRemoveBackgroundError] = useState<string | null>(null);\n\n // Elements snapshot for async flows — the provider call can take seconds,\n // so resolve-time application must re-find the element in CURRENT state.\n const elementsRef = useRef(elements);\n elementsRef.current = elements;\n\n const isMountedForServicesRef = useRef(true);\n useEffect(() => {\n isMountedForServicesRef.current = true;\n return () => {\n isMountedForServicesRef.current = false;\n };\n }, []);\n\n // Swap an image element's URL through command history — the canonical\n // \"change the picture\" flow from embed/ImagePanel.tsx, minus the\n // crop/flip/border-radius/dimension resets: background removal returns the\n // SAME picture (with alpha), so the existing crop, flips, radius, and size\n // all stay meaningful.\n const applyRemovedBackgroundUrl = useCallback(\n (elementId: string, processedUrl: string) => {\n const swapImageUrl = (oldImage: ImageElement): ImageElement => {\n const updated = oldImage.clone();\n updated.imageUrl = processedUrl;\n // Reset load state before loading the new bitmap.\n updated.imageLoaded = false;\n updated.imageElement = null;\n updated.onLoadCallback = (loadedElement) => {\n // Load-time adjustments bypass command history (same as ImagePanel).\n const el = loadedElement as ImageElement;\n setElements((prevElements) => prevElements.map((s) => (s.id === el.id ? el : s)));\n };\n updated.loadImage(processedUrl);\n return updated;\n };\n\n const currentElements = elementsRef.current;\n\n // Top-level image element.\n const topLevel = currentElements.find((e) => e.id === elementId);\n if (topLevel) {\n if (!(topLevel instanceof ImageElement)) return;\n executeElementUpdate(topLevel, swapImageUrl(topLevel));\n return;\n }\n\n // Group child — clone the group, swap the child inside the clone.\n for (const el of currentElements) {\n if (!(el instanceof GroupElement)) continue;\n const childIndex = el.children.findIndex((c) => c.id === elementId);\n if (childIndex === -1) continue;\n const child = el.children[childIndex];\n if (!(child instanceof ImageElement)) return;\n const updatedGroup = el.clone() as GroupElement;\n updatedGroup.children[childIndex] = swapImageUrl(child);\n executeElementUpdate(el, updatedGroup);\n return;\n }\n // Element no longer exists (deleted mid-flight) → drop the result.\n },\n [executeElementUpdate, setElements]\n );\n\n const handleRemoveBackground = useCallback(() => {\n if (!removeBackground || removingBackground) return;\n const element = elementForProperties;\n if (!element || !(element instanceof ImageElement) || !element.imageUrl) return;\n\n // Capture the id at click time — the selection (or the element itself)\n // can change/disappear while the provider call is in flight.\n const elementId = element.id;\n\n setRemovingBackground(true);\n setRemoveBackgroundError(null);\n\n removeBackground(element.imageUrl)\n .then((processedUrl) => {\n if (!isMountedForServicesRef.current) return;\n applyRemovedBackgroundUrl(elementId, processedUrl);\n })\n .catch((err: unknown) => {\n logger.error('Error removing background:', err);\n if (!isMountedForServicesRef.current) return;\n setRemoveBackgroundError(safeErrorMessage(err, REMOVE_BG_UNAVAILABLE));\n })\n .finally(() => {\n if (isMountedForServicesRef.current) setRemovingBackground(false);\n });\n }, [removeBackground, removingBackground, elementForProperties, applyRemovedBackgroundUrl]);\n\n // Clear the inline bg-remove error once the selection moves on.\n useEffect(() => {\n setRemoveBackgroundError(null);\n }, [stableElementId]);\n\n // ── Shape property change handlers ─────────────────────────────────────\n const handleShapeBorderRadiusChange = useCallback(\n (value: number) => {\n if (!elementForProperties || elementForProperties.transformType !== 'shape') return;\n const updatedElement = (elementForProperties as ShapeElement).clone();\n updatedElement.transformData.borderRadius = value;\n elementUpdateHandler(updatedElement);\n },\n [elementForProperties, elementUpdateHandler]\n );\n\n const handleShapeOpacityChange = useCallback(\n (value: number) => {\n if (!elementForProperties || elementForProperties.transformType !== 'shape') return;\n const updatedElement = (elementForProperties as ShapeElement).clone();\n updatedElement.transformData.fillOpacity = value;\n elementUpdateHandler(updatedElement);\n },\n [elementForProperties, elementUpdateHandler]\n );\n\n const handleShapeSidesChange = useCallback(\n (value: number) => {\n if (!elementForProperties || elementForProperties.transformType !== 'shape') return;\n const updatedElement = (elementForProperties as ShapeElement).clone();\n updatedElement.transformData.sides = value;\n elementUpdateHandler(updatedElement);\n },\n [elementForProperties, elementUpdateHandler]\n );\n\n const handleShapePointsChange = useCallback(\n (value: number) => {\n if (!elementForProperties || elementForProperties.transformType !== 'shape') return;\n const updatedElement = (elementForProperties as ShapeElement).clone();\n updatedElement.transformData.points = value;\n elementUpdateHandler(updatedElement);\n },\n [elementForProperties, elementUpdateHandler]\n );\n\n const handleShapeInnerRadiusChange = useCallback(\n (value: number) => {\n if (!elementForProperties || elementForProperties.transformType !== 'shape') return;\n const updatedElement = (elementForProperties as ShapeElement).clone();\n updatedElement.transformData.innerRadius = value;\n elementUpdateHandler(updatedElement);\n },\n [elementForProperties, elementUpdateHandler]\n );\n\n const handleShapeFillColorChange = useCallback(\n (color: string) => {\n if (!elementForProperties || elementForProperties.transformType !== 'shape') return;\n const updatedElement = (elementForProperties as ShapeElement).clone();\n updatedElement.transformData.fillColor = color;\n // A rich `fill` wins over `fillColor` at render time — clear it so the\n // picked solid color is what actually renders.\n delete updatedElement.transformData.fill;\n elementUpdateHandler(updatedElement);\n },\n [elementForProperties, elementUpdateHandler]\n );\n\n const handleShapeFillChange = useCallback(\n (fill: ShapeFill | null) => {\n if (!elementForProperties || elementForProperties.transformType !== 'shape') return;\n const updatedElement = (elementForProperties as ShapeElement).clone();\n if (fill === null) {\n delete updatedElement.transformData.fill;\n } else {\n updatedElement.transformData.fill = fill;\n }\n elementUpdateHandler(updatedElement);\n },\n [elementForProperties, elementUpdateHandler]\n );\n\n // ── Align to artboard (single selection) ───────────────────────────────\n // The hook aligns relative to the active artboard when exactly one movable\n // element is selected — the panel below is the single-selection surface\n // for it (multi-selections get inline buttons in MultiSelectionToolbar).\n const { canAlign, align: alignSelection } = useAlignDistribute();\n\n // ── Panel toggle handlers ──────────────────────────────────────────────\n const handleAlignToggle = useCallback(() => {\n setExpandedPanel((prev) =>\n prev?.type === 'align'\n ? null\n : { type: 'align', icon: 'gravity-ui:objects-align-center-vertical', label: 'Position' }\n );\n }, []);\n\n const handleCornerRadiusToggle = useCallback(() => {\n if (onOpenCornerRadiusDrawer) {\n onOpenCornerRadiusDrawer();\n } else {\n setExpandedPanel((prev) =>\n prev?.type === 'cornerRadius'\n ? null\n : { type: 'cornerRadius', icon: 'lucide:square-round-corner', label: 'Corner Radius' }\n );\n }\n }, [onOpenCornerRadiusDrawer]);\n\n const handleCropToggle = useCallback(() => {\n if (onOpenCropDrawer) {\n onOpenCropDrawer();\n } else {\n setExpandedPanel((prev) => (prev?.type === 'crop' ? null : { type: 'crop', icon: 'lucide:crop', label: 'Crop' }));\n }\n }, [onOpenCropDrawer]);\n\n const handleRotationToggle = useCallback(() => {\n setExpandedPanel((prev) =>\n prev?.type === 'rotation' ? null : { type: 'rotation', icon: icons.rotateLeft, label: 'Rotate' }\n );\n }, []);\n\n const handleOpacityToggle = useCallback(() => {\n setExpandedPanel((prev) =>\n prev?.type === 'opacity' ? null : { type: 'opacity', icon: 'lucide:blend', label: 'Transparency' }\n );\n }, []);\n\n const handleAdjustToggle = useCallback(() => {\n setExpandedPanel((prev) =>\n prev?.type === 'adjust' ? null : { type: 'adjust', icon: 'gravity-ui:sliders', label: 'Adjust' }\n );\n }, []);\n\n const handleFontSizeToggle = useCallback(() => {\n setExpandedPanel((prev) =>\n prev?.type === 'fontSize' ? null : { type: 'fontSize', icon: 'lucide:type', label: 'Font Size' }\n );\n }, []);\n\n // Text-box width handler. Custom text and transformed text (wave,\n // arch, etc.) store their bounding-box width on `transformData.width`\n // — the same field the resize handle writes. Updating it from the\n // slider is just a clone + assign, routed through `elementUpdateHandler`\n // so the change lands in undo/redo.\n const handleTextWidthChange = useCallback(\n (next: number) => {\n if (!elementForProperties) return;\n const td = elementForProperties.transformData as { width?: number } | undefined;\n if (!td || td.width === undefined) return;\n const updated = elementForProperties.clone();\n (updated.transformData as { width: number }).width = next;\n elementUpdateHandler(updated);\n },\n [elementForProperties, elementUpdateHandler]\n );\n\n // Read current text-box width if the element exposes one. Used to\n // drive the width slider in the font-size panel.\n const currentTextWidth =\n (elementForProperties?.transformData as { width?: number } | undefined)?.width ?? null;\n\n // Letter-spacing / line-height only apply to straight ('custom') text —\n // curved transforms (circle, arch, wave, …) lay glyphs along their own\n // path math and intentionally ignore both, so the sliders are hidden\n // there (pass null) rather than rendering dead controls.\n const isCustomText = elementForProperties?.transformType === 'custom';\n const currentLetterSpacing = isCustomText ? textToolbar.letterSpacing : null;\n const currentLineHeight = isCustomText ? textToolbar.lineHeight : null;\n\n const handleShapeCornerRadiusToggle = useCallback(() => {\n setExpandedPanel((prev) =>\n prev?.type === 'shapeCornerRadius'\n ? null\n : { type: 'shapeCornerRadius', icon: 'lucide:square-round-corner', label: 'Corner Radius' }\n );\n }, []);\n\n const handleShapeTransparencyToggle = useCallback(() => {\n setExpandedPanel((prev) =>\n prev?.type === 'shapeTransparency'\n ? null\n : { type: 'shapeTransparency', icon: 'lucide:blend', label: 'Transparency' }\n );\n }, []);\n\n const handleShapeSidesToggle = useCallback(() => {\n setExpandedPanel((prev) =>\n prev?.type === 'shapeSides' ? null : { type: 'shapeSides', icon: 'lucide:hexagon', label: 'Sides' }\n );\n }, []);\n\n const handleShapePointsToggle = useCallback(() => {\n setExpandedPanel((prev) =>\n prev?.type === 'shapePoints' ? null : { type: 'shapePoints', icon: 'lucide:star', label: 'Points' }\n );\n }, []);\n\n const handleShapeInnerRadiusToggle = useCallback(() => {\n setExpandedPanel((prev) =>\n prev?.type === 'shapeInnerRadius'\n ? null\n : { type: 'shapeInnerRadius', icon: 'lucide:circle-dashed', label: 'Inner Radius' }\n );\n }, []);\n\n const handleShapeColorToggle = useCallback(() => {\n setExpandedPanel((prev) =>\n prev?.type === 'shapeColor' ? null : { type: 'shapeColor', icon: 'lucide:paint-bucket', label: 'Fill Color' }\n );\n }, []);\n\n const handleTextColorToggle = useCallback(() => {\n setExpandedPanel((prev) =>\n prev?.type === 'textColor' ? null : { type: 'textColor', icon: icons.palette, label: 'Font Color' }\n );\n }, []);\n\n const handleCompositingToggle = useCallback(() => {\n setExpandedPanel((prev) =>\n prev?.type === 'compositing' ? null : { type: 'compositing', icon: 'lucide:scissors', label: 'Clip / Knockout' }\n );\n }, []);\n\n const handleDistressTextureToggle = useCallback(() => {\n setExpandedPanel((prev) =>\n prev?.type === 'distressTexture'\n ? null\n : { type: 'distressTexture', icon: 'lucide:stamp', label: 'Distress Texture' }\n );\n }, []);\n\n const handleImageMaskToggle = useCallback(() => {\n setExpandedPanel((prev) =>\n prev?.type === 'imageMask'\n ? null\n : { type: 'imageMask', icon: 'lucide:venetian-mask', label: 'Image Mask' }\n );\n }, []);\n\n const handleStrokeToggle = useCallback(() => {\n setExpandedPanel((prev) =>\n prev?.type === 'stroke'\n ? null\n : { type: 'stroke', icon: 'lucide:pen-line', label: 'Stroke' }\n );\n }, []);\n\n const handleShadowToggle = useCallback(() => {\n setExpandedPanel((prev) =>\n prev?.type === 'shadow'\n ? null\n : { type: 'shadow', icon: 'gravity-ui:square-dashed-circle', label: 'Shadow' }\n );\n }, []);\n\n const handleBlendModeToggle = useCallback(() => {\n setExpandedPanel((prev) =>\n prev?.type === 'blendMode'\n ? null\n : { type: 'blendMode', icon: 'gravity-ui:circles-intersection', label: 'Blend Mode' }\n );\n }, []);\n\n const handleCloseExpandedPanel = useCallback(() => {\n if (expandedPanel?.type === 'crop' && elementForProperties?.transformType === 'image') {\n const imageElement = elementForProperties as ImageElement;\n if (imageElement.isCropping) {\n const updatedElement = imageElement.clone();\n updatedElement.exitCropMode();\n elementUpdateHandler(updatedElement);\n }\n }\n setExpandedPanel(null);\n }, [expandedPanel, elementForProperties, elementUpdateHandler]);\n\n // ── Layer ordering handlers ────────────────────────────────────────────\n const handleMoveForward = useCallback(() => {\n if (!selectedElement) return;\n const idx = elements.findIndex((e) => e.id === selectedElement.id);\n if (idx < elements.length - 1) {\n const targetElement = elements[idx + 1];\n executeReorderElement(selectedElement.id, targetElement.id, 'after');\n }\n }, [selectedElement, elements, executeReorderElement]);\n\n const handleMoveBackward = useCallback(() => {\n if (!selectedElement) return;\n const idx = elements.findIndex((e) => e.id === selectedElement.id);\n if (idx > 0) {\n const targetElement = elements[idx - 1];\n executeReorderElement(selectedElement.id, targetElement.id, 'before');\n }\n }, [selectedElement, elements, executeReorderElement]);\n\n const handleDeleteElement = useCallback(() => {\n const elementToDelete = activeChildElement || selectedElement;\n // Locked elements ARE deletable — locking gates manipulation\n // (drag/resize/rotate), not removal.\n if (!elementToDelete) return;\n executeRemoveElement(elementToDelete);\n setSelectedId(null);\n }, [activeChildElement, selectedElement, executeRemoveElement, setSelectedId]);\n\n // Lock / unlock toggle for the leading chip in the toolbar. Operates\n // on `elementForProperties` so a focused group child gets locked\n // (not the parent group) — `elementUpdateHandler` already routes the\n // updated child back through the group when needed.\n const handleToggleLock = useCallback(() => {\n if (!elementForProperties) return;\n const next = elementForProperties.clone();\n next.locked = !elementForProperties.locked;\n elementUpdateHandler(next);\n }, [elementForProperties, elementUpdateHandler]);\n\n const handleUngroupElement = useCallback(() => {\n if (!selectedElement || selectedElement.transformType !== 'group') return;\n const group = selectedElement as GroupElement;\n if (!group.children || group.children.length === 0) return;\n\n const artboardId = artboardManager.getArtboardIdForElement(group.id);\n if (!artboardId) return;\n\n const extractedChildren = group.children.map(child => {\n const clone = child.clone();\n clone.x = child.x + group.x;\n clone.y = child.y + group.y;\n return clone;\n });\n\n executeRemoveElement(group);\n extractedChildren.forEach(child => executeAddElement(child, artboardId));\n\n setSelectedId(extractedChildren.length > 0 ? extractedChildren[0].id : null);\n }, [selectedElement, artboardManager, executeRemoveElement, executeAddElement, setSelectedId]);\n\n // ── Rotation / opacity handlers (before multiSelection early return) ──\n const handleRotationChange = useCallback(\n (value: number) => {\n if (!elementForProperties) return;\n const updatedElement = elementForProperties.clone();\n updatedElement.rotation = value;\n elementUpdateHandler(updatedElement);\n },\n [elementForProperties, elementUpdateHandler]\n );\n\n const handleRotate90 = useCallback(() => {\n if (!elementForProperties) return;\n const updatedElement = elementForProperties.clone();\n let newRotation = Math.floor(updatedElement.rotation / 90) * 90 + 90;\n newRotation = ((newRotation % 360) + 360) % 360;\n if (newRotation > 180) {\n newRotation -= 360;\n }\n updatedElement.rotation = newRotation;\n elementUpdateHandler(updatedElement);\n }, [elementForProperties, elementUpdateHandler]);\n\n const handleOpacityChange = useCallback(\n (value: number) => {\n if (!elementForProperties) return;\n const updatedElement = elementForProperties.clone();\n updatedElement.opacity = value;\n elementUpdateHandler(updatedElement);\n },\n [elementForProperties, elementUpdateHandler]\n );\n\n // ── Adjust (brightness/contrast/saturation) handlers ──────────────────\n // Top-level images go through the PUBLIC patch path (useCommands.updateElement)\n // with { coalesce } so an entire slider drag lands as ONE undo step — the run\n // starts on the first tick of a gesture and breaks on commit (slider release)\n // via handleAdjustmentsCommit. Group children aren't top-level store entries,\n // so they use the group-aware clone path like every other child slider.\n const { updateElement: updateElementCommand } = useCommands();\n const adjustRunActiveRef = useRef(false);\n\n const handleAdjustmentsChange = useCallback(\n (adjustments: ImageAdjustments) => {\n if (!elementForProperties || elementForProperties.transformType !== 'image') return;\n if (activeChildElement) {\n const updated = (elementForProperties as ImageElement).clone();\n const normalized = normalizeAdjustments(adjustments);\n if (normalized) {\n updated.transformData.adjustments = normalized;\n } else {\n delete updated.transformData.adjustments;\n }\n elementUpdateHandler(updated);\n return;\n }\n updateElementCommand(\n elementForProperties.id,\n { adjustments },\n { coalesce: adjustRunActiveRef.current }\n );\n adjustRunActiveRef.current = true;\n },\n [elementForProperties, activeChildElement, elementUpdateHandler, updateElementCommand]\n );\n\n const handleAdjustmentsCommit = useCallback(() => {\n adjustRunActiveRef.current = false;\n }, []);\n\n const handleAdjustmentsReset = useCallback(() => {\n // Reset is its own single undo step — never folded into a slider run.\n adjustRunActiveRef.current = false;\n handleAdjustmentsChange({ ...NEUTRAL_ADJUSTMENTS });\n adjustRunActiveRef.current = false;\n }, [handleAdjustmentsChange]);\n\n // ── Compositing handlers (Clip / Knockout) ───────────────────────────\n const handleCompositingModeChange = useCallback(\n (mode: CompositingMode) => {\n if (!elementForProperties) return;\n const updatedElement = elementForProperties.clone();\n updatedElement.blendMode = mode;\n if (!updatedElement.knockoutParts) {\n updatedElement.knockoutParts = { fill: true, scope: 'group' };\n }\n elementUpdateHandler(updatedElement);\n },\n [elementForProperties, elementUpdateHandler]\n );\n\n const handleCompositingFillChange = useCallback(\n (fill: boolean) => {\n if (!elementForProperties) return;\n const updatedElement = elementForProperties.clone();\n const currentMode = updatedElement.blendMode === 'clip' ? 'clip' : 'knockout';\n const newParts = { ...updatedElement.knockoutParts, fill };\n updatedElement.knockoutParts = newParts;\n updatedElement.blendMode = (newParts.fill || newParts.stroke) ? currentMode : 'normal';\n elementUpdateHandler(updatedElement);\n },\n [elementForProperties, elementUpdateHandler]\n );\n\n const handleCompositingStrokeChange = useCallback(\n (stroke: boolean) => {\n if (!elementForProperties) return;\n const updatedElement = elementForProperties.clone();\n const currentMode = updatedElement.blendMode === 'clip' ? 'clip' : 'knockout';\n const newParts = { ...updatedElement.knockoutParts, stroke };\n updatedElement.knockoutParts = newParts;\n updatedElement.blendMode = (newParts.fill || newParts.stroke) ? currentMode : 'normal';\n elementUpdateHandler(updatedElement);\n },\n [elementForProperties, elementUpdateHandler]\n );\n\n const handleCompositingScopeChange = useCallback(\n (scope: CompositingScope) => {\n if (!elementForProperties) return;\n const updatedElement = elementForProperties.clone();\n updatedElement.knockoutParts = { ...updatedElement.knockoutParts, scope };\n elementUpdateHandler(updatedElement);\n },\n [elementForProperties, elementUpdateHandler]\n );\n\n // ── Distress texture handlers ─────────────────────────────────────────\n const handleDistressTextureChange = useCallback(\n (url: string) => {\n if (!elementForProperties) return;\n const updatedElement = elementForProperties.clone();\n if (!url) {\n updatedElement.distressEffect = undefined;\n } else {\n updatedElement.distressEffect = {\n enabled: true,\n style: 'custom',\n intensity: updatedElement.distressEffect?.intensity ?? 50,\n textureUrl: url,\n textureOpacity: updatedElement.distressEffect?.textureOpacity ?? 0.5,\n };\n }\n elementUpdateHandler(updatedElement);\n },\n [elementForProperties, elementUpdateHandler]\n );\n\n const handleDistressOpacityChange = useCallback(\n (pct: number) => {\n if (!elementForProperties) return;\n const updatedElement = elementForProperties.clone();\n if (updatedElement.distressEffect) {\n updatedElement.distressEffect = {\n ...updatedElement.distressEffect,\n textureOpacity: pct / 100,\n };\n }\n elementUpdateHandler(updatedElement);\n },\n [elementForProperties, elementUpdateHandler]\n );\n\n // ── Image mask handlers (quick-mask via masks[] with id='quick-image-mask') ──\n const handleImageMaskImageChange = useCallback(\n (url: string) => {\n if (!elementForProperties) return;\n const updatedElement = elementForProperties.clone();\n if (!url) {\n // Remove quick-image-mask\n updatedElement.masks = (updatedElement.masks || []).filter((m: { id: string }) => m.id !== 'quick-image-mask');\n } else {\n // Store the mask's natural dimensions (512×512 for builtin presets).\n // MaskRenderer uses these to compute object-cover scaling at render time,\n // preserving the mask shape's aspect ratio on non-square images.\n const BUILTIN_MASK_SIZE = 512;\n\n const makeMaskElement = () => ({\n transformType: 'image' as const,\n imageUrl: url,\n x: 0, y: 0, rotation: 0,\n transformData: { type: 'image' as const, width: BUILTIN_MASK_SIZE, height: BUILTIN_MASK_SIZE, cropX: 0, cropY: 0, cropWidth: 1, cropHeight: 1, flipHorizontal: false, flipVertical: false, borderRadius: 0 },\n }) as import('../types/index.js').ImageElementConfig;\n\n // Reset crop when applying a mask — the mask handles clipping,\n // and stale crop values would cause position/rendering issues.\n if ('transformData' in updatedElement && updatedElement.transformData) {\n const td = updatedElement.transformData as Record<string, unknown>;\n td.cropX = 0;\n td.cropY = 0;\n td.cropWidth = 1;\n td.cropHeight = 1;\n }\n\n const existing = (updatedElement.masks || []).find((m: { id: string }) => m.id === 'quick-image-mask');\n if (existing) {\n existing.maskElement = makeMaskElement();\n } else {\n const masks = updatedElement.masks || [];\n masks.push({\n id: 'quick-image-mask',\n type: 'clip',\n maskElement: makeMaskElement(),\n opacity: 1,\n inverted: false,\n });\n updatedElement.masks = masks;\n }\n }\n elementUpdateHandler(updatedElement);\n },\n [elementForProperties, elementUpdateHandler]\n );\n\n const handleImageMaskTypeChange = useCallback(\n (type: 'clip' | 'alpha' | 'luma') => {\n if (!elementForProperties) return;\n const updatedElement = elementForProperties.clone();\n const mask = (updatedElement.masks || []).find((m: { id: string }) => m.id === 'quick-image-mask');\n if (mask) {\n mask.type = type;\n elementUpdateHandler(updatedElement);\n }\n },\n [elementForProperties, elementUpdateHandler]\n );\n\n const handleImageMaskOpacityChange = useCallback(\n (pct: number) => {\n if (!elementForProperties) return;\n const updatedElement = elementForProperties.clone();\n const mask = (updatedElement.masks || []).find((m: { id: string }) => m.id === 'quick-image-mask');\n if (mask) {\n mask.opacity = pct / 100;\n elementUpdateHandler(updatedElement);\n }\n },\n [elementForProperties, elementUpdateHandler]\n );\n\n const handleImageMaskInvertedChange = useCallback(\n (inv: boolean) => {\n if (!elementForProperties) return;\n const updatedElement = elementForProperties.clone();\n const mask = (updatedElement.masks || []).find((m: { id: string }) => m.id === 'quick-image-mask');\n if (mask) {\n mask.inverted = inv;\n elementUpdateHandler(updatedElement);\n }\n },\n [elementForProperties, elementUpdateHandler]\n );\n\n // ── Stroke change handler ─────────────────────────────────────────────\n const handleStrokeChange = useCallback(\n (stroke: import('../types/index.js').StrokeConfig | undefined) => {\n if (!elementForProperties) return;\n const updatedElement = elementForProperties.clone();\n updatedElement.stroke = stroke;\n elementUpdateHandler(updatedElement);\n },\n [elementForProperties, elementUpdateHandler]\n );\n\n // ── Shadow change handler ─────────────────────────────────────────────\n const handleShadowChange = useCallback(\n (shadow: ShadowConfig | undefined) => {\n if (!elementForProperties) return;\n const updatedElement = elementForProperties.clone();\n updatedElement.shadow = shadow;\n elementUpdateHandler(updatedElement);\n },\n [elementForProperties, elementUpdateHandler]\n );\n\n // ── Blend mode change handler ─────────────────────────────────────────\n // 'normal' clears the field back to the default (undefined). Picking a\n // standard mode replaces any knockout/clip compositing mode — the two are\n // mutually exclusive by design (one blendMode field).\n const handleBlendModeChange = useCallback(\n (blendMode: 'normal' | StandardBlendMode) => {\n if (!elementForProperties) return;\n const updatedElement = elementForProperties.clone();\n updatedElement.blendMode = blendMode === 'normal' ? undefined : blendMode;\n elementUpdateHandler(updatedElement);\n },\n [elementForProperties, elementUpdateHandler]\n );\n\n // ── Shape type change handler ──────────────────────────────────────────\n const handleShapeTypeChange = useCallback(\n (newShapeType: string) => {\n if (!elementForProperties || elementForProperties.transformType !== 'shape') return;\n const shapeElement = elementForProperties as ShapeElement;\n const updatedElement = shapeElement.clone() as ShapeElement;\n updatedElement.transformData.shapeType = newShapeType as ShapeElement['transformData']['shapeType'];\n elementUpdateHandler(updatedElement);\n setIsShapeTypeDrawerOpen(false);\n },\n [elementForProperties, elementUpdateHandler]\n );\n\n const handleOpenShapeTypeDrawer = useCallback(() => {\n if (onOpenShapeTypeDrawer) {\n onOpenShapeTypeDrawer();\n } else {\n setIsShapeTypeDrawerOpen(true);\n }\n }, [onOpenShapeTypeDrawer]);\n\n // ── Panel expand change notification ───────────────────────────────────\n useEffect(() => {\n onPanelExpandChange?.(expandedPanel !== null);\n onExpandedPanelTypeChange?.(\n (expandedPanel?.type as 'cornerRadius' | 'effects' | 'crop' | 'rotation' | null) ?? null\n );\n }, [expandedPanel, onPanelExpandChange, onExpandedPanelTypeChange]);\n\n // ── Sync local panel state TO context ──────────────────────────────────\n useEffect(() => {\n const localType = expandedPanel?.type ?? null;\n if (localType !== lastSyncedToContextRef.current) {\n lastSyncedToContextRef.current = localType;\n setContextExpandedPanelType(localType as Parameters<typeof setContextExpandedPanelType>[0]);\n }\n }, [expandedPanel, setContextExpandedPanelType]);\n\n // ── Sync FROM context when it changes externally ───────────────────────\n useEffect(() => {\n const prevType = prevContextExpandedPanelTypeRef.current;\n const currentType = contextExpandedPanelType;\n if (prevType === currentType) return;\n prevContextExpandedPanelTypeRef.current = currentType;\n\n if (prevType !== null && currentType === null && expandedPanel !== null) {\n lastSyncedToContextRef.current = null;\n setExpandedPanel(null);\n return;\n }\n\n if (currentType !== null && expandedPanel?.type !== currentType) {\n type PanelType = NonNullable<ExpandedPanelConfig>['type'];\n const panelConfigs: Record<PanelType, NonNullable<ExpandedPanelConfig>> = {\n align: { type: 'align', icon: 'gravity-ui:objects-align-center-vertical', label: 'Position' },\n crop: { type: 'crop', icon: 'lucide:crop', label: 'Crop' },\n cornerRadius: { type: 'cornerRadius', icon: 'lucide:square-round-corner', label: 'Corner Radius' },\n rotation: { type: 'rotation', icon: icons.rotateLeft, label: 'Rotate' },\n opacity: { type: 'opacity', icon: 'lucide:blend', label: 'Transparency' },\n adjust: { type: 'adjust', icon: 'gravity-ui:sliders', label: 'Adjust' },\n fontSize: { type: 'fontSize', icon: 'lucide:type', label: 'Font Size' },\n effects: { type: 'effects', icon: 'lucide:sparkles', label: 'Effects' },\n shapeCornerRadius: { type: 'shapeCornerRadius', icon: 'lucide:square-round-corner', label: 'Corner Radius' },\n shapeTransparency: { type: 'shapeTransparency', icon: icons.eye, label: 'Transparency' },\n shapeSides: { type: 'shapeSides', icon: 'lucide:triangle', label: 'Sides' },\n shapePoints: { type: 'shapePoints', icon: 'lucide:star', label: 'Points' },\n shapeInnerRadius: { type: 'shapeInnerRadius', icon: 'lucide:circle-dashed', label: 'Inner Radius' },\n shapeColor: { type: 'shapeColor', icon: icons.palette, label: 'Color' },\n textColor: { type: 'textColor', icon: icons.palette, label: 'Color' },\n stroke: { type: 'stroke', icon: 'lucide:pen-line', label: 'Stroke' },\n shadow: { type: 'shadow', icon: 'gravity-ui:square-dashed-circle', label: 'Shadow' },\n blendMode: { type: 'blendMode', icon: 'gravity-ui:circles-intersection', label: 'Blend Mode' },\n compositing: { type: 'compositing', icon: 'lucide:scissors', label: 'Clip / Knockout' },\n distressTexture: { type: 'distressTexture', icon: 'lucide:stamp', label: 'Distress Texture' },\n imageMask: { type: 'imageMask', icon: 'lucide:venetian-mask', label: 'Image Mask' },\n };\n const config = panelConfigs[currentType as PanelType];\n if (config) {\n lastSyncedToContextRef.current = currentType;\n setExpandedPanel(config);\n }\n }\n }, [contextExpandedPanelType, expandedPanel]);\n\n // ── Sync toolbar menu open state to context ────────────────────────────\n useEffect(() => {\n const isAnyMenuOpen =\n expandedPanel !== null ||\n openDropdown !== null ||\n isTransformMenuOpen ||\n isColorPickerOpen ||\n isTextMoreMenuOpen ||\n activeMenu !== 'root';\n setIsToolbarMenuOpen(isAnyMenuOpen);\n }, [expandedPanel, openDropdown, isTransformMenuOpen, isColorPickerOpen, isTextMoreMenuOpen, activeMenu, setIsToolbarMenuOpen]);\n\n // ── Close expanded panel when element changes or is deselected ─────────\n useEffect(() => {\n if (defaultExpandedPanel) return;\n if (prevStableSelectedIdRef.current !== undefined && prevStableSelectedIdRef.current !== stableSelectedId) {\n setExpandedPanel(null);\n }\n prevStableSelectedIdRef.current = stableSelectedId;\n }, [stableSelectedId, defaultExpandedPanel]);\n\n // ── Auto-dismiss artboard edit mode when an element is selected ────────\n useEffect(() => {\n if (editArtboardMode && selectedElement) {\n onEditArtboardModeChange?.(false);\n }\n }, [editArtboardMode, selectedElement, onEditArtboardModeChange]);\n\n // ── Close crop panel when element exits crop mode ──────────────────────\n useEffect(() => {\n const currentIsCropping =\n elementForProperties?.transformType === 'image' ? (elementForProperties as ImageElement).isCropping : false;\n if (expandedPanel?.type === 'crop' && prevIsCroppingRef.current === true && currentIsCropping === false) {\n setExpandedPanel(null);\n }\n prevIsCroppingRef.current = currentIsCropping;\n }, [elementForProperties, expandedPanel?.type]);\n\n // ── Cleanup on unmount: exit crop mode ─────────────────────────────────\n useEffect(() => {\n expandedPanelRef.current = expandedPanel;\n elementForPropertiesRef.current = elementForProperties ?? null;\n elementUpdateHandlerRef.current = elementUpdateHandler;\n });\n\n useEffect(() => {\n const timeoutId = setTimeout(() => {\n isFullyMountedRef.current = true;\n }, 0);\n return () => { clearTimeout(timeoutId); };\n }, []);\n\n useEffect(() => {\n return () => {\n if (!isFullyMountedRef.current) return;\n if (!isDrawerModeAtMount.current) return;\n if (expandedPanelRef.current?.type === 'crop') {\n const element = elementForPropertiesRef.current;\n if (element?.transformType === 'image') {\n const imageElement = element as ImageElement;\n if (imageElement.isCropping) {\n const updatedElement = imageElement.clone();\n updatedElement.exitCropMode();\n elementUpdateHandlerRef.current(updatedElement);\n }\n }\n }\n };\n }, []);\n\n // ── Dragging detection ─────────────────────────────────────────────────\n useEffect(() => {\n let mouseDownPos: { x: number; y: number } | null = null;\n let isDraggingStarted = false;\n const DRAG_THRESHOLD = 3;\n\n const handleMouseDown = (e: MouseEvent) => {\n const target = e.target as HTMLElement;\n if (toolbarRef.current?.contains(target)) return;\n if (\n target.closest('[data-slot=\"popover-content\"]') ||\n target.closest('[data-slot=\"dialog\"]') ||\n target.closest('[role=\"dialog\"]') ||\n target.closest('.popover-content') ||\n target.closest('[data-slot]')\n ) return;\n isMouseDownRef.current = true;\n mouseDownPos = { x: e.clientX, y: e.clientY };\n isDraggingStarted = false;\n };\n\n const handleMouseMove = (e: MouseEvent) => {\n if (mouseDownPos && !isDraggingStarted && !isRotatingRef.current) {\n const deltaX = e.clientX - mouseDownPos.x;\n const deltaY = e.clientY - mouseDownPos.y;\n const distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY);\n if (distance > DRAG_THRESHOLD) {\n isDraggingStarted = true;\n setIsDragging(true);\n }\n }\n };\n\n const handleMouseUp = () => {\n isMouseDownRef.current = false;\n mouseDownPos = null;\n isDraggingStarted = false;\n setIsDragging(false);\n };\n\n window.addEventListener('mousedown', handleMouseDown);\n window.addEventListener('mousemove', handleMouseMove);\n window.addEventListener('mouseup', handleMouseUp);\n return () => {\n window.removeEventListener('mousedown', handleMouseDown);\n window.removeEventListener('mousemove', handleMouseMove);\n window.removeEventListener('mouseup', handleMouseUp);\n };\n }, []);\n\n // ── Toolbar dimension tracking ─────────────────────────────────────────\n useEffect(() => {\n if (!toolbarRef.current) return;\n let timeoutId: number | null = null;\n\n const observer = new ResizeObserver((entries) => {\n if (timeoutId !== null) clearTimeout(timeoutId);\n timeoutId = window.setTimeout(() => {\n for (const entry of entries) {\n const newWidth = entry.contentRect.width;\n const newHeight = entry.contentRect.height;\n setToolbarDimensions((prev) => {\n if (prev.width === newWidth && prev.height === newHeight) return prev;\n return { width: newWidth, height: newHeight };\n });\n }\n }, 50);\n });\n\n observer.observe(toolbarRef.current);\n return () => {\n observer.disconnect();\n if (timeoutId !== null) clearTimeout(timeoutId);\n };\n }, [selectedElement]);\n\n // ── Floating toolbar position calculation ──────────────────────────────\n useEffect(() => {\n if (mode === 'embedded') return;\n if (isExiting) return;\n\n const currentRotation = (activeChildElement || selectedElement)?.rotation;\n lastElementRotationRef.current = currentRotation;\n\n if (!selectedElement) {\n setToolbarPosition(null);\n return;\n }\n\n const updateToolbarPosition = () => {\n try {\n const toolbarWidth = toolbarRef.current?.offsetWidth || toolbarDimensions.width || 0;\n const toolbarHeight = toolbarRef.current?.offsetHeight || toolbarDimensions.height || 48;\n const canvas = canvasRef?.current;\n const elementToPosition = activeChildElement || selectedElement;\n const transformData = elementToPosition.transformData as Record<string, unknown> | undefined;\n const elementBounds = elementToPosition.getBoundingBox?.() || {\n x: elementToPosition.x,\n y: elementToPosition.y,\n width: (transformData?.width as number) || 100,\n height: (transformData?.height as number) || 50,\n };\n\n const activeArtboard = artboardManager.getActiveArtboard();\n const artboardX = activeArtboard?.x || 0;\n const artboardY = activeArtboard?.y || 0;\n const currentZoom = canvasEditorRef?.current?.getZoom?.() || 1;\n\n let elementScreenX: number;\n let elementScreenY: number;\n let elementScreenWidth: number;\n let elementScreenHeight: number;\n\n if (canvas) {\n const canvasRect = canvas.getBoundingClientRect();\n elementScreenX = canvasRect.left + (elementBounds.x - artboardX) * currentZoom;\n elementScreenY = canvasRect.top + (elementBounds.y - artboardY) * currentZoom;\n elementScreenWidth = elementBounds.width * currentZoom;\n elementScreenHeight = elementBounds.height * currentZoom;\n } else if (artboardScreenBounds) {\n elementScreenX = artboardScreenBounds.left + (elementBounds.x - artboardX) * currentZoom;\n elementScreenY = artboardScreenBounds.top + (elementBounds.y - artboardY) * currentZoom;\n elementScreenWidth = elementBounds.width * currentZoom;\n elementScreenHeight = elementBounds.height * currentZoom;\n } else {\n const viewportCenterX = window.innerWidth / 2;\n const viewportCenterY = window.innerHeight / 2;\n elementScreenX = viewportCenterX - (elementBounds.width * currentZoom) / 2;\n elementScreenY = viewportCenterY - (elementBounds.height * currentZoom) / 2;\n elementScreenWidth = elementBounds.width * currentZoom;\n elementScreenHeight = elementBounds.height * currentZoom;\n }\n\n const gap = 12;\n const elementTop = elementScreenY;\n const elementCenterX = elementScreenX + elementScreenWidth / 2;\n\n let top = elementTop - toolbarHeight - gap;\n let left = elementCenterX;\n\n if (toolbarWidth > 0) {\n const padding = 20;\n const minLeft = toolbarWidth / 2 + padding;\n const maxLeft = window.innerWidth - toolbarWidth / 2 - padding;\n left = Math.max(minLeft, Math.min(maxLeft, left));\n }\n\n if (top < 10) {\n top = elementScreenY + elementScreenHeight + gap;\n }\n\n const maxTop = window.innerHeight - toolbarHeight - 10;\n top = Math.min(top, maxTop);\n top = Math.max(10, top);\n\n setToolbarPosition({ top, left });\n setPositionedElementId(elementToPosition.id);\n } catch (error) {\n logger.error('Error calculating toolbar position:', error);\n setToolbarPosition(null);\n }\n };\n\n updateToolbarPosition();\n window.addEventListener('resize', updateToolbarPosition);\n // Class-3 anchoring contract (ADR-0085 §5): this fixed body-portal must\n // stay anchored to the canvas element under page AND nested-container\n // scroll — the position derives from getBoundingClientRect() at update\n // time, so re-running on scroll absorbs any ancestor scroll. Capture\n // phase because scroll events don't bubble (but do capture), reaching\n // nested scrollers; passive keeps scrolling smooth. Mirrors\n // RotationHandle's existing listeners.\n window.addEventListener('scroll', updateToolbarPosition, { passive: true, capture: true });\n return () => {\n window.removeEventListener('resize', updateToolbarPosition);\n window.removeEventListener('scroll', updateToolbarPosition, { capture: true });\n };\n }, [mode, selectedElement, activeChildElement, canvasRef, artboardManager, canvasEditorRef, artboardScreenBounds, toolbarDimensions, isExiting, panOffset]);\n\n // ── Memoized color picker props ────────────────────────────────────────\n const colorPickerValue = getEffectiveStyle().color || fontColor;\n const colorPickerOnChange = useCallback(\n (e: { target: { value: string } }) => handleFontColorChange(e as React.ChangeEvent<HTMLInputElement>),\n [handleFontColorChange]\n );\n\n // Auto-derive every paint colour in the design — text colours,\n // rich-text span colours, shape fills, path fills + strokes,\n // element-level strokes, and artboard backgrounds — and union with\n // whatever the consumer explicitly passed in. Lets the shape /\n // text colour pickers offer \"match a colour already on the page\"\n // without every host app having to plumb the set through.\n // See `utils/documentColors.ts` for the full enumeration.\n const autoDocumentColors = useMemo(\n () => collectDocumentColors(elements, artboards),\n [elements, artboards]\n );\n\n const mergedDocumentColors = useMemo(() => {\n const out = new Set<string>(autoDocumentColors);\n for (const c of documentColors) out.add(c);\n return out;\n }, [autoDocumentColors, documentColors]);\n\n const documentColorsKey = Array.from(mergedDocumentColors).sort().join(',');\n const colorPickerDocumentColors = useMemo(\n () => Array.from(mergedDocumentColors),\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [documentColorsKey]\n );\n\n // Image colours — dominant palette extracted from each ImageElement\n // (recursing into groups), surfaced as a separate row in the\n // colour picker. Async because pixel access requires the image to\n // be loaded; cache lives in `documentColors.ts` so re-renders are\n // free after the first extraction. Empty until the first promise\n // resolves; the picker just hides the row in that case.\n const imageUrlsKey = useMemo(() => {\n const urls: string[] = [];\n const seen = new Set<string>();\n const walk = (el: EditorElement) => {\n if (el instanceof ImageElement) {\n if (el.imageUrl && !seen.has(el.imageUrl)) {\n seen.add(el.imageUrl);\n urls.push(el.imageUrl);\n }\n } else if (el instanceof GroupElement) {\n for (const c of el.children) walk(c as EditorElement);\n }\n };\n for (const el of elements) walk(el);\n urls.sort();\n return urls.join('|');\n }, [elements]);\n\n const [colorPickerImageColors, setColorPickerImageColors] = useState<string[]>([]);\n useEffect(() => {\n if (!imageUrlsKey) {\n setColorPickerImageColors([]);\n return;\n }\n let cancelled = false;\n collectImageColors(elements).then((colors) => {\n if (!cancelled) setColorPickerImageColors(colors);\n });\n return () => {\n cancelled = true;\n };\n // We deliberately key off the stable `imageUrlsKey` so that\n // dragging an image around (which mutates `elements` but not the\n // URL set) doesn't re-trigger palette extraction.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [imageUrlsKey]);\n\n // ── Toolbar div ref callback ───────────────────────────────────────────\n const toolbarDivRef = useCallback((node: HTMLDivElement | null) => {\n if (toolbarRef) {\n // MutableRefObject is needed to write to .current in a callback ref\n (toolbarRef as React.MutableRefObject<HTMLDivElement | null>).current = node;\n if (node) {\n const { width, height } = node.getBoundingClientRect();\n if (width > 0 && height > 0) {\n setToolbarDimensions({ width, height });\n }\n }\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n // ── Freeze toolbar position during rotation ────────────────────────────\n useEffect(() => {\n const wasRotating = prevIsRotatingRef.current;\n const isNowRotating = isRotating;\n if (!wasRotating && isNowRotating && toolbarPosition) {\n frozenPositionRef.current = { ...toolbarPosition };\n }\n if (wasRotating && !isNowRotating) {\n frozenPositionRef.current = null;\n }\n prevIsRotatingRef.current = isRotating;\n }, [isRotating, toolbarPosition]);\n\n // ── Entrance/exit animations ───────────────────────────────────────────\n useEffect(() => {\n const prevShouldShow = prevShouldShowRef.current;\n const prevSelectedId = prevSelectedIdRef.current;\n prevShouldShowRef.current = shouldShowToolbar;\n prevSelectedIdRef.current = stableSelectedId;\n\n if (!prevShouldShow && shouldShowToolbar) {\n setShouldRender(true);\n if (mode === 'embedded') {\n setIsWaitingForPosition(false);\n setIsEntering(true);\n setIsExiting(false);\n const enterTimer = setTimeout(() => { setIsEntering(false); }, 200);\n return () => clearTimeout(enterTimer);\n }\n setIsWaitingForPosition(true);\n setIsEntering(false);\n setIsExiting(false);\n return undefined;\n }\n\n if (prevShouldShow && shouldShowToolbar && prevSelectedId !== stableSelectedId && stableSelectedId !== undefined) {\n if (mode === 'embedded') {\n setIsEntering(false);\n return undefined;\n }\n setIsWaitingForPosition(true);\n setIsEntering(false);\n setIsExiting(false);\n return undefined;\n }\n\n if (prevShouldShow && !shouldShowToolbar) {\n if (isRotating) {\n setShouldRender(false);\n setIsEntering(false);\n setIsExiting(false);\n setIsWaitingForPosition(false);\n return undefined;\n }\n\n if (mode === 'embedded') {\n setIsExiting(true);\n setIsEntering(false);\n if (innerContentRef.current) {\n const currentHeight = innerContentRef.current.offsetHeight;\n setTransitionHeight(currentHeight);\n requestAnimationFrame(() => { setTransitionHeight(0); });\n }\n const exitTimer = setTimeout(() => {\n setShouldRender(false);\n setIsExiting(false);\n setTransitionHeight(null);\n }, 200);\n return () => clearTimeout(exitTimer);\n }\n\n setIsExiting(true);\n setIsEntering(false);\n setIsWaitingForPosition(false);\n const exitTimer = setTimeout(() => {\n setShouldRender(false);\n setIsExiting(false);\n setToolbarPosition(null);\n setPositionedElementId(null);\n }, 150);\n return () => clearTimeout(exitTimer);\n }\n\n return undefined;\n }, [shouldShowToolbar, isRotating, stableSelectedId, mode, currentElementType]);\n\n // ── Trigger entrance animation once position is ready ──────────────────\n useEffect(() => {\n if (isWaitingForPosition && toolbarPosition && positionedElementId === stableElementId) {\n setIsWaitingForPosition(false);\n setIsEntering(true);\n const enterTimer = setTimeout(() => { setIsEntering(false); }, 200);\n return () => clearTimeout(enterTimer);\n }\n return undefined;\n }, [isWaitingForPosition, toolbarPosition, positionedElementId, stableElementId]);\n\n // ── Height transitions for type changes (embedded mode) ────────────────\n useLayoutEffect(() => {\n if (mode !== 'embedded') return;\n const prevType = prevElementTypeRef.current;\n const typeChanged = prevType !== undefined && currentElementType !== undefined && prevType !== currentElementType;\n\n if (typeChanged && lastKnownHeightRef.current > 0 && transitionHeight === null) {\n const startHeight = lastKnownHeightRef.current;\n setTransitionHeight(startHeight);\n requestAnimationFrame(() => {\n requestAnimationFrame(() => {\n if (innerContentRef.current) {\n const newHeight = innerContentRef.current.scrollHeight;\n setTransitionHeight(newHeight);\n setTimeout(() => { setTransitionHeight(null); }, 200);\n }\n });\n });\n }\n\n if (innerContentRef.current && transitionHeight === null && !isEntering && !isExiting) {\n lastKnownHeightRef.current = innerContentRef.current.offsetHeight;\n }\n\n prevElementTypeRef.current = currentElementType;\n }, [mode, currentElementType, transitionHeight, isEntering, isExiting]);\n\n // ── Memoized toolbar style ─────────────────────────────────────────────\n const toolbarStyle = useMemo(() => {\n const maxWidthValue = maxWidth ? (typeof maxWidth === 'number' ? `${maxWidth}px` : maxWidth) : undefined;\n\n if (mode === 'embedded') {\n return {\n borderRadius: maxWidth ? '16px' : '9999px',\n visibility: 'visible' as const,\n position: 'static' as const,\n maxWidth: maxWidthValue,\n display: 'flex',\n justifyContent: 'flex-start',\n };\n }\n\n const position = frozenPositionRef.current || toolbarPosition;\n if (position && !isWaitingForPosition) {\n return {\n top: `${position.top}px`,\n left: `${position.left}px`,\n position: 'fixed' as const,\n transform: 'translateX(-50%)',\n borderRadius: maxWidth ? '16px' : '9999px',\n visibility: 'visible' as const,\n maxWidth: maxWidthValue,\n zIndex: 'var(--sc-z-tooltip)',\n };\n }\n\n return {\n borderRadius: maxWidth ? '16px' : '9999px',\n visibility: 'hidden' as const,\n maxWidth: maxWidthValue,\n position: 'fixed' as const,\n top: '-9999px',\n left: '-9999px',\n zIndex: 'var(--sc-z-tooltip)',\n };\n }, [mode, toolbarPosition, isWaitingForPosition, maxWidth]);\n\n // ── Early return for multi-selection ────────────────────────────────────\n // Multi-selections get their own contextual toolbar (align / distribute)\n // instead of the per-element-type toolbars below.\n if (multiSelection.length > 0) {\n return (\n <MultiSelectionToolbar\n mode={mode}\n artboardScreenBounds={artboardScreenBounds}\n partAttr={partAttr}\n />\n );\n }\n\n // ══════════════════════════════════════════════════════════════════════════\n // RENDER: Toolbar dispatch — select element-specific toolbar\n // ══════════════════════════════════════════════════════════════════════════\n\n const regularToolbarContent = (\n <>\n {/* Leading chip: thumbnail + lock toggle. Replaces the floating\n SelectionChip that used to live top-left of the canvas — now\n inline with the rest of the toolbar buttons. Only shows when\n there's actually a selected element (the empty / artboard\n states render their own content elsewhere). */}\n {activeMenu === 'root' && elementForProperties && (\n <LayerLeadingChip\n element={elementForProperties}\n onToggleLock={handleToggleLock}\n onThumbnailClick={onLayerThumbnailClick}\n />\n )}\n\n {/* Position (align to artboard) — element-type agnostic, so it lives\n here once instead of in every per-element toolbar (new element\n types get it for free). Hidden when the selection has no movable\n element (e.g. the layer is locked — lock gates manipulation). */}\n {activeMenu === 'root' && elementForProperties && canAlign && (\n <ToolbarButton\n icon=\"gravity-ui:objects-align-center-vertical\"\n onClick={handleAlignToggle}\n tooltip=\"Position\"\n active={expandedPanel?.type === 'align'}\n data-testid=\"align-toggle\"\n />\n )}\n\n {/* Image elements */}\n {activeMenu === 'root' && elementForProperties?.transformType === 'image' && (\n <ImageToolbar\n element={elementForProperties as ImageElement}\n onElementUpdate={elementUpdateHandler}\n showUngroupButton={!!activeChildElement && selectedElement?.transformType === 'group'}\n onUngroup={handleUngroupElement}\n onMoveForward={handleMoveForward}\n onMoveBackward={handleMoveBackward}\n onChangeImage={onChangeImage}\n onRemoveBackground={removeBackground ? handleRemoveBackground : undefined}\n removingBackground={removingBackground}\n removeBackgroundError={removeBackgroundError}\n onDelete={handleDeleteElement}\n cornerRadiusExpanded={expandedPanel?.type === 'cornerRadius'}\n onCornerRadiusToggle={handleCornerRadiusToggle}\n cropExpanded={expandedPanel?.type === 'crop'}\n onCropToggle={handleCropToggle}\n adjustExpanded={expandedPanel?.type === 'adjust'}\n onAdjustToggle={handleAdjustToggle}\n rotationExpanded={expandedPanel?.type === 'rotation'}\n onRotationToggle={handleRotationToggle}\n opacityExpanded={expandedPanel?.type === 'opacity'}\n onOpacityToggle={handleOpacityToggle}\n strokeExpanded={expandedPanel?.type === 'stroke'}\n onStrokeToggle={handleStrokeToggle}\n shadowExpanded={expandedPanel?.type === 'shadow'}\n onShadowToggle={handleShadowToggle}\n blendModeExpanded={expandedPanel?.type === 'blendMode'}\n onBlendModeToggle={handleBlendModeToggle}\n knockoutExpanded={expandedPanel?.type === 'compositing'}\n onKnockoutToggle={handleCompositingToggle}\n distressTextureExpanded={expandedPanel?.type === 'distressTexture'}\n onDistressTextureToggle={handleDistressTextureToggle}\n imageMaskExpanded={expandedPanel?.type === 'imageMask'}\n onImageMaskToggle={handleImageMaskToggle}\n />\n )}\n\n {/* Group elements (only when no child is active) */}\n {activeMenu === 'root' && selectedElement?.transformType === 'group' && !activeChildElement && (\n <GroupElementToolbar\n element={selectedElement as GroupElement}\n rotationExpanded={expandedPanel?.type === 'rotation'}\n onRotationToggle={handleRotationToggle}\n opacityExpanded={expandedPanel?.type === 'opacity'}\n onOpacityToggle={handleOpacityToggle}\n strokeExpanded={expandedPanel?.type === 'stroke'}\n onStrokeToggle={handleStrokeToggle}\n shadowExpanded={expandedPanel?.type === 'shadow'}\n onShadowToggle={handleShadowToggle}\n blendModeExpanded={expandedPanel?.type === 'blendMode'}\n onBlendModeToggle={handleBlendModeToggle}\n knockoutExpanded={expandedPanel?.type === 'compositing'}\n onKnockoutToggle={handleCompositingToggle}\n distressTextureExpanded={expandedPanel?.type === 'distressTexture'}\n onDistressTextureToggle={handleDistressTextureToggle}\n imageMaskExpanded={expandedPanel?.type === 'imageMask'}\n onImageMaskToggle={handleImageMaskToggle}\n onUngroup={handleUngroupElement}\n />\n )}\n\n {/* Shape elements */}\n {activeMenu === 'root' && elementForProperties?.transformType === 'shape' && (\n <ShapeToolbar\n element={elementForProperties as ShapeElement}\n onElementUpdate={elementUpdateHandler}\n documentColors={colorPickerDocumentColors}\n imageColors={colorPickerImageColors}\n showUngroupButton={!!activeChildElement && selectedElement?.transformType === 'group'}\n onUngroup={handleUngroupElement}\n onMoveForward={handleMoveForward}\n onMoveBackward={handleMoveBackward}\n onOpenShapeTypeDrawer={handleOpenShapeTypeDrawer}\n onDelete={handleDeleteElement}\n rotationExpanded={expandedPanel?.type === 'rotation'}\n onRotationToggle={handleRotationToggle}\n cornerRadiusExpanded={expandedPanel?.type === 'shapeCornerRadius'}\n onCornerRadiusToggle={handleShapeCornerRadiusToggle}\n transparencyExpanded={expandedPanel?.type === 'shapeTransparency'}\n onTransparencyToggle={handleShapeTransparencyToggle}\n sidesExpanded={expandedPanel?.type === 'shapeSides'}\n onSidesToggle={handleShapeSidesToggle}\n pointsExpanded={expandedPanel?.type === 'shapePoints'}\n onPointsToggle={handleShapePointsToggle}\n innerRadiusExpanded={expandedPanel?.type === 'shapeInnerRadius'}\n onInnerRadiusToggle={handleShapeInnerRadiusToggle}\n colorExpanded={expandedPanel?.type === 'shapeColor'}\n onColorToggle={handleShapeColorToggle}\n strokeExpanded={expandedPanel?.type === 'stroke'}\n onStrokeToggle={handleStrokeToggle}\n shadowExpanded={expandedPanel?.type === 'shadow'}\n onShadowToggle={handleShadowToggle}\n blendModeExpanded={expandedPanel?.type === 'blendMode'}\n onBlendModeToggle={handleBlendModeToggle}\n knockoutExpanded={expandedPanel?.type === 'compositing'}\n onKnockoutToggle={handleCompositingToggle}\n distressTextureExpanded={expandedPanel?.type === 'distressTexture'}\n onDistressTextureToggle={handleDistressTextureToggle}\n imageMaskExpanded={expandedPanel?.type === 'imageMask'}\n onImageMaskToggle={handleImageMaskToggle}\n />\n )}\n\n {/* Path elements */}\n {activeMenu === 'root' && elementForProperties?.transformType === 'path' && (\n <PathToolbar\n element={elementForProperties as PathElement}\n onElementUpdate={elementUpdateHandler}\n onMoveForward={handleMoveForward}\n onMoveBackward={handleMoveBackward}\n />\n )}\n\n {/* Text elements (anything not image/group/shape/path) */}\n {activeMenu === 'root' &&\n elementForProperties &&\n elementForProperties.transformType !== 'image' &&\n elementForProperties.transformType !== 'group' &&\n elementForProperties.transformType !== 'shape' &&\n elementForProperties.transformType !== 'path' && (\n <TextToolbar\n toolbar={textToolbar}\n stableElementId={stableElementId}\n viewportWidth={viewportWidth}\n colorPickerValue={colorPickerValue}\n isColorActive={expandedPanel?.type === 'textColor'}\n onColorToggle={handleTextColorToggle}\n onOpenGlyphBrowser={onOpenGlyphBrowser}\n strokeExpanded={expandedPanel?.type === 'stroke'}\n onStrokeToggle={handleStrokeToggle}\n shadowExpanded={expandedPanel?.type === 'shadow'}\n onShadowToggle={handleShadowToggle}\n blendModeExpanded={expandedPanel?.type === 'blendMode'}\n onBlendModeToggle={handleBlendModeToggle}\n hasGlyphs={hasGlyphs}\n expandedPanel={expandedPanel}\n onRotationToggle={handleRotationToggle}\n onOpacityToggle={handleOpacityToggle}\n onFontSizeToggle={handleFontSizeToggle}\n knockoutExpanded={expandedPanel?.type === 'compositing'}\n onKnockoutToggle={handleCompositingToggle}\n distressTextureExpanded={expandedPanel?.type === 'distressTexture'}\n onDistressTextureToggle={handleDistressTextureToggle}\n imageMaskExpanded={expandedPanel?.type === 'imageMask'}\n onImageMaskToggle={handleImageMaskToggle}\n getMoreMenuItems={getMoreMenuItems}\n onMoveForward={handleMoveForward}\n onMoveBackward={handleMoveBackward}\n onDelete={handleDeleteElement}\n elementForProperties={elementForProperties}\n elements={elements}\n isTransformMenuOpen={isTransformMenuOpen}\n onTransformMenuOpenChange={setIsTransformMenuOpen}\n elementUpdateHandler={elementUpdateHandler}\n showUngroupButton={!!activeChildElement && selectedElement?.transformType === 'group'}\n onUngroup={handleUngroupElement}\n isFontBrowserOpen={openDropdown === 'fontFamily'}\n onFontBrowserToggle={(isOpen) => setOpenDropdown(isOpen ? 'fontFamily' : null)}\n onTextMoreMenuOpenChange={setIsTextMoreMenuOpen}\n />\n )}\n\n {/* Color Menu (legacy) */}\n {activeMenu === 'color' && (\n <div className=\"sc-toolbar-items\">\n <BackButton onClick={() => setActiveMenu('root')} />\n <div className=\"sc-toolbar-scroll\">\n <input\n className=\"sc-toolbar-color\"\n type=\"color\"\n value={fontColor}\n onChange={(e) => { handleFontColorChange(e); }}\n />\n <span className=\"sc-toolbar-label\">{fontColor}</span>\n </div>\n </div>\n )}\n </>\n );\n\n // ── Build toolbar chrome (header + regular content) ────────────────────\n const shapeElement = elementForProperties?.transformType === 'shape' ? (elementForProperties as ShapeElement) : null;\n\n const toolbarContent = shouldRender ? (\n <div\n ref={toolbarDivRef}\n className=\"sc-toolbar\"\n data-sc-part={partAttr}\n data-mode={mode}\n data-wrap={maxWidth ? '' : undefined}\n data-transparent={transparent ? '' : undefined}\n data-panel-expanded={expandedPanel ? '' : undefined}\n data-preserve-selection\n style={{\n ...toolbarStyle,\n opacity: isRotating ? 0 : 1,\n // Embedded (docked) mode is visually transparent chrome — its empty\n // regions (flex gaps, leftover row width when the strip wraps) must\n // not swallow pointer events meant for the canvas behind it. The\n // root opts out and App.css re-enables hits on the actual controls\n // (.sc-toolbar-regular-content > *, .sc-toolbar-collapsed-header).\n // Floating mode keeps its opaque pill fully interactive.\n pointerEvents: isRotating ? 'none' : mode === 'embedded' ? 'none' : 'auto',\n transition: 'opacity 0.05s ease-out',\n }}\n data-entering={isEntering ? '' : undefined}\n data-exiting={isExiting ? '' : undefined}\n >\n <div className=\"sc-toolbar-slide-container\">\n <div className=\"sc-toolbar-regular-content\" data-hidden={expandedPanel ? '' : undefined}>\n {regularToolbarContent}\n </div>\n <div className=\"sc-toolbar-collapsed-header\" data-visible={expandedPanel ? '' : undefined}>\n {expandedPanel && (\n <CollapsedToolbarHeader\n icon={\n <ExpandedPanelIcon\n panelType={expandedPanel.type}\n defaultIcon={expandedPanel.icon}\n textColorValue={colorPickerValue}\n shapeFillColor={\n shapeElement\n ? shapeFillToCss(shapeElement.transformData?.fill, shapeElement.transformData?.fillColor)\n : undefined\n }\n />\n }\n label={expandedPanel.label}\n onClose={handleCloseExpandedPanel}\n closeButtonStyle={closeButtonStyle}\n />\n )}\n </div>\n </div>\n </div>\n ) : null;\n\n // ── Derive panel open states ───────────────────────────────────────────\n const isAlignPanelOpen = expandedPanel?.type === 'align';\n const isCornerRadiusPanelOpen = expandedPanel?.type === 'cornerRadius';\n const isCropPanelOpen = expandedPanel?.type === 'crop';\n const isRotationPanelOpen = expandedPanel?.type === 'rotation';\n const isOpacityPanelOpen = expandedPanel?.type === 'opacity';\n const isAdjustPanelOpen = expandedPanel?.type === 'adjust';\n const isFontSizePanelOpen = expandedPanel?.type === 'fontSize';\n const isShapeCornerRadiusPanelOpen = expandedPanel?.type === 'shapeCornerRadius';\n const isShapeTransparencyPanelOpen = expandedPanel?.type === 'shapeTransparency';\n const isShapeSidesPanelOpen = expandedPanel?.type === 'shapeSides';\n const isShapePointsPanelOpen = expandedPanel?.type === 'shapePoints';\n const isShapeInnerRadiusPanelOpen = expandedPanel?.type === 'shapeInnerRadius';\n const isShapeColorPanelOpen = expandedPanel?.type === 'shapeColor';\n const isTextColorPanelOpen = expandedPanel?.type === 'textColor';\n const isKnockoutPanelOpen = expandedPanel?.type === 'compositing';\n const isDistressTexturePanelOpen = expandedPanel?.type === 'distressTexture';\n const isStrokePanelOpen = expandedPanel?.type === 'stroke';\n const isShadowPanelOpen = expandedPanel?.type === 'shadow';\n const isBlendModePanelOpen = expandedPanel?.type === 'blendMode';\n const isImageMaskPanelOpen = expandedPanel?.type === 'imageMask';\n\n // ── Derive property values for panels ──────────────────────────────────\n const currentBorderRadius =\n elementForProperties?.transformType === 'image'\n ? (elementForProperties as ImageElement).transformData?.borderRadius || 0\n : 0;\n const currentRotation = elementForProperties?.rotation || 0;\n const currentOpacity = elementForProperties?.opacity ?? 1;\n const currentShapeBorderRadius = shapeElement?.transformData?.borderRadius || 0;\n const currentShapeOpacity = shapeElement?.transformData?.fillOpacity ?? 1;\n const currentShapeSides = shapeElement?.transformData?.sides || 5;\n const currentShapePoints = shapeElement?.transformData?.points || 5;\n const currentShapeInnerRadius = shapeElement?.transformData?.innerRadius || 0.4;\n const currentShapeFillColor = shapeElement?.transformData?.fillColor || '#3b82f6';\n const currentShapeFill = shapeElement?.transformData?.fill;\n const compositingFill = elementForProperties?.knockoutParts?.fill ?? false;\n const compositingStroke = elementForProperties?.knockoutParts?.stroke ?? false;\n const compositingScope: CompositingScope = elementForProperties?.knockoutParts?.scope ?? 'group';\n const compositingMode: CompositingMode = elementForProperties?.blendMode === 'clip' ? 'clip' : 'knockout';\n\n // ── Build secondary panel content ──────────────────────────────────────\n const alignPanel = isAlignPanelOpen && elementForProperties\n ? <AlignPanel onAlign={alignSelection} />\n : null;\n\n const cornerRadiusPanel = isCornerRadiusPanelOpen && elementForProperties?.transformType === 'image'\n ? <CornerRadiusPanel value={currentBorderRadius} onChange={handleBorderRadiusChange} />\n : null;\n\n const cropPanelContent = isCropPanelOpen && elementForProperties?.transformType === 'image'\n ? <CropPanelContent element={elementForProperties as ImageElement} onElementUpdate={elementUpdateHandler} />\n : null;\n\n const rotationPanel = isRotationPanelOpen && elementForProperties\n ? <RotationPanel value={currentRotation} onChange={handleRotationChange} onRotate90={handleRotate90} />\n : null;\n\n const opacityPanel = isOpacityPanelOpen && elementForProperties\n ? <OpacityPanel value={currentOpacity} onChange={handleOpacityChange} />\n : null;\n\n const currentAdjustments =\n elementForProperties?.transformType === 'image'\n ? (elementForProperties as ImageElement).transformData?.adjustments\n : undefined;\n\n const adjustPanel = isAdjustPanelOpen && elementForProperties?.transformType === 'image'\n ? (\n <AdjustPanel\n adjustments={currentAdjustments}\n onChange={handleAdjustmentsChange}\n onChangeEnd={handleAdjustmentsCommit}\n onReset={handleAdjustmentsReset}\n />\n )\n : null;\n\n // Font size panel — only relevant for text elements (and circle\n // text via getEffectiveFontSize). useTextToolbar's fontSize value\n // tracks the active text element's size and handleFontSizeChange\n // routes the update through the right element-specific path.\n const fontSizePanel = isFontSizePanelOpen\n ? (\n <FontSizePanel\n value={textToolbar.fontSize}\n onChange={textToolbar.handleFontSizeChange}\n widthValue={currentTextWidth}\n onWidthChange={handleTextWidthChange}\n letterSpacingValue={currentLetterSpacing}\n onLetterSpacingChange={textToolbar.handleLetterSpacingChange}\n lineHeightValue={currentLineHeight}\n onLineHeightChange={textToolbar.handleLineHeightChange}\n />\n )\n : null;\n\n const shapeCornerRadiusPanel = isShapeCornerRadiusPanelOpen && shapeElement\n ? <ShapeCornerRadiusPanel value={currentShapeBorderRadius} onChange={handleShapeBorderRadiusChange} />\n : null;\n\n const shapeTransparencyPanel = isShapeTransparencyPanelOpen && shapeElement\n ? <ShapeTransparencyPanel value={currentShapeOpacity} onChange={handleShapeOpacityChange} />\n : null;\n\n const shapeSidesPanel = isShapeSidesPanelOpen && shapeElement\n ? <ShapeSidesPanel value={currentShapeSides} onChange={handleShapeSidesChange} />\n : null;\n\n const shapePointsPanel = isShapePointsPanelOpen && shapeElement\n ? <ShapePointsPanel value={currentShapePoints} onChange={handleShapePointsChange} />\n : null;\n\n const shapeInnerRadiusPanel = isShapeInnerRadiusPanelOpen && shapeElement\n ? <ShapeInnerRadiusPanel value={currentShapeInnerRadius} onChange={handleShapeInnerRadiusChange} />\n : null;\n\n const shapeColorPanel = isShapeColorPanelOpen && shapeElement\n ? <ShapeColorPanel value={currentShapeFillColor} onChange={handleShapeFillColorChange} fill={currentShapeFill} onFillChange={handleShapeFillChange} documentColors={colorPickerDocumentColors} imageColors={colorPickerImageColors} />\n : null;\n\n const textColorPanel = isTextColorPanelOpen && elementForProperties\n ? <TextColorPanel value={colorPickerValue} onChange={colorPickerOnChange} documentColors={colorPickerDocumentColors} imageColors={colorPickerImageColors} />\n : null;\n\n const knockoutPanel = isKnockoutPanelOpen && elementForProperties\n ? <CompositingPanel\n mode={compositingMode}\n fill={compositingFill}\n stroke={compositingStroke}\n scope={compositingScope}\n onModeChange={handleCompositingModeChange}\n onFillChange={handleCompositingFillChange}\n onStrokeChange={handleCompositingStrokeChange}\n onScopeChange={handleCompositingScopeChange}\n />\n : null;\n\n const strokePanel = isStrokePanelOpen && elementForProperties\n ? <StrokePanel\n stroke={elementForProperties.stroke}\n onChange={handleStrokeChange}\n documentColors={colorPickerDocumentColors}\n imageColors={colorPickerImageColors}\n />\n : null;\n\n const shadowPanel = isShadowPanelOpen && elementForProperties\n ? <ShadowPanel\n shadow={elementForProperties.shadow}\n onChange={handleShadowChange}\n documentColors={colorPickerDocumentColors}\n imageColors={colorPickerImageColors}\n />\n : null;\n\n const blendModePanel = isBlendModePanelOpen && elementForProperties\n ? <BlendModePanel\n blendMode={\n isStandardBlendMode(elementForProperties.blendMode)\n ? elementForProperties.blendMode\n : 'normal'\n }\n onChange={handleBlendModeChange}\n />\n : null;\n\n const distressTexturePanel = isDistressTexturePanelOpen && elementForProperties\n ? <DistressTexturePanel\n textureUrl={elementForProperties.distressEffect?.textureUrl ?? ''}\n opacity={Math.round((elementForProperties.distressEffect?.textureOpacity ?? 0.5) * 100)}\n onTextureChange={handleDistressTextureChange}\n onOpacityChange={handleDistressOpacityChange}\n />\n : null;\n\n const quickMask = elementForProperties?.masks?.find((m: { id: string }) => m.id === 'quick-image-mask');\n const imageMaskPanel = isImageMaskPanelOpen && elementForProperties\n ? <ImageMaskPanel\n imageUrl={(quickMask?.maskElement as { imageUrl?: string })?.imageUrl ?? ''}\n maskType={(quickMask?.type as 'clip' | 'alpha' | 'luma') ?? 'clip'}\n opacity={Math.round((quickMask?.opacity ?? 1) * 100)}\n inverted={quickMask?.inverted ?? false}\n onImageChange={handleImageMaskImageChange}\n onMaskTypeChange={handleImageMaskTypeChange}\n onOpacityChange={handleImageMaskOpacityChange}\n onInvertedChange={handleImageMaskInvertedChange}\n />\n : null;\n\n // ── Empty state ────────────────────────────────────────────────────────\n const emptyStateContent =\n mode === 'embedded' && !selectedElement && !editArtboardMode ? (\n emptyStateRender ? (\n <div className=\"toolbar-empty-state\">{emptyStateRender}</div>\n ) : emptyStateMessage !== null ? (\n <div\n className=\"toolbar-empty-state\"\n style={{\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n padding: '16px 24px',\n color: 'var(--foreground)',\n opacity: 0.5,\n fontSize: '14px',\n textAlign: 'center',\n }}\n >\n {emptyStateMessage}\n </div>\n ) : null\n ) : null;\n\n // ── Artboard edit mode content (embedded only) ────────────────────────\n const artboardEditContent =\n mode === 'embedded' && editArtboardMode && !selectedElement && artboardManager.getActiveArtboard() ? (\n <div className=\"sc:px-4 sc:py-3 sc:flex sc:flex-col sc:gap-3\">\n <CollapsedToolbarHeader\n icon=\"lucide:palette\"\n label=\"Artboard Properties\"\n onClose={() => onEditArtboardModeChange?.(false)}\n closeButtonStyle=\"done\"\n />\n <ArtboardDistressPanel\n distressTexture={artboardManager.getActiveArtboard()!.distressTexture}\n onChange={(distressTexture) => {\n const currentArtboard = artboardManager.getActiveArtboard()!;\n if (onArtboardUpdate) {\n onArtboardUpdate(\n currentArtboard.id,\n { distressTexture: currentArtboard.distressTexture },\n { distressTexture }\n );\n } else {\n artboardManager.updateArtboard(currentArtboard.id, { distressTexture });\n refreshArtboards();\n }\n }}\n />\n <ArtboardImageMaskPanel\n imageMask={artboardManager.getActiveArtboard()!.imageMask}\n onChange={(imageMask) => {\n const currentArtboard = artboardManager.getActiveArtboard()!;\n if (onArtboardUpdate) {\n onArtboardUpdate(\n currentArtboard.id,\n { imageMask: currentArtboard.imageMask },\n { imageMask }\n );\n } else {\n artboardManager.updateArtboard(currentArtboard.id, { imageMask });\n refreshArtboards();\n }\n }}\n />\n </div>\n ) : null;\n\n // ── Embedded content ───────────────────────────────────────────────────\n const embeddedContent =\n mode === 'embedded' ? (\n <EmbeddedToolbarLayout\n toolbarContent={toolbarContent}\n innerContentRef={innerContentRef}\n shouldRender={shouldRender}\n isExiting={isExiting}\n transitionHeight={transitionHeight}\n emptyStateContent={artboardEditContent || emptyStateContent}\n isAlignPanelOpen={isAlignPanelOpen}\n isCornerRadiusPanelOpen={isCornerRadiusPanelOpen}\n isCropPanelOpen={isCropPanelOpen}\n isRotationPanelOpen={isRotationPanelOpen}\n isOpacityPanelOpen={isOpacityPanelOpen}\n isAdjustPanelOpen={isAdjustPanelOpen}\n isFontSizePanelOpen={isFontSizePanelOpen}\n isShapeCornerRadiusPanelOpen={isShapeCornerRadiusPanelOpen}\n isShapeTransparencyPanelOpen={isShapeTransparencyPanelOpen}\n isShapeSidesPanelOpen={isShapeSidesPanelOpen}\n isShapePointsPanelOpen={isShapePointsPanelOpen}\n isShapeInnerRadiusPanelOpen={isShapeInnerRadiusPanelOpen}\n isShapeColorPanelOpen={isShapeColorPanelOpen}\n isTextColorPanelOpen={isTextColorPanelOpen}\n isStrokePanelOpen={isStrokePanelOpen}\n isShadowPanelOpen={isShadowPanelOpen}\n isBlendModePanelOpen={isBlendModePanelOpen}\n isKnockoutPanelOpen={isKnockoutPanelOpen}\n isDistressTexturePanelOpen={isDistressTexturePanelOpen}\n isImageMaskPanelOpen={isImageMaskPanelOpen}\n cornerRadiusPanel={cornerRadiusPanel}\n cropPanelContent={cropPanelContent}\n rotationPanel={rotationPanel}\n opacityPanel={opacityPanel}\n adjustPanel={adjustPanel}\n fontSizePanel={fontSizePanel}\n shapeCornerRadiusPanel={shapeCornerRadiusPanel}\n shapeTransparencyPanel={shapeTransparencyPanel}\n shapeSidesPanel={shapeSidesPanel}\n shapePointsPanel={shapePointsPanel}\n shapeInnerRadiusPanel={shapeInnerRadiusPanel}\n shapeColorPanel={shapeColorPanel}\n textColorPanel={textColorPanel}\n strokePanel={strokePanel}\n shadowPanel={shadowPanel}\n blendModePanel={blendModePanel}\n knockoutPanel={knockoutPanel}\n distressTexturePanel={distressTexturePanel}\n alignPanel={alignPanel}\n imageMaskPanel={imageMaskPanel}\n />\n ) : null;\n\n // ── Floating mode secondary panels ─────────────────────────────────────\n const panelWidth = toolbarDimensions.width > 0 ? Math.max(toolbarDimensions.width, 200) : 280;\n\n const floatingCornerRadiusPanel =\n mode === 'floating' && isCornerRadiusPanelOpen && elementForProperties?.transformType === 'image' && toolbarPosition ? (\n <FloatingCornerRadiusPanel\n toolbarPosition={toolbarPosition}\n toolbarHeight={toolbarDimensions.height || 56}\n panelWidth={panelWidth}\n value={currentBorderRadius}\n onChange={handleBorderRadiusChange}\n />\n ) : null;\n\n const floatingCropPanel =\n mode === 'floating' && isCropPanelOpen && elementForProperties?.transformType === 'image' && toolbarPosition ? (\n <FloatingCropPanel\n toolbarPosition={toolbarPosition}\n toolbarHeight={toolbarDimensions.height || 56}\n element={elementForProperties as ImageElement}\n onElementUpdate={elementUpdateHandler}\n />\n ) : null;\n\n const floatingAlignPanel =\n mode === 'floating' && isAlignPanelOpen && elementForProperties && toolbarPosition ? (\n <FloatingAlignPanel\n toolbarPosition={toolbarPosition}\n toolbarHeight={toolbarDimensions.height || 56}\n onAlign={alignSelection}\n />\n ) : null;\n\n // ══════════════════════════════════════════════════════════════════════════\n // FINAL RENDER\n // ══════════════════════════════════════════════════════════════════════════\n\n return (\n <>\n {/* Contextual toolbar - use portal for floating mode to escape parent overflow:hidden */}\n {mode === 'floating' && typeof document !== 'undefined'\n ? createPortal(\n <>\n {toolbarContent}\n {floatingCornerRadiusPanel}\n {floatingCropPanel}\n {floatingAlignPanel}\n </>,\n document.body\n )\n : embeddedContent}\n\n {/* Artboard Properties Toolbar - Show when no element is selected (floating mode only) */}\n {mode !== 'embedded' && !selectedElement && artboardManager.getActiveArtboard() && onArtboardUpdate && (\n <ArtboardPropertiesToolbar\n artboard={artboardManager.getActiveArtboard()!}\n artboards={artboards}\n onArtboardUpdate={(updatedArtboard) => {\n const currentArtboard = artboardManager.getActiveArtboard()!;\n onArtboardUpdate(\n currentArtboard.id,\n {\n backgroundColor: currentArtboard.backgroundColor,\n backgroundType: currentArtboard.backgroundType,\n backgroundTexture: currentArtboard.backgroundTexture,\n exportBackground: currentArtboard.exportBackground,\n },\n {\n backgroundColor: updatedArtboard.backgroundColor,\n backgroundType: updatedArtboard.backgroundType,\n backgroundTexture: updatedArtboard.backgroundTexture,\n exportBackground: updatedArtboard.exportBackground,\n }\n );\n }}\n onRenameArtboard={(artboardId: string, newName: string) => {\n artboardManager.renameArtboard(artboardId, newName);\n refreshArtboards();\n }}\n onDeleteArtboard={(artboardId: string) => {\n artboardManager.deleteArtboard(artboardId);\n refreshArtboards();\n }}\n artboardScreenBounds={artboardScreenBounds}\n />\n )}\n\n {/* Shape Type Drawer - internal drawer when no external callback is provided */}\n {!onOpenShapeTypeDrawer && elementForProperties?.transformType === 'shape' && (\n <ShapeTypeDrawer\n isOpen={isShapeTypeDrawerOpen}\n onClose={() => setIsShapeTypeDrawerOpen(false)}\n onSelectType={handleShapeTypeChange}\n currentType={(elementForProperties as ShapeElement).transformData.shapeType}\n />\n )}\n </>\n );\n};\n\nexport default ContextualToolbars;\n"],"names":["Checkbox","React","className","checked","variant","props","ref","surface","useSurface","effectiveVariant","jsx","CheckboxPrimitive","cn","Icon","CollapsibleRoot","CollapsiblePrimitive","CollapsibleTrigger","CollapsibleContent","Disclosure","DisclosureTrigger","DisclosureContent","PopoverRoot","PopoverPrimitive","PopoverTrigger","PopoverAnchor","PopoverContent","align","sideOffset","preserveSelection","maxZIndex","children","style","SurfaceContext","PopoverBase","open","onOpenChange","Popover","Select","SelectPrimitive","SelectValue","SelectTrigger","jsxs","SelectScrollUpButton","SelectScrollDownButton","SelectContent","position","SelectLabel","SelectItem","SelectSeparator","Separator","orientation","decorative","SeparatorPrimitive","SliderContext","SliderTrack","SliderPrimitive","SliderThumb","SliderFill","SliderOutput","context","values","SliderBase","value","onValueChange","onChangeEnd","min","max","step","normalizedValue","internalValue","setInternalValue","isDraggingRef","touchMoveHandlerRef","preventScroll","e","handleChange","newValue","handleChangeEnd","handlePointerDown","handlePointerUp","hasChildren","thumbCount","_a","contextValue","Fragment","_","index","Slider","Switch","SwitchPrimitive","CollapsedToolbarHeader","icon","label","onClose","closeButtonStyle","containerRef","useRef","touchStartPos","useEffect","el","handleTouchStart","handleTouchMove","deltaX","deltaY","icons","TouchGuard","SliderRow","onChange","unit","showInput","inputWidth","displayValue","val","SELECTED_CLASSES","UNSELECTED_CLASSES","PresetCarousel","presets","selectedId","onSelect","showOff","size","ariaLabel","scrollToItem","useCallback","button","handleKeyDown","container","buttons","focused","currentIndex","btn","nextIndex","nextButton","presetId","isOffSelected","hasSelection","p","preset","isSelected","isTabbable","u","r","t","c","o","a","i","n","s","f","v","d","h","g","l","m","b","E","C","x","H","M","w","L","D","I","y","q","B","S","T","F","X","Y","U","V","G","J","Q","W","Z","ColorPickerDropdown","memo","documentColors","imageColors","showSquare","allowTransparent","controlledIsOpen","controlledOnOpenChange","embedded","internalIsOpen","setInternalIsOpen","useState","hexInput","setHexInput","localColor","setLocalColor","lastUpdateTimeRef","pendingUpdateRef","onChangeRef","isOpen","setIsOpen","handleColorChange","color","now","timeSinceLastUpdate","localColorRef","handleHexInputChange","input","hexPattern","withHash","handlePresetClick","handleTransparentClick","isTransparent","buttonContent","pickerContent","Button","HexColorPicker","BackIcon","BackButton","onClick","TooltipProvider","Tooltip","TooltipTrigger","TooltipContent","EPSILON","getFeatureApplied","element","td","letterSpacing","lineHeight","_b","_c","isStandardBlendMode","isNeutralAdjustments","ImageToolbar","onElementUpdate","showUngroupButton","onUngroup","onMoveForward","onMoveBackward","onChangeImage","onRemoveBackground","removingBackground","removeBackgroundError","onDelete","cornerRadiusExpanded","onCornerRadiusToggle","cropExpanded","onCropToggle","adjustExpanded","onAdjustToggle","rotationExpanded","onRotationToggle","opacityExpanded","onOpacityToggle","strokeExpanded","onStrokeToggle","shadowExpanded","onShadowToggle","blendModeExpanded","onBlendModeToggle","knockoutExpanded","onKnockoutToggle","distressTextureExpanded","onDistressTextureToggle","imageMaskExpanded","onImageMaskToggle","moreMenuOpen","setMoreMenuOpen","changeImageTooltipDisabled","setChangeImageTooltipDisabled","removeBgTooltipDisabled","setRemoveBgTooltipDisabled","cornerRadiusTooltipDisabled","setCornerRadiusTooltipDisabled","cropTooltipDisabled","setCropTooltipDisabled","adjustTooltipDisabled","setAdjustTooltipDisabled","rotationTooltipDisabled","setRotationTooltipDisabled","opacityTooltipDisabled","setOpacityTooltipDisabled","strokeTooltipDisabled","setStrokeTooltipDisabled","shadowTooltipDisabled","setShadowTooltipDisabled","blendModeTooltipDisabled","setBlendModeTooltipDisabled","knockoutTooltipDisabled","setKnockoutTooltipDisabled","distressTooltipDisabled","setDistressTooltipDisabled","imageMaskTooltipDisabled","setImageMaskTooltipDisabled","isCropping","applied","handleCropToggle","updatedElement","handleFlipHorizontal","handleFlipVertical","ToolbarButton","RotateLeftIcon","ARTBOARD_COLORS","ShapeToolbar","onOpenShapeTypeDrawer","transparencyExpanded","onTransparencyToggle","sidesExpanded","onSidesToggle","pointsExpanded","onPointsToggle","innerRadiusExpanded","onInnerRadiusToggle","colorExpanded","onColorToggle","shapeTypeTooltipDisabled","setShapeTypeTooltipDisabled","transparencyTooltipDisabled","setTransparencyTooltipDisabled","sidesTooltipDisabled","setSidesTooltipDisabled","pointsTooltipDisabled","setPointsTooltipDisabled","innerRadiusTooltipDisabled","setInnerRadiusTooltipDisabled","colorTooltipDisabled","setColorTooltipDisabled","presetDocumentColors","useMemo","effectiveDocumentColors","handleFillColorChange","shapeTypeLabels","currentShapeType","currentLabel","shapeFillToCss","PathToolbar","strokeColorOpen","setStrokeColorOpen","fillColorOpen","setFillColorOpen","strokeWidthOpen","setStrokeWidthOpen","handleStrokeColorChange","handleStrokeEnabledToggle","handleFillEnabledToggle","handleStrokeWidthChange","strokeColor","fillColor","strokeEnabled","fillEnabled","strokeWidth","isClosed","pointCount","Label","BackgroundPickerDropdown","backgroundType","backgroundColor","backgroundTexture","onBackgroundTypeChange","onColorChange","onTextureChange","activeTab","setActiveTab","handleTextureClick","textureId","handleTabChange","tab","defaultTexture","TextureManager","texture","ArtboardDistressPanel","distressTexture","ensureBuiltinTexturesReady","enabled","textureUrl","intensity","presetItems","DISTRESS_TEXTURE_PRESETS","handleEnabledChange","newEnabled","url","preloadTexture","handleTextureSelect","id","handleIntensityChange","ArtboardImageMaskPanel","imageMask","ensureMaskPresetsReady","imageUrl","maskType","opacity","inverted","MASK_IMAGE_PRESETS","handleImageSelect","handleMaskTypeChange","type","handleOpacityChange","handleInvertedChange","ArtboardPropertiesToolbar","artboard","artboards","onArtboardUpdate","onRenameArtboard","onDeleteArtboard","artboardScreenBounds","isEditing","setIsEditing","editingName","setEditingName","inputRef","handleBackgroundTypeChange","updatedArtboard","handleTextureChange","handleExportBackgroundToggle","handleDistressTextureChange","handleImageMaskChange","handleStartEdit","handleSaveEdit","handleCancelEdit","handleDelete","Surface","stripGlyphs","text","char","cp","logger","createLogger","FontBrowserDrawer","_fontFamilies","onToggle","previewText","elements","selectedFontRef","searchQuery","setSearchQuery","selectedCategory","setSelectedCategory","fontsLoadedTrigger","setFontsLoadedTrigger","displayMode","setDisplayMode","cardSize","setCardSize","viewMode","setViewMode","loadedFonts","setLoadedFonts","loadQueueRef","loadingRef","onFontUpload","useCanvasServices","customFonts","useSyncExternalStore","customFontRegistry","fontFileInputRef","fontUploadBusy","setFontUploadBusy","fontUploadError","setFontUploadError","customFamilies","seen","families","font","key","customFamilyKeys","ensureCustomFontsLoaded","error","handleFontFileChange","file","uploaded","loadCustomFont","registerCustomFonts","isEditorError","handleSelectCustom","family","cardSizeScale","styleId","UnifiedFontService","prev","loadFont","forSelection","textToLoad","fontsToLoad","allFonts","fontName","queueFontLoad","alreadyLoaded","alreadyQueued","handleSelect","selectedFont","FontItem","isUsedInDocument","fontItemRef","isLoaded","observer","entries","entry","mainText","showSecondaryLabel","shouldShowTooltip","surfaceContent","prevProps","nextProps","fontsUsedInDocument","usedFonts","addFontIfValid","fontFamily","child","fontSections","TSHIRT_FONTS","recommendedNames","query","remainingFonts","recommendedFonts","otherFonts","renderFontSection","fonts","categories","Drawer","TextField","Input","Tabs","category","CATEGORY_LABELS","TransformControlPanel","controls","onUpdate","draggingValues","setDraggingValues","control","storedValue","newElement","safeStoredValue","currentInternalValue","sliderValue","formatValue","newSliderValue","newInternalValue","updated","TextEffectsDropdown","onTransformTypeChange","currentTransformType","getTransformControls","textTransformTypes","TRANSFORM_TYPES","handleTransformChange","newType","transform","MoreMenu","items","showMenu","setShowMenu","item","FontColorButton","colorPickerValue","isActive","BoldButton","toolbar","ItalicButton","UnderlineButton","UppercaseButton","TextAlignButton","textAlign","handleTextAlignToggle","TextMoreMenu","handleOpenChange","TextToolbar","stableElementId","viewportWidth","isColorActive","onOpenGlyphBrowser","hasGlyphs","expandedPanel","onFontSizeToggle","getMoreMenuItems","elementForProperties","isTransformMenuOpen","onTransformMenuOpenChange","elementUpdateHandler","isFontBrowserOpen","onFontBrowserToggle","onTextMoreMenuOpenChange","glyphTooltipDisabled","setGlyphTooltipDisabled","fontSizeTooltipDisabled","setFontSizeTooltipDisabled","FONT_FAMILIES","convertTransform","sourceElement","targetType","TargetClass","rotationAnchor","currentEffectiveFontSize","config","calculateTransformConfig","effectiveFontSize","transformData","fontSize","minWidth","estimatedTextWidth","targetWidth","targetHeight","archMinWidth","archEstimatedWidth","ARCH_DEFAULTS","waveMinWidth","waveEstimatedWidth","WAVE_DEFAULTS","flagMinWidth","flagEstimatedWidth","FLAG_DEFAULTS","leanMinWidth","leanEstimatedWidth","LEAN_DEFAULTS","useTextToolbar","options","canvasEditorRef","selectedElement","activeChildElement","handleElementUpdate","useEditor","GroupElement","updatedGroup","childIndex","currentElementId","prevElementIdRef","localFontSize","setLocalFontSize","localFontColor","setLocalFontColor","localFontFamily","setLocalFontFamily","localTextAlign","setLocalTextAlign","TextElement","fontColor","textElement","bold","italic","underline","letterCase","setFontSizeValue","newSize","updateFontFamily","newFamily","updateFontColor","newColor","updateTextAlign","alignment","handleFontSizeChange","handleFontSizeIncrement","delta","handleLetterSpacingChange","newSpacing","handleLineHeightChange","newLineHeight","handleFontFamilyChange","handleFontColorChange","handleBoldToggle","handleItalicToggle","handleUnderlineToggle","handleLetterCaseToggle","newCase","isLetterCaseActive","alignments","nextAlign","getEffectiveStyle","selectionStyle","_d","handleTransformTypeChange","transformDef","getTransformById","useLayerPreview","previewUrl","setPreviewUrl","isLoading","setIsLoading","debounceRef","mounted","ImageElement","img","resolve","reject","generateElementPreview","ShapeElement","PathElement","_e","LayerLeadingChip","onToggleLock","onThumbnailClick","locked","SelectionThumbnail","LockIcon","inner","DISTRIBUTE_MIN_COUNT","ALIGN_SELECTION_MIN_COUNT","combinedBounds","minX","minY","maxX","maxY","computeAlign","mode","frame","updates","dx","dy","computeDistribute","EditorError","horizontal","sorted","first","last","span","totalSize","sum","gap","cursor","current","useAlignDistribute","multiSelection","artboardManager","executeCommandBatch","setElements","movableElements","applyUpdates","byId","commands","update","oldElement","replaceWith","distribute","ALIGN_BUTTONS","DISTRIBUTE_BUTTONS","MultiSelectionToolbar","partAttr","canvasRef","panOffset","useViewportContext","canAlign","canDistribute","toolbarRef","setPosition","selectionBounds","updatePosition","toolbarWidth","toolbarHeight","activeArtboard","artboardX","artboardY","currentZoom","canvas","screenX","screenY","canvasRect","screenWidth","screenHeight","top","left","minLeft","maxLeft","content","alignMode","distMode","createPortal","GroupElementToolbar","CropPanel","cropAnchor","setCropAnchor","currentCropWidth","currentCropHeight","handleCropChange","cropX","cropY","cropWidth","cropHeight","handleCropWidthChange","anchor","oldWidth","oldX","widthDiff","newX","handleCropHeightChange","oldHeight","oldY","heightDiff","newY","anchorPositions","pos","PANEL_BODY_CLASSES","COLOR_PANEL_BODY_CLASSES","CornerRadiusPanel","AlignPanel","onAlign","RotationPanel","onRotate90","FontSizePanel","widthValue","onWidthChange","letterSpacingValue","onLetterSpacingChange","lineHeightValue","onLineHeightChange","OpacityPanel","AdjustPanel","adjustments","onReset","NEUTRAL_ADJUSTMENTS","isNeutral","channelRow","channel","ShapeCornerRadiusPanel","ShapeTransparencyPanel","ShapeSidesPanel","ShapePointsPanel","ShapeInnerRadiusPanel","FILL_MODE_LABELS","ShapeColorPanel","fill","onFillChange","gradient","activeStop","setActiveStop","handleModeChange","next","stops","handleStopColorChange","handleAngleChange","angle","activeColor","stop","TextColorPanel","CompositingPanel","stroke","scope","onModeChange","onStrokeChange","onScopeChange","DistressTexturePanel","onOpacityChange","ImageMaskPanel","onImageChange","onMaskTypeChange","onInvertedChange","StrokePanel","showAdvanced","setShowAdvanced","width","lineCap","lineJoin","patch","cap","join","SHADOW_DEFAULTS","ShadowPanel","shadow","blur","offsetX","offsetY","BLEND_MODE_OPTIONS","STANDARD_BLEND_MODES","BlendModePanel","blendMode","CropPanelContent","ExpandedPanelIcon","panelType","defaultIcon","textColorValue","shapeFillColor","SecondaryPanelWrapper","ColorPanelWrapper","EmbeddedToolbarLayout","toolbarContent","innerContentRef","shouldRender","isExiting","transitionHeight","emptyStateContent","isAlignPanelOpen","isCornerRadiusPanelOpen","isCropPanelOpen","isRotationPanelOpen","isOpacityPanelOpen","isAdjustPanelOpen","isFontSizePanelOpen","isShapeCornerRadiusPanelOpen","isShapeTransparencyPanelOpen","isShapeSidesPanelOpen","isShapePointsPanelOpen","isShapeInnerRadiusPanelOpen","isShapeColorPanelOpen","isTextColorPanelOpen","isStrokePanelOpen","isShadowPanelOpen","isBlendModePanelOpen","isKnockoutPanelOpen","isDistressTexturePanelOpen","isImageMaskPanelOpen","alignPanel","cornerRadiusPanel","cropPanelContent","rotationPanel","opacityPanel","adjustPanel","fontSizePanel","shapeCornerRadiusPanel","shapeTransparencyPanel","shapeSidesPanel","shapePointsPanel","shapeInnerRadiusPanel","shapeColorPanel","textColorPanel","strokePanel","shadowPanel","blendModePanel","knockoutPanel","distressTexturePanel","imageMaskPanel","FloatingCornerRadiusPanel","toolbarPosition","panelWidth","FloatingAlignPanel","FloatingCropPanel","isPaintable","collectFromElement","out","richText","richFill","collectDocumentColors","ab","bg","IMAGE_PALETTE_CACHE","IMAGE_PALETTE_INFLIGHT","computeRanges","pixels","rMin","rMax","gMin","gMax","bMin","bMax","boxLongestAxis","box","boxSize","splitBox","axis","mid","leftPixels","rightPixels","averageColor","medianCutBoxes","targetBuckets","boxes","bestIdx","bestSize","target","redmeanDistance","rMean","dr","dg","db","furthestPointPalette","candidates","paletteSize","threshold","picked","used","bestMinDist","minDist","toHex","rgbToHex","extractImagePalette","cached","inflight","promise","loadCorsImage","SAMPLE","ctx","data","overExtract","collectImageColors","urls","visit","palettes","dedupe","palette","REMOVE_BG_UNAVAILABLE","safeErrorMessage","err","fallback","message","ContextualToolbars","services","ContextualToolbarsInner","CanvasServicesProvider","_breakpoints","maxWidth","transparent","onPanelExpandChange","defaultExpandedPanel","onExpandedPanelTypeChange","onOpenCropDrawer","onOpenCornerRadiusDrawer","emptyStateMessage","emptyStateRender","editArtboardMode","onEditArtboardModeChange","onLayerThumbnailClick","setSelectedId","useSelectionContext","contextExpandedPanelType","setContextExpandedPanelType","setIsToolbarMenuOpen","isRotating","useToolStateContext","executeElementUpdate","executeRemoveElement","executeAddElement","executeReorderElement","refreshArtboards","removeBackground","textToolbar","activeMenu","setActiveMenu","openDropdown","setOpenDropdown","setToolbarPosition","_isDragging","setIsDragging","setIsTransformMenuOpen","isColorPickerOpen","isTextMoreMenuOpen","setIsTextMoreMenuOpen","isShapeTypeDrawerOpen","setIsShapeTypeDrawerOpen","setExpandedPanel","isEntering","setIsEntering","setIsExiting","setShouldRender","isWaitingForPosition","setIsWaitingForPosition","positionedElementId","setPositionedElementId","setTransitionHeight","toolbarDimensions","setToolbarDimensions","lastKnownHeightRef","prevShouldShowRef","isMouseDownRef","frozenPositionRef","lastElementRotationRef","lastSyncedToContextRef","prevContextExpandedPanelTypeRef","prevSelectedIdRef","prevElementTypeRef","prevIsRotatingRef","isRotatingRef","isDrawerModeAtMount","isFullyMountedRef","expandedPanelRef","elementForPropertiesRef","elementUpdateHandlerRef","prevStableSelectedIdRef","prevIsCroppingRef","stableSelectedId","currentElementType","shouldShowToolbar","handleBorderRadiusChange","setRemovingBackground","setRemoveBackgroundError","elementsRef","isMountedForServicesRef","applyRemovedBackgroundUrl","elementId","processedUrl","swapImageUrl","oldImage","loadedElement","prevElements","currentElements","topLevel","handleRemoveBackground","handleShapeBorderRadiusChange","handleShapeOpacityChange","handleShapeSidesChange","handleShapePointsChange","handleShapeInnerRadiusChange","handleShapeFillColorChange","handleShapeFillChange","alignSelection","handleAlignToggle","handleCornerRadiusToggle","handleRotationToggle","handleOpacityToggle","handleAdjustToggle","handleFontSizeToggle","handleTextWidthChange","currentTextWidth","isCustomText","currentLetterSpacing","currentLineHeight","handleShapeCornerRadiusToggle","handleShapeTransparencyToggle","handleShapeSidesToggle","handleShapePointsToggle","handleShapeInnerRadiusToggle","handleShapeColorToggle","handleTextColorToggle","handleCompositingToggle","handleDistressTextureToggle","handleImageMaskToggle","handleStrokeToggle","handleShadowToggle","handleBlendModeToggle","handleCloseExpandedPanel","imageElement","handleMoveForward","idx","targetElement","handleMoveBackward","handleDeleteElement","elementToDelete","handleToggleLock","handleUngroupElement","group","artboardId","extractedChildren","clone","handleRotationChange","handleRotate90","newRotation","updateElementCommand","useCommands","adjustRunActiveRef","handleAdjustmentsChange","normalized","normalizeAdjustments","handleAdjustmentsCommit","handleAdjustmentsReset","handleCompositingModeChange","handleCompositingFillChange","currentMode","newParts","handleCompositingStrokeChange","handleCompositingScopeChange","handleDistressOpacityChange","pct","handleImageMaskImageChange","makeMaskElement","existing","masks","handleImageMaskTypeChange","mask","handleImageMaskOpacityChange","handleImageMaskInvertedChange","inv","handleStrokeChange","handleShadowChange","handleBlendModeChange","handleShapeTypeChange","newShapeType","handleOpenShapeTypeDrawer","localType","prevType","currentType","currentIsCropping","timeoutId","mouseDownPos","isDraggingStarted","DRAG_THRESHOLD","handleMouseDown","handleMouseMove","handleMouseUp","newWidth","newHeight","currentRotation","updateToolbarPosition","elementToPosition","elementBounds","elementScreenX","elementScreenY","elementScreenWidth","elementScreenHeight","viewportCenterX","viewportCenterY","elementTop","elementCenterX","maxTop","colorPickerOnChange","autoDocumentColors","mergedDocumentColors","documentColorsKey","colorPickerDocumentColors","imageUrlsKey","walk","colorPickerImageColors","setColorPickerImageColors","cancelled","colors","toolbarDivRef","node","height","wasRotating","isNowRotating","prevShouldShow","prevSelectedId","enterTimer","currentHeight","exitTimer","useLayoutEffect","startHeight","toolbarStyle","maxWidthValue","regularToolbarContent","shapeElement","currentBorderRadius","currentOpacity","currentShapeBorderRadius","currentShapeOpacity","_f","currentShapeSides","_g","currentShapePoints","_h","currentShapeInnerRadius","_i","currentShapeFillColor","_j","currentShapeFill","_k","compositingFill","_l","compositingStroke","_m","compositingScope","_n","compositingMode","currentAdjustments","_o","_p","_q","quickMask","_r","_s","artboardEditContent","currentArtboard","embeddedContent","floatingCornerRadiusPanel","floatingCropPanel","floatingAlignPanel","newName","ShapeTypeDrawer"],"mappings":"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","x_google_ignoreList":[10]}
|