@karni/ui 0.0.0-stage → 0.3.1
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/LICENSE +201 -0
- package/README.md +288 -2
- package/dist/index.cjs +9 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.js +4764 -0
- package/dist/index.js.map +1 -0
- package/dist/manifest.json +85 -0
- package/dist/mockServiceWorker.js +361 -0
- package/dist/src/auth/AuthGuard.d.ts +12 -0
- package/dist/src/auth/LoginForm.d.ts +29 -0
- package/dist/src/auth/engine.d.ts +99 -0
- package/dist/src/auth/provider.d.ts +43 -0
- package/dist/src/auth/storage.d.ts +26 -0
- package/dist/src/auth/types.d.ts +32 -0
- package/dist/src/auth/usePermission.d.ts +7 -0
- package/dist/src/components/brand/karni-mark.d.ts +21 -0
- package/dist/src/components/brand/mark-paths.d.ts +8 -0
- package/dist/src/components/chart/data-chart.d.ts +74 -0
- package/dist/src/components/empty-state/empty-state.d.ts +20 -0
- package/dist/src/components/file-upload/FileUpload.d.ts +44 -0
- package/dist/src/components/layout/layout.d.ts +55 -0
- package/dist/src/components/modal/modal.d.ts +45 -0
- package/dist/src/components/page/page.d.ts +29 -0
- package/dist/src/components/primitives/button.d.ts +44 -0
- package/dist/src/components/primitives/checkbox.d.ts +5 -0
- package/dist/src/components/primitives/dropdown-menu.d.ts +24 -0
- package/dist/src/components/primitives/icons.d.ts +11 -0
- package/dist/src/components/primitives/input.d.ts +4 -0
- package/dist/src/components/primitives/label.d.ts +5 -0
- package/dist/src/components/primitives/select.d.ts +63 -0
- package/dist/src/components/primitives/skeleton.d.ts +4 -0
- package/dist/src/components/primitives/switch.d.ts +5 -0
- package/dist/src/components/primitives/tabs.d.ts +10 -0
- package/dist/src/components/primitives/textarea.d.ts +4 -0
- package/dist/src/components/resource/ResourceDetail.d.ts +7 -0
- package/dist/src/components/resource/ResourceForm.d.ts +7 -0
- package/dist/src/components/resource/ResourceSelect.d.ts +7 -0
- package/dist/src/components/resource/ResourceTable.d.ts +11 -0
- package/dist/src/components/resource/audit-fields.d.ts +17 -0
- package/dist/src/components/resource/detail/ResourceDetail.d.ts +30 -0
- package/dist/src/components/resource/displayLabel.d.ts +12 -0
- package/dist/src/components/resource/form/ResourceForm.d.ts +50 -0
- package/dist/src/components/resource/form/field-inputs.d.ts +20 -0
- package/dist/src/components/resource/form/fixtures.d.ts +24 -0
- package/dist/src/components/resource/form/prepare.d.ts +54 -0
- package/dist/src/components/resource/history/ChangeHistory.d.ts +18 -0
- package/dist/src/components/resource/import/ResourceImport.d.ts +18 -0
- package/dist/src/components/resource/select/ResourceSelect.d.ts +36 -0
- package/dist/src/components/resource/select/use-debounced-value.d.ts +2 -0
- package/dist/src/components/resource/table/BulkActionsBar.d.ts +20 -0
- package/dist/src/components/resource/table/ExportButtons.d.ts +17 -0
- package/dist/src/components/resource/table/FilterBar.d.ts +29 -0
- package/dist/src/components/resource/table/PaginationControls.d.ts +19 -0
- package/dist/src/components/resource/table/ResourceTable.d.ts +72 -0
- package/dist/src/components/resource/table/demo-fixtures.d.ts +25 -0
- package/dist/src/components/resource/table/derive-columns.d.ts +33 -0
- package/dist/src/components/resource/table/table-utils.d.ts +24 -0
- package/dist/src/components/resource/table/use-debounced-value.d.ts +1 -0
- package/dist/src/components/stat/stat.d.ts +24 -0
- package/dist/src/components/toast/toast-store.d.ts +36 -0
- package/dist/src/components/toast/toaster.d.ts +33 -0
- package/dist/src/components/toast/use-toast.d.ts +24 -0
- package/dist/src/hooks/keys.d.ts +24 -0
- package/dist/src/hooks/multipart.d.ts +44 -0
- package/dist/src/hooks/params.d.ts +25 -0
- package/dist/src/hooks/types.d.ts +41 -0
- package/dist/src/hooks/useChangeHistory.d.ts +29 -0
- package/dist/src/hooks/useResourceImport.d.ts +107 -0
- package/dist/src/hooks/useResourceItem.d.ts +4 -0
- package/dist/src/hooks/useResourceList.d.ts +4 -0
- package/dist/src/hooks/useResourceMutations.d.ts +13 -0
- package/dist/src/index.d.ts +95 -0
- package/dist/src/lib/cn.d.ts +8 -0
- package/dist/src/lib/roles.d.ts +45 -0
- package/dist/src/lib/variants.d.ts +33 -0
- package/dist/src/schema/client.d.ts +90 -0
- package/dist/src/schema/parse.d.ts +101 -0
- package/dist/src/schema/provider.d.ts +13 -0
- package/dist/src/schema/types.d.ts +84 -0
- package/dist/src/schema/useSchema.d.ts +17 -0
- package/dist/src/schema/zod.d.ts +4 -0
- package/dist/styles.css +87 -0
- package/dist/tailwind-preset.cjs +2 -0
- package/dist/tailwind-preset.cjs.map +1 -0
- package/dist/tailwind-preset.d.ts +58 -0
- package/dist/tailwind-preset.js +64 -0
- package/dist/tailwind-preset.js.map +1 -0
- package/eslint-plugin/index.js +72 -0
- package/eslint-plugin/lib/docs.js +11 -0
- package/eslint-plugin/lib/glob.js +51 -0
- package/eslint-plugin/rules/max-page-lines.js +65 -0
- package/eslint-plugin/rules/no-deep-imports.js +61 -0
- package/eslint-plugin/rules/no-direct-http.js +128 -0
- package/eslint-plugin/rules/no-raw-elements.js +65 -0
- package/eslint-plugin/rules.json +26 -0
- package/package.json +153 -4
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../src/lib/cn.ts","../src/lib/roles.ts","../src/lib/variants.ts","../src/components/primitives/button.tsx","../src/components/primitives/input.tsx","../src/components/primitives/textarea.tsx","../src/components/primitives/icons.tsx","../src/components/primitives/select.tsx","../src/components/primitives/checkbox.tsx","../src/components/primitives/switch.tsx","../src/components/primitives/label.tsx","../src/components/primitives/tabs.tsx","../src/components/primitives/dropdown-menu.tsx","../src/components/primitives/skeleton.tsx","../src/hooks/params.ts","../src/hooks/keys.ts","../src/schema/provider.tsx","../src/hooks/useResourceList.ts","../src/hooks/multipart.ts","../src/hooks/useResourceMutations.ts","../src/schema/parse.ts","../src/schema/useSchema.ts","../src/components/empty-state/empty-state.tsx","../src/components/resource/audit-fields.ts","../src/components/resource/displayLabel.ts","../src/components/resource/table/BulkActionsBar.tsx","../src/components/resource/table/table-utils.ts","../src/components/resource/table/derive-columns.tsx","../src/hooks/useResourceImport.ts","../src/components/resource/table/ExportButtons.tsx","../src/hooks/useResourceItem.ts","../src/components/resource/select/use-debounced-value.ts","../src/components/resource/select/ResourceSelect.tsx","../src/components/resource/table/FilterBar.tsx","../src/components/resource/table/PaginationControls.tsx","../src/components/resource/table/use-debounced-value.ts","../src/components/resource/table/ResourceTable.tsx","../src/schema/zod.ts","../src/components/file-upload/FileUpload.tsx","../src/components/resource/form/prepare.ts","../src/components/resource/form/field-inputs.tsx","../src/components/resource/form/ResourceForm.tsx","../src/components/resource/detail/ResourceDetail.tsx","../src/hooks/useChangeHistory.ts","../src/components/resource/history/ChangeHistory.tsx","../src/components/resource/import/ResourceImport.tsx","../src/schema/client.ts","../src/auth/engine.ts","../src/auth/storage.ts","../src/auth/provider.tsx","../src/auth/AuthGuard.tsx","../src/auth/LoginForm.tsx","../src/auth/usePermission.ts","../src/components/page/page.tsx","../src/components/brand/mark-paths.ts","../src/components/brand/karni-mark.tsx","../src/components/layout/layout.tsx","../src/components/modal/modal.tsx","../src/components/toast/toast-store.ts","../src/components/toast/use-toast.ts","../src/components/toast/toaster.tsx","../src/components/stat/stat.tsx","../src/components/chart/data-chart.tsx"],"sourcesContent":["import { clsx, type ClassValue } from \"clsx\";\nimport { twMerge } from \"tailwind-merge\";\n\n/**\n * Merges class names: clsx semantics for conditionals plus tailwind-merge\n * conflict resolution, so consumer-supplied `className` always wins over a\n * component's own Tailwind classes. Every @karni/ui component funnels its\n * `className` prop through this.\n */\nexport function cn(...inputs: ClassValue[]): string {\n return twMerge(clsx(inputs));\n}\n","/**\n * Component role registry (enforcement contract §4 + F11).\n *\n * Every top-level component claims a semantic role (\"data-table\",\n * \"resource-form\", …) at module scope. Two components claiming the same role\n * is a conflict: it throws at import time (so vitest and the dev server both\n * surface it) and `scripts/generate-manifest.mjs` fails the build on the same\n * duplicate via a static scan of these call sites.\n *\n * Conventions:\n * - The `role` argument MUST be a string literal — the build-time scan rejects\n * any non-literal first argument.\n * - Same role + same component name is idempotent (modules re-evaluate under\n * HMR and across test files).\n * - Replacing on purpose is explicit and must carry a reason:\n * `{ replace: true, reason: \"<why>\" }` — an empty reason throws.\n * - Under Vite HMR (`import.meta.hot`) an accidental conflict logs a\n * console.error and replaces instead of throwing, so a rename mid-edit does\n * not kill the dev server.\n * - The registry reflects imported modules only (accepted v0.1 trade-off).\n */\n\nexport interface RegisterComponentRoleOptions {\n /** Replace an existing registration on purpose. Requires `reason`. */\n replace?: boolean;\n /** Why the replacement is intentional — required with `replace: true`. */\n reason?: string;\n}\n\nconst registry = new Map<string, string>();\n\n/**\n * `import.meta.hot` is defined by Vite's dev server and undefined in prod\n * builds. Vitest also ships an import.meta.hot stub, but tests must throw on\n * conflicts (F11), so the test environment is explicitly excluded.\n */\nfunction defaultHotDetector(): boolean {\n try {\n const meta = import.meta as ImportMeta & { hot?: unknown; env?: { MODE?: string } };\n if (!meta.hot) return false;\n if (meta.env?.MODE === \"test\") return false;\n if (typeof process !== \"undefined\" && process.env?.VITEST !== undefined) return false;\n return true;\n } catch {\n return false;\n }\n}\n\nlet detectHot: () => boolean = defaultHotDetector;\n\n/**\n * Test-only override for HMR detection; pass `null` to restore the default.\n * Not exported from the package barrel.\n * @internal\n */\nexport function __setHotDetectorForTests(detector: (() => boolean) | null): void {\n detectHot = detector ?? defaultHotDetector;\n}\n\n/**\n * Test-only registry reset. Not exported from the package barrel.\n * @internal\n */\nexport function __resetRoleRegistryForTests(): void {\n registry.clear();\n}\n\n/**\n * Claims a UI role (such as `data-table`) for a component, so a second component with the same role fails the build. The first argument must be a string literal\n * (build-scan convention, F11).\n */\nexport function registerComponentRole(\n role: string,\n component: string,\n options?: RegisterComponentRoleOptions,\n): void {\n if (options?.replace) {\n const reason = options.reason?.trim() ?? \"\";\n if (reason === \"\") {\n throw new Error(\n `[karni] registerComponentRole: replacing role \"${role}\" requires a non-empty reason — ` +\n `pass { replace: true, reason: \"<why>\" }.`,\n );\n }\n const previous = registry.get(role);\n if (previous !== undefined && previous !== component) {\n console.warn(\n `[karni] component role \"${role}\" replaced: \"${previous}\" -> \"${component}\" (${reason})`,\n );\n }\n registry.set(role, component);\n return;\n }\n\n const existing = registry.get(role);\n if (existing === undefined || existing === component) {\n // Idempotent: first registration, or the same component re-registering.\n registry.set(role, component);\n return;\n }\n\n const message =\n `[karni] duplicate component role \"${role}\": already registered by \"${existing}\", now ` +\n `claimed by \"${component}\". Compose or extend the existing component instead, or replace ` +\n `it on purpose with { replace: true, reason: \"<why>\" }.`;\n\n if (detectHot()) {\n // Dev HMR: a module re-evaluating mid-rename must not kill the app.\n console.error(message);\n registry.set(role, component);\n return;\n }\n throw new Error(message);\n}\n\n/** Snapshot of the current registry ({ role: component }) for tooling. */\nexport function getRoleRegistry(): Readonly<Record<string, string>> {\n return Object.freeze(Object.fromEntries(registry));\n}\n","import { cn } from \"./cn\";\n\n/**\n * Hand-rolled cva-style variant utility (no extra dependency).\n *\n * Every class string appears whole in source (contract D7): a variant map\n * value is a complete Tailwind class list, selected — never concatenated —\n * at call time and merged through cn().\n */\n\n/** A map of variant group name → allowed value → whole Tailwind class string. */\nexport type VariantShape = Record<string, Record<string, string>>;\n\n/** The props accepted for a given variant shape (each group optional). */\nexport type VariantSelection<V extends VariantShape> = {\n [K in keyof V]?: Extract<keyof V[K], string> | null;\n};\n\nexport interface VariantsConfig<V extends VariantShape> {\n /** Classes always applied, before any variant classes. */\n base?: string;\n variants: V;\n defaultVariants?: VariantSelection<V>;\n /** Extra classes applied when every listed variant value is selected. */\n compoundVariants?: ReadonlyArray<VariantSelection<V> & { className: string }>;\n}\n\nexport type VariantFn<V extends VariantShape> = (\n props?: VariantSelection<V> & { className?: string },\n) => string;\n\n/**\n * Extracts the variant props of a variant function, for typing component\n * props: `type ButtonVariantProps = VariantProps<typeof buttonVariants>`.\n */\nexport type VariantProps<F> = F extends VariantFn<infer V> ? VariantSelection<V> : never;\n\n/** Builds a typed class-name function from variant definitions, the way every themed component declares its looks. */\nexport function variants<V extends VariantShape>(config: VariantsConfig<V>): VariantFn<V> {\n const groupNames = Object.keys(config.variants) as Array<Extract<keyof V, string>>;\n\n return (props) => {\n const { className, ...rest } = props ?? {};\n const selection = rest as VariantSelection<V>;\n const chosen: Partial<Record<Extract<keyof V, string>, string>> = {};\n const classes: string[] = [];\n\n if (config.base) {\n classes.push(config.base);\n }\n\n for (const group of groupNames) {\n const value = selection[group] ?? config.defaultVariants?.[group];\n if (value == null) {\n continue;\n }\n chosen[group] = value;\n const groupClasses = config.variants[group][value];\n if (groupClasses) {\n classes.push(groupClasses);\n }\n }\n\n for (const compound of config.compoundVariants ?? []) {\n const { className: compoundClassName, ...rest } = compound;\n // TS cannot relate Omit<VariantSelection<V> & {...}, \"className\"> back to\n // the per-group selection shape, so narrow through unknown once here.\n const conditions = rest as unknown as Partial<\n Record<Extract<keyof V, string>, string | null>\n >;\n const conditionKeys = Object.keys(conditions) as Array<Extract<keyof V, string>>;\n const matches = conditionKeys.every((key) => {\n const expected = conditions[key];\n return expected != null && chosen[key] === expected;\n });\n if (matches) {\n classes.push(compoundClassName);\n }\n }\n\n return cn(...classes, className);\n };\n}\n","import * as React from \"react\";\nimport { variants, type VariantProps } from \"../../lib/variants\";\n\n/**\n * Exported for composition (escape hatch): render any element as a button\n * lookalike with `className={buttonVariants({ variant: \"outline\" })}`.\n */\nexport const buttonVariants = variants({\n base: \"inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50\",\n variants: {\n variant: {\n default: \"bg-primary text-primary-foreground hover:bg-primary/90\",\n destructive: \"bg-destructive text-destructive-foreground hover:bg-destructive/90\",\n outline: \"border border-input bg-background hover:bg-accent hover:text-accent-foreground\",\n secondary: \"bg-secondary text-secondary-foreground hover:bg-secondary/80\",\n ghost: \"hover:bg-accent hover:text-accent-foreground\",\n link: \"text-primary underline-offset-4 hover:underline\",\n },\n size: {\n default: \"h-10 px-4 py-2\",\n sm: \"h-9 rounded-md px-3\",\n lg: \"h-11 rounded-md px-8\",\n icon: \"h-10 w-10\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n size: \"default\",\n },\n});\n\nexport type ButtonVariantProps = VariantProps<typeof buttonVariants>;\n\nexport type ButtonProps = React.ButtonHTMLAttributes<HTMLButtonElement> & ButtonVariantProps;\n\n/**\n * Themed button. `type` defaults to \"button\" (pass type=\"submit\" in forms).\n * `className` is merged via cn(), so consumer classes win.\n */\nexport const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(\n ({ className, variant, size, type, ...props }, ref) => (\n <button\n ref={ref}\n type={type ?? \"button\"}\n className={buttonVariants({ variant, size, className })}\n {...props}\n />\n ),\n);\nButton.displayName = \"Button\";\n","import * as React from \"react\";\nimport { cn } from \"../../lib/cn\";\n\nexport type InputProps = React.InputHTMLAttributes<HTMLInputElement>;\n\n/** Themed text input; every native `<input>` prop passes through. */\nexport const Input = React.forwardRef<HTMLInputElement, InputProps>(\n ({ className, ...props }, ref) => (\n <input\n ref={ref}\n className={cn(\n \"flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-foreground placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50\",\n className,\n )}\n {...props}\n />\n ),\n);\nInput.displayName = \"Input\";\n","import * as React from \"react\";\nimport { cn } from \"../../lib/cn\";\n\nexport type TextareaProps = React.TextareaHTMLAttributes<HTMLTextAreaElement>;\n\n/** Themed multi-line text input; every native `<textarea>` prop passes through. */\nexport const Textarea = React.forwardRef<HTMLTextAreaElement, TextareaProps>(\n ({ className, ...props }, ref) => (\n <textarea\n ref={ref}\n className={cn(\n \"flex min-h-[80px] w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50\",\n className,\n )}\n {...props}\n />\n ),\n);\nTextarea.displayName = \"Textarea\";\n","import * as React from \"react\";\n\n/**\n * Minimal inline SVG icons used by the primitives (no icon dependency).\n * All strokes use `currentColor`, so they follow the text color tokens.\n * Internal to @karni/ui — not part of the public barrel.\n */\n\ntype IconProps = React.SVGAttributes<SVGSVGElement>;\n\nfunction baseProps(props: IconProps): IconProps {\n return {\n viewBox: \"0 0 24 24\",\n fill: \"none\",\n stroke: \"currentColor\",\n strokeWidth: 2,\n strokeLinecap: \"round\",\n strokeLinejoin: \"round\",\n \"aria-hidden\": true,\n focusable: false,\n ...props,\n };\n}\n\nexport function CheckIcon(props: IconProps): React.ReactElement {\n return (\n <svg {...baseProps(props)}>\n <polyline points=\"20 6 9 17 4 12\" />\n </svg>\n );\n}\n\nexport function ChevronDownIcon(props: IconProps): React.ReactElement {\n return (\n <svg {...baseProps(props)}>\n <polyline points=\"6 9 12 15 18 9\" />\n </svg>\n );\n}\n\nexport function ChevronUpIcon(props: IconProps): React.ReactElement {\n return (\n <svg {...baseProps(props)}>\n <polyline points=\"18 15 12 9 6 15\" />\n </svg>\n );\n}\n","import * as SelectPrimitive from \"@radix-ui/react-select\";\nimport * as React from \"react\";\nimport { cn } from \"../../lib/cn\";\nimport { CheckIcon, ChevronDownIcon, ChevronUpIcon } from \"./icons\";\n\n/**\n * The value that stands for \"nothing selected\" inside Radix Select, which reserves the empty string.\n *\n * This package maps the empty state through this sentinel at the component boundary (contract D8). Consumers of\n * the composed <Select> never see it: `value`/`onValueChange` use `null`.\n */\nexport const KARNI_SELECT_EMPTY = \"__karni_empty__\";\n\n// ---------------------------------------------------------------------------\n// Low-level styled Radix parts (escape hatch for fully custom selects)\n// ---------------------------------------------------------------------------\n\n/** Radix Select root, for composing a custom select from the styled parts. */\nexport const SelectRoot = SelectPrimitive.Root;\n/** Groups related options inside `SelectContent`. */\nexport const SelectGroup = SelectPrimitive.Group;\n/** Shows the selected option's label inside `SelectTrigger`. */\nexport const SelectValue = SelectPrimitive.Value;\n\n/** The styled button that opens the select. */\nexport const SelectTrigger = React.forwardRef<\n React.ElementRef<typeof SelectPrimitive.Trigger>,\n React.ComponentPropsWithoutRef<typeof SelectPrimitive.Trigger>\n>(({ className, children, ...props }, ref) => (\n <SelectPrimitive.Trigger\n ref={ref}\n className={cn(\n \"flex h-10 w-full items-center justify-between rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 [&>span]:line-clamp-1\",\n className,\n )}\n {...props}\n >\n {children}\n <SelectPrimitive.Icon asChild>\n <ChevronDownIcon className=\"h-4 w-4 shrink-0 opacity-50\" />\n </SelectPrimitive.Icon>\n </SelectPrimitive.Trigger>\n));\nSelectTrigger.displayName = \"SelectTrigger\";\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(\"flex cursor-default items-center justify-center py-1\", className)}\n {...props}\n >\n <ChevronUpIcon className=\"h-4 w-4\" />\n </SelectPrimitive.ScrollUpButton>\n));\nSelectScrollUpButton.displayName = \"SelectScrollUpButton\";\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(\"flex cursor-default items-center justify-center py-1\", className)}\n {...props}\n >\n <ChevronDownIcon className=\"h-4 w-4\" />\n </SelectPrimitive.ScrollDownButton>\n));\nSelectScrollDownButton.displayName = \"SelectScrollDownButton\";\n\n/** The styled dropdown panel that lists the options. */\nexport const 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 position={position}\n className={cn(\n \"relative z-50 max-h-96 min-w-[8rem] overflow-hidden rounded-md border border-border bg-popover text-popover-foreground shadow-md\",\n position === \"popper\" &&\n \"data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1\",\n className,\n )}\n {...props}\n >\n <SelectScrollUpButton />\n <SelectPrimitive.Viewport\n className={cn(\n \"p-1\",\n position === \"popper\" &&\n \"h-[var(--radix-select-trigger-height)] w-full min-w-[var(--radix-select-trigger-width)]\",\n )}\n >\n {children}\n </SelectPrimitive.Viewport>\n <SelectScrollDownButton />\n </SelectPrimitive.Content>\n </SelectPrimitive.Portal>\n));\nSelectContent.displayName = \"SelectContent\";\n\n/** A heading inside a `SelectGroup`. */\nexport const 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(\"py-1.5 pl-8 pr-2 text-sm font-semibold\", className)}\n {...props}\n />\n));\nSelectLabel.displayName = \"SelectLabel\";\n\n/** One selectable option; `value` is what the select reports. */\nexport const 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 \"relative flex w-full cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50\",\n className,\n )}\n {...props}\n >\n <span className=\"absolute left-2 flex h-3.5 w-3.5 items-center justify-center\">\n <SelectPrimitive.ItemIndicator>\n <CheckIcon className=\"h-4 w-4\" />\n </SelectPrimitive.ItemIndicator>\n </span>\n <SelectPrimitive.ItemText>{children}</SelectPrimitive.ItemText>\n </SelectPrimitive.Item>\n));\nSelectItem.displayName = \"SelectItem\";\n\n/** A divider line between option groups. */\nexport const SelectSeparator = React.forwardRef<\n React.ElementRef<typeof SelectPrimitive.Separator>,\n React.ComponentPropsWithoutRef<typeof SelectPrimitive.Separator>\n>(({ className, ...props }, ref) => (\n <SelectPrimitive.Separator\n ref={ref}\n className={cn(\"-mx-1 my-1 h-px bg-muted\", className)}\n {...props}\n />\n));\nSelectSeparator.displayName = \"SelectSeparator\";\n\n// ---------------------------------------------------------------------------\n// Composed, options-driven Select (what ResourceForm / the filter bar use)\n// ---------------------------------------------------------------------------\n\nexport interface SelectOption {\n /** Must be non-empty and not the reserved sentinel. */\n value: string;\n label: React.ReactNode;\n disabled?: boolean;\n}\n\nexport interface SelectProps {\n /** `null`/`\"\"`/`undefined` all mean \"no selection\". */\n value: string | null | undefined;\n /** Receives `null` when the clear item is chosen, else the option value. */\n onValueChange?: (value: string | null) => void;\n options: readonly SelectOption[];\n placeholder?: React.ReactNode;\n /**\n * Renders a clear item at the top of the list (contract D8): pass it for\n * nullable fields (label \"—\" by default) and filter contexts (e.g. \"All\").\n * Choosing it emits `null`.\n */\n clearable?: boolean;\n clearLabel?: React.ReactNode;\n disabled?: boolean;\n /** Forwarded to the hidden native select for HTML form submission. */\n name?: string;\n id?: string;\n /** Merged onto the trigger. */\n className?: string;\n contentClassName?: string;\n \"aria-label\"?: string;\n /** Extra <SelectItem>/<SelectGroup> nodes appended after `options` (escape hatch). */\n children?: React.ReactNode;\n}\n\n/**\n * Styled select for a list of `options`, with `null` for no selection. Maps the\n * empty state through the KARNI_SELECT_EMPTY sentinel so `\"\"` never reaches\n * Radix (D8). For fully custom composition use SelectRoot/SelectTrigger/\n * SelectContent/SelectItem directly.\n */\nexport const Select = React.forwardRef<HTMLButtonElement, SelectProps>((props, ref) => {\n const {\n value,\n onValueChange,\n options,\n placeholder,\n clearable = false,\n clearLabel = \"—\",\n disabled,\n name,\n id,\n className,\n contentClassName,\n children,\n \"aria-label\": ariaLabel,\n } = props;\n\n const safeOptions = React.useMemo(() => {\n const filtered = options.filter(\n (option) => option.value !== \"\" && option.value !== KARNI_SELECT_EMPTY,\n );\n if (filtered.length !== options.length) {\n console.warn(\n `[karni-ui] <Select> option values \"\" and \"${KARNI_SELECT_EMPTY}\" are reserved; those options were dropped. Use the \\`clearable\\` prop for an empty choice.`,\n );\n }\n return filtered;\n }, [options]);\n\n const isEmpty = value == null || value === \"\";\n // With a clear item present, the sentinel is a real Radix value, so the\n // trigger shows the clear label and the item renders checked. Without one,\n // \"\" makes Radix show the placeholder.\n const radixValue = isEmpty ? (clearable ? KARNI_SELECT_EMPTY : \"\") : value;\n\n const handleValueChange = React.useCallback(\n (next: string) => {\n onValueChange?.(next === KARNI_SELECT_EMPTY ? null : next);\n },\n [onValueChange],\n );\n\n return (\n <SelectRoot\n value={radixValue}\n onValueChange={handleValueChange}\n disabled={disabled}\n name={name}\n >\n <SelectTrigger ref={ref} id={id} className={className} aria-label={ariaLabel}>\n <SelectValue placeholder={placeholder} />\n </SelectTrigger>\n <SelectContent className={contentClassName}>\n {clearable ? (\n <SelectItem value={KARNI_SELECT_EMPTY} className=\"text-muted-foreground\">\n {clearLabel}\n </SelectItem>\n ) : null}\n {safeOptions.map((option) => (\n <SelectItem key={option.value} value={option.value} disabled={option.disabled}>\n {option.label}\n </SelectItem>\n ))}\n {children}\n </SelectContent>\n </SelectRoot>\n );\n});\nSelect.displayName = \"Select\";\n","import * as CheckboxPrimitive from \"@radix-ui/react-checkbox\";\nimport * as React from \"react\";\nimport { cn } from \"../../lib/cn\";\nimport { CheckIcon } from \"./icons\";\n\nexport type CheckboxProps = React.ComponentPropsWithoutRef<typeof CheckboxPrimitive.Root>;\n\n/** Themed checkbox (Radix Checkbox) with a check mark indicator. */\nexport const Checkbox = React.forwardRef<\n React.ElementRef<typeof CheckboxPrimitive.Root>,\n CheckboxProps\n>(({ className, ...props }, ref) => (\n <CheckboxPrimitive.Root\n ref={ref}\n className={cn(\n \"peer h-4 w-4 shrink-0 rounded-sm border border-primary ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:bg-primary data-[state=checked]:text-primary-foreground\",\n className,\n )}\n {...props}\n >\n <CheckboxPrimitive.Indicator className=\"flex items-center justify-center text-current\">\n <CheckIcon className=\"h-3.5 w-3.5\" />\n </CheckboxPrimitive.Indicator>\n </CheckboxPrimitive.Root>\n));\nCheckbox.displayName = \"Checkbox\";\n","import * as SwitchPrimitive from \"@radix-ui/react-switch\";\nimport * as React from \"react\";\nimport { cn } from \"../../lib/cn\";\n\nexport type SwitchProps = React.ComponentPropsWithoutRef<typeof SwitchPrimitive.Root>;\n\n/** Themed on/off toggle (Radix Switch). */\nexport const Switch = React.forwardRef<React.ElementRef<typeof SwitchPrimitive.Root>, SwitchProps>(\n ({ className, ...props }, ref) => (\n <SwitchPrimitive.Root\n ref={ref}\n className={cn(\n \"peer inline-flex h-6 w-11 shrink-0 cursor-pointer items-center rounded-full border-2 border-transparent transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:bg-primary data-[state=unchecked]:bg-input\",\n className,\n )}\n {...props}\n >\n <SwitchPrimitive.Thumb className=\"pointer-events-none block h-5 w-5 rounded-full bg-background shadow-lg ring-0 transition-transform data-[state=checked]:translate-x-5 data-[state=unchecked]:translate-x-0\" />\n </SwitchPrimitive.Root>\n ),\n);\nSwitch.displayName = \"Switch\";\n","import * as LabelPrimitive from \"@radix-ui/react-label\";\nimport * as React from \"react\";\nimport { cn } from \"../../lib/cn\";\n\nexport type LabelProps = React.ComponentPropsWithoutRef<typeof LabelPrimitive.Root>;\n\n/** Themed form label (Radix Label) that dims when its field is disabled. */\nexport const Label = React.forwardRef<React.ElementRef<typeof LabelPrimitive.Root>, LabelProps>(\n ({ className, ...props }, ref) => (\n <LabelPrimitive.Root\n ref={ref}\n className={cn(\n \"text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70\",\n className,\n )}\n {...props}\n />\n ),\n);\nLabel.displayName = \"Label\";\n","import * as TabsPrimitive from \"@radix-ui/react-tabs\";\nimport * as React from \"react\";\nimport { cn } from \"../../lib/cn\";\n\n/** Tab set root (Radix Tabs); holds the selected value. */\nexport const Tabs = TabsPrimitive.Root;\n\n/** The row of tab buttons. */\nexport const TabsList = React.forwardRef<\n React.ElementRef<typeof TabsPrimitive.List>,\n React.ComponentPropsWithoutRef<typeof TabsPrimitive.List>\n>(({ className, ...props }, ref) => (\n <TabsPrimitive.List\n ref={ref}\n className={cn(\n \"inline-flex h-10 items-center justify-center rounded-md bg-muted p-1 text-muted-foreground\",\n className,\n )}\n {...props}\n />\n));\nTabsList.displayName = \"TabsList\";\n\n/** One tab button; `value` names the panel it opens. */\nexport const TabsTrigger = React.forwardRef<\n React.ElementRef<typeof TabsPrimitive.Trigger>,\n React.ComponentPropsWithoutRef<typeof TabsPrimitive.Trigger>\n>(({ className, ...props }, ref) => (\n <TabsPrimitive.Trigger\n ref={ref}\n className={cn(\n \"inline-flex items-center justify-center whitespace-nowrap rounded-sm px-3 py-1.5 text-sm font-medium ring-offset-background transition-all focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 data-[state=active]:bg-background data-[state=active]:text-foreground data-[state=active]:shadow-sm\",\n className,\n )}\n {...props}\n />\n));\nTabsTrigger.displayName = \"TabsTrigger\";\n\n/** The panel shown while its `value` is the selected tab. */\nexport const TabsContent = React.forwardRef<\n React.ElementRef<typeof TabsPrimitive.Content>,\n React.ComponentPropsWithoutRef<typeof TabsPrimitive.Content>\n>(({ className, ...props }, ref) => (\n <TabsPrimitive.Content\n ref={ref}\n className={cn(\n \"mt-2 ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2\",\n className,\n )}\n {...props}\n />\n));\nTabsContent.displayName = \"TabsContent\";\n","import * as DropdownMenuPrimitive from \"@radix-ui/react-dropdown-menu\";\nimport * as React from \"react\";\nimport { cn } from \"../../lib/cn\";\nimport { CheckIcon } from \"./icons\";\n\n/** Dropdown menu root (Radix DropdownMenu). */\nexport const DropdownMenu = DropdownMenuPrimitive.Root;\n/** The element that opens the menu. */\nexport const DropdownMenuTrigger = DropdownMenuPrimitive.Trigger;\n/** Groups related menu items. */\nexport const DropdownMenuGroup = DropdownMenuPrimitive.Group;\n/** Renders the menu into `document.body`. */\nexport const DropdownMenuPortal = DropdownMenuPrimitive.Portal;\n\n/** The styled menu panel. */\nexport const DropdownMenuContent = React.forwardRef<\n React.ElementRef<typeof DropdownMenuPrimitive.Content>,\n React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Content>\n>(({ className, sideOffset = 4, ...props }, ref) => (\n <DropdownMenuPrimitive.Portal>\n <DropdownMenuPrimitive.Content\n ref={ref}\n sideOffset={sideOffset}\n className={cn(\n \"z-50 min-w-[8rem] overflow-hidden rounded-md border border-border bg-popover p-1 text-popover-foreground shadow-md\",\n className,\n )}\n {...props}\n />\n </DropdownMenuPrimitive.Portal>\n));\nDropdownMenuContent.displayName = \"DropdownMenuContent\";\n\n/** One menu item; `onSelect` runs the action. */\nexport const DropdownMenuItem = React.forwardRef<\n React.ElementRef<typeof DropdownMenuPrimitive.Item>,\n React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Item> & { inset?: boolean }\n>(({ className, inset, ...props }, ref) => (\n <DropdownMenuPrimitive.Item\n ref={ref}\n className={cn(\n \"relative flex cursor-default select-none items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50\",\n inset && \"pl-8\",\n className,\n )}\n {...props}\n />\n));\nDropdownMenuItem.displayName = \"DropdownMenuItem\";\n\n/** A menu item with a check mark that toggles `checked`. */\nexport const DropdownMenuCheckboxItem = React.forwardRef<\n React.ElementRef<typeof DropdownMenuPrimitive.CheckboxItem>,\n React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.CheckboxItem>\n>(({ className, children, checked, ...props }, ref) => (\n <DropdownMenuPrimitive.CheckboxItem\n ref={ref}\n checked={checked}\n className={cn(\n \"relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50\",\n className,\n )}\n {...props}\n >\n <span className=\"absolute left-2 flex h-3.5 w-3.5 items-center justify-center\">\n <DropdownMenuPrimitive.ItemIndicator>\n <CheckIcon className=\"h-4 w-4\" />\n </DropdownMenuPrimitive.ItemIndicator>\n </span>\n {children}\n </DropdownMenuPrimitive.CheckboxItem>\n));\nDropdownMenuCheckboxItem.displayName = \"DropdownMenuCheckboxItem\";\n\n/** A non-interactive heading inside the menu. */\nexport const DropdownMenuLabel = React.forwardRef<\n React.ElementRef<typeof DropdownMenuPrimitive.Label>,\n React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Label> & { inset?: boolean }\n>(({ className, inset, ...props }, ref) => (\n <DropdownMenuPrimitive.Label\n ref={ref}\n className={cn(\"px-2 py-1.5 text-sm font-semibold\", inset && \"pl-8\", className)}\n {...props}\n />\n));\nDropdownMenuLabel.displayName = \"DropdownMenuLabel\";\n\n/** A divider line between menu items. */\nexport const DropdownMenuSeparator = React.forwardRef<\n React.ElementRef<typeof DropdownMenuPrimitive.Separator>,\n React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Separator>\n>(({ className, ...props }, ref) => (\n <DropdownMenuPrimitive.Separator\n ref={ref}\n className={cn(\"-mx-1 my-1 h-px bg-muted\", className)}\n {...props}\n />\n));\nDropdownMenuSeparator.displayName = \"DropdownMenuSeparator\";\n","import * as React from \"react\";\nimport { cn } from \"../../lib/cn\";\n\nexport type SkeletonProps = React.HTMLAttributes<HTMLDivElement>;\n\n/** Loading placeholder block; size it with width/height utility classes. */\nexport const Skeleton = React.forwardRef<HTMLDivElement, SkeletonProps>(\n ({ className, ...props }, ref) => (\n <div ref={ref} className={cn(\"animate-pulse rounded-md bg-muted\", className)} {...props} />\n ),\n);\nSkeleton.displayName = \"Skeleton\";\n","/**\n * Query-param construction and key normalization for the resource hooks\n * (contract \"Hooks\" + D4).\n *\n * `buildListQuery` / `buildItemQuery` turn the typed param objects into the\n * flat record that is sent to the backend (page → `page`, pageSize →\n * `page_size`, expand → comma-joined per api contract B9, filters spread\n * flat). `normalizeParams` produces the canonical representation used inside\n * query keys (D4): undefined/null dropped, keys sorted recursively, values\n * stringified exactly as they hit the query string — so two call sites that\n * describe the same request always share one cache entry.\n *\n * Internal module: not re-exported from the barrel.\n */\nimport type { FilterValue, ResourceItemParams, ResourceListParams } from \"./types\";\n\n/** Canonical param value shape stored inside query keys (D4). */\nexport type NormalizedParamValue = string | readonly string[] | NormalizedParams;\nexport type NormalizedParams = { readonly [key: string]: NormalizedParamValue };\n\nfunction stringifyScalar(value: string | number | boolean): string {\n return typeof value === \"string\" ? value : String(value);\n}\n\nfunction isScalarArray(value: FilterValue): value is ReadonlyArray<string | number | boolean> {\n return Array.isArray(value);\n}\n\n/**\n * Flattens ResourceListParams into the query record sent to the server.\n * Explicit params win over a `filters` entry of the same name. Empty\n * `search`/`ordering` strings and empty `expand` arrays are omitted (they\n * describe \"no constraint\", and sending them would fragment the cache).\n */\nexport function buildListQuery(\n params?: ResourceListParams,\n): Record<string, string | readonly string[]> {\n const query: Record<string, string | readonly string[]> = {};\n if (params === undefined) return query;\n\n if (params.filters !== undefined) {\n for (const [key, value] of Object.entries(params.filters)) {\n if (value === null || value === undefined) continue;\n if (isScalarArray(value)) {\n if (value.length > 0) query[key] = value.map(stringifyScalar);\n } else {\n query[key] = stringifyScalar(value);\n }\n }\n }\n\n if (params.page !== undefined) query.page = String(params.page);\n if (params.pageSize !== undefined) query.page_size = String(params.pageSize);\n if (params.ordering !== undefined && params.ordering !== \"\") query.ordering = params.ordering;\n if (params.search !== undefined && params.search !== \"\") query.search = params.search;\n if (params.expand !== undefined && params.expand.length > 0) {\n query.expand = params.expand.join(\",\");\n }\n return query;\n}\n\n/** Detail requests only carry `expand` (api contract B9). */\nexport function buildItemQuery(params?: ResourceItemParams): Record<string, string> {\n const query: Record<string, string> = {};\n if (params?.expand !== undefined && params.expand.length > 0) {\n query.expand = params.expand.join(\",\");\n }\n return query;\n}\n\n/**\n * D4 normalization: drop undefined/null, sort keys recursively, stringify\n * values as they hit the query string. The result is what `karniKeys` embeds\n * in list keys.\n */\nexport function normalizeParams(value: Record<string, unknown>): NormalizedParams {\n const out: Record<string, NormalizedParamValue> = {};\n for (const key of Object.keys(value).sort()) {\n const normalized = normalizeValue(value[key]);\n if (normalized !== undefined) out[key] = normalized;\n }\n return out;\n}\n\nfunction normalizeValue(value: unknown): NormalizedParamValue | undefined {\n if (value === null || value === undefined) return undefined;\n if (Array.isArray(value)) {\n return (value as readonly unknown[])\n .filter((item) => item !== null && item !== undefined)\n .map((item) =>\n typeof item === \"object\" && item !== null ? JSON.stringify(item) : String(item),\n );\n }\n if (typeof value === \"object\") {\n return normalizeParams(value as Record<string, unknown>);\n }\n return String(value);\n}\n\n/** `/events/` for resource \"events\" (the DRF router prefix, api B13). */\nexport function listPath(resource: string): string {\n const trimmed = resource.replace(/^\\/+|\\/+$/g, \"\");\n return `/${trimmed}/`;\n}\n\n/** `/events/5/` — ids are encoded so UUIDs and slugs are safe. */\nexport function detailPath(resource: string, id: string | number): string {\n return `${listPath(resource)}${encodeURIComponent(String(id))}/`;\n}\n","/**\n * Query-key factory for every cache entry @karni/ui creates (contract D4).\n *\n * Key shapes:\n * - `[\"karni\", \"$schema\"]` — the parsed OpenAPI schema (staleTime Infinity).\n * - `[\"karni\", resource]` — the invalidation root for one resource.\n * - `[\"karni\", resource, \"list\", normalizedParams]` — one list page.\n * - `[\"karni\", resource, \"detail\", String(id)]` — one item; when the item was\n * fetched with params (e.g. `expand`), the normalized params are appended as\n * a fifth element so differently-shaped payloads never share a cache entry.\n * Prefix invalidation via `karniKeys.resource(...)` still reaches them.\n *\n * Use this factory for any manual cache work (`setQueryData`,\n * `invalidateQueries`, prefetching) so your keys and the library's keys never\n * drift.\n *\n * NEVER invalidate the bare `[\"karni\"]` root: it would also blow away the\n * schema entry (`[\"karni\", \"$schema\"]`), refetching and re-parsing the whole\n * OpenAPI document. Invalidate `karniKeys.resource(resource)` instead — the\n * `\"$\"` prefix guarantees the schema key can never collide with a real\n * resource name (DRF router prefixes cannot contain `$`).\n */\nimport { buildItemQuery, buildListQuery, normalizeParams } from \"./params\";\nimport type { ResourceItemParams, ResourceListParams } from \"./types\";\n\n/** TanStack Query keys for the schema, a resource, its lists and its items; invalidate `karniKeys.resource(name)` to refresh every view of a resource. */\nexport const karniKeys = {\n /** Cache key of the parsed OpenAPI schema document. */\n schema(): readonly unknown[] {\n return [\"karni\", \"$schema\"] as const;\n },\n\n /**\n * The invalidation root for one resource — every list and detail key of\n * `resource` lives under this prefix.\n */\n resource(resource: string): readonly unknown[] {\n return [\"karni\", resource] as const;\n },\n\n /**\n * Key for one list page. Params are normalized (D4): undefined/null\n * dropped, keys sorted recursively, values stringified as they hit the\n * query string — `{search: \"x\", page: 2}` and `{page: 2, search: \"x\"}`\n * share one entry.\n */\n list(resource: string, params?: ResourceListParams): readonly unknown[] {\n return [\"karni\", resource, \"list\", normalizeParams(buildListQuery(params))] as const;\n },\n\n /**\n * Key for one item. The id is always stringified, so `detail(\"events\", 5)`\n * and `detail(\"events\", \"5\")` share one entry. Params (expand) append a\n * normalized fifth element — see the module docs.\n */\n detail(resource: string, id: string | number, params?: ResourceItemParams): readonly unknown[] {\n const query = buildItemQuery(params);\n if (Object.keys(query).length > 0) {\n return [\"karni\", resource, \"detail\", String(id), normalizeParams(query)] as const;\n }\n return [\"karni\", resource, \"detail\", String(id)] as const;\n },\n};\n","/**\n * <KarniProvider> — wires the Karni client into React (contract \"Schema\n * client\"). Wraps TanStack's QueryClientProvider, creating a QueryClient when\n * none is given (the `queryClient` prop is the escape hatch for apps that\n * already have one), and provides the client via context for every hook and\n * component in the package.\n */\nimport { QueryClient, QueryClientProvider } from \"@tanstack/react-query\";\nimport { createContext, useContext, useState } from \"react\";\nimport type { ReactElement, ReactNode } from \"react\";\nimport type { KarniClient } from \"./client\";\n\nconst KarniClientContext = createContext<KarniClient | null>(null);\n\nexport interface KarniProviderProps {\n client: KarniClient;\n /** Bring your own QueryClient; one is created (once) when omitted. */\n queryClient?: QueryClient;\n children?: ReactNode;\n}\n\n/** Provides the Karni client and a TanStack QueryClient to everything inside it; render it once at the app root. */\nexport function KarniProvider(props: KarniProviderProps): ReactElement {\n const { client, queryClient, children } = props;\n // Lazy initial state so the fallback QueryClient is created exactly once\n // per provider instance, never on re-renders.\n const [ownQueryClient] = useState(() => queryClient ?? new QueryClient());\n return (\n <QueryClientProvider client={queryClient ?? ownQueryClient}>\n <KarniClientContext.Provider value={client}>{children}</KarniClientContext.Provider>\n </QueryClientProvider>\n );\n}\n\n/** Returns the Karni client from `KarniProvider`; throws a descriptive error outside one. */\nexport function useKarniClient(): KarniClient {\n const client = useContext(KarniClientContext);\n if (client === null) {\n throw new Error(\n \"useKarniClient must be used within <KarniProvider>. \" +\n \"Wrap your app in <KarniProvider client={createKarniClient({ baseUrl })}>.\",\n );\n }\n return client;\n}\n","/**\n * Paginated list hook for one resource (contract \"Hooks\" + D11).\n *\n * `useResourceList<Event>(\"events\", { page: 2, search: \"conf\" })` fetches\n * `GET /<resource>/?page=2&search=conf` through the KarniClient (auth-aware\n * inside an <AuthProvider>) and caches it under\n * `karniKeys.list(resource, params)`. The response is the raw DRF page:\n * `{ count, next, previous, results }`.\n *\n * Escape hatch: `options` forwards every TanStack Query option except\n * `queryKey`/`queryFn` (e.g. `enabled`, `placeholderData`, `staleTime`,\n * `select`).\n */\nimport { useQuery, type UseQueryOptions, type UseQueryResult } from \"@tanstack/react-query\";\nimport { useKarniClient } from \"../schema/provider\";\nimport { karniKeys } from \"./keys\";\nimport { buildListQuery, listPath } from \"./params\";\nimport type { Paginated, ResourceListParams } from \"./types\";\n\n/** Fetches one page of a resource's list (`GET /<resource>/`) with filters, search, ordering and `?expand=`. */\nexport function useResourceList<T = Record<string, unknown>>(\n resource: string,\n params?: ResourceListParams,\n options?: Omit<UseQueryOptions<Paginated<T>>, \"queryKey\" | \"queryFn\">,\n): UseQueryResult<Paginated<T>> {\n const client = useKarniClient();\n return useQuery<Paginated<T>>({\n ...options,\n queryKey: karniKeys.list(resource, params),\n queryFn: ({ signal }) =>\n client.request<Paginated<T>>(listPath(resource), { query: buildListQuery(params), signal }),\n });\n}\n","/**\n * Mutation body encoding (contract D2) + PATCH file-URL omission.\n *\n * D2: after the form's `transformSubmit` has run, a payload containing any\n * top-level `File` (or an array containing one) is encoded as `FormData`;\n * everything else is sent as JSON. FormData rules:\n * - arrays append as repeated keys,\n * - plain objects/arrays-of-objects (json fields) are JSON-stringified,\n * - numbers/booleans are stringified,\n * - `null`/`undefined` entries are OMITTED — multipart cannot express null\n * (DRF would parse the string \"null\"); to null a field, send a JSON PATCH\n * without the file field instead,\n * - Content-Type is never set manually: fetch derives the multipart boundary.\n *\n * PATCH omission (D2): a string value on a file-kind field is the unchanged\n * display URL the backend returned (D1: response-side `format: uri`); sending\n * it back would 400 (\"not a file\"), so it is dropped from PATCH payloads.\n * Field kinds come from the cached parsed schema when present; without it the\n * payload passes through untouched (graceful degradation).\n *\n * Internal module: not re-exported from the barrel.\n */\n\nfunction isFileValue(value: unknown): value is File {\n return typeof File !== \"undefined\" && value instanceof File;\n}\n\nfunction isBlobValue(value: unknown): value is Blob {\n return typeof Blob !== \"undefined\" && value instanceof Blob;\n}\n\n/** True when any top-level value is a File, or an array containing one (D2). */\nexport function containsFile(values: Record<string, unknown>): boolean {\n return Object.values(values).some(\n (value) =>\n isFileValue(value) || (Array.isArray(value) && value.some((item) => isFileValue(item))),\n );\n}\n\nfunction appendFormValue(form: FormData, key: string, value: unknown): void {\n if (value === null || value === undefined) return;\n if (isFileValue(value) || isBlobValue(value)) {\n form.append(key, value);\n return;\n }\n if (typeof value === \"object\") {\n form.append(key, JSON.stringify(value));\n return;\n }\n form.append(key, String(value));\n}\n\n/** Encodes a payload as FormData per the D2 rules above. */\nexport function toFormData(values: Record<string, unknown>): FormData {\n const form = new FormData();\n for (const [key, value] of Object.entries(values)) {\n if (value === null || value === undefined) continue;\n if (Array.isArray(value)) {\n for (const item of value) appendFormValue(form, key, item);\n } else {\n appendFormValue(form, key, value);\n }\n }\n return form;\n}\n\n/**\n * D2 dispatch: FormData when a top-level File is present, the payload itself\n * (JSON-serialized by the client) otherwise. Applies to create AND PATCH.\n */\nexport function encodeBody(values: Record<string, unknown>): Record<string, unknown> | FormData {\n return containsFile(values) ? toFormData(values) : values;\n}\n\n/**\n * Extracts the file-kind field names of `resource` from the cached parsed\n * schema (`karniKeys.schema()`'s cache entry). Every access is guarded: an\n * absent cache entry or an unexpected shape yields an empty set, never a\n * throw.\n */\nexport function fileFieldNames(cachedSchema: unknown, resource: string): ReadonlySet<string> {\n const names = new Set<string>();\n if (typeof cachedSchema !== \"object\" || cachedSchema === null) return names;\n const resources = (cachedSchema as Record<string, unknown>).resources;\n if (typeof resources !== \"object\" || resources === null) return names;\n const entry = (resources as Record<string, unknown>)[resource];\n if (typeof entry !== \"object\" || entry === null) return names;\n const fields = (entry as Record<string, unknown>).fields;\n if (!Array.isArray(fields)) return names;\n for (const field of fields as readonly unknown[]) {\n if (typeof field !== \"object\" || field === null) continue;\n const { name, kind } = field as Record<string, unknown>;\n if (typeof name === \"string\" && kind === \"file\") names.add(name);\n }\n return names;\n}\n\nfunction isStringOrStringArray(value: unknown): boolean {\n if (typeof value === \"string\") return true;\n return Array.isArray(value) && value.every((item) => typeof item === \"string\");\n}\n\n/**\n * Drops unchanged file values — strings (or arrays of strings) on file-kind\n * fields are the backend's display URLs, not new uploads — from a PATCH\n * payload (D2).\n */\nexport function omitUnchangedFileUrls(\n values: Record<string, unknown>,\n fileFields: ReadonlySet<string>,\n): Record<string, unknown> {\n if (fileFields.size === 0) return values;\n const out: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(values)) {\n if (fileFields.has(key) && isStringOrStringArray(value)) continue;\n out[key] = value;\n }\n return out;\n}\n","/**\n * Create / update / remove mutations for one resource (contract \"Hooks\" +\n * D2, D3, D11).\n *\n * - `create` → `POST /<resource>/`\n * - `update` → `PATCH /<resource>/<id>/` with `{ id, values }`\n * - `remove` → `DELETE /<resource>/<id>/`\n *\n * Every successful mutation invalidates `karniKeys.resource(resource)` (all\n * list + detail entries of the resource) plus any `options.invalidateKeys` —\n * never the bare `[\"karni\"]` root (D4), which would nuke the cached schema.\n *\n * ## Multipart (D2)\n * Payloads containing a top-level `File` (or an array containing one) are\n * encoded as FormData — on create AND PATCH — with arrays as repeated keys,\n * json values JSON-stringified, and no manual Content-Type. Unchanged file\n * values (the URL string the backend returned) are omitted from PATCH\n * payloads so they are never re-submitted as uploads.\n *\n * ## PATCH granularity — contract for the form builder (D3)\n * `update` sends EXACTLY the keys present in `values`; it never diffs or\n * drops fields itself (beyond the file-URL omission above). ResourceForm\n * must therefore build `values` at TOP-LEVEL FIELD granularity from\n * react-hook-form's `dirtyFields`: when ANY leaf inside a field's subtree is\n * dirty (nested object, array member, multi-relation), include that field's\n * ENTIRE current value — never a partial subtree, because DRF PATCH replaces\n * the whole field value. An emptied nullable field must be sent as `null`\n * (not `\"\"`/`undefined`): a key that is absent is simply left unchanged by\n * the backend, and `undefined` does not survive JSON serialization.\n */\nimport { useMutation, useQueryClient, type UseMutationResult } from \"@tanstack/react-query\";\nimport { useCallback } from \"react\";\nimport { useKarniClient } from \"../schema/provider\";\nimport { karniKeys } from \"./keys\";\nimport { encodeBody, fileFieldNames, omitUnchangedFileUrls } from \"./multipart\";\nimport { detailPath, listPath } from \"./params\";\nimport type { ResourceMutationsOptions } from \"./types\";\n\n/** Result bundle — the three mutations, each a full TanStack mutation object. */\nexport interface ResourceMutations<T> {\n create: UseMutationResult<T, unknown, Record<string, unknown>>;\n update: UseMutationResult<T, unknown, { id: string | number; values: Record<string, unknown> }>;\n remove: UseMutationResult<void, unknown, string | number>;\n}\n\n/** Create, update and remove mutations for a resource; each success refreshes the resource's cached lists and items. */\nexport function useResourceMutations<T = Record<string, unknown>>(\n resource: string,\n options?: ResourceMutationsOptions,\n): ResourceMutations<T> {\n const client = useKarniClient();\n const queryClient = useQueryClient();\n const invalidateKeys = options?.invalidateKeys;\n\n const invalidate = useCallback(async (): Promise<void> => {\n await queryClient.invalidateQueries({ queryKey: karniKeys.resource(resource) });\n if (invalidateKeys !== undefined) {\n await Promise.all(\n invalidateKeys.map((queryKey) => queryClient.invalidateQueries({ queryKey })),\n );\n }\n }, [queryClient, resource, invalidateKeys]);\n\n const create = useMutation<T, unknown, Record<string, unknown>>({\n mutationFn: (values) =>\n client.request<T>(listPath(resource), { method: \"POST\", body: encodeBody(values) }),\n onSuccess: () => invalidate(),\n });\n\n const update = useMutation<T, unknown, { id: string | number; values: Record<string, unknown> }>({\n mutationFn: ({ id, values }) => {\n const fileFields = fileFieldNames(queryClient.getQueryData(karniKeys.schema()), resource);\n const prepared = omitUnchangedFileUrls(values, fileFields);\n return client.request<T>(detailPath(resource, id), {\n method: \"PATCH\",\n body: encodeBody(prepared),\n });\n },\n onSuccess: () => invalidate(),\n });\n\n // `void` lives in the annotation, not in call-site type arguments: eslint's\n // strict no-invalid-void-type only permits it in type-reference positions.\n const remove: UseMutationResult<void, unknown, string | number> = useMutation({\n mutationFn: async (id: string | number): Promise<void> => {\n await client.request(detailPath(resource, id), { method: \"DELETE\" });\n },\n onSuccess: () => invalidate(),\n });\n\n return { create, update, remove };\n}\n","/**\n * OpenAPI → ResourceSchema parser (contract \"Schema client\" + amendment D1).\n *\n * Parses the real drf-spectacular dialect (OAS 3.0.3):\n * - resolves $ref against components.schemas (cycle-guarded),\n * - unwraps single-member allOf, merging its siblings (drf-spectacular uses\n * `allOf: [$ref] + readOnly/description` for annotated enum fields),\n * - maps oneOf [XEnum, NullEnum | BlankEnum] → kind \"enum\" (+ nullable from\n * NullEnum; BlankEnum's \"\" excluded from enumValues),\n * - handles `nullable: true` (3.0) and `type: [T, \"null\"]` (future-proofing),\n * - split-components merge algebra (COMPONENT_SPLIT_REQUEST=True, api B14):\n * fields = union(response props, create-request props); readOnly = flagged\n * OR response-only; writeOnly = flagged OR request-only; required = the\n * CREATE REQUEST body's required array ONLY; resources without a create op\n * fall back to response-only, all readOnly,\n * - kind \"file\" = request-side `format: binary` (the response-side format: uri\n * is just the display URL),\n * - unknown/unsupported constructs land as kind \"unknown\" (never crash).\n *\n * This module is internal to @karni/ui (not re-exported from the barrel), but\n * sibling builders (hooks/auth/components) import it relatively.\n */\n\nimport type {\n FieldDef,\n FieldKind,\n OperationDef,\n ParsedSchema,\n RelationRef,\n ResourceSchema,\n} from \"./types\";\n\n// minimal structural OpenAPI types\n\nexport interface KarniRelationExtension {\n resource?: string;\n many?: boolean;\n}\n\nexport interface SchemaObject {\n default?: unknown;\n $ref?: string;\n type?: string | readonly string[];\n format?: string;\n title?: string;\n description?: string;\n enum?: ReadonlyArray<string | number | null>;\n nullable?: boolean;\n readOnly?: boolean;\n writeOnly?: boolean;\n required?: readonly string[];\n properties?: Record<string, SchemaObject>;\n items?: SchemaObject;\n allOf?: readonly SchemaObject[];\n oneOf?: readonly SchemaObject[];\n anyOf?: readonly SchemaObject[];\n maxLength?: number;\n minLength?: number;\n minimum?: number;\n maximum?: number;\n \"x-karni-relation\"?: KarniRelationExtension;\n [extension: string]: unknown;\n}\n\nexport interface ParameterObject {\n name?: string;\n in?: string;\n required?: boolean;\n schema?: SchemaObject;\n [extension: string]: unknown;\n}\n\nexport interface MediaTypeObject {\n schema?: SchemaObject;\n [extension: string]: unknown;\n}\n\nexport interface RequestBodyObject {\n content?: Record<string, MediaTypeObject>;\n required?: boolean;\n [extension: string]: unknown;\n}\n\nexport interface ResponseObject {\n description?: string;\n content?: Record<string, MediaTypeObject>;\n [extension: string]: unknown;\n}\n\nexport interface OperationObject {\n operationId?: string;\n parameters?: readonly ParameterObject[];\n requestBody?: RequestBodyObject;\n responses?: Record<string, ResponseObject>;\n \"x-karni-resource\"?: string;\n [extension: string]: unknown;\n}\n\nexport interface PathItemObject {\n get?: OperationObject;\n post?: OperationObject;\n put?: OperationObject;\n patch?: OperationObject;\n delete?: OperationObject;\n [extension: string]: unknown;\n}\n\nexport interface OpenApiDocument {\n openapi?: string;\n paths?: Record<string, PathItemObject>;\n components?: { schemas?: Record<string, SchemaObject>; [extension: string]: unknown };\n \"x-karni-auth-mode\"?: string;\n [extension: string]: unknown;\n}\n\n// helpers\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\n/** \"starts_at\" → \"Starts at\"; \"is_public\" → \"Is public\". */\nexport function humanize(name: string): string {\n const spaced = name.replace(/[_-]+/g, \" \").trim();\n return spaced.length === 0 ? name : spaced.charAt(0).toUpperCase() + spaced.slice(1);\n}\n\nconst REF_PREFIX = \"#/components/schemas/\";\n\nfunction lookupRef(doc: OpenApiDocument, ref: string): SchemaObject | undefined {\n if (!ref.startsWith(REF_PREFIX)) return undefined;\n return doc.components?.schemas?.[ref.slice(REF_PREFIX.length)];\n}\n\n/**\n * Resolves $ref chains and unwraps single-member allOf, merging siblings over\n * the resolved target (so `{allOf: [$ref StatusEnum], readOnly: true}` yields\n * the enum schema plus readOnly). Cycle-guarded; a cycle resolves to {}.\n */\nexport function resolveSchema(\n doc: OpenApiDocument,\n schema: SchemaObject | undefined,\n seen: readonly string[] = [],\n): SchemaObject | undefined {\n if (schema === undefined) return undefined;\n\n if (typeof schema.$ref === \"string\") {\n if (seen.includes(schema.$ref)) return {};\n const target = lookupRef(doc, schema.$ref);\n if (target === undefined) return {};\n const resolved = resolveSchema(doc, target, [...seen, schema.$ref]) ?? {};\n const siblings: SchemaObject = { ...schema };\n delete siblings.$ref;\n return { ...resolved, ...siblings };\n }\n\n if (Array.isArray(schema.allOf) && schema.allOf.length === 1) {\n const inner = resolveSchema(doc, schema.allOf[0], seen) ?? {};\n const siblings: SchemaObject = { ...schema };\n delete siblings.allOf;\n return { ...inner, ...siblings };\n }\n\n return schema;\n}\n\n// per-property analysis\n\ninterface PropertyInfo {\n kind: FieldKind;\n nullable: boolean;\n enumValues?: ReadonlyArray<string | number>;\n enumLabels?: Readonly<Record<string, string>>;\n maxLength?: number;\n min?: number;\n max?: number;\n format?: string;\n description?: string;\n title?: string;\n default?: unknown;\n readOnly: boolean;\n writeOnly: boolean;\n relation?: RelationRef;\n relationValueType?: \"uuid\" | \"integer\" | \"string\";\n /** True when this side emits format: binary (request side of a file field). */\n binary: boolean;\n}\n\nfunction normalizeType(schema: SchemaObject): { type: string | undefined; nullable: boolean } {\n // `type: [T, \"null\"]` is handled as future-proofing only (D1).\n if (Array.isArray(schema.type)) {\n const nonNull = schema.type.filter((t) => t !== \"null\");\n return { type: nonNull[0], nullable: schema.type.includes(\"null\") || schema.nullable === true };\n }\n return {\n type: typeof schema.type === \"string\" ? schema.type : undefined,\n nullable: schema.nullable === true,\n };\n}\n\nfunction relationFromExtension(schema: SchemaObject): RelationRef | undefined {\n const ext = schema[\"x-karni-relation\"];\n if (isRecord(ext) && typeof ext.resource === \"string\" && ext.resource.length > 0) {\n return { resource: ext.resource, many: ext.many === true };\n }\n return undefined;\n}\n\nfunction relationValueTypeOf(schema: SchemaObject): \"uuid\" | \"integer\" | \"string\" {\n const { type } = normalizeType(schema);\n if (type === \"integer\" || type === \"number\") return \"integer\";\n if (schema.format === \"uuid\") return \"uuid\";\n return \"string\";\n}\n\n/**\n * Combines oneOf/anyOf members when they follow the drf-spectacular enum\n * pattern `[XEnum, BlankEnum?, NullEnum?]`. Returns undefined for any other\n * composition (which then lands as kind \"unknown\").\n */\nfunction combineEnumMembers(\n doc: OpenApiDocument,\n members: readonly SchemaObject[],\n seen: readonly string[],\n): { values: Array<string | number>; nullable: boolean; description?: string } | undefined {\n const values: Array<string | number> = [];\n let nullable = false;\n let description: string | undefined;\n for (const member of members) {\n const resolved = resolveSchema(doc, member, seen);\n if (resolved === undefined || !Array.isArray(resolved.enum)) return undefined;\n if (description === undefined && resolved.description !== undefined && values.length === 0) {\n description = resolved.description; // the XEnum member carries the choice list\n }\n for (const value of resolved.enum) {\n if (value === null) {\n nullable = true; // NullEnum\n } else if (value !== \"\") {\n values.push(value); // BlankEnum's \"\" excluded from enumValues (D1)\n }\n }\n }\n return { values, nullable, description };\n}\n\nconst CHOICE_LINE = /^\\* `(.+?)` - (.*)$/;\n\n/**\n * Splits drf-spectacular's generated choice list (\"* `draft` - Draft\" per\n * line, appended to a ChoiceField's description) into labels by value and\n * the human help text that remains (undefined when nothing remains). The\n * raw list is markdown a form would otherwise show verbatim as help text.\n */\nexport function choiceLabels(description: string | undefined): {\n labels?: Record<string, string>;\n rest?: string;\n} {\n if (description === undefined) return {};\n const labels: Record<string, string> = {};\n const rest: string[] = [];\n for (const line of description.split(\"\\n\")) {\n const match = CHOICE_LINE.exec(line.trim());\n if (match !== null && match[1] !== undefined && match[2] !== undefined) {\n labels[match[1]] = match[2].trim();\n } else {\n rest.push(line);\n }\n }\n const text = rest.join(\"\\n\").trim();\n return {\n ...(Object.keys(labels).length > 0 ? { labels } : {}),\n ...(text !== \"\" ? { rest: text } : {}),\n };\n}\n\nfunction applyChoiceLabels(info: PropertyInfo, description: string | undefined): void {\n const { labels, rest } = choiceLabels(description);\n if (labels !== undefined) info.enumLabels = labels;\n info.description = rest;\n}\n\n/** True for drf-spectacular's JSONField output: a schema with no constraints at all. */\nfunction isAnySchema(schema: SchemaObject): boolean {\n return (\n schema.type === undefined &&\n schema.enum === undefined &&\n schema.properties === undefined &&\n schema.items === undefined &&\n schema.oneOf === undefined &&\n schema.anyOf === undefined &&\n schema.allOf === undefined &&\n schema.$ref === undefined\n );\n}\n\nfunction analyzeProperty(doc: OpenApiDocument, raw: SchemaObject): PropertyInfo {\n const resolved = resolveSchema(doc, raw) ?? {};\n const relation = relationFromExtension(resolved);\n const { type, nullable: typeNullable } = normalizeType(resolved);\n\n const info: PropertyInfo = {\n kind: \"unknown\",\n nullable: typeNullable,\n format: resolved.format,\n description: resolved.description,\n title: resolved.title,\n default: resolved.default,\n readOnly: resolved.readOnly === true,\n writeOnly: resolved.writeOnly === true,\n maxLength: resolved.maxLength,\n min: resolved.minimum,\n max: resolved.maximum,\n relation,\n binary: false,\n };\n\n // drf-spectacular nullable/blank enums: oneOf [XEnum, BlankEnum?, NullEnum?].\n const composition = resolved.oneOf ?? resolved.anyOf;\n if (Array.isArray(composition)) {\n const combined = combineEnumMembers(doc, composition, []);\n if (combined !== undefined) {\n info.kind = \"enum\";\n info.enumValues = combined.values;\n info.nullable = info.nullable || combined.nullable;\n applyChoiceLabels(info, resolved.description ?? combined.description);\n return info;\n }\n return info; // unsupported composition → kind \"unknown\"\n }\n\n if (Array.isArray(resolved.enum)) {\n info.kind = \"enum\";\n info.nullable = info.nullable || resolved.enum.includes(null);\n info.enumValues = resolved.enum.filter(\n (value): value is string | number => value !== null && value !== \"\",\n );\n applyChoiceLabels(info, resolved.description);\n return info;\n }\n\n if (relation !== undefined && !relation.many) {\n info.kind = \"relation\";\n info.relationValueType = relationValueTypeOf(resolved);\n return info;\n }\n\n switch (type) {\n case \"string\": {\n if (resolved.format === \"binary\") {\n info.kind = \"file\";\n info.binary = true;\n } else if (resolved.format === \"date\") {\n info.kind = \"date\";\n } else if (resolved.format === \"date-time\") {\n info.kind = \"datetime\";\n } else if (resolved.format === undefined && resolved.maxLength === undefined) {\n // CharField always emits maxLength; a bare string is a TextField.\n info.kind = \"text\";\n } else {\n info.kind = \"string\";\n }\n return info;\n }\n case \"integer\":\n info.kind = \"integer\";\n return info;\n case \"number\":\n info.kind = \"number\";\n return info;\n case \"boolean\":\n info.kind = \"boolean\";\n return info;\n case \"array\": {\n if (relation !== undefined) {\n info.kind = \"relation\";\n const items = resolveSchema(doc, resolved.items) ?? {};\n info.relationValueType = relationValueTypeOf(items);\n } else {\n info.kind = \"array\";\n }\n return info;\n }\n case \"object\":\n info.kind = \"json\";\n return info;\n default: {\n if (relation !== undefined) {\n // Extension present but value type undeclared — still a relation.\n info.kind = \"relation\";\n info.relationValueType = relationValueTypeOf(resolved);\n } else if (isAnySchema(resolved)) {\n // drf-spectacular emits `{}` for JSONField (\"any\" schema).\n info.kind = \"json\";\n }\n return info;\n }\n }\n}\n\n// split-components field merge (D1)\n\nfunction mergeField(\n name: string,\n responseInfo: PropertyInfo | undefined,\n requestInfo: PropertyInfo | undefined,\n requiredSet: ReadonlySet<string>,\n hasCreateRequest: boolean,\n order: number,\n): FieldDef {\n // Request side wins for write-facing facts; response side fills the gaps.\n // kind \"file\" is request-side format: binary (D1) — the response side of the\n // same field is a display URL (format: uri) and must not mask it.\n let kind: FieldKind;\n if (requestInfo?.binary === true) {\n kind = \"file\";\n } else if (requestInfo !== undefined && requestInfo.kind !== \"unknown\") {\n kind = requestInfo.kind;\n } else if (responseInfo !== undefined && responseInfo.kind !== \"unknown\") {\n kind = responseInfo.kind;\n } else {\n kind = \"unknown\";\n }\n\n const relation = requestInfo?.relation ?? responseInfo?.relation;\n const title = requestInfo?.title ?? responseInfo?.title;\n\n const field: FieldDef = {\n name,\n label: title !== undefined && title.length > 0 ? title : humanize(name),\n kind,\n required: requiredSet.has(name),\n readOnly:\n !hasCreateRequest ||\n responseInfo?.readOnly === true ||\n requestInfo?.readOnly === true ||\n (hasCreateRequest && responseInfo !== undefined && requestInfo === undefined),\n writeOnly:\n requestInfo?.writeOnly === true ||\n responseInfo?.writeOnly === true ||\n (responseInfo === undefined && requestInfo !== undefined),\n // Write-facing: a file is a nullable URL on the way out and a plain upload\n // on the way in, and only the request side says what a form may send.\n nullable: requestInfo !== undefined ? requestInfo.nullable : (responseInfo?.nullable ?? false),\n order,\n };\n\n const enumValues = requestInfo?.enumValues ?? responseInfo?.enumValues;\n const fallback = requestInfo?.default ?? responseInfo?.default;\n if (fallback !== undefined) field.default = fallback;\n if (enumValues !== undefined) field.enumValues = enumValues;\n const enumLabels = requestInfo?.enumLabels ?? responseInfo?.enumLabels;\n if (enumLabels !== undefined) field.enumLabels = enumLabels;\n const maxLength = requestInfo?.maxLength ?? responseInfo?.maxLength;\n if (maxLength !== undefined) field.maxLength = maxLength;\n const min = requestInfo?.min ?? responseInfo?.min;\n if (min !== undefined) field.min = min;\n const max = requestInfo?.max ?? responseInfo?.max;\n if (max !== undefined) field.max = max;\n const format = requestInfo?.format ?? responseInfo?.format;\n if (format !== undefined) field.format = format;\n const description = responseInfo?.description ?? requestInfo?.description;\n if (description !== undefined) field.description = description;\n if (relation !== undefined) {\n field.relation = relation;\n const valueType = requestInfo?.relationValueType ?? responseInfo?.relationValueType;\n if (valueType !== undefined) field.relationValueType = valueType;\n }\n\n return field;\n}\n\n// operation extraction\n\nfunction operationDef(\n doc: OpenApiDocument,\n path: string,\n method: OperationDef[\"method\"],\n op: OperationObject,\n): OperationDef {\n const queryParams: string[] = [];\n let expandEnum: readonly string[] | undefined;\n for (const param of op.parameters ?? []) {\n if (!isRecord(param) || param.in !== \"query\" || typeof param.name !== \"string\") continue;\n queryParams.push(param.name);\n if (param.name === \"expand\") {\n const schema = resolveSchema(doc, param.schema);\n const items = resolveSchema(doc, schema?.items);\n const values = schema?.enum ?? items?.enum;\n if (Array.isArray(values)) {\n expandEnum = values.filter((value): value is string => typeof value === \"string\");\n }\n }\n }\n const def: OperationDef = {\n path,\n method,\n queryParams,\n hasSearch: queryParams.includes(\"search\"),\n };\n if (typeof op.operationId === \"string\") def.operationId = op.operationId;\n if (expandEnum !== undefined) def.expandEnum = expandEnum;\n return def;\n}\n\n/** Unwraps a DRF paginated list response down to the item component schema. */\nfunction listItemSchema(doc: OpenApiDocument, op: OperationObject): SchemaObject | undefined {\n const response =\n op.responses?.[\"200\"] ?? op.responses?.[\"201\"] ?? Object.values(op.responses ?? {})[0];\n const media = response?.content?.[\"application/json\"];\n const body = resolveSchema(doc, media?.schema);\n if (body === undefined) return undefined;\n const results = resolveSchema(doc, body.properties?.[\"results\"]);\n if (results !== undefined && results.type === \"array\") {\n return resolveSchema(doc, results.items);\n }\n if (body.type === \"array\") return resolveSchema(doc, body.items);\n return body;\n}\n\nfunction createRequestSchema(doc: OpenApiDocument, op: OperationObject): SchemaObject | undefined {\n const content = op.requestBody?.content;\n if (!isRecord(content)) return undefined;\n const media =\n content[\"application/json\"] ?? content[\"multipart/form-data\"] ?? Object.values(content)[0];\n return resolveSchema(doc, media?.schema);\n}\n\n// the parser\n\nconst METHODS = [\"get\", \"post\", \"put\", \"patch\", \"delete\"] as const;\n\n/**\n * Parses an OpenAPI document (fetched from the backend's schemaUrl) into the\n * normalized registry. Tolerates anything it does not understand: unknown\n * constructs become kind \"unknown\" fields, paths without x-karni-resource are\n * ignored, and a malformed document yields an empty registry.\n */\nexport function parseOpenApi(input: unknown): ParsedSchema {\n const doc: OpenApiDocument = isRecord(input) ? (input as OpenApiDocument) : {};\n const paths = isRecord(doc.paths) ? doc.paths : {};\n\n const resources: Record<string, ResourceSchema> = {};\n const rawAuthMode = doc[\"x-karni-auth-mode\"];\n const authMode = rawAuthMode === \"jwt\" || rawAuthMode === \"session\" ? rawAuthMode : undefined;\n\n // Pass 1: find every list operation via its x-karni-resource marker.\n const listOps: Array<{ resource: string; path: string; item: PathItemObject }> = [];\n for (const [path, item] of Object.entries(paths)) {\n if (!isRecord(item)) continue;\n const get = item.get;\n if (isRecord(get) && typeof get[\"x-karni-resource\"] === \"string\") {\n listOps.push({ resource: get[\"x-karni-resource\"], path, item });\n }\n }\n\n for (const { resource, path, item } of listOps) {\n const listOp = item.get;\n if (!isRecord(listOp)) continue;\n\n // The item path is the collection path plus a single `{param}/` segment.\n const itemEntry = Object.entries(paths).find(([candidate]) => {\n if (!candidate.startsWith(path)) return false;\n const rest = candidate.slice(path.length);\n return /^\\{[^/{}]+\\}\\/?$/.test(rest);\n });\n const itemPath = itemEntry?.[0];\n const itemItem = itemEntry !== undefined && isRecord(itemEntry[1]) ? itemEntry[1] : undefined;\n\n const operations: ResourceSchema[\"operations\"] = {\n list: operationDef(doc, path, \"get\", listOp),\n };\n const createOp = isRecord(item.post) ? item.post : undefined;\n if (createOp !== undefined) operations.create = operationDef(doc, path, \"post\", createOp);\n // karni.transfer (P6): the export and import actions live under the list path.\n const exportItem = paths[`${path}export/`];\n const exportOp = isRecord(exportItem) && isRecord(exportItem.get) ? exportItem.get : undefined;\n if (exportOp !== undefined) {\n operations.export = operationDef(doc, `${path}export/`, \"get\", exportOp);\n }\n const importItem = paths[`${path}import/`];\n const importOp =\n isRecord(importItem) && isRecord(importItem.post) ? importItem.post : undefined;\n if (importOp !== undefined) {\n operations.import = operationDef(doc, `${path}import/`, \"post\", importOp);\n }\n if (itemPath !== undefined && itemItem !== undefined) {\n for (const method of METHODS) {\n const op = itemItem[method];\n if (!isRecord(op)) continue;\n if (method === \"get\") operations.detail = operationDef(doc, itemPath, \"get\", op);\n else if (method === \"patch\") operations.update = operationDef(doc, itemPath, \"patch\", op);\n else if (method === \"put\" && operations.update === undefined)\n operations.update = operationDef(doc, itemPath, \"put\", op);\n else if (method === \"delete\") operations.remove = operationDef(doc, itemPath, \"delete\", op);\n }\n }\n\n // Field derivation: response component of the list op + create request body.\n const responseSchema = listItemSchema(doc, listOp);\n const requestSchema = createOp !== undefined ? createRequestSchema(doc, createOp) : undefined;\n const hasCreateRequest = requestSchema !== undefined;\n\n const responseProps = isRecord(responseSchema?.properties) ? responseSchema.properties : {};\n const requestProps = isRecord(requestSchema?.properties) ? requestSchema.properties : {};\n // required comes from the CREATE REQUEST body only — never the response (D1).\n const requiredSet = new Set<string>(\n Array.isArray(requestSchema?.required) ? requestSchema.required : [],\n );\n\n const fields: FieldDef[] = [];\n let order = 0;\n for (const [name, prop] of Object.entries(responseProps)) {\n const responseInfo = analyzeProperty(doc, prop);\n const requestProp = requestProps[name];\n const requestInfo = requestProp !== undefined ? analyzeProperty(doc, requestProp) : undefined;\n fields.push(\n mergeField(name, responseInfo, requestInfo, requiredSet, hasCreateRequest, order),\n );\n order += 1;\n }\n for (const [name, prop] of Object.entries(requestProps)) {\n if (name in responseProps) continue;\n const requestInfo = analyzeProperty(doc, prop);\n fields.push(mergeField(name, undefined, requestInfo, requiredSet, hasCreateRequest, order));\n order += 1;\n }\n\n resources[resource] = { resource, operations, fields };\n }\n\n const parsed: ParsedSchema = { resources };\n if (authMode !== undefined) parsed.authMode = authMode;\n return parsed;\n}\n","/**\n * useSchema — the schema registry hook (contract \"Schema client\").\n *\n * The OpenAPI document is fetched under the pinned [\"karni\", \"$schema\"] key\n * with staleTime Infinity and parsed ONCE inside the query function, so every\n * consumer shares a single ParsedSchema instance per fetch. The key literal\n * is duplicated from karniKeys.schema() (hooks/keys.ts) by design: both\n * modules are bound to the same D4-pinned shape and neither imports the\n * other at runtime.\n *\n * Asking for a resource the backend does not expose — after the schema has\n * loaded — throws during render (error-boundary friendly) with the list of\n * known resources, which catches typos immediately instead of rendering an\n * empty table.\n */\nimport { useQuery } from \"@tanstack/react-query\";\nimport type { UseQueryResult } from \"@tanstack/react-query\";\nimport { parseOpenApi } from \"./parse\";\nimport { useKarniClient } from \"./provider\";\nimport type { ParsedSchema, ResourceSchema } from \"./types\";\n\n/** D4-pinned query key for the parsed schema document. */\nexport const SCHEMA_QUERY_KEY = [\"karni\", \"$schema\"] as const;\n\n/**\n * The whole parsed registry (resources + root x-karni-auth-mode). Internal to\n * the package — the auth layer reads `data.authMode` from here; apps use\n * useSchema(resource).\n */\nexport function useParsedSchema(): UseQueryResult<ParsedSchema> {\n const client = useKarniClient();\n return useQuery<ParsedSchema>({\n queryKey: SCHEMA_QUERY_KEY,\n staleTime: Infinity,\n queryFn: async () => parseOpenApi(await client.request<unknown>(client.schemaUrl)),\n });\n}\n\nexport interface UseSchemaResult {\n data: ResourceSchema | undefined;\n isLoading: boolean;\n error: unknown;\n}\n\n/** Returns one resource's parsed schema (fields, types, relations, operations) from the backend's OpenAPI document, fetched once per app. */\nexport function useSchema(resource: string): UseSchemaResult {\n const query = useParsedSchema();\n\n if (query.data !== undefined) {\n const schema = query.data.resources[resource];\n if (schema === undefined) {\n const known = Object.keys(query.data.resources).sort();\n throw new Error(\n `Unknown resource \"${resource}\". Known resources: ` +\n `${known.length > 0 ? known.join(\", \") : \"(none — does the schema expose x-karni-resource?)\"}.`,\n );\n }\n return { data: schema, isLoading: false, error: query.error };\n }\n\n return { data: undefined, isLoading: query.isPending, error: query.error };\n}\n","import * as React from \"react\";\nimport { cn } from \"../../lib/cn\";\nimport { registerComponentRole } from \"../../lib/roles\";\n\nregisterComponentRole(\"empty-state\", \"EmptyState\");\n\nexport interface EmptyStateProps extends Omit<React.HTMLAttributes<HTMLDivElement>, \"title\"> {\n /** Optional illustration/icon slot, rendered above the title. */\n icon?: React.ReactNode;\n /** Short headline (\"No events yet\"). */\n title: React.ReactNode;\n /** Optional supporting copy under the title. */\n description?: React.ReactNode;\n /** Slot for a call to action (e.g. a \"Create\" button). */\n action?: React.ReactNode;\n children?: React.ReactNode;\n}\n\n/**\n * Centered placeholder for empty collections: icon, title, description and\n * an action slot. Used by ResourceTable's `empty` slot and reusable anywhere.\n *\n * Escape hatches: every visual part is a slot; `className` merges via cn();\n * extra children render under the action.\n */\nexport const EmptyState = React.forwardRef<HTMLDivElement, EmptyStateProps>(\n ({ icon, title, description, action, className, children, ...props }, ref) => (\n <div\n ref={ref}\n className={cn(\n \"flex w-full flex-col items-center justify-center gap-2 rounded-lg border border-dashed border-border bg-background px-6 py-12 text-center\",\n className,\n )}\n {...props}\n >\n {icon != null && (\n <div aria-hidden=\"true\" className=\"mb-2 text-muted-foreground [&>svg]:h-10 [&>svg]:w-10\">\n {icon}\n </div>\n )}\n <h3 className=\"text-base font-semibold text-foreground\">{title}</h3>\n {description != null && (\n <p className=\"max-w-sm text-sm text-muted-foreground\">{description}</p>\n )}\n {action != null && <div className=\"mt-3 flex items-center gap-2\">{action}</div>}\n {children}\n </div>\n ),\n);\nEmptyState.displayName = \"EmptyState\";\n","/**\n * Audit fields: the columns every Karni resource carries because every model\n * inherits BaseModel (`deleted_at` is never exposed by the API). They are\n * record bookkeeping, not domain data, so the generic resource components\n * de-emphasise them: ResourceTable hides them by default (escape hatches:\n * `columns` entries and `showAuditFields`), ResourceDetail renders them last\n * in a muted \"Record\" group.\n *\n * This list is the single source of truth — edit it here and every generic\n * component follows. Its order is also the display order whenever audit\n * fields are shown, whatever order the schema declares them in.\n */\nimport type { FieldDef } from \"../../schema/types\";\n\n/** The audit field names (`created_at`, `created_by`, …) that tables hide and detail views group last. */\nexport const AUDIT_FIELDS: readonly string[] = Object.freeze([\n \"id\",\n \"created_at\",\n \"updated_at\",\n \"created_by\",\n \"updated_by\",\n]);\n\n/**\n * True for a schema field that is one of AUDIT_FIELDS. The backend always\n * emits these readOnly; a writable field that merely shares a name (a natural\n * `id` key, say) is domain data and is never treated as audit.\n */\nexport function isAuditField(field: Pick<FieldDef, \"name\" | \"readOnly\">): boolean {\n return field.readOnly && AUDIT_FIELDS.includes(field.name);\n}\n\n/**\n * Splits fields into domain fields (schema order kept) and audit fields\n * (AUDIT_FIELDS order).\n */\nexport function partitionAuditFields<F extends Pick<FieldDef, \"name\" | \"readOnly\">>(\n fields: readonly F[],\n): { domain: F[]; audit: F[] } {\n const domain: F[] = [];\n const audit: F[] = [];\n for (const field of fields) {\n (isAuditField(field) ? audit : domain).push(field);\n }\n audit.sort((a, b) => AUDIT_FIELDS.indexOf(a.name) - AUDIT_FIELDS.indexOf(b.name));\n return { domain, audit };\n}\n","/**\n * Human label heuristic for resource objects (contract \"ResourceTable\").\n *\n * Used by ResourceTable's relation cells, ResourceSelect's options and\n * ResourceDetail's relation values. Overridable everywhere it is used:\n * ResourceTable takes `getRowLabel`, ResourceSelect takes `getOptionLabel`.\n */\n\nconst LABEL_KEYS = [\"name\", \"title\", \"label\", \"email\", \"str\"] as const;\n\n/**\n * Returns the first non-empty string among the `name` → `title` → `label` →\n * `email` → `str` keys, falling back to `String(id)` and finally \"\".\n */\nexport function displayLabel(obj: Record<string, unknown>): string {\n for (const key of LABEL_KEYS) {\n const value = obj[key];\n if (typeof value === \"string\" && value.trim().length > 0) return value;\n }\n const id = obj[\"id\"];\n if (id !== null && id !== undefined) return String(id);\n return \"\";\n}\n","/**\n * Selected-count toolbar for ResourceTable's bulk select (D5): shows how many\n * rows are selected (selection persists across pages), a clear affordance and\n * one button per configured bulk action.\n * Internal to @karni/ui — the public surface is ResourceTable's props.\n */\nimport * as React from \"react\";\nimport { cn } from \"../../../lib/cn\";\nimport { Button } from \"../../primitives/button\";\n\nexport interface BulkAction {\n label: React.ReactNode;\n onClick: (selectedIds: string[]) => void;\n destructive?: boolean;\n}\n\nexport interface BulkActionsBarProps {\n /** Row ids (String(row.id), D5) currently selected, across all pages. */\n selectedIds: readonly string[];\n bulkActions: ReadonlyArray<BulkAction>;\n onClear: () => void;\n className?: string;\n}\n\nexport function BulkActionsBar(props: BulkActionsBarProps): React.ReactElement {\n const { selectedIds, bulkActions, onClear, className } = props;\n return (\n <div\n role=\"toolbar\"\n aria-label=\"Bulk actions\"\n className={cn(\n \"flex flex-wrap items-center gap-2 rounded-md border border-border bg-muted px-3 py-2\",\n className,\n )}\n >\n <p className=\"text-sm font-medium text-foreground\">{selectedIds.length} selected</p>\n <Button variant=\"ghost\" size=\"sm\" onClick={onClear}>\n Clear\n </Button>\n <div className=\"ml-auto flex flex-wrap items-center gap-2\">\n {bulkActions.map((action, index) => (\n <Button\n key={index}\n variant={action.destructive === true ? \"destructive\" : \"outline\"}\n size=\"sm\"\n onClick={() => action.onClick([...selectedIds])}\n >\n {action.label}\n </Button>\n ))}\n </div>\n </div>\n );\n}\n","/**\n * Internal helpers for ResourceTable (contract \"ResourceTable\" + D5).\n * Pure functions, unit-tested directly; not part of the public barrel.\n */\nimport type { SortingState } from \"@tanstack/react-table\";\n\n/**\n * Maps TanStack sorting state to the DRF `ordering` query parameter.\n * Column ids equal schema field names verbatim — that IS the ordering\n * contract (D5) — so `[{id: \"title\", desc: true}]` becomes `-title`.\n */\nexport function sortingToOrdering(sorting: SortingState): string | undefined {\n if (sorting.length === 0) return undefined;\n return sorting.map((entry) => (entry.desc ? `-${entry.id}` : entry.id)).join(\",\");\n}\n\n/**\n * Duck-typed 404 check (works with KarniApiError or any error exposing a\n * numeric `status`), used for the D5 page-clamp: a list 404 with page > 1\n * decrements the page and refetches as loading, never as an error.\n */\nexport function isNotFoundError(error: unknown): boolean {\n return (\n typeof error === \"object\" &&\n error !== null &&\n \"status\" in error &&\n (error as { status: unknown }).status === 404\n );\n}\n\nexport function pageCountFor(count: number | undefined, pageSize: number): number {\n if (count === undefined || count <= 0 || pageSize <= 0) return 1;\n return Math.max(1, Math.ceil(count / pageSize));\n}\n\n/** Safe record view of an unknown row (rows are plain JSON objects). */\nexport function asRecord(value: unknown): Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value)\n ? (value as Record<string, unknown>)\n : {};\n}\n\n/** Best-effort human message from a KarniApiError-shaped or plain Error. */\nexport function errorMessage(error: unknown): string {\n if (typeof error === \"object\" && error !== null) {\n const data = (error as { data?: unknown }).data;\n if (typeof data === \"object\" && data !== null) {\n const detail = (data as { detail?: unknown }).detail;\n if (typeof detail === \"string\" && detail.length > 0) return detail;\n }\n const message = (error as { message?: unknown }).message;\n if (typeof message === \"string\" && message.length > 0) return message;\n }\n return \"Something went wrong while loading this table.\";\n}\n\n/**\n * Display label for an enum member: ALL_CAPS and lower_snake constants are\n * prettified (\"DRAFT\" → \"Draft\", \"in_progress\" → \"In progress\"); mixed-case\n * values (\"iOS\") pass through untouched.\n */\nexport function enumLabel(\n value: string | number,\n labels?: Readonly<Record<string, string>>,\n): string {\n const known = labels?.[String(value)];\n if (known !== undefined) return known;\n if (typeof value === \"number\") return String(value);\n const simple = /^[A-Za-z0-9_ ]+$/.test(value);\n if (simple && (value === value.toUpperCase() || value === value.toLowerCase())) {\n const spaced = value.toLowerCase().replace(/_+/g, \" \").trim();\n if (spaced.length === 0) return value;\n return spaced.charAt(0).toUpperCase() + spaced.slice(1);\n }\n return value;\n}\n","/**\n * Schema → TanStack column derivation (contract \"ResourceTable\" + D5).\n *\n * - Domain fields first, in declaration order; writeOnly / json / file /\n * unknown fields are skipped unless the consumer explicitly names them in\n * the `columns` prop.\n * - Audit fields (AUDIT_FIELDS: id, created_at, updated_at, created_by,\n * updated_by) are hidden by default. A `columns` entry naming one (without\n * `hidden: true`) or `showAuditFields` brings it back, after the domain\n * columns, in AUDIT_FIELDS order.\n * - Column ids equal schema field names verbatim — that IS the DRF `ordering`\n * contract (D5).\n * - relation / json / file / array / unknown columns are unsortable by\n * default; the per-field `sortable` override wins both ways.\n * - Cells: booleans → check icon, dates localized, enum labels prettified,\n * relations → displayLabel of the expanded object else the raw id in\n * <code>. The label heuristic is overridable via `getRowLabel`.\n */\nimport type { ColumnDef } from \"@tanstack/react-table\";\nimport * as React from \"react\";\nimport { humanize } from \"../../../schema/parse\";\nimport type { FieldDef, FieldKind } from \"../../../schema/types\";\nimport { CheckIcon } from \"../../primitives/icons\";\nimport { isAuditField, partitionAuditFields } from \"../audit-fields\";\nimport { displayLabel } from \"../displayLabel\";\nimport { asRecord, enumLabel } from \"./table-utils\";\n\n/** Per-field override merged over the schema-derived column. */\nexport interface ResourceColumn<T = Record<string, unknown>> {\n field: string;\n header?: React.ReactNode;\n cell?: (row: T) => React.ReactNode;\n hidden?: boolean;\n sortable?: boolean;\n}\n\ntype RowLabeler = (row: Record<string, unknown>) => string;\n\nconst DEFAULT_SKIPPED_KINDS: ReadonlySet<FieldKind> = new Set([\"json\", \"file\", \"unknown\"]);\nconst UNSORTABLE_KINDS: ReadonlySet<FieldKind> = new Set([\n \"relation\",\n \"json\",\n \"file\",\n \"array\",\n \"unknown\",\n]);\n\nfunction EmptyValue(): React.ReactElement {\n return (\n <span aria-hidden=\"true\" className=\"text-muted-foreground\">\n –\n </span>\n );\n}\n\nfunction BooleanCell({ value }: { value: boolean }): React.ReactElement {\n return value ? (\n <span className=\"inline-flex items-center text-foreground\">\n <CheckIcon className=\"h-4 w-4\" />\n <span className=\"sr-only\">Yes</span>\n </span>\n ) : (\n <span className=\"inline-flex items-center text-muted-foreground\">\n <span aria-hidden=\"true\">–</span>\n <span className=\"sr-only\">No</span>\n </span>\n );\n}\n\nfunction IdCode({ value }: { value: unknown }): React.ReactElement {\n return <code className=\"rounded bg-muted px-1 py-0.5 text-xs\">{String(value)}</code>;\n}\n\nfunction relationItem(item: unknown, label: RowLabeler): React.ReactNode {\n if (item === null || item === undefined) return <EmptyValue />;\n if (typeof item === \"object\" && !Array.isArray(item)) return label(asRecord(item));\n return <IdCode value={item} />;\n}\n\nfunction RelationCell({ value, label }: { value: unknown; label: RowLabeler }): React.ReactElement {\n if (value === null || value === undefined) return <EmptyValue />;\n if (Array.isArray(value)) {\n if (value.length === 0) return <EmptyValue />;\n return (\n <span className=\"inline-flex flex-wrap items-center gap-x-2 gap-y-1\">\n {value.map((item, index) => (\n <React.Fragment key={index}>{relationItem(item, label)}</React.Fragment>\n ))}\n </span>\n );\n }\n return <>{relationItem(value, label)}</>;\n}\n\nfunction dateText(value: unknown, withTime: boolean): string {\n const parsed = new Date(String(value));\n if (Number.isNaN(parsed.getTime())) return String(value);\n return withTime ? parsed.toLocaleString() : parsed.toLocaleDateString();\n}\n\nfunction FileCell({ value }: { value: unknown }): React.ReactElement {\n if (typeof value === \"string\" && value.length > 0) {\n const name = value.split(\"/\").filter(Boolean).pop() ?? value;\n return (\n <a\n href={value}\n target=\"_blank\"\n rel=\"noreferrer\"\n className=\"text-primary underline underline-offset-4\"\n onClick={(event) => event.stopPropagation()}\n >\n {name}\n </a>\n );\n }\n if (typeof File !== \"undefined\" && value instanceof File) return <>{value.name}</>;\n return <EmptyValue />;\n}\n\nfunction JsonCell({ value }: { value: unknown }): React.ReactElement {\n let text: string;\n try {\n text = JSON.stringify(value) ?? String(value);\n } catch {\n text = String(value);\n }\n const shown = text.length > 80 ? `${text.slice(0, 80)}…` : text;\n return (\n <code className=\"rounded bg-muted px-1 py-0.5 text-xs\" title={text}>\n {shown}\n </code>\n );\n}\n\n/**\n * Default cell renderer for a schema field's value. Exported for reuse by\n * custom cells that want the stock formatting for other fields.\n */\nexport function renderFieldCell(\n field: FieldDef,\n value: unknown,\n getRowLabel?: RowLabeler,\n): React.ReactNode {\n if (value === null || value === undefined) return <EmptyValue />;\n switch (field.kind) {\n case \"boolean\":\n return <BooleanCell value={value === true} />;\n case \"date\":\n return dateText(value, false);\n case \"datetime\":\n return dateText(value, true);\n case \"enum\":\n return typeof value === \"string\" || typeof value === \"number\"\n ? enumLabel(value, field.enumLabels)\n : String(value);\n case \"relation\":\n return <RelationCell value={value} label={getRowLabel ?? displayLabel} />;\n case \"number\":\n case \"integer\":\n return (\n <span className=\"tabular-nums\">\n {typeof value === \"number\" ? value.toLocaleString() : String(value)}\n </span>\n );\n case \"file\":\n return <FileCell value={value} />;\n case \"json\":\n return <JsonCell value={value} />;\n case \"array\":\n return Array.isArray(value) ? value.map((item) => String(item)).join(\", \") : String(value);\n case \"text\":\n return (\n <span className=\"block max-w-xs truncate\" title={String(value)}>\n {String(value)}\n </span>\n );\n default:\n return String(value);\n }\n}\n\n/** ColumnDef.header only takes a string or a render function — wrap nodes. */\nfunction headerTemplate<T>(content: React.ReactNode): ColumnDef<T>[\"header\"] {\n return typeof content === \"string\" ? content : () => content;\n}\n\nexport interface DeriveColumnsArgs<T> {\n fields: readonly FieldDef[];\n columns?: ReadonlyArray<ResourceColumn<T>>;\n getRowLabel?: RowLabeler;\n /** Show every audit field (AUDIT_FIELDS) without naming each in `columns`. */\n showAuditFields?: boolean;\n}\n\nfunction columnForField<T>(\n field: FieldDef,\n override: ResourceColumn<T> | undefined,\n getRowLabel: RowLabeler | undefined,\n): ColumnDef<T> {\n const customCell = override?.cell;\n return {\n id: field.name,\n accessorFn: (row) => asRecord(row)[field.name],\n header: headerTemplate(override?.header ?? field.label),\n cell:\n customCell !== undefined\n ? (ctx) => customCell(ctx.row.original)\n : (ctx) => renderFieldCell(field, ctx.getValue(), getRowLabel),\n enableSorting: override?.sortable ?? !UNSORTABLE_KINDS.has(field.kind),\n };\n}\n\n/**\n * Builds the derived column set: domain columns (schema order), then any\n * shown audit columns (AUDIT_FIELDS order), then `columns` entries naming\n * fields the schema does not declare — plain accessor columns (escape hatch\n * for computed or server-extra keys). `columns` overrides merge onto their\n * fields; naming a default-skipped field (json, audit, ...) shows it.\n */\nexport function deriveColumns<T>(args: DeriveColumnsArgs<T>): Array<ColumnDef<T>> {\n const pending = new Map<string, ResourceColumn<T>>(\n (args.columns ?? []).map((column) => [column.field, column]),\n );\n const defs: Array<ColumnDef<T>> = [];\n const { domain, audit } = partitionAuditFields(args.fields);\n\n for (const field of [...domain, ...audit]) {\n const override = pending.get(field.name);\n pending.delete(field.name);\n if (override?.hidden === true) continue;\n if (override === undefined) {\n if (field.writeOnly || DEFAULT_SKIPPED_KINDS.has(field.kind)) continue;\n if (args.showAuditFields !== true && isAuditField(field)) continue;\n }\n defs.push(columnForField(field, override, args.getRowLabel));\n }\n\n for (const [name, override] of pending) {\n if (override.hidden === true) continue;\n const customCell = override.cell;\n defs.push({\n id: name,\n accessorFn: (row) => asRecord(row)[name],\n header: headerTemplate(override.header ?? humanize(name)),\n cell:\n customCell !== undefined\n ? (ctx) => customCell(ctx.row.original)\n : (ctx) => {\n const value = ctx.getValue();\n return value === null || value === undefined ? <EmptyValue /> : String(value);\n },\n enableSorting: override.sortable ?? false,\n });\n }\n\n return defs;\n}\n","/**\n * Import and export hooks (karni.transfer, ADR 0002 P6).\n *\n * - `downloadResourceExport(client, resource, params, format)` fetches\n * `GET /<resource>/export/` with the list's own query (filters, search,\n * ordering) and hands the file to the browser — what ResourceTable's export\n * buttons call.\n * - `useImportDescribe(resource)` reads `GET /<resource>/import/`: the\n * importable fields and the user's remembered mapping.\n * - `useImportJob(resource, jobId)` reads one job's state and polls while the\n * backend is previewing or committing it in Celery.\n * - `useImportActions(resource)` holds the three mutations: upload (creates\n * the job), preview (the mandatory dry run, with the mapping) and commit.\n *\n * The backend decides everything that matters: which fields the role may\n * write, which rows are in scope, what a row's errors are. The hooks render\n * its answers without filtering.\n */\nimport {\n useMutation,\n useQuery,\n useQueryClient,\n type UseMutationResult,\n type UseQueryOptions,\n type UseQueryResult,\n} from \"@tanstack/react-query\";\nimport type { KarniClient, KarniQueryValue } from \"../schema/client\";\nimport { useKarniClient } from \"../schema/provider\";\nimport { karniKeys } from \"./keys\";\nimport { buildListQuery, listPath } from \"./params\";\nimport type { ResourceListParams } from \"./types\";\n\nexport type ExportFormat = \"csv\" | \"xlsx\";\n\nexport type ImportColumnKind =\n | \"text\"\n | \"integer\"\n | \"decimal\"\n | \"boolean\"\n | \"date\"\n | \"datetime\"\n | \"choice\"\n | \"relation\"\n | \"relations\"\n | \"json\"\n | \"file\"\n | \"other\";\n\nexport interface ImportColumn {\n name: string;\n label: string;\n kind: ImportColumnKind;\n required: boolean;\n readable: boolean;\n writable: boolean;\n choices: ReadonlyArray<{ value: string; label: string }>;\n /** `app_label.model` of a relation's target. */\n target: string | null;\n /** The target field a relation column carries (its natural key), else the id. */\n lookup: string | null;\n help: string;\n /** The column an import matches existing rows on. */\n key: boolean;\n}\n\nexport interface ImportDescription {\n fields: ImportColumn[];\n /** The mapping the user last confirmed for this resource (header → field). */\n mapping: Record<string, string>;\n /** Files with more rows than this run in Celery; poll the job. */\n inline_rows: number;\n max_rows: number;\n key: string | null;\n}\n\nexport type ImportStatus =\n \"uploaded\" | \"previewing\" | \"previewed\" | \"committing\" | \"done\" | \"failed\";\n\nexport interface ImportResult {\n rows_total: number;\n created: number;\n updated: number;\n unchanged: number;\n errors: number;\n skipped: number;\n}\n\nexport interface ImportProblem {\n /** The line in the file (the header is line 1). */\n row: number;\n field: string;\n message: string;\n}\n\nexport interface ImportJob {\n id: string;\n model: string | null;\n status: ImportStatus;\n file_name: string;\n format: string;\n columns: string[];\n mapping: Record<string, string>;\n rows_total: number;\n rows_done: number;\n async: boolean;\n result: ImportResult | null;\n problems: ImportProblem[];\n error: string | null;\n batch: number | null;\n created_at: string | null;\n fields?: ImportColumn[];\n}\n\n/** The query key of a resource's import description. */\nexport function importDescribeKey(resource: string): readonly unknown[] {\n return [...karniKeys.resource(resource), \"import\", \"describe\"] as const;\n}\n\n/** The query key of one import job. */\nexport function importJobKey(resource: string, jobId: string): readonly unknown[] {\n return [...karniKeys.resource(resource), \"import\", \"job\", jobId] as const;\n}\n\nfunction importPath(resource: string, suffix = \"\"): string {\n return `${listPath(resource)}import/${suffix}`;\n}\n\nconst IN_FLIGHT: ReadonlySet<ImportStatus> = new Set<ImportStatus>([\"previewing\", \"committing\"]);\n\n/** True while an import job is previewing or committing (the states worth polling). */\nexport function isImportInFlight(job: ImportJob | undefined): boolean {\n return job !== undefined && IN_FLIGHT.has(job.status);\n}\n\n/** The name the backend suggested, else \"<resource>.<format>\". */\nfunction filenameFrom(response: Response, fallback: string): string {\n const header = response.headers.get(\"content-disposition\") ?? \"\";\n const match = /filename=\"?([^\";]+)\"?/i.exec(header);\n return match?.[1] ?? fallback;\n}\n\n/**\n * Fetches `GET /<resource>/export/?format=…` with the list's query and saves\n * it through a temporary object URL. Resolves with the file name. Throws the\n * `KarniApiError` the backend answered (a 400 with code E803 when the export\n * is larger than `KARNI_EXPORT_MAX_ROWS`).\n */\nexport async function downloadResourceExport(\n client: KarniClient,\n resource: string,\n params: ResourceListParams | undefined,\n format: ExportFormat = \"csv\",\n): Promise<string> {\n const query: Record<string, KarniQueryValue> = { ...buildListQuery(params), format };\n delete query[\"page\"];\n delete query[\"page_size\"];\n const response = await client.requestRaw(`${listPath(resource)}export/`, { query });\n const blob = await response.blob();\n const filename = filenameFrom(response, `${resource}.${format}`);\n saveBlob(blob, filename);\n return filename;\n}\n\n/** Hands a blob to the browser as a download (a no-op outside a DOM, e.g. SSR). */\nexport function saveBlob(blob: Blob, filename: string): void {\n if (typeof document === \"undefined\" || typeof URL.createObjectURL !== \"function\") return;\n const url = URL.createObjectURL(blob);\n const anchor = document.createElement(\"a\");\n anchor.href = url;\n anchor.download = filename;\n document.body.appendChild(anchor);\n anchor.click();\n anchor.remove();\n URL.revokeObjectURL(url);\n}\n\n/** Fetches `GET /<resource>/import/template/?format=…` and saves it (the headers, an example, allowed values). */\nexport async function downloadImportTemplate(\n client: KarniClient,\n resource: string,\n format: ExportFormat = \"xlsx\",\n): Promise<string> {\n const response = await client.requestRaw(importPath(resource, \"template/\"), {\n query: { format },\n });\n const blob = await response.blob();\n const filename = filenameFrom(response, `${resource}-template.${format}`);\n saveBlob(blob, filename);\n return filename;\n}\n\n/** Fetches what a resource's import accepts: its columns, required fields and allowed values. */\nexport function useImportDescribe(\n resource: string,\n options?: Omit<UseQueryOptions<ImportDescription>, \"queryKey\" | \"queryFn\">,\n): UseQueryResult<ImportDescription> {\n const client = useKarniClient();\n return useQuery<ImportDescription>({\n ...options,\n queryKey: importDescribeKey(resource),\n queryFn: ({ signal }) => client.request<ImportDescription>(importPath(resource), { signal }),\n });\n}\n\nexport interface UseImportJobOptions {\n /** Polling interval while the job is previewing/committing. Default 1500 ms. */\n pollMs?: number;\n}\n\n/** Fetches one import job and polls it while it runs. */\nexport function useImportJob(\n resource: string,\n jobId: string | undefined,\n options?: UseImportJobOptions,\n): UseQueryResult<ImportJob> {\n const client = useKarniClient();\n const pollMs = options?.pollMs ?? 1500;\n return useQuery<ImportJob>({\n queryKey: importJobKey(resource, jobId ?? \"\"),\n enabled: jobId !== undefined,\n queryFn: ({ signal }) =>\n client.request<ImportJob>(importPath(resource, `${encodeURIComponent(jobId ?? \"\")}/`), {\n signal,\n }),\n refetchInterval: (query) => (isImportInFlight(query.state.data) ? pollMs : false),\n });\n}\n\nexport interface UploadImportInput {\n file: File;\n /** An explicit mapping; otherwise the backend suggests or remembers one. */\n mapping?: Record<string, string>;\n}\n\nexport interface PreviewImportInput {\n jobId: string;\n mapping: Record<string, string>;\n}\n\nexport interface ImportActions {\n upload: UseMutationResult<ImportJob, unknown, UploadImportInput>;\n preview: UseMutationResult<ImportJob, unknown, PreviewImportInput>;\n commit: UseMutationResult<ImportJob, unknown, string>;\n}\n\n/** Upload, preview and commit mutations for a resource's import jobs. */\nexport function useImportActions(resource: string): ImportActions {\n const client = useKarniClient();\n const queryClient = useQueryClient();\n\n const store = (job: ImportJob): ImportJob => {\n queryClient.setQueryData(importJobKey(resource, job.id), job);\n return job;\n };\n\n const upload = useMutation<ImportJob, unknown, UploadImportInput>({\n mutationFn: async ({ file, mapping }) => {\n const form = new FormData();\n form.append(\"file\", file);\n if (mapping !== undefined) form.append(\"mapping\", JSON.stringify(mapping));\n return store(\n await client.request<ImportJob>(importPath(resource), { method: \"POST\", body: form }),\n );\n },\n });\n\n const preview = useMutation<ImportJob, unknown, PreviewImportInput>({\n mutationFn: async ({ jobId, mapping }) =>\n store(\n await client.request<ImportJob>(\n importPath(resource, `${encodeURIComponent(jobId)}/preview/`),\n {\n method: \"POST\",\n body: { mapping },\n },\n ),\n ),\n onSuccess: () => {\n void queryClient.invalidateQueries({ queryKey: importDescribeKey(resource) });\n },\n });\n\n const commit = useMutation<ImportJob, unknown, string>({\n mutationFn: async (jobId) =>\n store(\n await client.request<ImportJob>(\n importPath(resource, `${encodeURIComponent(jobId)}/commit/`),\n {\n method: \"POST\",\n body: {},\n },\n ),\n ),\n onSuccess: (job) => {\n if (job.status === \"done\") {\n void queryClient.invalidateQueries({ queryKey: karniKeys.resource(resource) });\n }\n },\n });\n\n return { upload, preview, commit };\n}\n","/**\n * ResourceTable's export buttons (karni.transfer, ADR 0002 P6): one per\n * format, each downloading `GET /<resource>/export/` with the table's current\n * filters, search and ordering — the backend applies the row scope and the\n * role's field visibility, so the file is exactly what the table may show.\n *\n * Internal to @karni/ui — the public surface is ResourceTable's `exportFormats`.\n */\nimport * as React from \"react\";\nimport type { ResourceListParams } from \"../../../hooks/types\";\nimport { downloadResourceExport, type ExportFormat } from \"../../../hooks/useResourceImport\";\nimport { useKarniClient } from \"../../../schema/provider\";\nimport { Button } from \"../../primitives/button\";\n\nexport interface ExportButtonsProps {\n resource: string;\n params: ResourceListParams;\n formats: readonly ExportFormat[];\n}\n\nfunction describe(error: unknown): string {\n if (error instanceof Error) {\n const data = (error as { data?: unknown }).data;\n if (typeof data === \"object\" && data !== null && \"detail\" in data) {\n const detail = (data as { detail?: unknown }).detail;\n if (typeof detail === \"string\") return detail;\n }\n return error.message;\n }\n return \"The export failed.\";\n}\n\nexport function ExportButtons({\n resource,\n params,\n formats,\n}: ExportButtonsProps): React.ReactElement {\n const client = useKarniClient();\n const [busy, setBusy] = React.useState<ExportFormat | null>(null);\n const [error, setError] = React.useState<string | null>(null);\n\n const run = (format: ExportFormat): void => {\n setBusy(format);\n setError(null);\n downloadResourceExport(client, resource, params, format)\n .catch((failure: unknown) => setError(describe(failure)))\n .finally(() => setBusy(null));\n };\n\n return (\n <div className=\"flex items-center gap-2\" data-testid=\"resource-table-export\">\n {formats.map((format) => (\n <Button\n key={format}\n type=\"button\"\n variant=\"outline\"\n size=\"sm\"\n disabled={busy !== null}\n onClick={() => run(format)}\n aria-label={`Export as ${format.toUpperCase()}`}\n >\n {busy === format ? \"Exporting…\" : `Export ${format.toUpperCase()}`}\n </Button>\n ))}\n {error !== null && (\n <span role=\"alert\" className=\"text-sm text-destructive\">\n {error}\n </span>\n )}\n </div>\n );\n}\n","/**\n * Single-item hook for one resource (contract \"Hooks\" + D11).\n *\n * `useResourceItem<Event>(\"events\", id, { expand: [\"venue\"] })` fetches\n * `GET /<resource>/<id>/?expand=venue` and caches it under\n * `karniKeys.detail(resource, id, params)` — params participate in the key,\n * so an expanded detail view and an unexpanded edit form never clobber each\n * other's cache entry, while `karniKeys.resource(resource)` invalidation\n * still reaches both.\n *\n * Escape hatch: `options` forwards every TanStack Query option except\n * `queryKey`/`queryFn` (e.g. `enabled` for \"fetch only when an id exists\").\n */\nimport { useQuery, type UseQueryOptions, type UseQueryResult } from \"@tanstack/react-query\";\nimport { useKarniClient } from \"../schema/provider\";\nimport { karniKeys } from \"./keys\";\nimport { buildItemQuery, detailPath } from \"./params\";\nimport type { ResourceItemParams } from \"./types\";\n\n/** Fetches one row of a resource (`GET /<resource>/<id>/`), optionally expanded. */\nexport function useResourceItem<T = Record<string, unknown>>(\n resource: string,\n id: string | number,\n params?: ResourceItemParams,\n options?: Omit<UseQueryOptions<T>, \"queryKey\" | \"queryFn\">,\n): UseQueryResult<T> {\n const client = useKarniClient();\n return useQuery<T>({\n ...options,\n queryKey: karniKeys.detail(resource, id, params),\n queryFn: ({ signal }) =>\n client.request<T>(detailPath(resource, id), { query: buildItemQuery(params), signal }),\n });\n}\n","import * as React from \"react\";\n\n/** Returns `value` after it has been stable for `delayMs` (D8: search debounce). */\nexport function useDebouncedValue<T>(value: T, delayMs: number): T {\n const [debounced, setDebounced] = React.useState(value);\n\n React.useEffect(() => {\n if (delayMs <= 0) {\n setDebounced(value);\n return undefined;\n }\n const timer = setTimeout(() => setDebounced(value), delayMs);\n return () => clearTimeout(timer);\n }, [value, delayMs]);\n\n return debounced;\n}\n","import * as PopoverPrimitive from \"@radix-ui/react-popover\";\nimport * as React from \"react\";\nimport { useResourceItem } from \"../../../hooks/useResourceItem\";\nimport { useResourceList } from \"../../../hooks/useResourceList\";\nimport type { ResourceListParams } from \"../../../hooks/types\";\nimport { cn } from \"../../../lib/cn\";\nimport { CheckIcon, ChevronDownIcon } from \"../../primitives/icons\";\nimport { displayLabel } from \"../displayLabel\";\nimport { useDebouncedValue } from \"./use-debounced-value\";\nimport { registerComponentRole } from \"../../../lib/roles\";\n\nregisterComponentRole(\"async-select\", \"ResourceSelect\");\n\ntype ResourceItemRecord = Record<string, unknown>;\n\nexport interface ResourceSelectProps {\n resource: string;\n value: string | number | ReadonlyArray<string | number> | null;\n onChange: (value: string | number | Array<string | number> | null) => void;\n multiple?: boolean;\n disabled?: boolean;\n placeholder?: string;\n /** Defaults to displayLabel(). */\n getOptionLabel?: (item: Record<string, unknown>) => React.ReactNode;\n /** Extra filter params sent with the search request. */\n filter?: Record<string, string | number | boolean>;\n id?: string;\n className?: string;\n /** Page size for the option request (only the first page is fetched, D8). */\n pageSize?: number;\n /** Set false to hide the clear affordance (which emits null). Default true. */\n clearable?: boolean;\n /** Debounce for the ?search= request in ms. Default 300 (D8). */\n searchDebounceMs?: number;\n \"aria-label\"?: string;\n \"aria-labelledby\"?: string;\n}\n\nfunction idOf(item: ResourceItemRecord): string | number {\n const value = item[\"id\"];\n if (typeof value === \"string\" || typeof value === \"number\") return value;\n return String(value);\n}\n\nfunction optionDomId(listboxId: string, index: number): string {\n return `${listboxId}-option-${index}`;\n}\n\nfunction XIcon(props: React.SVGAttributes<SVGSVGElement>): React.ReactElement {\n return (\n <svg\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth={2}\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n focusable={false}\n {...props}\n >\n <line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\" />\n <line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\" />\n </svg>\n );\n}\n\n/**\n * Searchable picker for a related row, querying the related resource as you type.\n *\n * Contract D8.\n *\n * A text input drives a debounced `?search=` list request; options render in\n * a NON-MODAL Radix Popover whose auto-focus is prevented so keyboard focus\n * never leaves the input. The input implements the ARIA 1.2 combobox pattern\n * (combobox → listbox with aria-activedescendant). Pre-selected ids that were\n * never seen in a result page are resolved through detail fetches, and the\n * clear affordance emits `null`.\n */\nexport function ResourceSelect(props: ResourceSelectProps): React.ReactElement {\n const {\n resource,\n value,\n onChange,\n multiple = false,\n disabled = false,\n placeholder,\n getOptionLabel,\n filter,\n id,\n className,\n pageSize,\n clearable = true,\n searchDebounceMs = 300,\n } = props;\n\n const reactId = React.useId();\n const inputId = id ?? reactId;\n const listboxId = `${inputId}-listbox`;\n\n const [open, setOpen] = React.useState(false);\n const [inputText, setInputText] = React.useState(\"\");\n const [activeIndex, setActiveIndex] = React.useState(0);\n const [cache, setCache] = React.useState<Record<string, ResourceItemRecord>>({});\n\n const rootRef = React.useRef<HTMLDivElement>(null);\n const contentRef = React.useRef<HTMLDivElement>(null);\n const inputRef = React.useRef<HTMLInputElement>(null);\n\n const debouncedSearch = useDebouncedValue(inputText.trim(), searchDebounceMs);\n\n const selected: ReadonlyArray<string | number> = React.useMemo(() => {\n if (value == null) return [];\n return Array.isArray(value) ? value : [value as string | number];\n }, [value]);\n\n const listParams: ResourceListParams = React.useMemo(() => {\n const params: ResourceListParams = { page: 1 };\n if (pageSize !== undefined) params.pageSize = pageSize;\n if (debouncedSearch !== \"\") params.search = debouncedSearch;\n if (filter !== undefined) params.filters = filter;\n return params;\n }, [pageSize, debouncedSearch, filter]);\n\n const listQuery = useResourceList(resource, listParams, { enabled: open && !disabled });\n const results: readonly ResourceItemRecord[] = listQuery.data?.results ?? [];\n\n // Remember every row we have seen, so selected values can always be labelled.\n React.useEffect(() => {\n const rows = listQuery.data?.results;\n if (rows === undefined || rows.length === 0) return;\n setCache((previous) => {\n let changed = false;\n const next = { ...previous };\n for (const row of rows) {\n const key = String(idOf(row));\n if (!(key in next)) {\n next[key] = row;\n changed = true;\n }\n }\n return changed ? next : previous;\n });\n }, [listQuery.data]);\n\n // Pre-selected ids never seen in a result page are resolved one at a time\n // through the detail endpoint (D8 selected-id resolution).\n const unresolvedId = selected.find((sel) => !(String(sel) in cache));\n const itemQuery = useResourceItem(resource, unresolvedId ?? \"\", undefined, {\n enabled: unresolvedId !== undefined && !disabled,\n retry: false,\n });\n const resolvedItem = itemQuery.data;\n const resolveError = itemQuery.error;\n\n React.useEffect(() => {\n if (unresolvedId === undefined) return;\n if (resolvedItem !== undefined) {\n setCache((previous) => ({ ...previous, [String(unresolvedId)]: resolvedItem }));\n } else if (resolveError != null) {\n // Give up on this id (the raw id becomes its label) so resolution of any\n // remaining ids can continue instead of refetching forever.\n setCache((previous) => ({ ...previous, [String(unresolvedId)]: { id: unresolvedId } }));\n }\n }, [unresolvedId, resolvedItem, resolveError]);\n\n const labelOf = React.useCallback(\n (item: ResourceItemRecord): React.ReactNode =>\n getOptionLabel !== undefined ? getOptionLabel(item) : displayLabel(item),\n [getOptionLabel],\n );\n\n const textOf = React.useCallback(\n (sel: string | number): string => {\n const item = cache[String(sel)];\n if (item === undefined) return String(sel);\n const label = getOptionLabel !== undefined ? getOptionLabel(item) : displayLabel(item);\n if (typeof label === \"string\") return label;\n if (typeof label === \"number\") return String(label);\n return displayLabel(item);\n },\n [cache, getOptionLabel],\n );\n\n const openPopover = React.useCallback(() => {\n if (disabled) return;\n setInputText(\"\");\n setActiveIndex(0);\n setOpen(true);\n }, [disabled]);\n\n const closePopover = React.useCallback(() => {\n setOpen(false);\n setInputText(\"\");\n }, []);\n\n const isSelected = React.useCallback(\n (optionId: string | number): boolean =>\n selected.some((sel) => String(sel) === String(optionId)),\n [selected],\n );\n\n const toggleOption = (item: ResourceItemRecord): void => {\n const optionId = idOf(item);\n setCache((previous) =>\n String(optionId) in previous ? previous : { ...previous, [String(optionId)]: item },\n );\n if (multiple) {\n const next = isSelected(optionId)\n ? selected.filter((sel) => String(sel) !== String(optionId))\n : [...selected, optionId];\n onChange([...next]);\n } else {\n onChange(optionId);\n closePopover();\n }\n };\n\n const clearSelection = (): void => {\n onChange(null);\n setInputText(\"\");\n inputRef.current?.focus();\n };\n\n const singleText = !multiple && selected.length > 0 ? textOf(selected[0]) : \"\";\n const inputValue = open ? inputText : multiple ? \"\" : singleText;\n\n const handleInputChange = (event: React.ChangeEvent<HTMLInputElement>): void => {\n const next = event.target.value;\n if (!open) {\n if (disabled) return;\n setActiveIndex(0);\n setOpen(true);\n // While closed the input showed the selected label; typing appends to\n // it, so strip the label prefix and keep only the fresh keystrokes.\n setInputText(\n singleText !== \"\" && next.startsWith(singleText) ? next.slice(singleText.length) : next,\n );\n return;\n }\n setActiveIndex(0);\n setInputText(next);\n };\n\n const handleKeyDown = (event: React.KeyboardEvent<HTMLInputElement>): void => {\n if (disabled) return;\n switch (event.key) {\n case \"ArrowDown\":\n event.preventDefault();\n if (!open) openPopover();\n else if (results.length > 0) setActiveIndex((index) => (index + 1) % results.length);\n break;\n case \"ArrowUp\":\n event.preventDefault();\n if (!open) openPopover();\n else if (results.length > 0) {\n setActiveIndex((index) => (index - 1 + results.length) % results.length);\n }\n break;\n case \"Enter\":\n if (open) {\n event.preventDefault();\n const item = results[activeIndex];\n if (item !== undefined) toggleOption(item);\n }\n break;\n case \"Escape\":\n if (open) {\n event.preventDefault();\n event.stopPropagation();\n closePopover();\n }\n break;\n case \"Backspace\":\n if (multiple && inputText === \"\" && selected.length > 0) {\n onChange([...selected.slice(0, -1)]);\n }\n break;\n case \"Tab\":\n if (open) closePopover();\n break;\n default:\n break;\n }\n };\n\n const handleBlur = (event: React.FocusEvent<HTMLInputElement>): void => {\n const next = event.relatedTarget as Node | null;\n if (\n next !== null &&\n (rootRef.current?.contains(next) === true || contentRef.current?.contains(next) === true)\n ) {\n return;\n }\n if (open) closePopover();\n };\n\n const listContent = ((): React.ReactNode => {\n if (listQuery.isLoading) {\n return <div className=\"px-2 py-1.5 text-sm text-muted-foreground\">Loading…</div>;\n }\n if (listQuery.error != null) {\n return (\n <div role=\"alert\" className=\"px-2 py-1.5 text-sm text-destructive\">\n Failed to load options.\n </div>\n );\n }\n if (results.length === 0) {\n return <div className=\"px-2 py-1.5 text-sm text-muted-foreground\">No results</div>;\n }\n return results.map((item, index) => {\n const optionId = idOf(item);\n const optionSelected = isSelected(optionId);\n return (\n <div\n key={String(optionId)}\n id={optionDomId(listboxId, index)}\n role=\"option\"\n aria-selected={optionSelected}\n data-highlighted={index === activeIndex ? \"true\" : undefined}\n className=\"flex cursor-default select-none items-center justify-between gap-2 rounded-sm px-2 py-1.5 text-sm outline-none data-[highlighted=true]:bg-accent data-[highlighted=true]:text-accent-foreground\"\n onMouseDown={(event) => event.preventDefault()}\n onMouseMove={() => setActiveIndex(index)}\n onClick={() => toggleOption(item)}\n >\n <span className=\"truncate\">{labelOf(item)}</span>\n {optionSelected ? <CheckIcon className=\"h-4 w-4 shrink-0\" /> : null}\n </div>\n );\n });\n })();\n\n return (\n <PopoverPrimitive.Root\n open={open}\n onOpenChange={(next) => {\n if (!next) closePopover();\n }}\n modal={false}\n >\n <PopoverPrimitive.Anchor asChild>\n <div\n ref={rootRef}\n onClick={() => {\n if (disabled) return;\n inputRef.current?.focus();\n if (!open) openPopover();\n }}\n className={cn(\n \"flex min-h-10 w-full flex-wrap items-center gap-1.5 rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background focus-within:ring-2 focus-within:ring-ring focus-within:ring-offset-2\",\n disabled && \"cursor-not-allowed opacity-50\",\n className,\n )}\n >\n {multiple\n ? selected.map((sel) => {\n const chipText = textOf(sel);\n return (\n <span\n key={String(sel)}\n className=\"inline-flex items-center gap-1 rounded-sm bg-secondary px-1.5 py-0.5 text-xs text-secondary-foreground\"\n >\n {chipText}\n {!disabled ? (\n <button\n type=\"button\"\n aria-label={`Remove ${chipText}`}\n className=\"rounded-sm opacity-70 hover:opacity-100 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring\"\n onClick={(event) => {\n event.stopPropagation();\n onChange([...selected.filter((other) => String(other) !== String(sel))]);\n }}\n >\n <XIcon className=\"h-3 w-3\" />\n </button>\n ) : null}\n </span>\n );\n })\n : null}\n <input\n ref={inputRef}\n id={inputId}\n type=\"text\"\n role=\"combobox\"\n aria-expanded={open}\n aria-controls={listboxId}\n aria-autocomplete=\"list\"\n aria-activedescendant={\n open && results.length > 0 ? optionDomId(listboxId, activeIndex) : undefined\n }\n aria-label={props[\"aria-label\"]}\n aria-labelledby={props[\"aria-labelledby\"]}\n autoComplete=\"off\"\n disabled={disabled}\n placeholder={selected.length === 0 ? placeholder : undefined}\n value={inputValue}\n onChange={handleInputChange}\n onKeyDown={handleKeyDown}\n onClick={() => {\n if (!open) openPopover();\n }}\n onBlur={handleBlur}\n className=\"min-w-16 flex-1 bg-transparent outline-none placeholder:text-muted-foreground disabled:cursor-not-allowed\"\n />\n {clearable && selected.length > 0 && !disabled ? (\n <button\n type=\"button\"\n aria-label=\"Clear selection\"\n className=\"rounded-sm p-0.5 text-muted-foreground hover:text-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring\"\n onMouseDown={(event) => event.preventDefault()}\n onClick={(event) => {\n event.stopPropagation();\n clearSelection();\n }}\n >\n <XIcon className=\"h-4 w-4\" />\n </button>\n ) : null}\n <ChevronDownIcon className=\"h-4 w-4 shrink-0 opacity-50\" />\n </div>\n </PopoverPrimitive.Anchor>\n <PopoverPrimitive.Portal>\n <PopoverPrimitive.Content\n ref={contentRef}\n side=\"bottom\"\n align=\"start\"\n sideOffset={4}\n onOpenAutoFocus={(event) => event.preventDefault()}\n onCloseAutoFocus={(event) => event.preventDefault()}\n onInteractOutside={(event) => {\n const target = event.target;\n if (\n rootRef.current !== null &&\n target instanceof Node &&\n rootRef.current.contains(target)\n ) {\n event.preventDefault();\n }\n }}\n className=\"z-50 max-h-72 w-[var(--radix-popover-trigger-width)] min-w-[12rem] overflow-y-auto rounded-md border border-border bg-popover p-1 text-popover-foreground shadow-md\"\n >\n <div role=\"listbox\" id={listboxId} aria-multiselectable={multiple || undefined}>\n {listContent}\n </div>\n </PopoverPrimitive.Content>\n </PopoverPrimitive.Portal>\n </PopoverPrimitive.Root>\n );\n}\n","/**\n * ResourceTable's search box + declared-params-derived filter bar (D5).\n *\n * The parent decides WHICH fields filter (enum/boolean/relation fields ∩ the\n * list operation's declared query params, cap 4, `filters` prop overrides);\n * this component only renders the controls:\n * - enum → clearable <Select> (\"All\" clears),\n * - boolean → clearable Yes/No <Select>,\n * - relation → <ResourceSelect> (multiple for many-relations).\n *\n * Internal to @karni/ui — the public surface is ResourceTable's props.\n */\nimport * as React from \"react\";\nimport type { FilterValue } from \"../../../hooks/types\";\nimport type { FieldDef } from \"../../../schema/types\";\nimport { cn } from \"../../../lib/cn\";\nimport { Input } from \"../../primitives/input\";\nimport { Select } from \"../../primitives/select\";\nimport { ResourceSelect } from \"../ResourceSelect\";\nimport { enumLabel } from \"./table-utils\";\n\nexport interface FilterBarProps {\n /** Whether the list operation declares a `search` query param. */\n searchEnabled: boolean;\n searchValue: string;\n onSearchChange: (value: string) => void;\n searchPlaceholder?: string;\n /** Already-derived filter fields, in render order. */\n filterFields: readonly FieldDef[];\n values: Readonly<Record<string, FilterValue>>;\n onFilterChange: (field: FieldDef, value: FilterValue) => void;\n className?: string;\n}\n\nfunction toSelectValue(value: FilterValue): string | null {\n if (value === null || value === undefined || typeof value === \"object\") return null;\n return String(value);\n}\n\nfunction toRelationValue(\n value: FilterValue,\n): string | number | ReadonlyArray<string | number> | null {\n if (value === null || value === undefined || typeof value === \"boolean\") return null;\n if (Array.isArray(value)) {\n return value.filter(\n (item): item is string | number => typeof item === \"string\" || typeof item === \"number\",\n );\n }\n return value as string | number;\n}\n\nfunction EnumFilter({\n field,\n value,\n onFilterChange,\n}: {\n field: FieldDef;\n value: FilterValue;\n onFilterChange: FilterBarProps[\"onFilterChange\"];\n}): React.ReactElement {\n const options = (field.enumValues ?? []).map((member) => ({\n value: String(member),\n label: enumLabel(member, field.enumLabels),\n }));\n return (\n <Select\n aria-label={field.label}\n className=\"h-9 w-auto min-w-36\"\n value={toSelectValue(value)}\n options={options}\n placeholder={field.label}\n clearable\n clearLabel=\"All\"\n onValueChange={(next) => {\n if (next === null) {\n onFilterChange(field, null);\n return;\n }\n // Preserve the member's original type (numeric enums stay numbers).\n const member = (field.enumValues ?? []).find((candidate) => String(candidate) === next);\n onFilterChange(field, member ?? next);\n }}\n />\n );\n}\n\nfunction BooleanFilter({\n field,\n value,\n onFilterChange,\n}: {\n field: FieldDef;\n value: FilterValue;\n onFilterChange: FilterBarProps[\"onFilterChange\"];\n}): React.ReactElement {\n return (\n <Select\n aria-label={field.label}\n className=\"h-9 w-auto min-w-36\"\n value={typeof value === \"boolean\" ? String(value) : null}\n options={[\n { value: \"true\", label: \"Yes\" },\n { value: \"false\", label: \"No\" },\n ]}\n placeholder={field.label}\n clearable\n clearLabel=\"All\"\n onValueChange={(next) => onFilterChange(field, next === null ? null : next === \"true\")}\n />\n );\n}\n\n/** Search box + up to four filter controls in one wrapping row. */\nexport function FilterBar(props: FilterBarProps): React.ReactElement {\n const {\n searchEnabled,\n searchValue,\n onSearchChange,\n searchPlaceholder = \"Search…\",\n filterFields,\n values,\n onFilterChange,\n className,\n } = props;\n\n return (\n <div className={cn(\"flex flex-wrap items-center gap-2\", className)}>\n {searchEnabled && (\n <Input\n type=\"search\"\n aria-label=\"Search\"\n placeholder={searchPlaceholder}\n value={searchValue}\n onChange={(event) => onSearchChange(event.target.value)}\n className=\"h-9 w-full max-w-xs\"\n />\n )}\n {filterFields.map((field) => {\n const value = values[field.name];\n if (field.kind === \"enum\") {\n return (\n <EnumFilter\n key={field.name}\n field={field}\n value={value}\n onFilterChange={onFilterChange}\n />\n );\n }\n if (field.kind === \"boolean\") {\n return (\n <BooleanFilter\n key={field.name}\n field={field}\n value={value}\n onFilterChange={onFilterChange}\n />\n );\n }\n if (field.kind === \"relation\" && field.relation !== undefined) {\n return (\n <div key={field.name} className=\"min-w-36\">\n <ResourceSelect\n resource={field.relation.resource}\n multiple={field.relation.many}\n value={toRelationValue(value)}\n placeholder={field.label}\n onChange={(next) => onFilterChange(field, next)}\n />\n </div>\n );\n }\n return null;\n })}\n </div>\n );\n}\n","/**\n * ResourceTable's server-mode pagination row (DRF PageNumberPagination:\n * `{count, next, previous, results}` with `page` / `page_size` params).\n * Internal to @karni/ui — the public surface is ResourceTable's props.\n */\nimport * as React from \"react\";\nimport { cn } from \"../../../lib/cn\";\nimport { Button } from \"../../primitives/button\";\n\nexport interface PaginationControlsProps {\n /** 1-based current page. */\n page: number;\n pageCount: number;\n /** Total item count across all pages (DRF `count`). */\n totalCount: number;\n /** From DRF `previous` / `next` — the server is the authority. */\n hasPrevious: boolean;\n hasNext: boolean;\n onPageChange: (page: number) => void;\n className?: string;\n}\n\nexport function PaginationControls(props: PaginationControlsProps): React.ReactElement {\n const { page, pageCount, totalCount, hasPrevious, hasNext, onPageChange, className } = props;\n return (\n <nav\n aria-label=\"Pagination\"\n className={cn(\"flex flex-wrap items-center justify-between gap-3\", className)}\n >\n <p className=\"text-sm text-muted-foreground\">\n Page {page} of {pageCount} · {totalCount} {totalCount === 1 ? \"item\" : \"items\"}\n </p>\n <div className=\"flex items-center gap-2\">\n <Button\n variant=\"outline\"\n size=\"sm\"\n disabled={!hasPrevious}\n onClick={() => onPageChange(Math.max(1, page - 1))}\n >\n Previous\n </Button>\n <Button\n variant=\"outline\"\n size=\"sm\"\n disabled={!hasNext}\n onClick={() => onPageChange(page + 1)}\n >\n Next\n </Button>\n </div>\n </nav>\n );\n}\n","/**\n * Tiny debounce hook for ResourceTable's search box, so a keystroke burst\n * becomes one list query. Internal to @karni/ui.\n */\nimport * as React from \"react\";\n\nexport function useDebouncedValue<T>(value: T, delayMs: number): T {\n const [debounced, setDebounced] = React.useState(value);\n React.useEffect(() => {\n const timer = setTimeout(() => setDebounced(value), delayMs);\n return () => clearTimeout(timer);\n }, [value, delayMs]);\n return debounced;\n}\n","/**\n * ResourceTable — the schema-driven data table (contract \"ResourceTable\" + D5).\n *\n * `<Page title=\"Events\"><ResourceTable resource=\"events\" /></Page>` is a\n * complete screen: columns derive from the parsed OpenAPI schema, sorting maps\n * to DRF `ordering`, the search box renders only when the list operation\n * declares `search`, the filter bar derives from the declared query params,\n * and pagination speaks `page` / `page_size`.\n *\n * Audit fields (AUDIT_FIELDS — id, created_at, updated_at, created_by,\n * updated_by, carried by every BaseModel resource) are hidden by default so\n * domain fields lead; rows stay keyed by `id` regardless (getRowId, row\n * actions, onRowClick, bulk selection). Show one with a `columns` entry\n * (`{ field: \"created_at\" }`), or all of them with `showAuditFields`.\n *\n * Escape hatches: `columns` (per-field overrides), `extraColumns` (ColumnDef\n * passthrough), `columnsOverride` (applied last over the derived + merged\n * domain columns; the selection and actions columns are structural and follow\n * `bulkActions` / `rowActions` / `onEdit` / `enableDelete`), `rowActions`,\n * `bulkActions`, `filters`, `toolbar` / `empty` / `footer` slots,\n * `getRowLabel`, and `className`.\n */\nimport { keepPreviousData, useQueryClient } from \"@tanstack/react-query\";\nimport {\n flexRender,\n getCoreRowModel,\n useReactTable,\n type ColumnDef,\n type RowSelectionState,\n type SortingState,\n type Updater,\n} from \"@tanstack/react-table\";\nimport * as React from \"react\";\nimport { karniKeys } from \"../../../hooks/keys\";\nimport type { FilterValue, ResourceListParams } from \"../../../hooks/types\";\nimport { useResourceList } from \"../../../hooks/useResourceList\";\nimport type { KarniQueryValue } from \"../../../schema/client\";\nimport { useResourceMutations } from \"../../../hooks/useResourceMutations\";\nimport { cn } from \"../../../lib/cn\";\nimport type { FieldDef } from \"../../../schema/types\";\nimport { useSchema } from \"../../../schema/useSchema\";\nimport { EmptyState } from \"../../empty-state/empty-state\";\nimport { Button } from \"../../primitives/button\";\nimport { Checkbox } from \"../../primitives/checkbox\";\nimport { ChevronDownIcon, ChevronUpIcon } from \"../../primitives/icons\";\nimport { Skeleton } from \"../../primitives/skeleton\";\nimport { isAuditField, partitionAuditFields } from \"../audit-fields\";\nimport { displayLabel } from \"../displayLabel\";\nimport type { ExportFormat } from \"../../../hooks/useResourceImport\";\nimport { BulkActionsBar, type BulkAction } from \"./BulkActionsBar\";\nimport { deriveColumns, type ResourceColumn } from \"./derive-columns\";\nimport { ExportButtons } from \"./ExportButtons\";\nimport { FilterBar } from \"./FilterBar\";\nimport { PaginationControls } from \"./PaginationControls\";\nimport {\n asRecord,\n errorMessage,\n isNotFoundError,\n pageCountFor,\n sortingToOrdering,\n} from \"./table-utils\";\nimport { useDebouncedValue } from \"./use-debounced-value\";\nimport { registerComponentRole } from \"../../../lib/roles\";\n\nregisterComponentRole(\"data-table\", \"ResourceTable\");\n\nexport type { BulkAction, ResourceColumn };\n\nexport const DEFAULT_PAGE_SIZE = 25;\nconst SEARCH_DEBOUNCE_MS = 300;\nconst MAX_DERIVED_FILTERS = 4;\n\nexport interface ResourceTableProps<T = Record<string, unknown>> {\n resource: string;\n /**\n * Per-field overrides. Naming a default-hidden field (an audit field such\n * as `created_at`, or a json/file field) shows it; `hidden: true` hides one.\n */\n columns?: ReadonlyArray<ResourceColumn<T>>;\n /**\n * Show the audit columns (AUDIT_FIELDS: id, created_at, updated_at,\n * created_by, updated_by) after the domain columns, and let audit fields\n * into the derived filter bar. Default false: they are hidden.\n */\n showAuditFields?: boolean;\n /** TanStack ColumnDef pass-through, appended after derived columns. */\n extraColumns?: ReadonlyArray<ColumnDef<T>>;\n /** Full escape hatch, applied last over the derived + merged columns. */\n columnsOverride?: (derived: Array<ColumnDef<T>>) => Array<ColumnDef<T>>;\n rowActions?: (row: T) => React.ReactNode;\n /** Passing this enables the default edit row action. */\n onEdit?: (row: T) => void;\n /** Enables the default delete row action (uses useResourceMutations). */\n enableDelete?: boolean;\n bulkActions?: ReadonlyArray<BulkAction>;\n onRowClick?: (row: T) => void;\n /**\n * `expand` query values. Default: single-relation field names ∩ the list\n * operation's expand enum — never guessed beyond the schema (D5).\n */\n expand?: readonly string[];\n initialSorting?: SortingState;\n /** Sent as `page_size`. Default 25. */\n pageSize?: number;\n /**\n * Field names to build the filter bar from; `false` disables it. Default:\n * (enum/boolean/relation fields) ∩ declared list query params, domain\n * fields first, audit fields only with `showAuditFields`, cap 4 (D5).\n * Only enum, boolean and relation fields get controls.\n */\n filters?: readonly string[] | false;\n /**\n * Fixed filters sent with every request and hidden from the filter bar —\n * e.g. `{ event: eventId }` for \"the bookings of this event\". A user filter\n * on the same field never overrides them.\n */\n params?: Readonly<Record<string, KarniQueryValue>>;\n /**\n * Export buttons (one per format) when the resource serves\n * `GET /<resource>/export/` — every Karni BaseViewSet does. The file carries\n * the table's current filters, search and ordering; the backend applies the\n * row scope and field visibility. Default `[\"csv\", \"xlsx\"]`; `false` hides them.\n */\n exportFormats?: readonly ExportFormat[] | false;\n /** Extra toolbar content, rendered to the right of the search/filter row. */\n toolbar?: React.ReactNode;\n /** Replaces the default EmptyState when the list has no results. */\n empty?: React.ReactNode;\n /** Rendered under the pagination row. */\n footer?: React.ReactNode;\n /** Overrides displayLabel() for relation cells (and the delete confirm). */\n getRowLabel?: (row: Record<string, unknown>) => string;\n className?: string;\n}\n\n// structural columns\n\nfunction selectionColumn<T>(): ColumnDef<T> {\n return {\n id: \"__select__\",\n enableSorting: false,\n header: ({ table }) => (\n <Checkbox\n aria-label=\"Select all rows\"\n checked={\n table.getIsAllPageRowsSelected()\n ? true\n : table.getIsSomePageRowsSelected()\n ? \"indeterminate\"\n : false\n }\n onCheckedChange={(checked) => table.toggleAllPageRowsSelected(checked === true)}\n />\n ),\n cell: ({ row }) => (\n <div className=\"flex items-center\" onClick={(event) => event.stopPropagation()}>\n <Checkbox\n aria-label=\"Select row\"\n checked={row.getIsSelected()}\n onCheckedChange={(checked) => row.toggleSelected(checked === true)}\n />\n </div>\n ),\n };\n}\n\nfunction DeleteRowButton(props: {\n resource: string;\n row: Record<string, unknown>;\n getRowLabel?: (row: Record<string, unknown>) => string;\n}): React.ReactElement {\n const mutations = useResourceMutations(props.resource);\n const label = (props.getRowLabel ?? displayLabel)(props.row);\n return (\n <Button\n variant=\"ghost\"\n size=\"sm\"\n className=\"text-destructive hover:text-destructive\"\n disabled={mutations.remove.isPending}\n onClick={() => {\n const id = props.row[\"id\"];\n if (id === null || id === undefined) return;\n const confirmed =\n typeof window === \"undefined\" ||\n typeof window.confirm !== \"function\" ||\n window.confirm(`Delete \"${label}\"? This cannot be undone.`);\n if (confirmed) mutations.remove.mutate(id as string | number);\n }}\n >\n Delete\n </Button>\n );\n}\n\nfunction actionsColumn<T>(options: {\n resource: string;\n rowActions?: (row: T) => React.ReactNode;\n onEdit?: (row: T) => void;\n enableDelete?: boolean;\n getRowLabel?: (row: Record<string, unknown>) => string;\n}): ColumnDef<T> {\n const { resource, rowActions, onEdit, enableDelete, getRowLabel } = options;\n return {\n id: \"__actions__\",\n enableSorting: false,\n header: () => <span className=\"sr-only\">Actions</span>,\n cell: ({ row }) => (\n <div\n className=\"flex items-center justify-end gap-1\"\n onClick={(event) => event.stopPropagation()}\n >\n {onEdit !== undefined && (\n <Button variant=\"ghost\" size=\"sm\" onClick={() => onEdit(row.original)}>\n Edit\n </Button>\n )}\n {rowActions?.(row.original)}\n {enableDelete === true && (\n <DeleteRowButton\n resource={resource}\n row={asRecord(row.original)}\n getRowLabel={getRowLabel}\n />\n )}\n </div>\n ),\n };\n}\n\n// states\n\nfunction TableSkeleton({ rows = 8 }: { rows?: number }): React.ReactElement {\n return (\n <div\n role=\"status\"\n aria-live=\"polite\"\n className=\"flex w-full flex-col gap-3 rounded-md border border-border p-4\"\n >\n <span className=\"sr-only\">Loading…</span>\n <Skeleton className=\"h-6 w-1/3\" />\n {Array.from({ length: rows }, (_, index) => (\n <Skeleton key={index} className=\"h-8 w-full\" />\n ))}\n </div>\n );\n}\n\nfunction ErrorPanel(props: { error: unknown; onRetry?: () => void }): React.ReactElement {\n return (\n <div\n role=\"alert\"\n className=\"flex w-full flex-col items-center gap-3 rounded-md border border-destructive/50 bg-destructive/10 px-6 py-8 text-center\"\n >\n <p className=\"text-sm font-medium text-destructive\">{errorMessage(props.error)}</p>\n {props.onRetry !== undefined && (\n <Button variant=\"outline\" size=\"sm\" onClick={props.onRetry}>\n Retry\n </Button>\n )}\n </div>\n );\n}\n\n/** Mounted only on schema errors, so the hook never runs otherwise. */\nfunction SchemaErrorPanel(props: { error: unknown }): React.ReactElement {\n const queryClient = useQueryClient();\n return (\n <ErrorPanel\n error={props.error}\n onRetry={() => {\n void queryClient.invalidateQueries({ queryKey: karniKeys.schema() });\n }}\n />\n );\n}\n\n// the table\n\n/** Schema-driven data table for one resource: columns, sorting, filters, search, pagination, row actions and bulk select, all derived from the OpenAPI schema. */\nexport function ResourceTable<T = Record<string, unknown>>(\n props: ResourceTableProps<T>,\n): React.ReactElement {\n const {\n resource,\n columns,\n showAuditFields,\n extraColumns,\n columnsOverride,\n rowActions,\n onEdit,\n enableDelete,\n bulkActions,\n onRowClick,\n expand,\n initialSorting,\n pageSize,\n filters,\n params,\n exportFormats,\n toolbar,\n empty,\n footer,\n getRowLabel,\n className,\n } = props;\n\n const schemaResult = useSchema(resource);\n const schema = schemaResult.data;\n\n // server-mode state (TanStack manual)\n const [sorting, setSorting] = React.useState<SortingState>(initialSorting ?? []);\n const [rowSelection, setRowSelection] = React.useState<RowSelectionState>({});\n const [page, setPage] = React.useState(1);\n const [searchInput, setSearchInput] = React.useState(\"\");\n const [filterValues, setFilterValues] = React.useState<Record<string, FilterValue>>({});\n\n const effectivePageSize = pageSize ?? DEFAULT_PAGE_SIZE;\n const debouncedSearch = useDebouncedValue(searchInput, SEARCH_DEBOUNCE_MS);\n\n // A settled search change starts over from page 1 (skip the initial value).\n const lastSearch = React.useRef(debouncedSearch);\n React.useEffect(() => {\n if (lastSearch.current !== debouncedSearch) {\n lastSearch.current = debouncedSearch;\n setPage(1);\n }\n }, [debouncedSearch]);\n\n const handleSortingChange = React.useCallback((updater: Updater<SortingState>) => {\n setSorting((old) => (typeof updater === \"function\" ? updater(old) : updater));\n setPage(1);\n }, []);\n\n const handleFilterChange = React.useCallback((field: FieldDef, value: FilterValue) => {\n setFilterValues((old) => {\n const cleared =\n value === null ||\n value === undefined ||\n value === \"\" ||\n (Array.isArray(value) && value.length === 0);\n if (cleared) {\n return Object.fromEntries(Object.entries(old).filter(([key]) => key !== field.name));\n }\n return { ...old, [field.name]: value };\n });\n setPage(1);\n }, []);\n\n // schema-derived behaviour (D5)\n const expandList = React.useMemo<readonly string[]>(() => {\n if (expand !== undefined) return expand;\n const allowed = schema?.operations.list?.expandEnum;\n if (schema === undefined || allowed === undefined) return [];\n return schema.fields\n .filter(\n (field) =>\n field.kind === \"relation\" &&\n field.relation !== undefined &&\n !field.relation.many &&\n allowed.includes(field.name),\n )\n .map((field) => field.name);\n }, [expand, schema]);\n\n const pinned = React.useMemo(() => new Set(Object.keys(params ?? {})), [params]);\n const filterFields = React.useMemo<readonly FieldDef[]>(() => {\n if (filters === false || schema === undefined) return [];\n if (filters !== undefined) {\n const byName = new Map(schema.fields.map((field) => [field.name, field]));\n return filters\n .filter((name) => !pinned.has(name))\n .map((name) => byName.get(name))\n .filter((field): field is FieldDef => field !== undefined);\n }\n const declared = new Set(schema.operations.list?.queryParams ?? []);\n const { domain, audit } = partitionAuditFields(schema.fields);\n return [...domain, ...audit]\n .filter(\n (field) =>\n !field.writeOnly &&\n !pinned.has(field.name) &&\n (showAuditFields === true || !isAuditField(field)) &&\n declared.has(field.name) &&\n (field.kind === \"enum\" ||\n field.kind === \"boolean\" ||\n (field.kind === \"relation\" && field.relation !== undefined)),\n )\n .slice(0, MAX_DERIVED_FILTERS);\n }, [filters, pinned, schema, showAuditFields]);\n\n const searchEnabled = schema?.operations.list?.hasSearch === true;\n\n // the list query\n const trimmedSearch = debouncedSearch.trim();\n const listParams = React.useMemo<ResourceListParams>(\n () => ({\n page,\n pageSize: effectivePageSize,\n ordering: sortingToOrdering(sorting),\n search: searchEnabled && trimmedSearch.length > 0 ? trimmedSearch : undefined,\n filters:\n Object.keys(filterValues).length > 0 || params !== undefined\n ? { ...filterValues, ...params }\n : undefined,\n expand: expandList.length > 0 ? expandList : undefined,\n }),\n [\n page,\n effectivePageSize,\n sorting,\n searchEnabled,\n trimmedSearch,\n filterValues,\n params,\n expandList,\n ],\n );\n\n const list = useResourceList<T>(resource, listParams, {\n enabled: schema !== undefined,\n placeholderData: keepPreviousData,\n // A 404 is the page-clamp signal (D5) — retrying it only delays the clamp.\n retry: (failureCount, error) => !isNotFoundError(error) && failureCount < 3,\n });\n\n // D5 page-clamp: list 404 with page > 1 → decrement + refetch as loading.\n const clamping = isNotFoundError(list.error) && page > 1;\n React.useEffect(() => {\n if (clamping) setPage((current) => Math.max(1, current - 1));\n }, [clamping, page]);\n\n // columns\n const hasBulkSelect = bulkActions !== undefined && bulkActions.length > 0;\n const hasActions = rowActions !== undefined || onEdit !== undefined || enableDelete === true;\n\n const columnDefs = React.useMemo<Array<ColumnDef<T>>>(() => {\n if (schema === undefined) return [];\n let defs = deriveColumns<T>({ fields: schema.fields, columns, getRowLabel, showAuditFields });\n if (extraColumns !== undefined) defs = [...defs, ...extraColumns];\n if (columnsOverride !== undefined) defs = columnsOverride(defs);\n const leading: Array<ColumnDef<T>> = hasBulkSelect ? [selectionColumn<T>()] : [];\n const trailing: Array<ColumnDef<T>> = hasActions\n ? [actionsColumn<T>({ resource, rowActions, onEdit, enableDelete, getRowLabel })]\n : [];\n return [...leading, ...defs, ...trailing];\n }, [\n schema,\n columns,\n getRowLabel,\n showAuditFields,\n extraColumns,\n columnsOverride,\n hasBulkSelect,\n hasActions,\n resource,\n rowActions,\n onEdit,\n enableDelete,\n ]);\n\n const rows = React.useMemo<T[]>(() => list.data?.results ?? [], [list.data]);\n const count = list.data?.count;\n const pageCount = pageCountFor(count, effectivePageSize);\n\n const table = useReactTable<T>({\n data: rows,\n columns: columnDefs,\n state: { sorting, rowSelection },\n manualSorting: true,\n manualPagination: true,\n manualFiltering: true,\n pageCount,\n enableRowSelection: hasBulkSelect,\n onSortingChange: handleSortingChange,\n onRowSelectionChange: setRowSelection,\n // D5: selection is keyed by String(row.id) and persists across pages —\n // rows always carry `id`, even while its column is hidden.\n getRowId: (row) => String(asRecord(row).id),\n getCoreRowModel: getCoreRowModel(),\n });\n\n const selectedIds = React.useMemo(\n () => Object.keys(rowSelection).filter((id) => rowSelection[id]),\n [rowSelection],\n );\n\n const hasActiveNarrowing = trimmedSearch.length > 0 || Object.keys(filterValues).length > 0;\n\n // render\n let body: React.ReactNode;\n if (schemaResult.error !== null && schemaResult.error !== undefined) {\n body = <SchemaErrorPanel error={schemaResult.error} />;\n } else if (schemaResult.isLoading || schema === undefined || list.isPending || clamping) {\n body = <TableSkeleton />;\n } else if (list.error !== null && list.error !== undefined) {\n body = (\n <ErrorPanel\n error={list.error}\n onRetry={() => {\n void list.refetch();\n }}\n />\n );\n } else if (rows.length === 0) {\n body =\n empty ??\n (hasActiveNarrowing ? (\n <EmptyState title=\"No results\" description=\"Try adjusting your search or filters.\" />\n ) : (\n <EmptyState title=\"Nothing here yet\" description=\"Records will appear here once created.\" />\n ));\n } else {\n body = (\n <>\n <div\n className={cn(\n \"w-full overflow-x-auto rounded-md border border-border\",\n list.isFetching && \"opacity-60\",\n )}\n >\n <table className=\"w-full caption-bottom text-sm\" aria-busy={list.isFetching}>\n <thead className=\"border-b border-border bg-muted\">\n <tr>\n {table.getFlatHeaders().map((header) => {\n const canSort = header.column.getCanSort();\n const direction = header.column.getIsSorted();\n return (\n <th\n key={header.id}\n scope=\"col\"\n aria-sort={\n direction === \"asc\"\n ? \"ascending\"\n : direction === \"desc\"\n ? \"descending\"\n : undefined\n }\n className=\"h-10 px-3 text-left align-middle text-xs font-medium text-muted-foreground\"\n >\n {header.isPlaceholder ? null : canSort ? (\n <button\n type=\"button\"\n className=\"inline-flex items-center gap-1 rounded-sm hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring\"\n onClick={(event) => header.column.getToggleSortingHandler()?.(event)}\n >\n {flexRender(header.column.columnDef.header, header.getContext())}\n {direction === \"asc\" ? (\n <ChevronUpIcon className=\"h-3.5 w-3.5\" />\n ) : direction === \"desc\" ? (\n <ChevronDownIcon className=\"h-3.5 w-3.5\" />\n ) : null}\n </button>\n ) : (\n flexRender(header.column.columnDef.header, header.getContext())\n )}\n </th>\n );\n })}\n </tr>\n </thead>\n <tbody>\n {table.getRowModel().rows.map((row) => (\n <tr\n key={row.id}\n data-state={row.getIsSelected() ? \"selected\" : undefined}\n onClick={onRowClick !== undefined ? () => onRowClick(row.original) : undefined}\n className={cn(\n \"border-b border-border transition-colors last:border-0 hover:bg-muted data-[state=selected]:bg-muted\",\n onRowClick !== undefined && \"cursor-pointer\",\n )}\n >\n {row.getVisibleCells().map((cell) => (\n <td key={cell.id} className=\"px-3 py-2 align-middle\">\n {flexRender(cell.column.columnDef.cell, cell.getContext())}\n </td>\n ))}\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n {count !== undefined && count > 0 && (\n <PaginationControls\n page={page}\n pageCount={pageCount}\n totalCount={count}\n hasPrevious={list.data?.previous !== null && list.data?.previous !== undefined}\n hasNext={list.data?.next !== null && list.data?.next !== undefined}\n onPageChange={setPage}\n />\n )}\n </>\n );\n }\n\n const exportList: readonly ExportFormat[] =\n exportFormats === undefined ? [\"csv\", \"xlsx\"] : exportFormats === false ? [] : exportFormats;\n const exportEnabled = exportList.length > 0 && schema?.operations.export !== undefined;\n\n const showFilterRow =\n schema !== undefined &&\n (searchEnabled || filterFields.length > 0 || toolbar !== undefined || exportEnabled);\n\n return (\n <div className={cn(\"flex w-full flex-col gap-3\", className)}>\n {showFilterRow && (\n <div className=\"flex flex-wrap items-center justify-between gap-3\">\n <FilterBar\n searchEnabled={searchEnabled}\n searchValue={searchInput}\n onSearchChange={setSearchInput}\n filterFields={filterFields}\n values={filterValues}\n onFilterChange={handleFilterChange}\n className=\"min-w-0 flex-1\"\n />\n {(toolbar !== undefined || exportEnabled) && (\n <div className=\"flex shrink-0 items-center gap-2\">\n {exportEnabled && (\n <ExportButtons resource={resource} params={listParams} formats={exportList} />\n )}\n {toolbar}\n </div>\n )}\n </div>\n )}\n {hasBulkSelect && selectedIds.length > 0 && (\n <BulkActionsBar\n selectedIds={selectedIds}\n bulkActions={bulkActions}\n onClear={() => setRowSelection({})}\n />\n )}\n {body}\n {footer}\n </div>\n );\n}\n","/**\n * zodFor — runtime Zod schema generation from a ResourceSchema (contract\n * \"Schema client\" + D3).\n *\n * Rules:\n * - mode \"create\": the create request's required fields are required, the\n * rest are `.optional()`; mode \"update\": ALL fields are optional, with\n * `.nullable()` nested INSIDE `.optional()` so `undefined` means \"not\n * touched\" and `null` means \"clear this nullable field\".\n * - readOnly fields are excluded, writeOnly fields are included.\n * - nullable / maxLength / min / max and the email / url / uuid string\n * formats map onto the obvious Zod validators.\n * - enum → z.enum when every member is a string, otherwise a union of\n * z.literal; \"\" (BlankEnum) and null (NullEnum) are never members — the\n * parser already stripped them, nullability travels on the field.\n * - relation values take their schema from the property's own emitted\n * type/format (integer pk vs uuid pk), arrays of it when `many`.\n * - file → File-or-string; when `File` does not exist (SSR) it degrades to\n * z.string() so imports never crash.\n * - json → z.unknown(); number/integer coerce (form inputs produce strings).\n * - datetime accepts datetime-local input (\"YYYY-MM-DDTHH:mm[:ss]\") and\n * transforms it to full ISO-8601 with offset on submit (D3).\n */\nimport { z } from \"zod\";\nimport type { ZodObject, ZodRawShape, ZodTypeAny } from \"zod\";\nimport type { FieldDef, ResourceSchema } from \"./types\";\n\nconst REQUIRED_MESSAGE = \"This field is required.\";\n\n/** datetime-local output: no timezone designator at the end. */\nconst LOCAL_DATETIME = /^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}(:\\d{2}(\\.\\d{1,6})?)?$/;\n\nfunction toIsoWithOffset(value: string): string {\n if (!LOCAL_DATETIME.test(value)) return value; // already zoned (or server-side format)\n const date = new Date(value); // datetime-local strings parse as local time\n if (Number.isNaN(date.getTime())) return value;\n return date.toISOString();\n}\n\nfunction enumSchema(values: ReadonlyArray<string | number>): ZodTypeAny {\n if (values.length === 0) return z.never();\n if (values.every((value): value is string => typeof value === \"string\")) {\n return z.enum(values as [string, ...string[]]);\n }\n const literals = values.map((value) => z.literal(value));\n if (literals.length === 1) return literals[0];\n return z.union(literals as unknown as [ZodTypeAny, ZodTypeAny, ...ZodTypeAny[]]);\n}\n\nfunction stringSchema(field: FieldDef, requireNonEmpty: boolean): ZodTypeAny {\n let schema = z.string();\n if (field.format === \"email\") schema = schema.email();\n else if (field.format === \"uri\" || field.format === \"url\") schema = schema.url();\n else if (field.format === \"uuid\") schema = schema.uuid();\n if (field.maxLength !== undefined) schema = schema.max(field.maxLength);\n if (requireNonEmpty) schema = schema.min(1, REQUIRED_MESSAGE);\n return schema;\n}\n\nfunction numberSchema(field: FieldDef, integer: boolean): ZodTypeAny {\n let schema = z.coerce.number();\n if (integer) schema = schema.int();\n if (field.min !== undefined) schema = schema.min(field.min);\n if (field.max !== undefined) schema = schema.max(field.max);\n return schema;\n}\n\nfunction relationValueSchema(field: FieldDef, coerce: boolean): ZodTypeAny {\n switch (field.relationValueType) {\n case \"uuid\":\n return z.string({ required_error: REQUIRED_MESSAGE }).uuid();\n case \"integer\":\n return coerce\n ? z.coerce.number().int()\n : z.number({ required_error: REQUIRED_MESSAGE }).int();\n default:\n return z.string({ required_error: REQUIRED_MESSAGE }).min(1, REQUIRED_MESSAGE);\n }\n}\n\n/**\n * A single relation input left empty arrives as \"\" (an untouched select) or\n * null (a cleared one). A nullable relation then carries null (DRF's\n * allow_null); a required non-nullable one fails with REQUIRED_MESSAGE\n * instead of \"Invalid uuid\" / \"Expected string, received null\"; an optional\n * non-nullable one is omitted. Integer ids typed as strings are coerced.\n */\nfunction singleRelationSchema(field: FieldDef, requireNonEmpty: boolean): ZodTypeAny {\n const value = relationValueSchema(field, false);\n let target: ZodTypeAny = field.nullable ? value.nullable() : value;\n if (!requireNonEmpty) target = target.optional();\n return z.preprocess((raw) => {\n if (raw === \"\" || raw === null || raw === undefined) return field.nullable ? null : undefined;\n if (field.relationValueType === \"integer\" && typeof raw === \"string\" && raw.trim() !== \"\") {\n const parsed = Number(raw);\n return Number.isNaN(parsed) ? raw : parsed;\n }\n return raw;\n }, target);\n}\n\nfunction fileSchema(): ZodTypeAny {\n if (typeof File === \"undefined\") return z.string();\n return z.union([z.instanceof(File), z.string()]);\n}\n\nfunction baseSchemaFor(field: FieldDef, requireNonEmpty: boolean): ZodTypeAny {\n switch (field.kind) {\n case \"string\":\n case \"text\":\n return stringSchema(field, requireNonEmpty);\n case \"integer\":\n return numberSchema(field, true);\n case \"number\":\n return numberSchema(field, false);\n case \"boolean\":\n return z.boolean();\n case \"date\": {\n const schema = z.string();\n return requireNonEmpty ? schema.min(1, REQUIRED_MESSAGE) : schema;\n }\n case \"datetime\": {\n const schema = requireNonEmpty ? z.string().min(1, REQUIRED_MESSAGE) : z.string();\n return schema.transform(toIsoWithOffset);\n }\n case \"enum\":\n return enumSchema(field.enumValues ?? []);\n case \"relation\": {\n if (field.relation?.many === true) return z.array(relationValueSchema(field, true));\n return singleRelationSchema(field, requireNonEmpty);\n }\n case \"file\":\n return fileSchema();\n case \"json\":\n return z.unknown();\n case \"array\":\n return z.array(z.unknown());\n case \"unknown\":\n return z.unknown();\n }\n}\n\n/** Builds a Zod validator for a resource's create or update payload from its schema. */\nexport function zodFor(schema: ResourceSchema, mode: \"create\" | \"update\"): ZodObject<ZodRawShape> {\n const shape: ZodRawShape = {};\n\n for (const field of schema.fields) {\n if (field.readOnly) continue; // writeOnly stays in (D3)\n\n // A required string provided as \"\" must fail in BOTH modes: DRF rejects\n // blank values on required CharFields; in update mode the field may be\n // omitted entirely instead.\n const requireNonEmpty = field.required;\n let fieldSchema = baseSchemaFor(field, requireNonEmpty);\n\n if (field.nullable) fieldSchema = fieldSchema.nullable();\n // D3: in update mode .nullable() sits INSIDE .optional() — undefined\n // means untouched, null clears.\n if (mode === \"update\" || !field.required) fieldSchema = fieldSchema.optional();\n\n shape[field.name] = fieldSchema;\n }\n\n return z.object(shape);\n}\n","import * as React from \"react\";\nimport { cn } from \"../../lib/cn\";\nimport { registerComponentRole } from \"../../lib/roles\";\n\nregisterComponentRole(\"file-upload\", \"FileUpload\");\n\n/** Why a file was refused by <FileUpload> (surfaced through `onReject`). */\nexport type FileUploadRejectReason = \"accept\" | \"size\";\n\nexport interface FileUploadProps {\n /**\n * Current value. A `string` is an existing uploaded file (the display URL a\n * karni backend returns); a `File` is a pending upload. Arrays are for\n * `multiple` mode and may mix both.\n */\n value?: File | string | ReadonlyArray<File | string> | null;\n /**\n * Emits the newly chosen `File` (or `File[]` when `multiple`), and `null`\n * when the value is cleared. Existing URL strings are display-only: they\n * can be removed (emitting `null` / the remaining files) but never re-emitted.\n */\n onChange?: (value: File | File[] | null) => void;\n /** Same grammar as the native `accept` attribute (\".png,image/*,application/pdf\"). */\n accept?: string;\n multiple?: boolean;\n disabled?: boolean;\n /** Maximum size per file, in bytes. Larger files are rejected via `onReject`. */\n maxSize?: number;\n /** Called once per refused file with the reason (\"accept\" | \"size\"). */\n onReject?: (file: File, reason: FileUploadRejectReason) => void;\n id?: string;\n /** Forwarded to the hidden native file input. */\n name?: string;\n className?: string;\n /** Replaces the default dropzone content (escape hatch). */\n children?: React.ReactNode;\n /** Set false to hide the per-file remove affordance. Default true. */\n clearable?: boolean;\n \"aria-label\"?: string;\n}\n\nfunction matchesAccept(file: File, accept: string | undefined): boolean {\n if (accept === undefined || accept.trim() === \"\") return true;\n const tokens = accept\n .split(\",\")\n .map((token) => token.trim().toLowerCase())\n .filter((token) => token !== \"\");\n if (tokens.length === 0) return true;\n const name = file.name.toLowerCase();\n const type = file.type.toLowerCase();\n return tokens.some((token) => {\n if (token.startsWith(\".\")) return name.endsWith(token);\n if (token.endsWith(\"/*\")) return type.startsWith(token.slice(0, -1));\n return type === token;\n });\n}\n\nfunction formatFileSize(bytes: number): string {\n if (bytes < 1024) return `${bytes} B`;\n if (bytes < 1024 * 1024) return `${Math.round(bytes / 1024)} KB`;\n return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;\n}\n\nfunction fileBasename(url: string): string {\n const withoutQuery = url.split(/[?#]/, 1)[0] ?? url;\n const segments = withoutQuery.split(\"/\").filter((segment) => segment !== \"\");\n return segments[segments.length - 1] ?? url;\n}\n\nfunction UploadIcon(props: React.SVGAttributes<SVGSVGElement>): React.ReactElement {\n return (\n <svg\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth={2}\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n focusable={false}\n {...props}\n >\n <path d=\"M21 15v3a3 3 0 0 1-3 3H6a3 3 0 0 1-3-3v-3\" />\n <polyline points=\"7 8 12 3 17 8\" />\n <line x1=\"12\" y1=\"3\" x2=\"12\" y2=\"15\" />\n </svg>\n );\n}\n\nfunction XIcon(props: React.SVGAttributes<SVGSVGElement>): React.ReactElement {\n return (\n <svg\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth={2}\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n focusable={false}\n {...props}\n >\n <line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\" />\n <line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\" />\n </svg>\n );\n}\n\n/**\n * Drag-and-drop or click-to-browse file picker that shows the current file and the pending ones.\n *\n * Contract \"FileUpload\".\n *\n * Shows an existing uploaded value (URL string) as a link, pending `File`\n * values with name and size, and emits `File` objects — the hooks layer turns\n * them into multipart bodies per amendment D2.\n */\nexport function FileUpload(props: FileUploadProps): React.ReactElement {\n const {\n value = null,\n onChange,\n accept,\n multiple = false,\n disabled = false,\n maxSize,\n onReject,\n id,\n name,\n className,\n children,\n clearable = true,\n } = props;\n\n const inputRef = React.useRef<HTMLInputElement>(null);\n const [dragging, setDragging] = React.useState(false);\n\n const entries: ReadonlyArray<File | string> =\n value == null ? [] : Array.isArray(value) ? value : [value as File | string];\n\n const acceptFiles = (list: ArrayLike<File>): void => {\n if (disabled) return;\n const accepted: File[] = [];\n for (const file of Array.from(list)) {\n if (!matchesAccept(file, accept)) {\n onReject?.(file, \"accept\");\n continue;\n }\n if (maxSize !== undefined && file.size > maxSize) {\n onReject?.(file, \"size\");\n continue;\n }\n accepted.push(file);\n }\n if (accepted.length === 0) return;\n onChange?.(multiple ? accepted : accepted[0]);\n };\n\n const handleInputChange = (event: React.ChangeEvent<HTMLInputElement>): void => {\n if (event.target.files !== null) acceptFiles(event.target.files);\n // Reset so selecting the same file again re-fires the change event.\n event.target.value = \"\";\n };\n\n const handleDrop = (event: React.DragEvent<HTMLButtonElement>): void => {\n event.preventDefault();\n setDragging(false);\n if (disabled) return;\n acceptFiles(event.dataTransfer.files);\n };\n\n const handleDragOver = (event: React.DragEvent<HTMLButtonElement>): void => {\n event.preventDefault();\n if (!disabled) setDragging(true);\n };\n\n const removeEntry = (index: number): void => {\n if (onChange === undefined) return;\n const remaining = entries.filter((_, i) => i !== index);\n if (remaining.length === 0) {\n onChange(null);\n return;\n }\n // Existing URL strings cannot be re-emitted (onChange carries File values\n // only); the remaining pending files are kept.\n const files = remaining.filter((entry): entry is File => typeof entry !== \"string\");\n if (multiple) {\n onChange(files);\n } else {\n onChange(files[0] ?? null);\n }\n };\n\n return (\n <div className={cn(\"space-y-2\", className)}>\n <button\n type=\"button\"\n id={id}\n disabled={disabled}\n aria-label={props[\"aria-label\"]}\n onClick={() => inputRef.current?.click()}\n onDragOver={handleDragOver}\n onDragEnter={handleDragOver}\n onDragLeave={() => setDragging(false)}\n onDrop={handleDrop}\n data-dragging={dragging ? \"true\" : undefined}\n className=\"flex w-full flex-col items-center justify-center gap-1 rounded-md border border-dashed border-input bg-background px-4 py-6 text-sm text-muted-foreground transition-colors hover:border-ring hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 data-[dragging=true]:border-ring data-[dragging=true]:bg-accent data-[dragging=true]:text-accent-foreground\"\n >\n {children ?? (\n <>\n <UploadIcon className=\"h-5 w-5\" />\n <span>\n {multiple\n ? \"Drag and drop files here, or click to browse\"\n : \"Drag and drop a file here, or click to browse\"}\n </span>\n </>\n )}\n </button>\n <input\n ref={inputRef}\n type=\"file\"\n name={name}\n accept={accept}\n multiple={multiple}\n disabled={disabled}\n onChange={handleInputChange}\n tabIndex={-1}\n aria-hidden=\"true\"\n className=\"sr-only\"\n />\n {entries.length > 0 ? (\n <ul className=\"space-y-1\">\n {entries.map((entry, index) => {\n const label = typeof entry === \"string\" ? fileBasename(entry) : entry.name;\n return (\n <li\n key={typeof entry === \"string\" ? `url-${entry}` : `file-${entry.name}-${index}`}\n className=\"flex items-center justify-between gap-2 rounded-md border border-border bg-muted/50 px-3 py-1.5 text-sm\"\n >\n {typeof entry === \"string\" ? (\n <a\n href={entry}\n target=\"_blank\"\n rel=\"noreferrer\"\n className=\"truncate font-medium text-primary underline underline-offset-4\"\n >\n {label}\n </a>\n ) : (\n <span className=\"truncate\">\n {entry.name}\n <span className=\"ml-2 text-xs text-muted-foreground\">\n {formatFileSize(entry.size)}\n </span>\n </span>\n )}\n {clearable && !disabled ? (\n <button\n type=\"button\"\n aria-label={`Remove ${label}`}\n onClick={() => removeEntry(index)}\n className=\"rounded-sm p-1 text-muted-foreground hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring\"\n >\n <XIcon className=\"h-4 w-4\" />\n </button>\n ) : null}\n </li>\n );\n })}\n </ul>\n ) : null}\n </div>\n );\n}\n","/**\n * Pure helpers behind <ResourceForm>: initial-value construction, the D3\n * submit pipeline (dirty-field PATCH granularity, null-clearing, input\n * coercions) and small formatting utilities shared with <ResourceDetail>.\n */\nimport type { FieldDef } from \"../../../schema/types\";\n\nexport type FormValues = Record<string, unknown>;\n\n/** \"published_on\" / \"draft-mode\" → \"Published on\" / \"Draft mode\". */\nexport function humanizeValue(value: string): string {\n const spaced = value.replace(/[_-]+/g, \" \").trim();\n if (spaced === \"\") return value;\n return spaced.charAt(0).toUpperCase() + spaced.slice(1);\n}\n\nfunction pad(n: number): string {\n return String(n).padStart(2, \"0\");\n}\n\n/** ISO-8601 (any offset) → the local \"YYYY-MM-DDTHH:mm\" a datetime-local input needs. */\nexport function toDatetimeLocal(value: string): string {\n const date = new Date(value);\n if (Number.isNaN(date.getTime())) return value;\n return `${date.getFullYear()}-${pad(date.getMonth() + 1)}-${pad(date.getDate())}T${pad(\n date.getHours(),\n )}:${pad(date.getMinutes())}`;\n}\n\nconst HAS_ZONE = /(?:Z|[+-]\\d{2}:?\\d{2})$/i;\n\n/**\n * datetime-local value (\"YYYY-MM-DDTHH:mm[:ss]\", implicitly local) →\n * ISO-8601 with an explicit UTC offset, per the submit rule in the contract.\n * Values that already carry a zone pass through untouched.\n */\nexport function toIsoWithOffset(value: string): string {\n if (HAS_ZONE.test(value)) return value;\n const date = new Date(value);\n if (Number.isNaN(date.getTime())) return value;\n const offsetMinutes = -date.getTimezoneOffset();\n const sign = offsetMinutes >= 0 ? \"+\" : \"-\";\n const abs = Math.abs(offsetMinutes);\n const offset = `${sign}${pad(Math.floor(abs / 60))}:${pad(abs % 60)}`;\n return `${date.getFullYear()}-${pad(date.getMonth() + 1)}-${pad(date.getDate())}T${pad(\n date.getHours(),\n )}:${pad(date.getMinutes())}:${pad(date.getSeconds())}${offset}`;\n}\n\n/**\n * D3 dirtiness at TOP-LEVEL field granularity: a react-hook-form dirtyFields\n * entry counts as dirty when anything in its subtree is truthy, and the whole\n * field value is then sent (DRF PATCH replaces whole field values).\n */\nexport function isDirtyEntry(entry: unknown): boolean {\n if (entry === true) return true;\n if (Array.isArray(entry)) return entry.some(isDirtyEntry);\n if (entry !== null && typeof entry === \"object\") {\n return Object.values(entry).some(isDirtyEntry);\n }\n return false;\n}\n\n/** Unwraps an (accidentally expanded) relation object to its pk. */\nfunction pkOf(value: unknown): unknown {\n if (value !== null && typeof value === \"object\" && !Array.isArray(value) && \"id\" in value) {\n return (value as { id: unknown }).id;\n }\n return value;\n}\n\nexport interface BuildFormValuesInput {\n fields: readonly FieldDef[];\n /** Edit mode: the UNEXPANDED detail record (D10). Wins over defaultValues. */\n item?: Record<string, unknown>;\n defaultValues?: Record<string, unknown>;\n}\n\nfunction initialFieldValue(field: FieldDef, value: unknown): unknown {\n switch (field.kind) {\n case \"string\":\n case \"text\":\n return value == null ? \"\" : String(value);\n case \"number\":\n case \"integer\":\n return value == null ? \"\" : value;\n case \"boolean\":\n return Boolean(value);\n case \"date\":\n return value == null || value === \"\" ? \"\" : String(value).slice(0, 10);\n case \"datetime\":\n return value == null || value === \"\" ? \"\" : toDatetimeLocal(String(value));\n case \"enum\":\n return value == null ? null : value;\n case \"relation\":\n if (field.relation?.many === true) {\n return Array.isArray(value) ? value.map(pkOf) : [];\n }\n return value == null ? null : pkOf(value);\n case \"file\":\n return value == null ? null : value;\n case \"json\":\n return value == null ? \"\" : JSON.stringify(value, null, 2);\n default:\n return value;\n }\n}\n\n/**\n * Builds the react-hook-form value map: every form field gets a defined,\n * controlled-input-safe initial value. Unmatched `defaultValues` keys are kept\n * verbatim (they seed `extraFields`).\n */\nexport function buildFormValues({ fields, item, defaultValues }: BuildFormValuesInput): FormValues {\n const out: FormValues = {};\n for (const field of fields) {\n let source: unknown = defaultValues?.[field.name];\n if (source === undefined) source = field.default; // the model default, on create\n if (item !== undefined && field.name in item) source = item[field.name];\n out[field.name] = initialFieldValue(field, source);\n }\n if (defaultValues !== undefined) {\n for (const [key, value] of Object.entries(defaultValues)) {\n if (!(key in out)) out[key] = value;\n }\n }\n return out;\n}\n\ntype CoercionResult =\n { kind: \"value\"; value: unknown } | { kind: \"omit\" } | { kind: \"error\"; message: string };\n\nfunction val(value: unknown): CoercionResult {\n return { kind: \"value\", value };\n}\n\nconst OMIT: CoercionResult = { kind: \"omit\" };\n\n/** D3: an emptied nullable field is sent as null; a non-nullable one is omitted. */\nfunction emptied(field: FieldDef): CoercionResult {\n return field.nullable ? val(null) : OMIT;\n}\n\nfunction coerceFieldValue(field: FieldDef, value: unknown): CoercionResult {\n switch (field.kind) {\n case \"string\":\n case \"text\": {\n if (value == null) return emptied(field);\n const text = String(value);\n if (text === \"\" && field.nullable) return val(null);\n return val(text);\n }\n case \"number\":\n case \"integer\": {\n if (value == null || value === \"\") return emptied(field);\n const numeric = typeof value === \"number\" ? value : Number(value);\n if (!Number.isFinite(numeric)) return emptied(field);\n return val(numeric);\n }\n case \"boolean\":\n if (value == null) return emptied(field);\n return val(Boolean(value));\n case \"date\":\n if (value == null || value === \"\") return emptied(field);\n return val(String(value).slice(0, 10));\n case \"datetime\":\n if (value == null || value === \"\") return emptied(field);\n return val(toIsoWithOffset(String(value)));\n case \"enum\": {\n if (value == null || value === \"\") return emptied(field);\n const member = (field.enumValues ?? []).find(\n (candidate) => String(candidate) === String(value),\n );\n return val(member ?? value);\n }\n case \"relation\": {\n if (field.relation?.many === true) {\n // M2M fields are cleared with [] — null is not a valid DRF value here.\n if (value == null) return val([]);\n return val(Array.isArray(value) ? value.map(pkOf) : [pkOf(value)]);\n }\n if (value == null || value === \"\") return emptied(field);\n return val(pkOf(value));\n }\n case \"file\": {\n if (value == null) return emptied(field);\n // An unchanged string value is the existing file's URL — never resent (D2).\n if (typeof value === \"string\") return OMIT;\n return val(value);\n }\n case \"json\": {\n if (typeof value !== \"string\") {\n return value == null ? emptied(field) : val(value);\n }\n if (value.trim() === \"\") return emptied(field);\n try {\n return val(JSON.parse(value));\n } catch {\n return { kind: \"error\", message: \"Enter valid JSON.\" };\n }\n }\n default:\n return val(value);\n }\n}\n\nexport interface JsonFieldError {\n name: string;\n message: string;\n}\n\nexport interface PrepareSubmitInput {\n /** The writable schema fields rendered by the form. */\n fields: readonly FieldDef[];\n /** Resolver output from handleSubmit. */\n raw: FormValues;\n mode: \"create\" | \"update\";\n /** react-hook-form dirtyFields; only consulted in \"update\" mode (D3). */\n dirtyFields?: Record<string, unknown>;\n}\n\nexport interface PreparedSubmit {\n values: Record<string, unknown>;\n /** Per-field validation failures (invalid JSON) that must block the submit. */\n jsonErrors: JsonFieldError[];\n}\n\n/**\n * The D3 submit pipeline. Create mode sends every defined value; update mode\n * sends only fields whose dirtyFields subtree is truthy — always the WHOLE\n * field value. Keys without a schema field (extraFields) pass through as-is.\n */\nexport function prepareSubmit({\n fields,\n raw,\n mode,\n dirtyFields,\n}: PrepareSubmitInput): PreparedSubmit {\n const byName = new Map(fields.map((field) => [field.name, field]));\n const values: Record<string, unknown> = {};\n const jsonErrors: JsonFieldError[] = [];\n\n for (const [name, rawValue] of Object.entries(raw)) {\n if (mode === \"update\" && !isDirtyEntry(dirtyFields?.[name])) continue;\n const field = byName.get(name);\n if (field === undefined) {\n if (rawValue !== undefined) values[name] = rawValue;\n continue;\n }\n const result = coerceFieldValue(field, rawValue);\n if (result.kind === \"error\") {\n jsonErrors.push({ name, message: result.message });\n } else if (result.kind === \"value\" && result.value !== undefined) {\n values[name] = result.value;\n }\n }\n\n return { values, jsonErrors };\n}\n","/**\n * Default per-kind inputs for <ResourceForm> (contract: string → Input,\n * text → Textarea, number/integer → Input[type=number], boolean → Switch,\n * date/datetime → native inputs, enum → Select, relation → ResourceSelect\n * (multiple for many), file → FileUpload, json → Textarea with validation).\n */\nimport * as React from \"react\";\nimport { Controller } from \"react-hook-form\";\nimport type { Control, FieldValues } from \"react-hook-form\";\nimport type { FieldDef } from \"../../../schema/types\";\nimport { FileUpload } from \"../../file-upload/FileUpload\";\nimport { Input } from \"../../primitives/input\";\nimport { Select } from \"../../primitives/select\";\nimport { Switch } from \"../../primitives/switch\";\nimport { Textarea } from \"../../primitives/textarea\";\nimport { ResourceSelect } from \"../select/ResourceSelect\";\nimport { humanizeValue } from \"./prepare\";\n\nexport interface DefaultFieldControlProps {\n field: FieldDef;\n control: Control<FieldValues>;\n inputId: string;\n describedBy?: string;\n invalid: boolean;\n disabled?: boolean;\n /** FieldOverride.props pass-through, spread onto the rendered input. */\n inputProps?: Record<string, unknown>;\n}\n\nfunction stringInputType(field: FieldDef): string {\n switch (field.format) {\n case \"email\":\n return \"email\";\n case \"uri\":\n case \"url\":\n return \"url\";\n case \"password\":\n return \"password\";\n default:\n return \"text\";\n }\n}\n\nexport function DefaultFieldControl({\n field,\n control,\n inputId,\n describedBy,\n invalid,\n disabled,\n inputProps,\n}: DefaultFieldControlProps): React.ReactElement {\n const aria = {\n \"aria-invalid\": invalid || undefined,\n \"aria-describedby\": describedBy,\n } as const;\n\n return (\n <Controller\n control={control}\n name={field.name}\n render={({ field: rhf }) => {\n switch (field.kind) {\n case \"text\":\n return (\n <Textarea\n id={inputId}\n rows={4}\n maxLength={field.maxLength}\n disabled={disabled}\n value={rhf.value == null ? \"\" : String(rhf.value)}\n onChange={(event) => rhf.onChange(event.target.value)}\n onBlur={rhf.onBlur}\n {...aria}\n {...inputProps}\n />\n );\n case \"number\":\n case \"integer\":\n return (\n <Input\n id={inputId}\n type=\"number\"\n inputMode={field.kind === \"integer\" ? \"numeric\" : \"decimal\"}\n step={field.kind === \"integer\" ? 1 : \"any\"}\n min={field.min}\n max={field.max}\n disabled={disabled}\n value={rhf.value == null ? \"\" : (rhf.value as number | string)}\n onChange={(event) => rhf.onChange(event.target.value)}\n onBlur={rhf.onBlur}\n {...aria}\n {...inputProps}\n />\n );\n case \"boolean\":\n return (\n <Switch\n id={inputId}\n disabled={disabled}\n checked={Boolean(rhf.value)}\n onCheckedChange={(checked) => rhf.onChange(checked)}\n onBlur={rhf.onBlur}\n {...aria}\n {...inputProps}\n />\n );\n case \"date\":\n return (\n <Input\n id={inputId}\n type=\"date\"\n disabled={disabled}\n value={rhf.value == null ? \"\" : String(rhf.value)}\n onChange={(event) => rhf.onChange(event.target.value)}\n onBlur={rhf.onBlur}\n {...aria}\n {...inputProps}\n />\n );\n case \"datetime\":\n return (\n <Input\n id={inputId}\n type=\"datetime-local\"\n disabled={disabled}\n value={rhf.value == null ? \"\" : String(rhf.value)}\n onChange={(event) => rhf.onChange(event.target.value)}\n onBlur={rhf.onBlur}\n {...aria}\n {...inputProps}\n />\n );\n case \"enum\": {\n const members = field.enumValues ?? [];\n const options = members.map((member) => ({\n value: String(member),\n label: field.enumLabels?.[String(member)] ?? humanizeValue(String(member)),\n }));\n return (\n <Select\n id={inputId}\n disabled={disabled}\n value={rhf.value == null ? null : String(rhf.value)}\n options={options}\n clearable={field.nullable}\n placeholder=\"Select…\"\n onValueChange={(next) => {\n if (next === null) {\n rhf.onChange(null);\n return;\n }\n const member = members.find((candidate) => String(candidate) === next);\n rhf.onChange(member ?? next);\n }}\n {...inputProps}\n />\n );\n }\n case \"relation\": {\n const relation = field.relation;\n if (relation === undefined) {\n // Degraded mode: no x-karni-relation extension, edit the raw pk.\n return (\n <Input\n id={inputId}\n type=\"text\"\n disabled={disabled}\n value={rhf.value == null ? \"\" : String(rhf.value)}\n onChange={(event) => rhf.onChange(event.target.value)}\n onBlur={rhf.onBlur}\n {...aria}\n {...inputProps}\n />\n );\n }\n return (\n <ResourceSelect\n id={inputId}\n resource={relation.resource}\n multiple={relation.many}\n disabled={disabled}\n value={\n (rhf.value ?? null) as string | number | ReadonlyArray<string | number> | null\n }\n onChange={(next) => rhf.onChange(next)}\n {...inputProps}\n />\n );\n }\n case \"file\":\n return (\n <FileUpload\n id={inputId}\n disabled={disabled}\n value={(rhf.value ?? null) as File | string | null}\n onChange={(next) => rhf.onChange(next)}\n {...inputProps}\n />\n );\n case \"json\":\n return (\n <Textarea\n id={inputId}\n rows={5}\n disabled={disabled}\n className=\"font-mono\"\n value={\n typeof rhf.value === \"string\"\n ? rhf.value\n : rhf.value == null\n ? \"\"\n : JSON.stringify(rhf.value, null, 2)\n }\n onChange={(event) => rhf.onChange(event.target.value)}\n onBlur={rhf.onBlur}\n {...aria}\n {...inputProps}\n />\n );\n default:\n return (\n <Input\n id={inputId}\n type={stringInputType(field)}\n maxLength={field.maxLength}\n disabled={disabled}\n value={rhf.value == null ? \"\" : String(rhf.value)}\n onChange={(event) => rhf.onChange(event.target.value)}\n onBlur={rhf.onBlur}\n {...aria}\n {...inputProps}\n />\n );\n }\n }}\n />\n );\n}\n","import { zodResolver } from \"@hookform/resolvers/zod\";\nimport * as React from \"react\";\nimport { FormProvider, useForm } from \"react-hook-form\";\nimport type { Control, FieldValues, Resolver, UseFormReturn } from \"react-hook-form\";\nimport { useResourceItem } from \"../../../hooks/useResourceItem\";\nimport { useResourceMutations } from \"../../../hooks/useResourceMutations\";\nimport { cn } from \"../../../lib/cn\";\nimport type { FieldDef, ResourceSchema } from \"../../../schema/types\";\nimport { useSchema } from \"../../../schema/useSchema\";\nimport { zodFor } from \"../../../schema/zod\";\nimport { Button } from \"../../primitives/button\";\nimport { Label } from \"../../primitives/label\";\nimport { Skeleton } from \"../../primitives/skeleton\";\nimport { DefaultFieldControl } from \"./field-inputs\";\nimport { buildFormValues, prepareSubmit } from \"./prepare\";\nimport { registerComponentRole } from \"../../../lib/roles\";\n\nregisterComponentRole(\"resource-form\", \"ResourceForm\");\n\n/** Props passed to a custom field component (the `fields` escape hatch). */\nexport interface KarniFieldProps {\n field: FieldDef;\n name: string;\n label: string;\n required: boolean;\n control: Control<FieldValues>;\n error?: string;\n disabled?: boolean;\n /** Pass-through from FieldOverride.props. */\n props?: Record<string, unknown>;\n}\n\nexport interface FieldOverride {\n component?: React.ComponentType<KarniFieldProps>;\n label?: string;\n hidden?: boolean;\n props?: Record<string, unknown>;\n}\n\nexport interface ResourceFormProps {\n resource: string;\n /** Present → edit mode: loads the UNEXPANDED item, PATCHes dirty fields only (D10). */\n id?: string | number;\n defaultValues?: Record<string, unknown>;\n onSuccess?: (result: Record<string, unknown>) => void;\n onError?: (error: unknown) => void;\n fields?: Record<string, FieldOverride>;\n /** Custom RHF-registered nodes appended after the derived fields. */\n extraFields?: React.ReactNode;\n transformSubmit?: (values: Record<string, unknown>) => Record<string, unknown>;\n /** Replaces the submit row. */\n actions?: React.ReactNode;\n className?: string;\n}\n\n/** Field kinds the generic form knows how to render (others need an override). */\nconst EDITABLE_KINDS: ReadonlySet<string> = new Set([\n \"string\",\n \"text\",\n \"number\",\n \"integer\",\n \"boolean\",\n \"date\",\n \"datetime\",\n \"enum\",\n \"relation\",\n \"file\",\n \"json\",\n]);\n\nfunction errorMessage(error: unknown): string {\n if (error instanceof Error) return error.message;\n return String(error);\n}\n\nfunction FormSkeleton({ className }: { className?: string }): React.ReactElement {\n return (\n <div role=\"status\" aria-label=\"Loading form\" className={cn(\"space-y-5\", className)}>\n {[0, 1, 2].map((row) => (\n <div key={row} className=\"space-y-2\">\n <Skeleton className=\"h-4 w-24\" />\n <Skeleton className=\"h-10 w-full\" />\n </div>\n ))}\n <Skeleton className=\"h-10 w-28\" />\n </div>\n );\n}\n\nfunction FormErrorPanel({\n error,\n className,\n}: {\n error: unknown;\n className?: string;\n}): React.ReactElement {\n return (\n <div\n role=\"alert\"\n className={cn(\n \"rounded-md border border-destructive/50 bg-destructive/10 p-4 text-sm text-destructive\",\n className,\n )}\n >\n {errorMessage(error)}\n </div>\n );\n}\n\n/**\n * Maps a DRF 400 body ({field: [messages], non_field_errors: [...], detail})\n * onto react-hook-form errors. Unknown keys and non-field messages land on\n * `root.server`.\n */\nfunction applyServerErrors(\n error: unknown,\n knownNames: ReadonlySet<string>,\n methods: UseFormReturn<FieldValues>,\n): void {\n if (typeof error !== \"object\" || error === null) return;\n const maybe = error as { status?: unknown; data?: unknown };\n if (maybe.status !== 400) return;\n const data = maybe.data;\n if (Array.isArray(data)) {\n methods.setError(\"root.server\", { type: \"server\", message: data.map(String).join(\" \") });\n return;\n }\n if (typeof data !== \"object\" || data === null) return;\n const rootMessages: string[] = [];\n for (const [key, messages] of Object.entries(data as Record<string, unknown>)) {\n const message = Array.isArray(messages) ? messages.map(String).join(\" \") : String(messages);\n if (key === \"non_field_errors\" || key === \"detail\") {\n rootMessages.push(message);\n } else if (knownNames.has(key)) {\n methods.setError(key, { type: \"server\", message });\n } else {\n rootMessages.push(`${key}: ${message}`);\n }\n }\n if (rootMessages.length > 0) {\n methods.setError(\"root.server\", { type: \"server\", message: rootMessages.join(\" \") });\n }\n}\n\ninterface FormFieldRowProps {\n field: FieldDef;\n override?: FieldOverride;\n control: Control<FieldValues>;\n error?: string;\n disabled?: boolean;\n}\n\nfunction FormFieldRow({\n field,\n override,\n control,\n error,\n disabled,\n}: FormFieldRowProps): React.ReactElement {\n const inputId = React.useId();\n const label = override?.label ?? field.label;\n\n if (override?.component !== undefined) {\n const Component = override.component;\n return (\n <Component\n field={field}\n name={field.name}\n label={label}\n required={field.required}\n control={control}\n error={error}\n disabled={disabled}\n props={override.props}\n />\n );\n }\n\n const errorId = `${inputId}-error`;\n const descriptionId = `${inputId}-description`;\n const describedBy =\n [field.description !== undefined ? descriptionId : null, error !== undefined ? errorId : null]\n .filter((part): part is string => part !== null)\n .join(\" \") || undefined;\n\n return (\n <div className=\"space-y-2\">\n <Label htmlFor={inputId}>\n {label}\n {field.required ? (\n <span aria-hidden=\"true\" className=\"text-destructive\">\n {\" *\"}\n </span>\n ) : null}\n </Label>\n <DefaultFieldControl\n field={field}\n control={control}\n inputId={inputId}\n describedBy={describedBy}\n invalid={error !== undefined}\n disabled={disabled}\n inputProps={override?.props}\n />\n {field.description !== undefined ? (\n <p id={descriptionId} className=\"text-sm text-muted-foreground\">\n {field.description}\n </p>\n ) : null}\n {error !== undefined ? (\n <p id={errorId} className=\"text-sm font-medium text-destructive\">\n {error}\n </p>\n ) : null}\n </div>\n );\n}\n\ninterface ResourceFormInnerProps extends ResourceFormProps {\n schema: ResourceSchema;\n item?: Record<string, unknown>;\n}\n\nfunction ResourceFormInner(props: ResourceFormInnerProps): React.ReactElement {\n const {\n resource,\n id,\n defaultValues,\n onSuccess,\n onError,\n fields: fieldOverrides,\n extraFields,\n transformSubmit,\n actions,\n className,\n schema,\n item,\n } = props;\n const mode = id === undefined ? \"create\" : \"update\";\n const mutations = useResourceMutations(resource);\n\n const formFields = React.useMemo(\n () =>\n schema.fields.filter(\n (field) =>\n !field.readOnly &&\n (EDITABLE_KINDS.has(field.kind) || fieldOverrides?.[field.name]?.component !== undefined),\n ),\n [schema, fieldOverrides],\n );\n\n const initialValues = React.useMemo(\n () => buildFormValues({ fields: formFields, item, defaultValues }),\n [formFields, item, defaultValues],\n );\n\n const resolver = React.useMemo<Resolver<FieldValues>>(() => {\n const base = zodResolver(zodFor(schema, mode)) as unknown as Resolver<FieldValues>;\n // A cleared optional, non-nullable field (a select's \"no selection\") is\n // omitted from the request (D3), so it must not fail validation as null.\n // Many relations are cleared with [] and stay.\n const omittable = new Set(\n schema.fields\n .filter(\n (field) =>\n !field.required &&\n !field.nullable &&\n !(field.kind === \"relation\" && field.relation?.many === true),\n )\n .map((field) => field.name),\n );\n return (values, context, options) => {\n const cleaned: FieldValues = Object.fromEntries(\n Object.entries(values).filter(([name, value]) => !(value === null && omittable.has(name))),\n );\n return base(cleaned, context, options);\n };\n }, [schema, mode]);\n\n const methods = useForm<FieldValues>({\n resolver,\n values: initialValues,\n resetOptions: { keepDirtyValues: true },\n });\n\n const { formState } = methods;\n const submitting =\n formState.isSubmitting || mutations.create.isPending || mutations.update.isPending;\n\n const onSubmit = methods.handleSubmit(async (raw) => {\n methods.clearErrors(\"root.server\");\n const { values, jsonErrors } = prepareSubmit({\n fields: formFields,\n raw,\n mode,\n dirtyFields: methods.formState.dirtyFields,\n });\n if (jsonErrors.length > 0) {\n for (const jsonError of jsonErrors) {\n methods.setError(jsonError.name, { type: \"validate\", message: jsonError.message });\n }\n return;\n }\n const payload = transformSubmit !== undefined ? transformSubmit(values) : values;\n try {\n const result =\n id === undefined\n ? await mutations.create.mutateAsync(payload)\n : await mutations.update.mutateAsync({ id, values: payload });\n if (id === undefined) {\n methods.reset();\n } else {\n // Keep the (possibly server-normalized) values but clear dirtiness.\n methods.reset(undefined, { keepValues: true });\n }\n onSuccess?.(result);\n } catch (error) {\n const knownNames = new Set([...formFields.map((field) => field.name), ...Object.keys(raw)]);\n applyServerErrors(error, knownNames, methods);\n onError?.(error);\n }\n });\n\n const rootError = formState.errors.root?.[\"server\"]?.message ?? formState.errors.root?.message;\n\n const fieldError = (name: string): string | undefined => {\n const entry = formState.errors[name];\n return typeof entry?.message === \"string\" ? entry.message : undefined;\n };\n\n return (\n <FormProvider {...methods}>\n <form\n onSubmit={(event) => {\n void onSubmit(event);\n }}\n noValidate\n aria-busy={submitting || undefined}\n className={cn(\"space-y-5\", className)}\n >\n {typeof rootError === \"string\" ? (\n <div\n role=\"alert\"\n className=\"rounded-md border border-destructive/50 bg-destructive/10 px-3 py-2 text-sm text-destructive\"\n >\n {rootError}\n </div>\n ) : null}\n {formFields.map((field) => {\n const override = fieldOverrides?.[field.name];\n if (override?.hidden === true) return null;\n return (\n <FormFieldRow\n key={field.name}\n field={field}\n override={override}\n control={methods.control}\n error={fieldError(field.name)}\n disabled={submitting}\n />\n );\n })}\n {extraFields}\n {actions !== undefined ? (\n actions\n ) : (\n <div className=\"flex items-center justify-end gap-3 pt-2\">\n <Button type=\"submit\" disabled={submitting}>\n {id === undefined ? \"Create\" : \"Save changes\"}\n </Button>\n </div>\n )}\n </form>\n </FormProvider>\n );\n}\n\n/**\n * Schema-driven create and edit form for one resource: inputs, validation and\n * server errors derived from the OpenAPI schema.\n *\n * Contract \"ResourceForm\" + D2/D3/D10.\n *\n * Create mode POSTs every prepared value; edit mode loads the UNEXPANDED\n * detail record and PATCHes only dirty fields at top-level granularity, with\n * emptied nullable fields sent as null (D3). DRF 400 bodies map onto field\n * errors via setError (non_field_errors → root). Escape hatches: per-field\n * overrides (`fields`), `extraFields`, `transformSubmit` and the `actions`\n * slot.\n */\nexport function ResourceForm(props: ResourceFormProps): React.ReactElement {\n const { resource, id } = props;\n const schemaResult = useSchema(resource);\n const isEdit = id !== undefined;\n const itemQuery = useResourceItem(resource, id ?? \"\", undefined, { enabled: isEdit });\n\n if (schemaResult.error != null) {\n return <FormErrorPanel error={schemaResult.error} className={props.className} />;\n }\n if (isEdit && itemQuery.error != null) {\n return <FormErrorPanel error={itemQuery.error} className={props.className} />;\n }\n if (schemaResult.data === undefined || (isEdit && itemQuery.data === undefined)) {\n return <FormSkeleton className={props.className} />;\n }\n return (\n <ResourceFormInner\n {...props}\n schema={schemaResult.data}\n item={isEdit ? itemQuery.data : undefined}\n />\n );\n}\n","import * as React from \"react\";\nimport { useResourceItem } from \"../../../hooks/useResourceItem\";\nimport type { ResourceItemParams } from \"../../../hooks/types\";\nimport { cn } from \"../../../lib/cn\";\nimport type { FieldDef } from \"../../../schema/types\";\nimport { useSchema } from \"../../../schema/useSchema\";\nimport { Button } from \"../../primitives/button\";\nimport { Skeleton } from \"../../primitives/skeleton\";\nimport { partitionAuditFields } from \"../audit-fields\";\nimport { displayLabel } from \"../displayLabel\";\nimport { humanizeValue } from \"../form/prepare\";\nimport { registerComponentRole } from \"../../../lib/roles\";\n\nregisterComponentRole(\"detail-view\", \"ResourceDetail\");\n\nexport interface ResourceDetailFieldOverride {\n label?: string;\n hidden?: boolean;\n render?: (value: unknown, item: Record<string, unknown>) => React.ReactNode;\n}\n\nexport interface ResourceDetailProps {\n resource: string;\n id: string | number;\n fields?: Record<string, ResourceDetailFieldOverride>;\n /** Appended below the field list (e.g. a child <ResourceTable>). */\n sections?: ReadonlyArray<React.ReactNode>;\n expand?: readonly string[];\n title?: React.ReactNode;\n actions?: React.ReactNode;\n className?: string;\n}\n\nfunction fileBasename(url: string): string {\n const withoutQuery = url.split(/[?#]/, 1)[0] ?? url;\n const segments = withoutQuery.split(\"/\").filter((segment) => segment !== \"\");\n return segments[segments.length - 1] ?? url;\n}\n\nfunction formatDate(value: string): string {\n const match = /^(\\d{4})-(\\d{2})-(\\d{2})/.exec(value);\n if (match !== null) {\n const date = new Date(Number(match[1]), Number(match[2]) - 1, Number(match[3]));\n return date.toLocaleDateString();\n }\n const date = new Date(value);\n return Number.isNaN(date.getTime()) ? value : date.toLocaleDateString();\n}\n\nfunction formatDateTime(value: string): string {\n const date = new Date(value);\n return Number.isNaN(date.getTime()) ? value : date.toLocaleString();\n}\n\nfunction RelationEntry({ value }: { value: unknown }): React.ReactElement {\n if (value !== null && typeof value === \"object\") {\n return <>{displayLabel(value as Record<string, unknown>)}</>;\n }\n return <code className=\"rounded bg-muted px-1 py-0.5 font-mono text-xs\">{String(value)}</code>;\n}\n\nfunction RelationValue({ value }: { value: unknown }): React.ReactElement {\n if (Array.isArray(value)) {\n if (value.length === 0) return <EmptyValue />;\n return (\n <span className=\"flex flex-wrap gap-1.5\">\n {value.map((entry, index) => (\n <span\n key={index}\n className=\"inline-flex items-center rounded-sm bg-secondary px-1.5 py-0.5 text-xs text-secondary-foreground\"\n >\n <RelationEntry value={entry} />\n </span>\n ))}\n </span>\n );\n }\n return <RelationEntry value={value} />;\n}\n\nfunction EmptyValue(): React.ReactElement {\n return <span className=\"text-muted-foreground\">—</span>;\n}\n\n/** Default value renderer per field kind; overridable per field via `fields`. */\nfunction DefaultValue({ field, value }: { field: FieldDef; value: unknown }): React.ReactElement {\n if (value === undefined || value === null || value === \"\") return <EmptyValue />;\n switch (field.kind) {\n case \"boolean\":\n return <>{value ? \"Yes\" : \"No\"}</>;\n case \"date\":\n return <>{formatDate(String(value))}</>;\n case \"datetime\":\n return <>{formatDateTime(String(value))}</>;\n case \"enum\":\n return <>{field.enumLabels?.[String(value)] ?? humanizeValue(String(value))}</>;\n case \"relation\":\n return <RelationValue value={value} />;\n case \"file\":\n return (\n <a\n href={String(value)}\n target=\"_blank\"\n rel=\"noreferrer\"\n className=\"font-medium text-primary underline underline-offset-4\"\n >\n {fileBasename(String(value))}\n </a>\n );\n case \"json\":\n return (\n <pre className=\"overflow-x-auto rounded-md bg-muted p-3 text-xs\">\n {JSON.stringify(value, null, 2)}\n </pre>\n );\n case \"number\":\n case \"integer\":\n return <>{typeof value === \"number\" ? value.toLocaleString() : String(value)}</>;\n case \"array\":\n return <>{Array.isArray(value) ? value.map(String).join(\", \") : String(value)}</>;\n default:\n return <>{String(value)}</>;\n }\n}\n\nfunction DetailSkeleton({ className }: { className?: string }): React.ReactElement {\n return (\n <div role=\"status\" aria-label=\"Loading details\" className={cn(\"space-y-4\", className)}>\n {[0, 1, 2, 3].map((row) => (\n <div key={row} className=\"grid grid-cols-1 gap-2 sm:grid-cols-3 sm:gap-4\">\n <Skeleton className=\"h-4 w-24\" />\n <Skeleton className=\"h-4 w-48 sm:col-span-2\" />\n </div>\n ))}\n </div>\n );\n}\n\nfunction DetailError({\n error,\n onRetry,\n className,\n}: {\n error: unknown;\n onRetry: () => void;\n className?: string;\n}): React.ReactElement {\n return (\n <div\n role=\"alert\"\n className={cn(\n \"space-y-3 rounded-md border border-destructive/50 bg-destructive/10 p-4 text-sm text-destructive\",\n className,\n )}\n >\n <p>{error instanceof Error ? error.message : String(error)}</p>\n <Button variant=\"outline\" size=\"sm\" onClick={onRetry}>\n Retry\n </Button>\n </div>\n );\n}\n\nfunction DetailRow(props: {\n field: FieldDef;\n item: Record<string, unknown>;\n override: ResourceDetailFieldOverride | undefined;\n muted: boolean;\n}): React.ReactElement {\n const { field, item, override, muted } = props;\n const value = item[field.name];\n return (\n <div\n className={cn(\n \"grid grid-cols-1 gap-1 sm:grid-cols-3 sm:gap-4\",\n muted ? \"py-2 text-xs\" : \"py-3 text-sm\",\n )}\n >\n <dt className=\"font-medium text-muted-foreground\">{override?.label ?? field.label}</dt>\n <dd className={cn(\"sm:col-span-2\", muted ? \"text-muted-foreground\" : \"text-foreground\")}>\n {override?.render !== undefined ? (\n override.render(value, item)\n ) : (\n <DefaultValue field={field} value={value} />\n )}\n </dd>\n </div>\n );\n}\n\n/**\n * Schema-driven read view of one row: every readable field, labelled and formatted.\n *\n * Contract \"ResourceDetail\": a definition list of\n * every non-writeOnly field — domain fields first (schema order), then the\n * audit fields (AUDIT_FIELDS: id, created_at, updated_at, created_by,\n * updated_by) in a visually muted \"Record\" group. Relations render through\n * displayLabel when the object is expanded (the field is in `expand`), else\n * as the raw id in <code>. Escape hatches: per-field `fields` overrides\n * (label/hidden/render — audit fields included), appended `sections`, and the\n * title/actions header slots.\n */\nexport function ResourceDetail(props: ResourceDetailProps): React.ReactElement {\n const { resource, id, fields, sections, expand, title, actions, className } = props;\n const recordHeadingId = React.useId();\n const schemaResult = useSchema(resource);\n const params: ResourceItemParams | undefined = React.useMemo(\n () => (expand !== undefined && expand.length > 0 ? { expand } : undefined),\n [expand],\n );\n const itemQuery = useResourceItem(resource, id, params);\n\n const error = schemaResult.error ?? itemQuery.error;\n if (error != null) {\n return (\n <DetailError\n error={error}\n onRetry={() => {\n void itemQuery.refetch();\n }}\n className={className}\n />\n );\n }\n if (schemaResult.data === undefined || itemQuery.data === undefined) {\n return <DetailSkeleton className={className} />;\n }\n\n const item = itemQuery.data;\n const visibleFields = schemaResult.data.fields.filter(\n (field) =>\n !field.writeOnly && field.kind !== \"unknown\" && fields?.[field.name]?.hidden !== true,\n );\n const { domain, audit } = partitionAuditFields(visibleFields);\n\n return (\n <div className={cn(\"space-y-6\", className)}>\n {title !== undefined || actions !== undefined ? (\n <div className=\"flex flex-wrap items-center justify-between gap-3\">\n {title !== undefined ? (\n <h2 className=\"text-lg font-semibold tracking-tight\">{title}</h2>\n ) : (\n <div />\n )}\n {actions !== undefined ? <div className=\"flex items-center gap-2\">{actions}</div> : null}\n </div>\n ) : null}\n <dl className=\"divide-y divide-border\">\n {domain.map((field) => (\n <DetailRow\n key={field.name}\n field={field}\n item={item}\n override={fields?.[field.name]}\n muted={false}\n />\n ))}\n </dl>\n {audit.length > 0 ? (\n <section\n aria-labelledby={recordHeadingId}\n className=\"rounded-md border border-border bg-muted/40 px-4 py-2\"\n >\n <h3\n id={recordHeadingId}\n className=\"py-1 text-xs font-medium uppercase tracking-wide text-muted-foreground\"\n >\n Record\n </h3>\n <dl className=\"divide-y divide-border\">\n {audit.map((field) => (\n <DetailRow\n key={field.name}\n field={field}\n item={item}\n override={fields?.[field.name]}\n muted\n />\n ))}\n </dl>\n </section>\n ) : null}\n {sections !== undefined && sections.length > 0 ? (\n <div className=\"space-y-6\">\n {sections.map((section, index) => (\n <div key={index}>{section}</div>\n ))}\n </div>\n ) : null}\n </div>\n );\n}\n","/**\n * useChangeHistory — one row's field-level change history (karni.audit, ADR 0002 P4).\n *\n * `useChangeHistory(\"prices\", id)` fetches `GET /<resource>/<id>/history/`,\n * the paginated list a `BaseViewSet` serves for models that opt in with\n * `class Karni: audit = True`. The backend answers 404 for the rest, and\n * hides from each entry's `diff` the fields the requesting role may not see,\n * so the hook renders whatever it is given without filtering.\n */\nimport { useQuery, type UseQueryOptions, type UseQueryResult } from \"@tanstack/react-query\";\nimport { useKarniClient } from \"../schema/provider\";\nimport { karniKeys } from \"./keys\";\nimport { detailPath } from \"./params\";\n\nexport type ChangeAction = \"create\" | \"update\" | \"delete\" | \"restore\";\n\nexport interface ChangeLogEntry {\n id: number;\n timestamp: string;\n actor: { id: string | number; email?: string } | null;\n action: ChangeAction;\n /** `{ field: [old, new] }`; a redacted field carries `\"[redacted]\"` on both sides. */\n diff: Record<string, [unknown, unknown]>;\n fields_changed: string[];\n}\n\nexport interface ChangeHistoryPage {\n count: number;\n next: string | null;\n previous: string | null;\n results: ChangeLogEntry[];\n}\n\nexport interface ChangeHistoryParams {\n /** Entries per page (the backend caps it). Default: the API's page size. */\n pageSize?: number;\n page?: number;\n}\n\n/** The query key of one row's change history. */\nexport function changeHistoryKey(\n resource: string,\n id: string | number,\n params?: ChangeHistoryParams,\n): readonly unknown[] {\n return [...karniKeys.resource(resource), \"history\", String(id), params ?? {}] as const;\n}\n\n/** Fetches one row's field-level change history (`GET /<resource>/<id>/history/`) for models with `audit = True`. */\nexport function useChangeHistory(\n resource: string,\n id: string | number,\n params?: ChangeHistoryParams,\n options?: Omit<UseQueryOptions<ChangeHistoryPage>, \"queryKey\" | \"queryFn\">,\n): UseQueryResult<ChangeHistoryPage> {\n const client = useKarniClient();\n return useQuery<ChangeHistoryPage>({\n ...options,\n queryKey: changeHistoryKey(resource, id, params),\n queryFn: ({ signal }) =>\n client.request<ChangeHistoryPage>(`${detailPath(resource, id)}history/`, {\n query: { page_size: params?.pageSize, page: params?.page },\n signal,\n }),\n });\n}\n","import * as React from \"react\";\nimport { useChangeHistory, type ChangeLogEntry } from \"../../../hooks/useChangeHistory\";\nimport { cn } from \"../../../lib/cn\";\nimport { registerComponentRole } from \"../../../lib/roles\";\nimport { Skeleton } from \"../../primitives/skeleton\";\n\nregisterComponentRole(\"change-history\", \"ChangeHistory\");\n\nexport interface ChangeHistoryProps {\n resource: string;\n id: string | number;\n /** Entries to show (the backend paginates; default: the API's page size). */\n pageSize?: number;\n title?: React.ReactNode;\n /** Shown when the row has no recorded changes. */\n empty?: React.ReactNode;\n className?: string;\n}\n\nconst ACTION_LABEL: Record<ChangeLogEntry[\"action\"], string> = {\n create: \"Created\",\n update: \"Updated\",\n delete: \"Deleted\",\n restore: \"Restored\",\n};\n\nfunction formatWhen(value: string): string {\n const date = new Date(value);\n return Number.isNaN(date.getTime()) ? value : date.toLocaleString();\n}\n\nfunction Value({ value }: { value: unknown }): React.ReactElement {\n if (value === null || value === undefined || value === \"\") {\n return <span className=\"text-muted-foreground\">—</span>;\n }\n if (value === \"[redacted]\") {\n return <span className=\"italic text-muted-foreground\">redacted</span>;\n }\n const text = typeof value === \"object\" ? JSON.stringify(value) : String(value);\n return <span className=\"break-words\">{text}</span>;\n}\n\nfunction Entry({ entry }: { entry: ChangeLogEntry }): React.ReactElement {\n const fields = Object.entries(entry.diff);\n return (\n <li className=\"rounded-md border bg-card p-3 text-sm\" data-action={entry.action}>\n <div className=\"flex flex-wrap items-baseline gap-x-3 gap-y-1\">\n <span className=\"font-medium\">{ACTION_LABEL[entry.action] ?? entry.action}</span>\n <time dateTime={entry.timestamp} className=\"text-muted-foreground\">\n {formatWhen(entry.timestamp)}\n </time>\n <span className=\"text-muted-foreground\">{entry.actor?.email ?? \"—\"}</span>\n </div>\n {fields.length > 0 ? (\n <dl className=\"mt-2 grid grid-cols-[max-content_1fr] gap-x-3 gap-y-1\">\n {fields.map(([name, [before, after]]) => (\n <React.Fragment key={name}>\n <dt className=\"font-mono text-xs text-muted-foreground\">{name}</dt>\n <dd className=\"flex flex-wrap items-center gap-2\">\n <Value value={before} />\n <span aria-hidden=\"true\" className=\"text-muted-foreground\">\n →\n </span>\n <Value value={after} />\n </dd>\n </React.Fragment>\n ))}\n </dl>\n ) : (\n <p className=\"mt-2 text-muted-foreground\">No visible field changed.</p>\n )}\n </li>\n );\n}\n\n/**\n * The field-level change history of one row: when, by whom, what changed\n * from what to what. Reads `GET /<resource>/<id>/history/` (models that opt\n * in with `class Karni: audit = True`); fields the role may not see are\n * already absent from each diff, redacted ones say so.\n */\nexport function ChangeHistory({\n resource,\n id,\n pageSize,\n title = \"History\",\n empty = \"No changes recorded.\",\n className,\n}: ChangeHistoryProps): React.ReactElement {\n const query = useChangeHistory(resource, id, pageSize !== undefined ? { pageSize } : undefined);\n return (\n <section className={cn(\"space-y-3\", className)} aria-label=\"Change history\">\n {title !== null ? <h3 className=\"text-base font-semibold\">{title}</h3> : null}\n {query.isPending ? (\n <div className=\"space-y-2\" data-testid=\"change-history-loading\">\n <Skeleton className=\"h-16 w-full\" />\n <Skeleton className=\"h-16 w-full\" />\n </div>\n ) : query.error ? (\n <p role=\"alert\" className=\"text-sm text-destructive\">\n {query.error instanceof Error ? query.error.message : \"History could not be loaded.\"}\n </p>\n ) : query.data.results.length === 0 ? (\n <p className=\"text-sm text-muted-foreground\">{empty}</p>\n ) : (\n <ol className=\"space-y-2\">\n {query.data.results.map((entry) => (\n <Entry key={entry.id} entry={entry} />\n ))}\n </ol>\n )}\n </section>\n );\n}\n","import * as React from \"react\";\nimport {\n downloadImportTemplate,\n isImportInFlight,\n useImportActions,\n useImportDescribe,\n useImportJob,\n type ImportColumn,\n type ImportJob,\n} from \"../../../hooks/useResourceImport\";\nimport { cn } from \"../../../lib/cn\";\nimport { registerComponentRole } from \"../../../lib/roles\";\nimport { useKarniClient } from \"../../../schema/provider\";\nimport { Button } from \"../../primitives/button\";\nimport { Select } from \"../../primitives/select\";\nimport { Skeleton } from \"../../primitives/skeleton\";\n\nregisterComponentRole(\"resource-import\", \"ResourceImport\");\n\nexport interface ResourceImportProps {\n resource: string;\n title?: React.ReactNode;\n /** Called when a commit finishes (the job is `done`). */\n onDone?: (job: ImportJob) => void;\n className?: string;\n}\n\nfunction errorText(error: unknown): string {\n if (error instanceof Error) {\n const data = (error as { data?: unknown }).data;\n if (typeof data === \"object\" && data !== null && \"detail\" in data) {\n const detail = (data as { detail?: unknown }).detail;\n if (typeof detail === \"string\") return detail;\n }\n return error.message;\n }\n return \"Something went wrong.\";\n}\n\nfunction Stats({ job }: { job: ImportJob }): React.ReactElement | null {\n if (job.result === null) return null;\n const { created, updated, skipped, unchanged, errors } = job.result;\n return (\n <dl className=\"flex flex-wrap gap-6\" data-testid=\"import-stats\">\n <div>\n <dt className=\"text-xs uppercase text-muted-foreground\">Created</dt>\n <dd className=\"text-2xl font-semibold\">{created}</dd>\n </div>\n <div>\n <dt className=\"text-xs uppercase text-muted-foreground\">Updated</dt>\n <dd className=\"text-2xl font-semibold\">{updated}</dd>\n </div>\n <div>\n <dt className=\"text-xs uppercase text-muted-foreground\">Skipped</dt>\n <dd className=\"text-2xl font-semibold\">\n {skipped}{\" \"}\n <span className=\"text-sm font-normal text-muted-foreground\">\n ({unchanged} unchanged, {errors} with errors)\n </span>\n </dd>\n </div>\n </dl>\n );\n}\n\nfunction Problems({ job }: { job: ImportJob }): React.ReactElement | null {\n if (job.problems.length === 0) return null;\n return (\n <div className=\"overflow-x-auto rounded-md border border-border\">\n <table className=\"w-full text-sm\" aria-label=\"Rows with errors\">\n <thead className=\"bg-muted text-left text-xs uppercase text-muted-foreground\">\n <tr>\n <th className=\"px-3 py-2\">Row</th>\n <th className=\"px-3 py-2\">Field</th>\n <th className=\"px-3 py-2\">Problem</th>\n </tr>\n </thead>\n <tbody>\n {job.problems.map((problem, index) => (\n <tr key={`${problem.row}-${problem.field}-${index}`} className=\"border-t border-border\">\n <td className=\"px-3 py-2 tabular-nums\">{problem.row}</td>\n <td className=\"px-3 py-2 font-mono text-xs\">{problem.field || \"—\"}</td>\n <td className=\"px-3 py-2 text-destructive\">{problem.message}</td>\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n );\n}\n\nfunction Progress({ job }: { job: ImportJob }): React.ReactElement {\n const percent = job.rows_total > 0 ? Math.round((job.rows_done * 100) / job.rows_total) : 0;\n return (\n <div className=\"space-y-2\" role=\"status\" aria-live=\"polite\">\n <p className=\"text-sm\">\n {job.status === \"previewing\" ? \"Previewing\" : \"Committing\"}… {job.rows_done} /{\" \"}\n {job.rows_total} rows\n </p>\n <div className=\"h-2 w-full overflow-hidden rounded bg-muted\">\n <div className=\"h-full bg-primary transition-all\" style={{ width: `${percent}%` }} />\n </div>\n </div>\n );\n}\n\nfunction MappingTable(props: {\n job: ImportJob;\n fields: readonly ImportColumn[];\n mapping: Record<string, string>;\n onChange: (header: string, field: string) => void;\n}): React.ReactElement {\n const { job, fields, mapping, onChange } = props;\n const options = fields.map((field) => ({\n value: field.name,\n label: `${field.name}${field.required ? \" *\" : \"\"}${field.key ? \" (key)\" : \"\"}`,\n }));\n return (\n <div className=\"overflow-x-auto rounded-md border border-border\">\n <table className=\"w-full text-sm\" aria-label=\"Column mapping\">\n <thead className=\"bg-muted text-left text-xs uppercase text-muted-foreground\">\n <tr>\n <th className=\"px-3 py-2\">Column in the file</th>\n <th className=\"px-3 py-2\">Field</th>\n </tr>\n </thead>\n <tbody>\n {job.columns.map((header) => (\n <tr key={header} className=\"border-t border-border\">\n <td className=\"px-3 py-2\">{header}</td>\n <td className=\"px-3 py-2\">\n <Select\n aria-label={`Field for ${header}`}\n className=\"h-9 w-auto min-w-48\"\n value={mapping[header] ?? \"\"}\n options={options}\n clearable\n clearLabel=\"— ignore —\"\n onValueChange={(next) => onChange(header, next ?? \"\")}\n />\n </td>\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n );\n}\n\n/**\n * Import a CSV or XLSX file into a resource: upload, map columns to fields,\n * preview (the mandatory dry run — N created / updated / skipped with every\n * row's errors), then commit. Drives `/<resource>/import/…`; the backend\n * validates every row through the same serializer the API uses, keeps rows\n * inside the user's scope and refuses fields the role may not write. Large\n * files run in the background with progress.\n */\nexport function ResourceImport({\n resource,\n title = \"Import\",\n onDone,\n className,\n}: ResourceImportProps): React.ReactElement {\n const client = useKarniClient();\n const describe = useImportDescribe(resource);\n const actions = useImportActions(resource);\n const [jobId, setJobId] = React.useState<string | undefined>(undefined);\n const [mapping, setMapping] = React.useState<Record<string, string>>({});\n const [remap, setRemap] = React.useState(false);\n const [templateError, setTemplateError] = React.useState<string | null>(null);\n const fileRef = React.useRef<HTMLInputElement>(null);\n const jobQuery = useImportJob(resource, jobId);\n const job = jobQuery.data;\n\n // The job's mapping (suggested or remembered) seeds the editable one.\n const seededFor = React.useRef<string | undefined>(undefined);\n React.useEffect(() => {\n if (job !== undefined && seededFor.current !== job.id) {\n seededFor.current = job.id;\n setMapping(job.mapping);\n }\n }, [job]);\n\n React.useEffect(() => {\n if (job?.status === \"done\") onDone?.(job);\n // eslint-disable-next-line react-hooks/exhaustive-deps -- fire once per completion\n }, [job?.status, job?.id]);\n\n const fields = job?.fields ?? describe.data?.fields ?? [];\n const busy = actions.upload.isPending || actions.preview.isPending || actions.commit.isPending;\n const mutationError = actions.upload.error ?? actions.preview.error ?? actions.commit.error;\n\n const handleUpload = (event: React.FormEvent<HTMLFormElement>): void => {\n event.preventDefault();\n const file = fileRef.current?.files?.[0];\n if (file === undefined) return;\n setRemap(false);\n actions.upload.mutate({ file }, { onSuccess: (created) => setJobId(created.id) });\n };\n\n const handlePreview = (): void => {\n if (job === undefined) return;\n setRemap(false);\n actions.preview.mutate({ jobId: job.id, mapping });\n };\n\n const handleTemplate = (format: \"xlsx\" | \"csv\"): void => {\n setTemplateError(null);\n downloadImportTemplate(client, resource, format).catch((error: unknown) =>\n setTemplateError(errorText(error)),\n );\n };\n\n let body: React.ReactNode;\n if (describe.isPending) {\n body = <Skeleton className=\"h-24 w-full\" data-testid=\"resource-import-loading\" />;\n } else if (job === undefined || (jobId !== undefined && jobQuery.isPending)) {\n body = (\n <form onSubmit={handleUpload} className=\"flex flex-wrap items-end gap-3\">\n <label className=\"flex flex-col gap-1 text-sm\">\n <span>CSV or XLSX file</span>\n <input\n ref={fileRef}\n type=\"file\"\n name=\"file\"\n accept=\".csv,.xlsx\"\n required\n className=\"text-sm\"\n aria-label=\"File to import\"\n />\n </label>\n <Button type=\"submit\" disabled={busy}>\n Upload\n </Button>\n </form>\n );\n } else if (isImportInFlight(job)) {\n body = <Progress job={job} />;\n } else if (job.status === \"uploaded\" || job.status === \"failed\" || remap) {\n body = (\n <div className=\"space-y-3\">\n {job.error !== null && (\n <p role=\"alert\" className=\"text-sm text-destructive\">\n {job.error}\n </p>\n )}\n <p className=\"text-sm text-muted-foreground\">\n {job.file_name} — {job.rows_total} rows. Map each column to a field; blank cells leave a\n field unchanged.\n </p>\n <MappingTable\n job={job}\n fields={fields}\n mapping={mapping}\n onChange={(header, field) => setMapping((old) => ({ ...old, [header]: field }))}\n />\n <div className=\"flex flex-wrap gap-2\">\n <Button onClick={handlePreview} disabled={busy}>\n Preview\n </Button>\n <Button variant=\"outline\" onClick={() => setJobId(undefined)} disabled={busy}>\n Upload another file\n </Button>\n </div>\n </div>\n );\n } else {\n body = (\n <div className=\"space-y-3\">\n <p className=\"text-sm text-muted-foreground\">\n {job.file_name} — {job.rows_total} rows,{\" \"}\n {job.status === \"done\" ? \"imported.\" : \"previewed; nothing is saved yet.\"}\n </p>\n <Stats job={job} />\n <Problems job={job} />\n <div className=\"flex flex-wrap gap-2\">\n {job.status === \"previewed\" ? (\n <>\n <Button onClick={() => actions.commit.mutate(job.id)} disabled={busy}>\n Commit\n </Button>\n <Button variant=\"outline\" onClick={() => setRemap(true)} disabled={busy}>\n Change the mapping\n </Button>\n </>\n ) : (\n <Button variant=\"outline\" onClick={() => setJobId(undefined)}>\n Import another file\n </Button>\n )}\n </div>\n </div>\n );\n }\n\n return (\n <section className={cn(\"space-y-3\", className)} aria-label=\"Import\">\n <div className=\"flex flex-wrap items-baseline justify-between gap-2\">\n {title !== null ? <h3 className=\"text-base font-semibold\">{title}</h3> : null}\n <div className=\"flex gap-2 text-sm\">\n <button\n type=\"button\"\n className=\"text-primary underline-offset-4 hover:underline\"\n onClick={() => handleTemplate(\"xlsx\")}\n >\n Download template (XLSX)\n </button>\n <button\n type=\"button\"\n className=\"text-primary underline-offset-4 hover:underline\"\n onClick={() => handleTemplate(\"csv\")}\n >\n CSV\n </button>\n </div>\n </div>\n {describe.error !== null && describe.error !== undefined ? (\n <p role=\"alert\" className=\"text-sm text-destructive\">\n {errorText(describe.error)}\n </p>\n ) : null}\n {mutationError !== null && mutationError !== undefined ? (\n <p role=\"alert\" className=\"text-sm text-destructive\">\n {errorText(mutationError)}\n </p>\n ) : null}\n {templateError !== null ? (\n <p role=\"alert\" className=\"text-sm text-destructive\">\n {templateError}\n </p>\n ) : null}\n {body}\n </section>\n );\n}\n","/**\n * createKarniClient — the typed fetch wrapper every @karni/ui layer sits on\n * (contract \"Schema client\" + D6).\n *\n * Responsibilities:\n * - URL joining + query-string serialization (arrays become repeated keys,\n * null/undefined are dropped),\n * - JSON request/response handling; a FormData body is passed through\n * untouched with NO manual Content-Type (the D2 multipart rule),\n * - DRF error passthrough: non-2xx responses throw KarniApiError carrying the\n * parsed body (field errors / detail / non_field_errors) verbatim,\n * - auth hook points per D6's client-owns-tokens design: the auth layer (not\n * React) registers token injection, extra headers (session CSRF),\n * credentials mode and a 401 handler via `setAuthHooks`. The client calls\n * `onUnauthorized` at most ONCE per request and retries at most ONCE — a\n * request that 401s again after a successful refresh is surfaced, never\n * re-triggers refresh (the single-flight refresh promise itself lives in\n * the auth layer behind this hook).\n */\n\nexport interface KarniClientOptions {\n /**\n * Origin (plus optional path prefix) requests resolve against, e.g.\n * \"https://api.example.com\" or \"\" for same-origin. Paths that already start\n * with the prefix are not double-prefixed, so operation paths taken from\n * the OpenAPI document (\"/api/events/\") work with any baseUrl.\n */\n baseUrl: string;\n /** Path of the OpenAPI document. Default \"/api/schema/\". */\n schemaUrl?: string;\n /** Initial access-token getter; `setAuthHooks` can replace it later (D6). */\n getAccessToken?: () => string | null;\n /** Custom fetch implementation (tests, SSR). Resolved per request. */\n fetch?: typeof globalThis.fetch;\n}\n\nexport type KarniQueryValue =\n string | number | boolean | ReadonlyArray<string | number | boolean> | null | undefined;\n\nexport interface KarniRequestOptions {\n method?: \"GET\" | \"POST\" | \"PUT\" | \"PATCH\" | \"DELETE\";\n query?: Record<string, KarniQueryValue>;\n /** JSON-serialized unless it is FormData (multipart rule D2). */\n body?: unknown;\n headers?: Record<string, string>;\n signal?: AbortSignal;\n /**\n * Skip the 401 → onUnauthorized → retry cycle for this request. The auth\n * layer sets it on its own login/refresh/logout calls so a failing refresh\n * can never recurse into another refresh (D6).\n */\n skipAuthRefresh?: boolean;\n}\n\n/**\n * Hook points the auth layer registers on the client (D6). Keys present in\n * the object passed to `setAuthHooks` override the current value (an explicit\n * `undefined` clears one); absent keys are kept.\n */\nexport interface KarniAuthHooks {\n /** Called before every request; a non-null return is sent as Bearer. */\n getAccessToken?: () => string | null;\n /**\n * Called once when a request gets a 401 (unless `skipAuthRefresh`). Return\n * true to retry the request once with freshly-injected credentials, false\n * to surface the error. Single-flight refresh lives behind this hook.\n */\n onUnauthorized?: (error: KarniApiError) => Promise<boolean>;\n /** Extra headers merged into every request (session-mode X-CSRFToken). */\n getHeaders?: () => Record<string, string>;\n /** fetch credentials mode; session mode sets \"include\". */\n credentials?: RequestCredentials;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction defaultMessage(status: number, data: unknown): string {\n if (isRecord(data) && typeof data[\"detail\"] === \"string\") return data[\"detail\"];\n return `Karni API request failed with status ${status}`;\n}\n\n/** Thrown for non-2xx responses; `data` carries the parsed DRF error body. */\nexport class KarniApiError extends Error {\n readonly status: number;\n /** Parsed body when JSON (field errors, detail, non_field_errors), else text. */\n readonly data: unknown;\n\n constructor(status: number, data: unknown, message?: string) {\n super(message ?? defaultMessage(status, data));\n this.name = \"KarniApiError\";\n this.status = status;\n this.data = data;\n }\n}\n\nexport interface KarniClient {\n readonly baseUrl: string;\n readonly schemaUrl: string;\n request<T>(path: string, options?: KarniRequestOptions): Promise<T>;\n /**\n * The same request (auth, query, 401 retry) returning the raw `Response`\n * instead of a parsed body — for file downloads (`GET /<resource>/export/`).\n * Non-2xx responses still throw `KarniApiError` with the parsed error body.\n */\n requestRaw(path: string, options?: KarniRequestOptions): Promise<Response>;\n /** D6 hook point: the auth layer wires tokens/CSRF/401 handling here. */\n setAuthHooks(hooks: KarniAuthHooks): void;\n}\n\n// URL handling\n\nfunction splitBaseUrl(baseUrl: string): { origin: string; basePath: string } {\n const match = /^(https?:\\/\\/[^/]+)(\\/.*)?$/.exec(baseUrl);\n if (match !== null) {\n return { origin: match[1] ?? \"\", basePath: (match[2] ?? \"\").replace(/\\/+$/, \"\") };\n }\n return { origin: \"\", basePath: baseUrl.replace(/\\/+$/, \"\") };\n}\n\nfunction joinUrl(baseUrl: string, path: string): string {\n if (/^https?:\\/\\//.test(path)) return path;\n const { origin, basePath } = splitBaseUrl(baseUrl);\n const normalized = path.startsWith(\"/\") ? path : `/${path}`;\n if (basePath !== \"\" && (normalized === basePath || normalized.startsWith(`${basePath}/`))) {\n return origin + normalized;\n }\n return origin + basePath + normalized;\n}\n\nfunction appendQuery(url: string, query: Record<string, KarniQueryValue> | undefined): string {\n if (query === undefined) return url;\n const params = new URLSearchParams();\n for (const [key, value] of Object.entries(query)) {\n if (value === null || value === undefined) continue;\n if (Array.isArray(value)) {\n for (const item of value) params.append(key, String(item));\n } else {\n params.append(key, String(value));\n }\n }\n const qs = params.toString();\n if (qs === \"\") return url;\n return url.includes(\"?\") ? `${url}&${qs}` : `${url}?${qs}`;\n}\n\n// body handling\n\nasync function parseBody(response: Response): Promise<unknown> {\n if (response.status === 204 || response.status === 205) return undefined;\n const text = await response.text();\n if (text === \"\") return undefined;\n const contentType = response.headers.get(\"content-type\") ?? \"\";\n if (contentType.includes(\"json\")) {\n try {\n return JSON.parse(text);\n } catch {\n return text;\n }\n }\n return text;\n}\n\n// the client\n\n/** Creates the fetch client every hook in this package uses: base URL, JSON and multipart bodies, DRF errors as `KarniApiError`, and auth hooks. */\nexport function createKarniClient(options: KarniClientOptions): KarniClient {\n const { baseUrl, schemaUrl = \"/api/schema/\", fetch: fetchOption } = options;\n\n let hooks: KarniAuthHooks = {};\n if (options.getAccessToken !== undefined) {\n hooks = { getAccessToken: options.getAccessToken };\n }\n\n async function perform(url: string, requestOptions: KarniRequestOptions): Promise<Response> {\n const headers = new Headers({ accept: \"application/json\" });\n const hookHeaders = hooks.getHeaders?.();\n if (hookHeaders !== undefined) {\n for (const [name, value] of Object.entries(hookHeaders)) headers.set(name, value);\n }\n if (requestOptions.headers !== undefined) {\n for (const [name, value] of Object.entries(requestOptions.headers)) {\n headers.set(name, value);\n }\n }\n const token = hooks.getAccessToken?.() ?? null;\n if (token !== null && token !== \"\") headers.set(\"authorization\", `Bearer ${token}`);\n\n let body: BodyInit | undefined;\n if (typeof FormData !== \"undefined\" && requestOptions.body instanceof FormData) {\n body = requestOptions.body; // the runtime sets the multipart boundary (D2)\n } else if (requestOptions.body !== undefined) {\n body = JSON.stringify(requestOptions.body);\n if (!headers.has(\"content-type\")) headers.set(\"content-type\", \"application/json\");\n }\n\n const init: RequestInit = { method: requestOptions.method ?? \"GET\", headers };\n if (body !== undefined) init.body = body;\n if (requestOptions.signal !== undefined) init.signal = requestOptions.signal;\n if (hooks.credentials !== undefined) init.credentials = hooks.credentials;\n\n const fetchImpl = fetchOption ?? globalThis.fetch;\n return fetchImpl(url, init);\n }\n\n async function requestRaw(\n path: string,\n requestOptions: KarniRequestOptions = {},\n ): Promise<Response> {\n const url = appendQuery(joinUrl(baseUrl, path), requestOptions.query);\n\n let response = await perform(url, requestOptions);\n if (response.ok) return response;\n\n const error = new KarniApiError(response.status, await parseBody(response));\n if (\n response.status === 401 &&\n hooks.onUnauthorized !== undefined &&\n requestOptions.skipAuthRefresh !== true\n ) {\n const shouldRetry = await hooks.onUnauthorized(error);\n if (shouldRetry) {\n response = await perform(url, requestOptions);\n if (response.ok) return response;\n // A 401 (or anything else) after a successful refresh is surfaced\n // as-is — it never re-triggers refresh (D6).\n throw new KarniApiError(response.status, await parseBody(response));\n }\n }\n throw error;\n }\n\n return {\n baseUrl,\n schemaUrl,\n\n async request<T>(path: string, requestOptions: KarniRequestOptions = {}): Promise<T> {\n const response = await requestRaw(path, requestOptions);\n return (await parseBody(response)) as T;\n },\n\n requestRaw,\n\n setAuthHooks(next: KarniAuthHooks): void {\n hooks = { ...hooks, ...next };\n },\n };\n}\n","/**\n * The non-React auth core (contract \"Hooks + auth\" + D6): the client side\n * owns tokens and refresh; <AuthProvider> merely mirrors this engine's state\n * into React.\n *\n * The engine registers itself on the KarniClient via its D6 hook points\n * (`setAuthHooks`): access-token injection, extra headers (session CSRF),\n * credentials mode, and the 401 handler. EVERY request made through the\n * client — resource hooks, schema loading, custom calls — therefore carries\n * credentials and takes part in the refresh flow, with no per-callsite\n * wiring.\n *\n * ## JWT mode (D6)\n * - The access token lives in memory only; the refresh token lives in the\n * pluggable TokenStorage (localStorage by default).\n * - On a 401 the client calls `onUnauthorized` (at most once per request):\n * the engine runs ONE shared in-flight refresh (`POST\n * <authBasePath>/refresh/`) — every concurrent 401 awaits the same\n * promise. A rotated refresh token is persisted BEFORE that promise\n * resolves, so queued retries can never observe the stale token. The\n * client then retries each request exactly once; a request that 401s\n * AFTER a successful refresh is surfaced and never re-triggers refresh.\n * - Refresh failure clears the storage and flips the engine to \"anonymous\";\n * the original 401s surface to the queued callers.\n * - The engine's own auth calls (login/refresh/me/logout/csrf) set\n * `skipAuthRefresh`, so a 401 from them can never recurse into another\n * refresh. During a refresh the in-memory access token is nulled, so the\n * refresh request itself never carries a stale Bearer header (which would\n * trip DRF authentication/throttling before the view runs).\n * - Multi-tab: tabs do not coordinate (documented limitation). With\n * refresh-token rotation + blacklisting, a refresh in tab A can invalidate\n * the token tab B just read, logging tab B out on its next refresh.\n * Storage events are intentionally not consumed in v0.1.\n *\n * ## Session mode (A4)\n * Django's session cookie authenticates requests; the engine registers\n * `credentials: \"include\"` and a header hook that mirrors the CSRF cookie\n * (\"csrftoken\") into the CSRF header (\"X-CSRFToken\") — names pinned by A4,\n * both overridable. When the cookie is absent it is bootstrapped via\n * `GET <authBasePath>/csrf/` (204 + ensure_csrf_cookie) during initialization\n * and before login. Cross-origin note: `credentials: \"include\"` is only\n * registered once the mode is known — pass `mode=\"session\"` to\n * <AuthProvider> (skipping async schema detection) so the very first\n * requests already include cookies.\n *\n * ## Mode resolution\n * `modeOverride` prop → cached parsed schema (`authMode`) → the schema\n * document's root `x-karni-auth-mode` (api B14) → \"jwt\".\n *\n * Internal module: not re-exported from the barrel.\n */\nimport type { KarniClient } from \"../schema/client\";\nimport type { TokenStorage } from \"./storage\";\nimport type { AuthStatus, KarniUser, LoginResult } from \"./types\";\n\nexport type AuthMode = \"jwt\" | \"session\";\n\nexport interface AuthEngineOptions {\n client: KarniClient;\n tokenStorage: TokenStorage;\n /** Skips schema-based mode detection entirely when set. */\n modeOverride?: AuthMode;\n /** Session-mode CSRF cookie name (A4 pin). Default \"csrftoken\". */\n csrfCookieName?: string;\n /** Session-mode CSRF header name (A4 pin). Default \"X-CSRFToken\". */\n csrfHeaderName?: string;\n /** Path prefix of the auth endpoints, relative to the client's baseUrl. */\n authBasePath?: string;\n /**\n * Reads whatever the schema loader cached under karniKeys.schema() —\n * consulted (shape-guarded) for `authMode` before fetching the document.\n */\n readCachedSchema?: () => unknown;\n}\n\nexport interface AuthSnapshot {\n readonly status: AuthStatus;\n readonly user: KarniUser | null;\n readonly mode: AuthMode | null;\n}\n\n/**\n * Reads the auth mode out of either a ParsedSchema (`authMode`) or a raw\n * OpenAPI document (root `x-karni-auth-mode`), shape-guarded.\n */\nexport function readAuthMode(value: unknown): AuthMode | undefined {\n if (typeof value !== \"object\" || value === null) return undefined;\n const record = value as Record<string, unknown>;\n const candidate = record[\"authMode\"] ?? record[\"x-karni-auth-mode\"];\n return candidate === \"jwt\" || candidate === \"session\" ? candidate : undefined;\n}\n\n/** Validates/normalizes a `me` payload into a KarniUser (roles default []). */\nexport function normalizeUser(value: unknown): KarniUser | null {\n if (typeof value !== \"object\" || value === null) return null;\n const record = value as Record<string, unknown>;\n const { id, email } = record;\n if (typeof id !== \"string\" && typeof id !== \"number\") return null;\n if (typeof email !== \"string\") return null;\n const roles = Array.isArray(record.roles)\n ? record.roles.filter((role): role is string => typeof role === \"string\")\n : [];\n return { ...record, id, email, roles };\n}\n\nfunction readCookie(name: string): string | null {\n if (typeof document === \"undefined\") return null;\n try {\n for (const part of document.cookie.split(\";\")) {\n const trimmed = part.trim();\n const separator = trimmed.indexOf(\"=\");\n if (separator === -1) continue;\n if (trimmed.slice(0, separator) === name) {\n return decodeURIComponent(trimmed.slice(separator + 1));\n }\n }\n } catch {\n // Cookie access can throw in sandboxed documents.\n }\n return null;\n}\n\nfunction describeShape(value: unknown): string {\n if (typeof value !== \"object\" || value === null) return `a ${typeof value}`;\n const keys = Object.keys(value);\n return keys.length === 0 ? \"an empty object\" : `an object with keys [${keys.join(\", \")}]`;\n}\n\nfunction read2fa(value: unknown): { ephemeralToken: string } | null {\n if (typeof value !== \"object\" || value === null) return null;\n const record = value as Record<string, unknown>;\n if (record.requires_2fa !== true) return null;\n return typeof record.ephemeral_token === \"string\"\n ? { ephemeralToken: record.ephemeral_token }\n : null;\n}\n\nexport class AuthEngine {\n private readonly client: KarniClient;\n private readonly tokenStorage: TokenStorage;\n private readonly modeOverride: AuthMode | undefined;\n private readonly csrfCookieName: string;\n private readonly csrfHeaderName: string;\n private readonly authBasePath: string;\n private readonly readCachedSchema: (() => unknown) | undefined;\n\n private mode: AuthMode | null;\n private accessToken: string | null = null;\n private refreshPromise: Promise<boolean> | null = null;\n private initPromise: Promise<void> | null = null;\n private readonly listeners = new Set<() => void>();\n private state: AuthSnapshot;\n\n constructor(options: AuthEngineOptions) {\n this.client = options.client;\n this.tokenStorage = options.tokenStorage;\n this.modeOverride = options.modeOverride;\n this.csrfCookieName = options.csrfCookieName ?? \"csrftoken\";\n this.csrfHeaderName = options.csrfHeaderName ?? \"X-CSRFToken\";\n this.authBasePath = (options.authBasePath ?? \"/auth\").replace(/\\/+$/, \"\");\n this.readCachedSchema = options.readCachedSchema;\n this.mode = options.modeOverride ?? null;\n this.state = { status: \"loading\", user: null, mode: this.mode };\n // Register the hook points during construction (render phase), not in an\n // effect: children of <AuthProvider> fire their first queries from\n // effects that run BEFORE the parent's own effects, and those requests\n // must already flow through the auth machinery.\n this.attach();\n }\n\n // client hook registration\n\n /** Registers the D6 hook points on the client. Idempotent. */\n attach(): void {\n this.client.setAuthHooks({\n getAccessToken: () => this.accessToken,\n onUnauthorized: () => this.handleUnauthorized(),\n getHeaders: () => this.csrfHeaders(),\n ...(this.mode === \"session\" ? { credentials: \"include\" as RequestCredentials } : {}),\n });\n }\n\n /**\n * Clears every hook this engine registered (including a `getAccessToken`\n * the app passed to createKarniClient — an unmounted AuthProvider leaves\n * the client fully unauthenticated by design).\n */\n detach(): void {\n this.client.setAuthHooks({\n getAccessToken: undefined,\n onUnauthorized: undefined,\n getHeaders: undefined,\n credentials: undefined,\n });\n }\n\n private csrfHeaders(): Record<string, string> {\n if (this.mode !== \"session\") return {};\n const token = readCookie(this.csrfCookieName);\n return token === null ? {} : { [this.csrfHeaderName]: token };\n }\n\n /**\n * The client calls this at most once per 401-ing request (D6). Returning\n * true makes the client retry that request exactly once with\n * freshly-injected credentials; the retry's outcome is always surfaced.\n */\n private async handleUnauthorized(): Promise<boolean> {\n await this.ensureInitialized();\n if (this.mode !== \"jwt\") {\n // The session evaporated server-side; mirror it.\n if (this.state.status === \"authenticated\") this.setState(\"anonymous\", null);\n return false;\n }\n if (this.tokenStorage.get() === null) return false;\n return this.ensureRefresh();\n }\n\n // --- state mirroring (consumed by <AuthProvider> via useSyncExternalStore)\n\n readonly subscribe = (listener: () => void): (() => void) => {\n this.listeners.add(listener);\n return () => {\n this.listeners.delete(listener);\n };\n };\n\n readonly getSnapshot = (): AuthSnapshot => this.state;\n\n private setState(status: AuthStatus, user: KarniUser | null): void {\n this.state = { status, user, mode: this.mode };\n for (const listener of this.listeners) listener();\n }\n\n // bootstrap\n\n /** Idempotent: the first call kicks off mode resolution + session restore. */\n ensureInitialized(): Promise<void> {\n this.initPromise ??= this.initialize();\n return this.initPromise;\n }\n\n private async initialize(): Promise<void> {\n try {\n this.mode =\n this.modeOverride ??\n readAuthMode(this.readCachedSchema?.()) ??\n (await this.fetchSchemaAuthMode()) ??\n \"jwt\";\n if (this.mode === \"session\") {\n this.client.setAuthHooks({ credentials: \"include\" });\n await this.ensureCsrfToken(); // A4: bootstrap the cookie when absent.\n await this.syncUser();\n return;\n }\n if (this.tokenStorage.get() === null) {\n this.setState(\"anonymous\", null);\n return;\n }\n const refreshed = await this.ensureRefresh();\n if (!refreshed) return; // performRefresh already cleared + emitted.\n await this.syncUser();\n } catch {\n this.setState(\"anonymous\", null);\n }\n }\n\n private async fetchSchemaAuthMode(): Promise<AuthMode | undefined> {\n try {\n // joinUrl never double-prefixes, so passing the absolute schema path is\n // safe with any baseUrl; the client's accept header selects JSON.\n const document = await this.client.request<unknown>(this.client.schemaUrl, {\n skipAuthRefresh: true,\n });\n return readAuthMode(document);\n } catch {\n return undefined;\n }\n }\n\n /** Fetches `/me/` and mirrors the result; any failure means anonymous. */\n private async syncUser(): Promise<void> {\n try {\n const data = await this.client.request<unknown>(`${this.authBasePath}/me/`, {\n skipAuthRefresh: true,\n });\n const user = normalizeUser(data);\n if (user === null) {\n this.setState(\"anonymous\", null);\n } else {\n this.setState(\"authenticated\", user);\n }\n } catch {\n this.setState(\"anonymous\", null);\n }\n }\n\n /**\n * Reads the CSRF cookie, bootstrapping it via `GET <authBasePath>/csrf/`\n * when absent (A4). Returns null when the cookie stays unreadable (e.g.\n * CSRF_COOKIE_HTTPONLY) — requests then go out without the header and the\n * backend's 403 surfaces, which is the honest failure mode.\n */\n private async ensureCsrfToken(): Promise<string | null> {\n let token = readCookie(this.csrfCookieName);\n if (token === null) {\n try {\n await this.client.request<unknown>(`${this.authBasePath}/csrf/`, {\n method: \"GET\",\n skipAuthRefresh: true,\n });\n } catch {\n // Bootstrap is best-effort; the cookie re-read below decides.\n }\n token = readCookie(this.csrfCookieName);\n }\n return token;\n }\n\n // refresh (D6)\n\n /** ONE shared in-flight refresh; resolves true on success. */\n private ensureRefresh(): Promise<boolean> {\n if (this.refreshPromise === null) {\n this.refreshPromise = this.performRefresh().finally(() => {\n this.refreshPromise = null;\n });\n }\n return this.refreshPromise;\n }\n\n private async performRefresh(): Promise<boolean> {\n const refreshToken = this.tokenStorage.get();\n if (refreshToken === null) {\n this.accessToken = null;\n this.setState(\"anonymous\", null);\n return false;\n }\n // Null the stale access token for the duration of the refresh so the\n // refresh request itself (and anything racing it) never carries a Bearer\n // header the backend would reject before reaching the view.\n this.accessToken = null;\n try {\n const data = await this.client.request<unknown>(`${this.authBasePath}/refresh/`, {\n method: \"POST\",\n body: { refresh: refreshToken },\n skipAuthRefresh: true, // a 401 here can never recurse (D6)\n });\n const record =\n typeof data === \"object\" && data !== null ? (data as Record<string, unknown>) : {};\n const access = record.access;\n if (typeof access !== \"string\" || access === \"\") {\n throw new Error(\n `Karni auth: ${this.authBasePath}/refresh/ returned ${describeShape(data)} ` +\n \"instead of { access, refresh? }.\",\n );\n }\n // Persist the rotated refresh token BEFORE this promise resolves, so\n // every queued 401 retry runs against the rotated token (D6).\n const rotated = record.refresh;\n if (typeof rotated === \"string\" && rotated !== \"\") {\n this.tokenStorage.set(rotated);\n }\n this.accessToken = access;\n return true;\n } catch {\n this.tokenStorage.clear();\n this.accessToken = null;\n this.setState(\"anonymous\", null);\n return false;\n }\n }\n\n // public auth actions\n\n async login(email: string, password: string): Promise<LoginResult> {\n await this.ensureInitialized();\n const path = `${this.authBasePath}/login/`;\n if (this.mode === \"session\") {\n await this.ensureCsrfToken(); // header rides in via the getHeaders hook\n const data = await this.client.request<unknown>(path, {\n method: \"POST\",\n body: { email, password },\n skipAuthRefresh: true,\n });\n const twoFactor = read2fa(data);\n if (twoFactor !== null) {\n return { requires2fa: true, ephemeralToken: twoFactor.ephemeralToken };\n }\n const user = normalizeUser(data) ?? (await this.fetchMe(path));\n this.setState(\"authenticated\", user);\n return { ok: true, user };\n }\n\n const data = await this.client.request<unknown>(path, {\n method: \"POST\",\n body: { email, password },\n skipAuthRefresh: true,\n });\n const twoFactor = read2fa(data);\n if (twoFactor !== null) {\n return { requires2fa: true, ephemeralToken: twoFactor.ephemeralToken };\n }\n const record =\n typeof data === \"object\" && data !== null ? (data as Record<string, unknown>) : {};\n const { access, refresh } = record;\n if (typeof access !== \"string\" || typeof refresh !== \"string\") {\n throw new Error(\n `Karni auth: unexpected response from POST ${path} — expected ` +\n \"{ access, refresh } (JWT mode) or { requires_2fa, ephemeral_token }, got \" +\n `${describeShape(data)}. Check the backend's KARNI_AUTH_MODE and the ` +\n 'AuthProvider \"mode\" prop.',\n );\n }\n this.tokenStorage.set(refresh);\n this.accessToken = access;\n const user = normalizeUser(record.user) ?? (await this.fetchMe(path));\n this.setState(\"authenticated\", user);\n return { ok: true, user };\n }\n\n private async fetchMe(loginPath: string): Promise<KarniUser> {\n const data = await this.client.request<unknown>(`${this.authBasePath}/me/`, {\n skipAuthRefresh: true,\n });\n const user = normalizeUser(data);\n if (user === null) {\n throw new Error(\n `Karni auth: POST ${loginPath} succeeded but ${this.authBasePath}/me/ returned ` +\n `${describeShape(data)} instead of a user object with id and email.`,\n );\n }\n return user;\n }\n\n /** Best-effort server logout, then always clears local state (anonymous). */\n async logout(): Promise<void> {\n await this.ensureInitialized();\n try {\n if (this.mode === \"session\") {\n await this.ensureCsrfToken();\n await this.client.request<unknown>(`${this.authBasePath}/logout/`, {\n method: \"POST\",\n skipAuthRefresh: true,\n });\n } else {\n const refresh = this.tokenStorage.get();\n if (refresh !== null) {\n await this.client.request<unknown>(`${this.authBasePath}/logout/`, {\n method: \"POST\",\n body: { refresh },\n skipAuthRefresh: true,\n });\n }\n }\n } catch {\n // Server-side logout is best effort; local state clears regardless.\n }\n this.accessToken = null;\n this.tokenStorage.clear();\n this.setState(\"anonymous\", null);\n }\n\n /**\n * Adopts tokens issued out of band — what `@karni/impersonation-ui` does\n * when a support user starts or stops impersonating (the backend answers\n * with tokens for the other identity). JWT mode only; in session mode the\n * server-side session already changed, so this just re-syncs `/me/`.\n */\n async adoptTokens(access: string | null, refresh: string | null): Promise<void> {\n await this.ensureInitialized();\n if (this.mode === \"jwt\") {\n if (typeof refresh === \"string\" && refresh !== \"\") this.tokenStorage.set(refresh);\n if (typeof access === \"string\" && access !== \"\") this.accessToken = access;\n }\n await this.syncUser();\n }\n\n /**\n * Re-syncs the session: rotates the tokens in JWT mode (A3: /refresh/ is\n * 405 in session mode, so session mode only re-fetches /me/).\n */\n async refresh(): Promise<void> {\n await this.ensureInitialized();\n if (this.mode === \"jwt\") {\n const refreshed = await this.ensureRefresh();\n if (!refreshed) return; // Already anonymous + cleared.\n }\n await this.syncUser();\n }\n}\n","/**\n * Pluggable refresh-token storage for JWT mode (contract \"Hooks + auth\").\n *\n * The default adapter is `localStorage`: it survives reloads and is the\n * simplest thing that works, but any XSS on your page can read it. Stricter\n * setups use `createMemoryTokenStorage()` (logout on reload) or implement\n * the three-method `TokenStorage` interface themselves (e.g. backed by a\n * worker, or by an HttpOnly-cookie BFF). Session mode needs no storage.\n */\n\nexport interface TokenStorage {\n get(): string | null;\n set(token: string): void;\n clear(): void;\n}\n\n/**\n * Keeps the refresh token in localStorage; the default storage. `key` defaults to \"karni.refreshToken\". Every storage\n * access is guarded: when localStorage is unavailable (SSR, private windows,\n * blocked site data) the adapter degrades to a no-op that returns `null`\n * instead of throwing.\n */\nexport function createLocalStorageTokenStorage(key = \"karni.refreshToken\"): TokenStorage {\n return {\n get(): string | null {\n try {\n return globalThis.localStorage.getItem(key);\n } catch {\n return null;\n }\n },\n set(token: string): void {\n try {\n globalThis.localStorage.setItem(key, token);\n } catch {\n // Storage unavailable — the session simply won't survive a reload.\n }\n },\n clear(): void {\n try {\n globalThis.localStorage.removeItem(key);\n } catch {\n // Nothing stored, nothing to clear.\n }\n },\n };\n}\n\n/**\n * In-memory adapter: most secure (nothing persisted anywhere), but a page\n * reload logs the user out.\n */\nexport function createMemoryTokenStorage(): TokenStorage {\n let token: string | null = null;\n return {\n get: () => token,\n set: (next: string) => {\n token = next;\n },\n clear: () => {\n token = null;\n },\n };\n}\n","/**\n * <AuthProvider> + useAuth (contract \"Hooks + auth\" + D6).\n *\n * The provider instantiates the non-React AuthEngine — which owns the tokens\n * and the single-flight refresh machinery, and registers itself on the\n * KarniClient's auth hook points (see ./engine.ts) — and mirrors its state\n * into React. It must be rendered inside <KarniProvider>: it takes the\n * KarniClient from context and uses the shared QueryClient to peek at the\n * cached schema for `x-karni-auth-mode`.\n *\n * Because the engine hooks into the client itself, EVERY request made\n * through the client while an <AuthProvider> is mounted — resource hooks,\n * schema loading, custom `client.request` calls — carries credentials\n * (Bearer in JWT mode; CSRF header + `credentials: \"include\"` in session\n * mode) and takes part in the 401 → refresh → retry flow.\n *\n * Escape hatches: `mode` pins the auth mode (skipping schema detection —\n * recommended for cross-origin session setups so the very first requests\n * already include cookies), `tokenStorage` swaps the refresh-token store,\n * `csrfCookieName` / `csrfHeaderName` re-pin the session CSRF names (A4),\n * and `authBasePath` moves the auth endpoints off `/auth`.\n *\n * The OpenAPI document is generated per role (`Karni.field_roles`, ADR 0002\n * P3): a field a role may not read is absent from its schema. When the\n * identity changes (login, logout, a refresh that lands on another user) the\n * provider invalidates the cached schema, so tables, forms and detail views\n * follow the new user's field set without any per-role component code.\n *\n * Known limitations (D6): browser tabs do not coordinate refreshes — with\n * refresh-token rotation, a refresh in one tab can log another tab out on\n * its next refresh. Identity changes also do not auto-invalidate resource\n * queries; call `queryClient.invalidateQueries({ queryKey:\n * karniKeys.resource(...) })` after login/logout where it matters.\n */\nimport { useQueryClient } from \"@tanstack/react-query\";\nimport {\n createContext,\n useContext,\n useEffect,\n useMemo,\n useRef,\n useSyncExternalStore,\n type ReactElement,\n type ReactNode,\n} from \"react\";\nimport { karniKeys } from \"../hooks/keys\";\nimport { useKarniClient } from \"../schema/provider\";\nimport { AuthEngine } from \"./engine\";\nimport { createLocalStorageTokenStorage, type TokenStorage } from \"./storage\";\nimport type { AuthStatus, KarniUser, LoginResult } from \"./types\";\n\nexport interface AuthProviderProps {\n /**\n * \"jwt\" | \"session\"; when omitted, the mode comes from the schema root's\n * x-karni-auth-mode (D6), falling back to \"jwt\" when the schema does not\n * declare one.\n */\n mode?: \"jwt\" | \"session\";\n /** JWT mode refresh-token storage; default localStorage adapter. */\n tokenStorage?: TokenStorage;\n /** Session mode CSRF cookie name; default \"csrftoken\" (D6/A4). */\n csrfCookieName?: string;\n /** Session mode CSRF header name; default \"X-CSRFToken\" (D6/A4). */\n csrfHeaderName?: string;\n /** Path prefix of the auth endpoints relative to baseUrl; default \"/auth\". */\n authBasePath?: string;\n children?: ReactNode;\n}\n\nexport interface AuthContextValue {\n user: KarniUser | null;\n roles: string[];\n status: AuthStatus;\n login(email: string, password: string): Promise<LoginResult>;\n logout(): Promise<void>;\n refresh(): Promise<void>;\n /**\n * Adopts tokens issued out of band (JWT mode; session mode re-syncs `/me/`),\n * e.g. after starting or stopping an impersonated session.\n */\n adoptTokens(access: string | null, refresh: string | null): Promise<void>;\n}\n\n/**\n * The React mirror of the auth engine's state. Exported for advanced\n * composition (stories, tests, custom providers); application code should\n * use <AuthProvider> + useAuth().\n */\nexport const AuthContext = createContext<AuthContextValue | null>(null);\n\n/** Holds the signed-in user and attaches credentials (JWT or session) to every request; render it inside `KarniProvider`. */\nexport function AuthProvider({\n mode,\n tokenStorage,\n csrfCookieName,\n csrfHeaderName,\n authBasePath,\n children,\n}: AuthProviderProps): ReactElement {\n const client = useKarniClient();\n const queryClient = useQueryClient();\n const storage = useMemo(() => tokenStorage ?? createLocalStorageTokenStorage(), [tokenStorage]);\n\n // The engine registers the client auth hooks in its constructor (render\n // phase) so that children's first queries — fired from effects that run\n // BEFORE this component's own effects — already flow through it.\n const engine = useMemo(\n () =>\n new AuthEngine({\n client,\n tokenStorage: storage,\n ...(mode !== undefined ? { modeOverride: mode } : {}),\n ...(csrfCookieName !== undefined ? { csrfCookieName } : {}),\n ...(csrfHeaderName !== undefined ? { csrfHeaderName } : {}),\n ...(authBasePath !== undefined ? { authBasePath } : {}),\n readCachedSchema: () => queryClient.getQueryData(karniKeys.schema()),\n }),\n [client, queryClient, storage, mode, csrfCookieName, csrfHeaderName, authBasePath],\n );\n\n useEffect(() => {\n engine.attach(); // re-assert after StrictMode remounts / engine swaps\n void engine.ensureInitialized();\n return () => {\n engine.detach();\n };\n }, [engine]);\n\n const snapshot = useSyncExternalStore(engine.subscribe, engine.getSnapshot, engine.getSnapshot);\n\n // The schema is per role: a new identity (or none) means a new field set.\n const identity = snapshot.user?.id ?? null;\n const previousIdentity = useRef(identity);\n useEffect(() => {\n if (previousIdentity.current === identity) return;\n previousIdentity.current = identity;\n void queryClient.invalidateQueries({ queryKey: karniKeys.schema() });\n }, [identity, queryClient]);\n\n const value = useMemo<AuthContextValue>(\n () => ({\n user: snapshot.user,\n roles: snapshot.user?.roles ?? [],\n status: snapshot.status,\n login: (email, password) => engine.login(email, password),\n logout: () => engine.logout(),\n refresh: () => engine.refresh(),\n adoptTokens: (access, refresh) => engine.adoptTokens(access, refresh),\n }),\n [engine, snapshot],\n );\n\n return <AuthContext.Provider value={value}>{children}</AuthContext.Provider>;\n}\n\n/** Returns the signed-in user, auth status, `login` and `logout`; throws a descriptive error outside `AuthProvider`. */\nexport function useAuth(): AuthContextValue {\n const value = useContext(AuthContext);\n if (value === null) {\n throw new Error(\n \"useAuth must be used within an <AuthProvider> (itself inside <KarniProvider>). \" +\n \"Wrap your tree: <KarniProvider client={...}><AuthProvider>...</AuthProvider></KarniProvider>.\",\n );\n }\n return value;\n}\n","/**\n * <AuthGuard> — renders children only for authenticated users (optionally\n * holding one of the given roles); otherwise the `fallback` slot (contract\n * \"Hooks + auth\").\n *\n * While the initial auth state resolves, the `loading` slot renders\n * (default: nothing) so protected content never flashes a login screen\n * during session restore.\n */\nimport type { ReactElement, ReactNode } from \"react\";\nimport { useAuth } from \"./provider\";\nimport { registerComponentRole } from \"../lib/roles\";\n\nregisterComponentRole(\"auth-guard\", \"AuthGuard\");\n\nexport interface AuthGuardProps {\n /** Grant access when the user holds AT LEAST ONE of these role names. */\n roles?: string[];\n /** Rendered for anonymous users and role mismatches; default nothing. */\n fallback?: ReactNode;\n /** Rendered while the auth status is still \"loading\"; default nothing. */\n loading?: ReactNode;\n children?: ReactNode;\n}\n\n/** Renders its children only for a signed-in user, optionally with one of the given roles; otherwise its `fallback`. */\nexport function AuthGuard({\n roles,\n fallback = null,\n loading = null,\n children,\n}: AuthGuardProps): ReactElement | null {\n const { status, user } = useAuth();\n if (status === \"loading\") return <>{loading}</>;\n if (status !== \"authenticated\" || user === null) return <>{fallback}</>;\n if (roles !== undefined && roles.length > 0 && !roles.some((role) => user.roles.includes(role))) {\n return <>{fallback}</>;\n }\n return <>{children}</>;\n}\n","/**\n * LoginForm — the sign-in form every app needs (contract: auth).\n *\n * Email + password against `useAuth().login`, with the error inline. On\n * success it calls `onSuccess(user)` (navigate there). When the backend's\n * 2FA gate fires, `on2FA` receives the ephemeral token so the app can render\n * its code step (`POST <authBasePath>/2fa/login/`); without a handler the\n * form explains that a code is required. Render it inside `AuthProvider`,\n * e.g. as `AuthGuard`'s `fallback`.\n */\nimport * as React from \"react\";\nimport { cn } from \"../lib/cn\";\nimport { registerComponentRole } from \"../lib/roles\";\nimport { Button } from \"../components/primitives/button\";\nimport { Input } from \"../components/primitives/input\";\nimport { Label } from \"../components/primitives/label\";\nimport { useAuth } from \"./provider\";\nimport type { KarniUser } from \"./types\";\n\nregisterComponentRole(\"login-form\", \"LoginForm\");\n\nexport interface LoginFormProps {\n /** Called with the signed-in user; navigate from here. */\n onSuccess?: (user: KarniUser) => void;\n /** Called when the account needs a second factor (the token completes it). */\n on2FA?: (ephemeralToken: string) => void;\n /** Heading above the fields; `null` renders none. Default \"Sign in\". */\n title?: React.ReactNode;\n /** Text under the heading (demo logins, a signup link, ...). */\n description?: React.ReactNode;\n /** The submit button's label. Default \"Sign in\". */\n submitLabel?: React.ReactNode;\n /** Shown while the auth status is \"loading\" is irrelevant here; this disables the form. */\n disabled?: boolean;\n className?: string;\n}\n\n/** Email and password sign-in form with inline errors and a callback for the two-factor step. */\nexport function LoginForm({\n onSuccess,\n on2FA,\n title = \"Sign in\",\n description,\n submitLabel = \"Sign in\",\n disabled = false,\n className,\n}: LoginFormProps) {\n const { login } = useAuth();\n const id = React.useId();\n const [busy, setBusy] = React.useState(false);\n const [error, setError] = React.useState<string | null>(null);\n\n async function submit(event: React.FormEvent<HTMLFormElement>) {\n event.preventDefault();\n const data = new FormData(event.currentTarget);\n setBusy(true);\n setError(null);\n try {\n const result = await login(\n String(data.get(\"email\") ?? \"\"),\n String(data.get(\"password\") ?? \"\"),\n );\n if (\"ok\" in result) {\n onSuccess?.(result.user);\n } else if (on2FA !== undefined) {\n on2FA(result.ephemeralToken);\n } else {\n setError(\"This account needs a two-factor code; the app has not enabled that step.\");\n }\n } catch {\n setError(\"That email and password do not match.\");\n } finally {\n setBusy(false);\n }\n }\n\n return (\n <form\n className={cn(\"space-y-4\", className)}\n onSubmit={(event) => void submit(event)}\n aria-busy={busy}\n noValidate={false}\n >\n {title !== null ? <h2 className=\"text-lg font-semibold\">{title}</h2> : null}\n {description !== undefined ? (\n <p className=\"text-sm text-muted-foreground\">{description}</p>\n ) : null}\n <div className=\"space-y-1\">\n <Label htmlFor={`${id}-email`}>Email</Label>\n <Input\n id={`${id}-email`}\n name=\"email\"\n type=\"email\"\n autoComplete=\"email\"\n required\n disabled={disabled || busy}\n />\n </div>\n <div className=\"space-y-1\">\n <Label htmlFor={`${id}-password`}>Password</Label>\n <Input\n id={`${id}-password`}\n name=\"password\"\n type=\"password\"\n autoComplete=\"current-password\"\n required\n disabled={disabled || busy}\n />\n </div>\n {error !== null ? (\n <p role=\"alert\" className=\"text-sm text-destructive\">\n {error}\n </p>\n ) : null}\n <Button type=\"submit\" disabled={disabled || busy}>\n {submitLabel}\n </Button>\n </form>\n );\n}\n","/**\n * Role helpers over the authenticated user (contract \"Hooks + auth\",\n * accounts A15: the me endpoint returns `roles: string[]`).\n */\nimport { useMemo } from \"react\";\nimport { useAuth } from \"./provider\";\n\nexport interface PermissionHelpers {\n /** True when the user has at least one of the given role names. */\n hasRole(...names: string[]): boolean;\n isAuthenticated: boolean;\n}\n\n/** `isAuthenticated` and `hasRole(...names)` for the signed-in user. */\nexport function usePermission(): PermissionHelpers {\n const { roles, status } = useAuth();\n return useMemo<PermissionHelpers>(\n () => ({\n isAuthenticated: status === \"authenticated\",\n hasRole: (...names: string[]) =>\n status === \"authenticated\" && names.some((name) => roles.includes(name)),\n }),\n [roles, status],\n );\n}\n","import * as React from \"react\";\nimport { cn } from \"../../lib/cn\";\nimport { registerComponentRole } from \"../../lib/roles\";\n\nregisterComponentRole(\"page-shell\", \"Page\");\n\nexport interface PageProps extends Omit<React.HTMLAttributes<HTMLElement>, \"title\"> {\n /** Page heading, rendered as an <h1>. */\n title: React.ReactNode;\n /** Optional sub-heading under the title. */\n description?: React.ReactNode;\n /** Slot rendered to the right of the title (buttons, menus, …). */\n actions?: React.ReactNode;\n /**\n * Escape hatch: replaces the entire derived header (title/description/\n * actions are ignored when given).\n */\n header?: React.ReactNode;\n /** Extra classes for the derived header row. */\n headerClassName?: string;\n /** Extra classes for the content area under the header. */\n contentClassName?: string;\n children?: React.ReactNode;\n}\n\n/**\n * Standard page chrome: an <h1> title row with an actions slot, then the\n * content. The target usage `<Page title=\"Events\"><ResourceTable … /></Page>`\n * is a complete screen.\n *\n * Escape hatches: `header` replaces the whole derived header; `className`,\n * `headerClassName` and `contentClassName` merge through cn(); every other\n * prop passes through to the root <section>.\n */\nexport const Page = React.forwardRef<HTMLElement, PageProps>(\n (\n {\n title,\n description,\n actions,\n header,\n headerClassName,\n contentClassName,\n className,\n children,\n ...props\n },\n ref,\n ) => (\n <section ref={ref} className={cn(\"flex w-full flex-col gap-6\", className)} {...props}>\n {header ?? (\n <header className={cn(\"flex flex-wrap items-start justify-between gap-4\", headerClassName)}>\n <div className=\"grid gap-1\">\n <h1 className=\"text-2xl font-semibold tracking-tight text-foreground\">{title}</h1>\n {description != null && <p className=\"text-sm text-muted-foreground\">{description}</p>}\n </div>\n {actions != null && <div className=\"flex shrink-0 items-center gap-2\">{actions}</div>}\n </header>\n )}\n <div className={cn(\"flex flex-col gap-4\", contentClassName)}>{children}</div>\n </section>\n ),\n);\nPage.displayName = \"Page\";\n","// Generated by scripts/brand/render.mjs from assets/brand/ — do not edit.\nexport const MARK_VIEWBOX = \"0 0 1000 1000\";\n/** The full mark: ground, rings, strokes. */\nexport const MARK_PATHS: ReadonlyArray<{ readonly fill: string; readonly d: string }> = [\n {\n \"fill\": \"#000000\",\n \"d\": \"M495.8 884.4C366.3 877.9 255.3 816.3 182.4 710.5C128.6 632.2 103.2 521.3 115 415.5C128.3 296.3 188.2 205.8 290.9 150.2C389.1 97 470.1 78.3 564.8 87C689.6 98.4 790.1 167.2 844.3 278.1C896.3 384.6 901.7 498.4 860.4 619.6C833.4 698.7 806.7 746.3 766.3 787.1C699.4 854.6 601.9 889.7 495.8 884.4Z\"\n },\n {\n \"fill\": \"#FB5D08\",\n \"d\": \"M355.6 514.1C355.6 509.2 355.7 507.3 355.8 509.8C355.9 512.3 355.9 516.3 355.8 518.7C355.7 521 355.6 519 355.6 514.1ZM677.1 423C637.3 415.7 624.1 366.4 654.9 340.2C672.8 325 696 324.3 713.7 338.5C741 360.3 735.8 403.2 704.1 418.6C696.1 422.4 684.6 424.3 677.1 423ZM330.5 421.6C299.1 415 283.8 379.9 300.6 352.7C317.1 325.8 352.4 320.7 373.7 342.2C398.9 367.6 387.2 410.3 352.3 420.8C347.4 422.3 335.7 422.7 330.5 421.6ZM504.5 399.6C466.4 392.2 453.2 345.4 481.5 318.2C509.6 291.1 556 308.2 560.5 347.3C564.1 377.9 534.5 405.5 504.5 399.6ZM349.4 395.9C367.2 387.1 367.7 363.1 350.2 354.5C329.3 344.3 308.5 369.4 321.8 388.6C327.9 397.5 339.8 400.7 349.4 395.9ZM694 395.9C716 385.1 709 352 684.8 352C665.4 352 654.8 375.3 667.3 390.4C673.5 397.8 685.2 400.2 694 395.9ZM522.4 373.7C534.6 368 539.9 353.6 534.2 341.9C525.3 323.9 501.3 323.8 492.5 341.8C482.8 361.3 503 382.8 522.4 373.7Z\"\n },\n {\n \"fill\": \"#FFFFFF\",\n \"d\": \"M363 677.8C348.7 675.4 341.3 657.2 334.1 606.9C326.6 554.4 325.7 485.2 332.2 459.2C336.3 442.9 349.3 435.9 362.9 442.6C374.7 448.4 394.4 475.1 427.1 529.5C428.9 532.4 430.5 534.9 430.8 534.9C431 534.9 433.5 530.7 436.3 525.6C486 435.8 497.3 419.9 512.2 419.2C523.9 418.6 531.9 426.3 550 455.6C555.3 464.3 582.5 513.2 591.4 530.3C592.7 532.8 594 534.9 594.2 534.9C594.4 534.9 595.9 532.7 597.5 530C621.8 490.2 643.6 458.3 652.7 449.5C668.6 434.2 686.9 437.8 692.6 457.4C703.9 496.4 693.7 637.6 677.5 666.3C673 674.5 663.4 679.5 655.8 677.8C642.6 674.9 633.9 663.4 598.7 602.7C592.7 592.3 593.3 593.1 592.3 594.4C590.8 596.2 572.8 626.4 560.2 648.2C546.9 671 546 672.4 541.7 674.3C531.2 679.1 519.1 669.5 522.1 658.7C523.4 654.4 551 607 571.8 573.6C575 568.5 577.6 564.2 577.6 564C577.6 563.7 560.8 532.5 547.2 507.4C527.8 471.7 514.9 450.1 513.1 450.1C512.4 450.1 510.6 452.9 504.3 463.4C492.7 482.5 447.9 562.5 447.9 564C447.9 564.3 449.8 567.6 452.1 571.4C475.2 609.2 501.1 653.4 502.6 657.5C506.1 667.6 496.6 677.8 485.8 675.3C479.8 673.9 479.1 673.1 468.6 655.1C464.9 648.8 456 633.6 448.7 621.3C441.5 608.9 434.9 597.8 434.2 596.5C432.8 594 431.8 593 431.5 593.9C431.3 594.5 427.1 601.6 414 623.8C386.6 670 377.1 680.1 363 677.8ZM373.8 636.7C376.1 632.9 382.1 622.9 387.1 614.4C408.9 577.2 413.5 569.4 414.6 567.2L415.7 564.9L411.3 557.5C374 495.9 359.9 473.9 357.6 473.9C355.5 473.9 355.1 527.7 357.1 556.7C359.2 587.2 364.9 630.4 368.5 642.5C369 644.1 369.4 643.7 373.8 636.7ZM658.1 639.2C666.8 598 672.3 509 668.1 476.6C667.7 473.1 667.4 473.2 663.8 478C657.6 486.3 651.5 495.7 631.2 529C626.9 536.1 622.1 543.9 620.5 546.5C618.9 549.1 615.7 554.3 613.4 558.1L609.1 565L610.6 567.5C611.4 568.9 616.6 577.6 622.1 586.9C627.5 596.2 634.1 607.5 636.7 611.9C649.4 633.6 655.7 643.4 656.8 643.4C657 643.4 657.6 641.5 658.1 639.2Z\"\n }\n];\n/** The small-size variant's SVG body (use at 32px and below). */\nexport const MARK_SIMPLE_BODY = \"<path fill=\\\"#000000\\\" d=\\\"M495.8 884.4C291.9 874.2 135.4 724 114.7 518.5C97.9 351.3 160.2 221 290.9 150.2C372.3 106.1 439.7 86.4 513.6 85.2C686 82.3 812.9 171.5 867 333.5C903.9 444 890.2 573.8 828.6 698.6C766.8 823.4 644.3 891.8 495.8 884.4Z\\\"/>\\n<circle cx=\\\"340\\\" cy=\\\"300\\\" r=\\\"44\\\" fill=\\\"#FB5D08\\\"/>\\n<circle cx=\\\"500\\\" cy=\\\"276\\\" r=\\\"44\\\" fill=\\\"#FB5D08\\\"/>\\n<circle cx=\\\"660\\\" cy=\\\"300\\\" r=\\\"44\\\" fill=\\\"#FB5D08\\\"/>\\n<path fill=\\\"none\\\" stroke=\\\"#FFFFFF\\\" stroke-width=\\\"58\\\" stroke-linecap=\\\"round\\\" stroke-linejoin=\\\"round\\\"\\n d=\\\"M318 420v280l182-250 182 250V420M500 450 410 700M500 450l90 250\\\"/>\";\n","import * as React from \"react\";\nimport { cn } from \"../../lib/cn\";\nimport { MARK_PATHS, MARK_SIMPLE_BODY, MARK_VIEWBOX } from \"./mark-paths\";\n\nexport interface KarniMarkProps extends Omit<React.SVGAttributes<SVGSVGElement>, \"children\"> {\n /** Rendered size in px (width and height). Default 28. */\n size?: number;\n /**\n * Which drawing: the full mark, the small-size variant, or `auto` (the\n * default) — the small variant at 32px and below, the full mark above.\n */\n variant?: \"auto\" | \"full\" | \"simple\";\n /** Accessible name; pass an empty string to hide a purely decorative mark. */\n title?: string;\n}\n\n/**\n * The Karni mark, inline SVG — no asset to load or bundle.\n *\n * It is the default content of `<Layout>`'s `sidebarHeader` slot so a bare\n * shell is never nameless; a project replaces it by passing its own\n * `sidebarHeader` (the scaffold already does). Do not recolour or restyle it:\n * the mark is Karni's, see assets/brand/README.md in the repository.\n */\nexport const KarniMark = React.forwardRef<SVGSVGElement, KarniMarkProps>(\n ({ size = 28, variant = \"auto\", title = \"Karni\", className, ...props }, ref) => {\n const simple = variant === \"simple\" || (variant === \"auto\" && size <= 32);\n const labelled = title !== \"\";\n return (\n <svg\n ref={ref}\n viewBox={MARK_VIEWBOX}\n width={size}\n height={size}\n role={labelled ? \"img\" : undefined}\n aria-hidden={labelled ? undefined : true}\n aria-label={labelled ? title : undefined}\n className={cn(\"shrink-0\", className)}\n {...props}\n {...(simple ? { dangerouslySetInnerHTML: { __html: MARK_SIMPLE_BODY } } : {})}\n >\n {simple\n ? null\n : MARK_PATHS.map((path) => (\n <path key={path.fill + path.d.length} fill={path.fill} d={path.d} />\n ))}\n </svg>\n );\n },\n);\nKarniMark.displayName = \"KarniMark\";\n","import * as React from \"react\";\nimport { cn } from \"../../lib/cn\";\nimport { registerComponentRole } from \"../../lib/roles\";\nimport { KarniMark } from \"../brand/karni-mark\";\n\nregisterComponentRole(\"layout-shell\", \"Layout\");\n\ntype IconProps = React.SVGAttributes<SVGSVGElement>;\n\nfunction MenuIcon(props: IconProps): React.ReactElement {\n return (\n <svg\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth={2}\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n focusable={false}\n {...props}\n >\n <line x1=\"4\" y1=\"6\" x2=\"20\" y2=\"6\" />\n <line x1=\"4\" y1=\"12\" x2=\"20\" y2=\"12\" />\n <line x1=\"4\" y1=\"18\" x2=\"20\" y2=\"18\" />\n </svg>\n );\n}\n\nfunction CloseIcon(props: IconProps): React.ReactElement {\n return (\n <svg\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth={2}\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n focusable={false}\n {...props}\n >\n <line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\" />\n <line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\" />\n </svg>\n );\n}\n\nexport interface LayoutNavItem {\n /** Visible label of the nav entry. */\n label: React.ReactNode;\n /** Target URL (rendered as a plain <a> by default). */\n href: string;\n /** Optional icon rendered before the label. */\n icon?: React.ReactNode;\n /** Marks the current page (aria-current=\"page\" + active styling). */\n active?: boolean;\n /** React key override when `href` is not unique. */\n key?: string;\n}\n\nexport interface LayoutProps extends React.HTMLAttributes<HTMLDivElement> {\n /** Items of the derived sidebar nav. */\n navItems?: readonly LayoutNavItem[];\n /**\n * Escape hatch for router integration: wraps/replaces the default anchor of\n * one item. `defaultNode` is the styled <a> the layout would render — return\n * it, or your own node (e.g. a TanStack Router <Link> with\n * `className={defaultClassName}`).\n */\n renderNavItem?: (\n item: LayoutNavItem,\n defaults: { defaultNode: React.ReactNode; defaultClassName: string },\n ) => React.ReactNode;\n /** Escape hatch: replaces the entire derived nav inside the sidebar. */\n sidebar?: React.ReactNode;\n /**\n * Brand/logo slot pinned to the top of the sidebar. Defaults to the Karni\n * mark (`<KarniMark />`); pass your own brand, or `null` for no header.\n */\n sidebarHeader?: React.ReactNode;\n /** Slot pinned to the bottom of the sidebar (user menu, logout, …). */\n sidebarFooter?: React.ReactNode;\n /** Header slot, rendered in the top bar next to the mobile menu button. */\n header?: React.ReactNode;\n /** Accessible name of the sidebar navigation (default \"Main\"). */\n navLabel?: string;\n sidebarClassName?: string;\n headerClassName?: string;\n contentClassName?: string;\n children?: React.ReactNode;\n}\n\nconst NAV_ITEM_CLASS =\n \"flex items-center gap-3 rounded-md px-3 py-2 text-sm font-medium text-muted-foreground transition-colors hover:bg-accent hover:text-accent-foreground [&_svg]:h-4 [&_svg]:w-4\";\nconst NAV_ITEM_ACTIVE_CLASS = \"bg-accent text-accent-foreground\";\n\nconst SIDEBAR_ID = \"karni-layout-sidebar\";\n\n/**\n * App shell: sidebar navigation + header slot + content area.\n *\n * Responsive: under the `md` breakpoint the sidebar collapses behind a menu\n * button and opens as an overlay drawer (Escape or backdrop click closes it).\n *\n * Escape hatches: `renderNavItem` wraps each derived link (router\n * integration), `sidebar` replaces the derived nav wholesale, and\n * `sidebarHeader`/`sidebarFooter`/`header` are free slots.\n */\nexport const Layout = React.forwardRef<HTMLDivElement, LayoutProps>(\n (\n {\n navItems = [],\n renderNavItem,\n sidebar,\n sidebarHeader = <KarniMark className=\"mx-3\" />,\n sidebarFooter,\n header,\n navLabel = \"Main\",\n sidebarClassName,\n headerClassName,\n contentClassName,\n className,\n children,\n ...props\n },\n ref,\n ) => {\n const [mobileOpen, setMobileOpen] = React.useState(false);\n\n const closeMobile = React.useCallback(() => {\n setMobileOpen(false);\n }, []);\n\n React.useEffect(() => {\n if (!mobileOpen) {\n return;\n }\n const onKeyDown = (event: KeyboardEvent): void => {\n if (event.key === \"Escape\") {\n setMobileOpen(false);\n }\n };\n document.addEventListener(\"keydown\", onKeyDown);\n return () => {\n document.removeEventListener(\"keydown\", onKeyDown);\n };\n }, [mobileOpen]);\n\n const navContent = sidebar ?? (\n <nav aria-label={navLabel} className=\"grid gap-1\">\n {navItems.map((item) => {\n const defaultClassName = cn(\n NAV_ITEM_CLASS,\n item.active === true && NAV_ITEM_ACTIVE_CLASS,\n );\n const defaultNode = (\n <a\n href={item.href}\n aria-current={item.active === true ? \"page\" : undefined}\n className={defaultClassName}\n onClick={closeMobile}\n >\n {item.icon != null && <span aria-hidden=\"true\">{item.icon}</span>}\n {item.label}\n </a>\n );\n return (\n <React.Fragment key={item.key ?? item.href}>\n {renderNavItem ? renderNavItem(item, { defaultNode, defaultClassName }) : defaultNode}\n </React.Fragment>\n );\n })}\n </nav>\n );\n\n const sidebarInner = (\n <>\n {sidebarHeader != null && <div className=\"mb-4\">{sidebarHeader}</div>}\n <div className=\"flex-1 overflow-y-auto\">{navContent}</div>\n {sidebarFooter != null && <div className=\"mt-4\">{sidebarFooter}</div>}\n </>\n );\n\n return (\n <div\n ref={ref}\n className={cn(\"flex min-h-screen w-full bg-background text-foreground\", className)}\n {...props}\n >\n {/* Static sidebar (md and up). */}\n <aside\n className={cn(\n \"hidden w-64 shrink-0 flex-col border-r border-border bg-card p-4 md:flex\",\n sidebarClassName,\n )}\n >\n {sidebarInner}\n </aside>\n\n {/* Overlay drawer (below md). */}\n {mobileOpen && (\n <div className=\"fixed inset-0 z-40 md:hidden\">\n <div\n data-testid=\"karni-layout-backdrop\"\n aria-hidden=\"true\"\n className=\"absolute inset-0 bg-foreground/40\"\n onClick={closeMobile}\n />\n <aside\n id={SIDEBAR_ID}\n className={cn(\n \"absolute inset-y-0 left-0 flex w-64 flex-col border-r border-border bg-card p-4 shadow-lg\",\n sidebarClassName,\n )}\n >\n <div className=\"mb-2 flex justify-end\">\n <button\n type=\"button\"\n onClick={closeMobile}\n className=\"inline-flex h-8 w-8 items-center justify-center rounded-md text-muted-foreground hover:bg-accent hover:text-accent-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring\"\n >\n <CloseIcon className=\"h-4 w-4\" />\n <span className=\"sr-only\">Close navigation</span>\n </button>\n </div>\n {sidebarInner}\n </aside>\n </div>\n )}\n\n <div className=\"flex min-w-0 flex-1 flex-col\">\n <header\n className={cn(\n \"flex h-14 shrink-0 items-center gap-3 border-b border-border px-4\",\n headerClassName,\n )}\n >\n <button\n type=\"button\"\n aria-expanded={mobileOpen}\n aria-controls={SIDEBAR_ID}\n onClick={() => {\n setMobileOpen((open) => !open);\n }}\n className=\"inline-flex h-9 w-9 items-center justify-center rounded-md text-muted-foreground hover:bg-accent hover:text-accent-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring md:hidden\"\n >\n <MenuIcon className=\"h-5 w-5\" />\n <span className=\"sr-only\">Open navigation</span>\n </button>\n {header != null && (\n <div className=\"flex min-w-0 flex-1 items-center gap-3\">{header}</div>\n )}\n </header>\n <main className={cn(\"flex-1 p-6\", contentClassName)}>{children}</main>\n </div>\n </div>\n );\n },\n);\nLayout.displayName = \"Layout\";\n","import * as DialogPrimitive from \"@radix-ui/react-dialog\";\nimport * as React from \"react\";\nimport { cn } from \"../../lib/cn\";\nimport { registerComponentRole } from \"../../lib/roles\";\n\nregisterComponentRole(\"modal\", \"Modal\");\n\ntype IconProps = React.SVGAttributes<SVGSVGElement>;\n\nfunction CloseIcon(props: IconProps): React.ReactElement {\n return (\n <svg\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth={2}\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n focusable={false}\n {...props}\n >\n <line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\" />\n <line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\" />\n </svg>\n );\n}\n\n/**\n * Escape hatch for footer buttons: any element wrapped in <ModalClose asChild>\n * closes the modal on click (re-exported Radix Dialog.Close).\n */\nexport const ModalClose = DialogPrimitive.Close;\n\nexport interface ModalProps {\n /** Dialog title — always rendered (Radix requires it for accessibility). */\n title: React.ReactNode;\n /** Optional description under the title, linked via aria-describedby. */\n description?: React.ReactNode;\n /** Body content. */\n children?: React.ReactNode;\n /** Footer slot (actions row). Use <ModalClose asChild> for cancel buttons. */\n footer?: React.ReactNode;\n /**\n * Uncontrolled usage: a node (usually a Button) that opens the modal,\n * rendered through Radix `asChild`.\n */\n trigger?: React.ReactNode;\n /** Controlled open state (pair with onOpenChange). */\n open?: boolean;\n /** Initial state for uncontrolled usage. */\n defaultOpen?: boolean;\n onOpenChange?: (open: boolean) => void;\n /** Hides the top-right X button. */\n hideCloseButton?: boolean;\n /** Extra classes for the content panel. */\n className?: string;\n /**\n * Escape hatch: props spread onto Radix Dialog.Content\n * (onEscapeKeyDown, onInteractOutside, …).\n */\n contentProps?: Omit<\n React.ComponentPropsWithoutRef<typeof DialogPrimitive.Content>,\n \"children\" | \"className\"\n >;\n}\n\n/**\n * Themed Radix Dialog. Works controlled (`open` + `onOpenChange`) or\n * uncontrolled via the `trigger` slot; `footer` is the actions row.\n *\n * Escape hatches: `contentProps` reaches the Radix content part, `className`\n * restyles the panel, `hideCloseButton` drops the X, and `ModalClose` lets any\n * footer element close the dialog.\n */\nexport function Modal({\n title,\n description,\n children,\n footer,\n trigger,\n open,\n defaultOpen,\n onOpenChange,\n hideCloseButton = false,\n className,\n contentProps,\n}: ModalProps): React.ReactElement {\n // Without a Description part, Radix warns unless aria-describedby is\n // explicitly cleared; with one (or a consumer-supplied id) leave the key\n // alone so the automatic wiring stands.\n const clearDescribedBy =\n description == null && contentProps?.[\"aria-describedby\"] === undefined\n ? { \"aria-describedby\": undefined }\n : {};\n return (\n <DialogPrimitive.Root open={open} defaultOpen={defaultOpen} onOpenChange={onOpenChange}>\n {trigger != null && <DialogPrimitive.Trigger asChild>{trigger}</DialogPrimitive.Trigger>}\n <DialogPrimitive.Portal>\n <DialogPrimitive.Overlay className=\"fixed inset-0 z-50 bg-foreground/40\" />\n <DialogPrimitive.Content\n {...contentProps}\n {...clearDescribedBy}\n className={cn(\n \"fixed left-1/2 top-1/2 z-50 grid w-full max-w-lg -translate-x-1/2 -translate-y-1/2 gap-4 rounded-lg border border-border bg-background p-6 text-foreground shadow-lg\",\n className,\n )}\n >\n <div className=\"grid gap-1.5\">\n <DialogPrimitive.Title className=\"text-lg font-semibold leading-none tracking-tight\">\n {title}\n </DialogPrimitive.Title>\n {description != null && (\n <DialogPrimitive.Description className=\"text-sm text-muted-foreground\">\n {description}\n </DialogPrimitive.Description>\n )}\n </div>\n {children}\n {footer != null && (\n <div className=\"flex flex-col-reverse gap-2 sm:flex-row sm:justify-end\">{footer}</div>\n )}\n {!hideCloseButton && (\n <DialogPrimitive.Close className=\"absolute right-4 top-4 rounded-sm text-muted-foreground opacity-70 transition-opacity hover:opacity-100 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none\">\n <CloseIcon className=\"h-4 w-4\" />\n <span className=\"sr-only\">Close</span>\n </DialogPrimitive.Close>\n )}\n </DialogPrimitive.Content>\n </DialogPrimitive.Portal>\n </DialogPrimitive.Root>\n );\n}\n","import type * as React from \"react\";\n\n/**\n * Module-level toast store.\n *\n * `useToast()` can be called anywhere (no provider requirement beyond a\n * mounted <Toaster/>): toasts are pushed into this store and every mounted\n * Toaster/useToast subscriber re-renders via useSyncExternalStore.\n */\n\nexport type ToastVariant = \"default\" | \"success\" | \"error\" | \"info\";\n\nexport interface ToastOptions {\n /** Stable id (defaults to an auto-generated one). Re-using an id replaces. */\n id?: string;\n title?: React.ReactNode;\n description?: React.ReactNode;\n variant?: ToastVariant;\n /** Per-toast auto-dismiss override in ms (Toaster default otherwise). */\n duration?: number;\n /** Action slot (e.g. an \"Undo\" button), rendered inside the toast. */\n action?: React.ReactNode;\n}\n\nexport interface ToastInstance extends ToastOptions {\n id: string;\n variant: ToastVariant;\n}\n\nexport interface ToastHandle {\n id: string;\n dismiss: () => void;\n}\n\n/** Oldest toasts beyond this count are dropped. */\nconst TOAST_LIMIT = 5;\n\ntype Listener = () => void;\n\nlet toasts: readonly ToastInstance[] = [];\nconst listeners = new Set<Listener>();\nlet counter = 0;\n\nfunction emit(): void {\n for (const listener of listeners) {\n listener();\n }\n}\n\nexport function subscribeToToasts(listener: Listener): () => void {\n listeners.add(listener);\n return () => {\n listeners.delete(listener);\n };\n}\n\nexport function getToasts(): readonly ToastInstance[] {\n return toasts;\n}\n\nexport function dismissToast(id?: string): void {\n const next = id === undefined ? [] : toasts.filter((item) => item.id !== id);\n if (next.length !== toasts.length) {\n toasts = next;\n emit();\n }\n}\n\nexport function addToast(options: ToastOptions): ToastHandle {\n counter += 1;\n const id = options.id ?? `karni-toast-${String(counter)}`;\n const instance: ToastInstance = {\n ...options,\n id,\n variant: options.variant ?? \"default\",\n };\n toasts = [...toasts.filter((item) => item.id !== id), instance].slice(-TOAST_LIMIT);\n emit();\n return {\n id,\n dismiss: () => {\n dismissToast(id);\n },\n };\n}\n\n/** Test helper — clears all toasts and listeners' state (not in the barrel). */\nexport function resetToastStore(): void {\n toasts = [];\n counter = 0;\n emit();\n}\n","import * as React from \"react\";\nimport {\n addToast,\n dismissToast,\n getToasts,\n subscribeToToasts,\n type ToastHandle,\n type ToastInstance,\n type ToastOptions,\n} from \"./toast-store\";\n\nexport interface UseToastResult {\n /** Currently visible toasts (rendered by <Toaster/>). */\n toasts: readonly ToastInstance[];\n /** Full-control entry point: show any ToastOptions. */\n toast: (options: ToastOptions) => ToastHandle;\n /** Shorthand: success variant. */\n success: (title: React.ReactNode, options?: Omit<ToastOptions, \"variant\">) => ToastHandle;\n /** Shorthand: error variant. */\n error: (title: React.ReactNode, options?: Omit<ToastOptions, \"variant\">) => ToastHandle;\n /** Shorthand: info variant. */\n info: (title: React.ReactNode, options?: Omit<ToastOptions, \"variant\">) => ToastHandle;\n /** Dismiss one toast by id, or all when called without arguments. */\n dismiss: (id?: string) => void;\n}\n\nfunction makeShorthand(\n variant: \"success\" | \"error\" | \"info\",\n): (title: React.ReactNode, options?: Omit<ToastOptions, \"variant\">) => ToastHandle {\n return (title, options) => addToast({ ...options, title, variant });\n}\n\nconst stableApi = {\n toast: addToast,\n success: makeShorthand(\"success\"),\n error: makeShorthand(\"error\"),\n info: makeShorthand(\"info\"),\n dismiss: dismissToast,\n} as const;\n\n/**\n * Imperative toast API + the live toast list.\n *\n * Requires a mounted <Toaster/> somewhere in the tree to actually render the\n * toasts; the functions themselves are stable module-level references, safe\n * to use in effects and callbacks without dependency churn.\n */\nexport function useToast(): UseToastResult {\n const toasts = React.useSyncExternalStore(subscribeToToasts, getToasts, getToasts);\n return React.useMemo(() => ({ toasts, ...stableApi }), [toasts]);\n}\n","import * as ToastPrimitive from \"@radix-ui/react-toast\";\nimport * as React from \"react\";\nimport { cn } from \"../../lib/cn\";\nimport { variants, type VariantProps } from \"../../lib/variants\";\nimport { dismissToast, type ToastVariant } from \"./toast-store\";\nimport { useToast } from \"./use-toast\";\nimport { registerComponentRole } from \"../../lib/roles\";\n\nregisterComponentRole(\"toast\", \"Toaster\");\n\ntype IconProps = React.SVGAttributes<SVGSVGElement>;\n\nfunction CloseIcon(props: IconProps): React.ReactElement {\n return (\n <svg\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth={2}\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n focusable={false}\n {...props}\n >\n <line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\" />\n <line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\" />\n </svg>\n );\n}\n\n/**\n * Per-variant toast styling — colors resolve through --karni-* tokens only\n * (success leans on primary, error on destructive, info on muted).\n */\nexport const toastVariants = variants({\n base: \"pointer-events-auto relative flex w-full items-start gap-3 overflow-hidden rounded-md border p-4 pr-8 shadow-lg\",\n variants: {\n variant: {\n default: \"border-border bg-background text-foreground\",\n success: \"border-primary bg-background text-foreground\",\n error: \"border-destructive bg-destructive text-destructive-foreground\",\n info: \"border-border bg-muted text-foreground\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n },\n});\n\nexport type ToastVariantProps = VariantProps<typeof toastVariants>;\n\nexport interface ToasterProps {\n /** Auto-dismiss duration in ms for toasts without their own (default 5000). */\n duration?: number;\n /** Swipe-to-dismiss direction (default \"right\"). */\n swipeDirection?: \"right\" | \"left\" | \"up\" | \"down\";\n /** Accessible label prefix announced with each toast (Radix Provider). */\n label?: string;\n /** Extra classes for the viewport (position/stacking escape hatch). */\n viewportClassName?: string;\n /** Extra classes for every toast root. */\n toastClassName?: string;\n}\n\n/**\n * Renders the toasts pushed through useToast(). Mount exactly one near the\n * app root. Position defaults to the bottom-right corner; override with\n * `viewportClassName` (it merges via cn(), so e.g. \"top-0 bottom-auto\" wins).\n */\nexport function Toaster({\n duration = 5000,\n swipeDirection = \"right\",\n label = \"Notification\",\n viewportClassName,\n toastClassName,\n}: ToasterProps): React.ReactElement {\n const { toasts } = useToast();\n\n return (\n <ToastPrimitive.Provider duration={duration} swipeDirection={swipeDirection} label={label}>\n {toasts.map((item) => (\n <ToastPrimitive.Root\n key={item.id}\n duration={item.duration}\n data-variant={item.variant satisfies ToastVariant}\n onOpenChange={(open) => {\n if (!open) {\n dismissToast(item.id);\n }\n }}\n className={toastVariants({ variant: item.variant, className: toastClassName })}\n >\n <div className=\"grid flex-1 gap-1\">\n {item.title != null && (\n <ToastPrimitive.Title className=\"text-sm font-semibold\">\n {item.title}\n </ToastPrimitive.Title>\n )}\n {item.description != null && (\n <ToastPrimitive.Description className=\"text-sm opacity-90\">\n {item.description}\n </ToastPrimitive.Description>\n )}\n </div>\n {item.action != null && <div className=\"flex shrink-0 items-center\">{item.action}</div>}\n <ToastPrimitive.Close\n aria-label=\"Dismiss\"\n className=\"absolute right-2 top-2 rounded-md p-1 opacity-70 transition-opacity hover:opacity-100 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring\"\n >\n <CloseIcon className=\"h-4 w-4\" />\n </ToastPrimitive.Close>\n </ToastPrimitive.Root>\n ))}\n <ToastPrimitive.Viewport\n className={cn(\n \"fixed bottom-0 right-0 z-[100] flex w-full max-w-sm flex-col gap-2 p-4 outline-none\",\n viewportClassName,\n )}\n />\n </ToastPrimitive.Provider>\n );\n}\n","import * as React from \"react\";\nimport { cn } from \"../../lib/cn\";\nimport { registerComponentRole } from \"../../lib/roles\";\n\nregisterComponentRole(\"stat\", \"Stat\");\n\ntype ArrowProps = React.SVGAttributes<SVGSVGElement>;\n\nfunction ArrowUpIcon(props: ArrowProps): React.ReactElement {\n return (\n <svg\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth={2}\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n focusable={false}\n {...props}\n >\n <line x1=\"12\" y1=\"19\" x2=\"12\" y2=\"5\" />\n <polyline points=\"5 12 12 5 19 12\" />\n </svg>\n );\n}\n\nfunction ArrowDownIcon(props: ArrowProps): React.ReactElement {\n return (\n <svg\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth={2}\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n focusable={false}\n {...props}\n >\n <line x1=\"12\" y1=\"5\" x2=\"12\" y2=\"19\" />\n <polyline points=\"19 12 12 19 5 12\" />\n </svg>\n );\n}\n\nexport interface StatProps extends React.HTMLAttributes<HTMLDivElement> {\n /** What the number measures (\"Active users\"). */\n label: React.ReactNode;\n /** The headline value — preformatted string or any node. */\n value: React.ReactNode;\n /**\n * Change indicator. A number renders a signed figure with an up/down arrow\n * (negative numbers use the destructive token) plus screen-reader context;\n * any other node renders verbatim in the delta slot.\n */\n delta?: number | React.ReactNode;\n /** Formats a numeric `delta` (default: signed, locale formatted). */\n formatDelta?: (delta: number) => string;\n /** Optional icon slot, top-right. */\n icon?: React.ReactNode;\n}\n\nfunction defaultFormatDelta(delta: number): string {\n const formatted = Math.abs(delta).toLocaleString();\n return delta >= 0 ? `+${formatted}` : `-${formatted}`;\n}\n\n/**\n * KPI tile: label, value, optional delta and icon.\n *\n * Escape hatches: `value`/`delta`/`icon` accept arbitrary nodes,\n * `formatDelta` overrides numeric formatting, `className` merges via cn().\n */\nexport const Stat = React.forwardRef<HTMLDivElement, StatProps>(\n ({ label, value, delta, formatDelta = defaultFormatDelta, icon, className, ...props }, ref) => {\n let deltaNode: React.ReactNode = null;\n if (typeof delta === \"number\" && Number.isFinite(delta)) {\n const down = delta < 0;\n deltaNode = (\n <p\n className={cn(\n \"flex items-center gap-1 text-sm font-medium\",\n down ? \"text-destructive\" : \"text-muted-foreground\",\n )}\n >\n {down ? (\n <ArrowDownIcon className=\"h-3.5 w-3.5\" />\n ) : (\n <ArrowUpIcon className=\"h-3.5 w-3.5\" />\n )}\n <span className=\"sr-only\">{down ? \"Decreased by\" : \"Increased by\"} </span>\n {formatDelta(delta)}\n </p>\n );\n } else if (delta != null) {\n deltaNode = <div className=\"text-sm text-muted-foreground\">{delta}</div>;\n }\n\n return (\n <div\n ref={ref}\n className={cn(\n \"flex flex-col gap-1 rounded-lg border border-border bg-card p-4 text-card-foreground\",\n className,\n )}\n {...props}\n >\n <div className=\"flex items-start justify-between gap-2\">\n <p className=\"text-sm font-medium text-muted-foreground\">{label}</p>\n {icon != null && (\n <span aria-hidden=\"true\" className=\"text-muted-foreground [&>svg]:h-4 [&>svg]:w-4\">\n {icon}\n </span>\n )}\n </div>\n <p className=\"text-2xl font-semibold tracking-tight\">{value}</p>\n {deltaNode}\n </div>\n );\n },\n);\nStat.displayName = \"Stat\";\n","import * as VisuallyHidden from \"@radix-ui/react-visually-hidden\";\nimport * as React from \"react\";\nimport { cn } from \"../../lib/cn\";\nimport { registerComponentRole } from \"../../lib/roles\";\n\nregisterComponentRole(\"chart\", \"DataChart\");\n\n/**\n * In-house SVG chart (contract: no chart dependency).\n *\n * Accessibility model (contract D10): the SVG is a labelled image\n * (role=\"img\" + aria-label + <title>/<desc>); the REAL accessible data\n * surface is a visually-hidden <table> rendered next to it. The hover\n * tooltip is a visual-only affordance rendered OUTSIDE the role=\"img\"\n * element and hidden from assistive tech.\n *\n * Colors come exclusively from the --karni-chart-1..5 tokens, via the\n * Tailwind preset's chart color scale (stroke-chart-N / fill-chart-N /\n * bg-chart-N classes — whole class names, per contract D7).\n */\n\nexport type DataChartKind = \"line\" | \"bar\";\n\nexport interface DataChartPoint {\n label: string;\n value: number;\n}\n\nexport interface DataChartSeries {\n name: string;\n data: readonly DataChartPoint[];\n}\n\nexport interface DataChartTooltipContext {\n /** Category (x-axis) label under the pointer. */\n label: string;\n /** One entry per series that has a value at this category. */\n points: ReadonlyArray<{ seriesName: string; value: number; swatchClassName: string }>;\n}\n\nexport interface DataChartProps {\n kind: DataChartKind;\n /** Single-series shorthand (ignored when `series` is given). */\n data?: readonly DataChartPoint[];\n /** Multi-series data; series cycle through --karni-chart-1..5. */\n series?: readonly DataChartSeries[];\n /** Chart title: SVG <title>, aria-label and the hidden table's caption. */\n title: string;\n /** Longer description for the SVG <desc>. */\n description?: string;\n /** Formats values in the tooltip, y-axis ticks and the hidden table. */\n valueFormatter?: (value: number) => string;\n /** Formats x-axis tick labels (default: the category label itself). */\n xTickFormatter?: (label: string) => string;\n /** Escape hatch: fully custom tooltip content. */\n renderTooltip?: (context: DataChartTooltipContext) => React.ReactNode;\n /** viewBox width (default 640) — rendered size is responsive. */\n width?: number;\n /** viewBox height (default 240). */\n height?: number;\n /** Approximate number of y-axis ticks (default 4). */\n yTickCount?: number;\n /** Show the series legend (default: only for 2+ series). */\n showLegend?: boolean;\n /** Show the hover tooltip (default true). */\n showTooltip?: boolean;\n /** Column header of the hidden table's category column (default \"Label\"). */\n categoryHeader?: string;\n /** Text shown when there is no plottable data. */\n emptyLabel?: string;\n className?: string;\n}\n\nconst SERIES_STROKE = [\n \"stroke-chart-1\",\n \"stroke-chart-2\",\n \"stroke-chart-3\",\n \"stroke-chart-4\",\n \"stroke-chart-5\",\n] as const;\n\nconst SERIES_FILL = [\n \"fill-chart-1\",\n \"fill-chart-2\",\n \"fill-chart-3\",\n \"fill-chart-4\",\n \"fill-chart-5\",\n] as const;\n\nconst SERIES_SWATCH = [\n \"bg-chart-1\",\n \"bg-chart-2\",\n \"bg-chart-3\",\n \"bg-chart-4\",\n \"bg-chart-5\",\n] as const;\n\nfunction seriesClass(classes: readonly string[], index: number): string {\n const value = classes[index % classes.length];\n // The modulo keeps the index in range; the fallback only satisfies strict\n // indexing and never triggers at runtime.\n return value ?? classes[0] ?? \"\";\n}\n\nconst MARGIN = { top: 8, right: 12, bottom: 28, left: 48 } as const;\n\nfunction niceNum(range: number, round: boolean): number {\n const exponent = Math.floor(Math.log10(range));\n const fraction = range / 10 ** exponent;\n let niceFraction: number;\n if (round) {\n niceFraction = fraction < 1.5 ? 1 : fraction < 3 ? 2 : fraction < 7 ? 5 : 10;\n } else {\n niceFraction = fraction <= 1 ? 1 : fraction <= 2 ? 2 : fraction <= 5 ? 5 : 10;\n }\n return niceFraction * 10 ** exponent;\n}\n\nfunction niceTicks(min: number, max: number, count: number): number[] {\n const span = max > min ? max - min : 1;\n const step = niceNum(niceNum(span, false) / Math.max(1, count), true);\n const start = Math.floor(min / step) * step;\n const end = Math.ceil(max / step) * step;\n const ticks: number[] = [];\n for (let value = start; value <= end + step / 2; value += step) {\n // Trim float noise (0.30000000000000004 → 0.3).\n ticks.push(Number(value.toFixed(10)));\n }\n return ticks;\n}\n\ninterface NormalizedChart {\n categories: readonly string[];\n seriesNames: readonly string[];\n /** matrix[seriesIndex][categoryIndex] — null when missing/non-finite. */\n matrix: ReadonlyArray<ReadonlyArray<number | null>>;\n}\n\nfunction normalize(\n data: readonly DataChartPoint[] | undefined,\n series: readonly DataChartSeries[] | undefined,\n): NormalizedChart {\n const resolved: readonly DataChartSeries[] =\n series ?? (data !== undefined ? [{ name: \"Value\", data }] : []);\n\n const categories: string[] = [];\n const seen = new Set<string>();\n for (const s of resolved) {\n for (const point of s.data) {\n if (!seen.has(point.label)) {\n seen.add(point.label);\n categories.push(point.label);\n }\n }\n }\n\n const matrix = resolved.map((s) => {\n const byLabel = new Map<string, number>();\n for (const point of s.data) {\n if (Number.isFinite(point.value)) {\n byLabel.set(point.label, point.value);\n }\n }\n return categories.map((label) => byLabel.get(label) ?? null);\n });\n\n return { categories, seriesNames: resolved.map((s) => s.name), matrix };\n}\n\nfunction defaultValueFormatter(value: number): string {\n return value.toLocaleString();\n}\n\n/**\n * Minimal line/bar chart driven by `{label, value}` points or named series.\n *\n * Escape hatches: `valueFormatter`/`xTickFormatter`, `renderTooltip`,\n * `width`/`height`/`yTickCount`, legend and tooltip toggles, `className`\n * (merged via cn()). Colors are only themeable through the\n * --karni-chart-1..5 CSS variables.\n */\nexport function DataChart({\n kind,\n data,\n series,\n title,\n description,\n valueFormatter = defaultValueFormatter,\n xTickFormatter,\n renderTooltip,\n width = 640,\n height = 240,\n yTickCount = 4,\n showLegend,\n showTooltip = true,\n categoryHeader = \"Label\",\n emptyLabel = \"No data\",\n className,\n}: DataChartProps): React.ReactElement {\n const titleId = React.useId();\n const descId = React.useId();\n const [hovered, setHovered] = React.useState<number | null>(null);\n\n const { categories, seriesNames, matrix } = React.useMemo(\n () => normalize(data, series),\n [data, series],\n );\n\n const values = matrix.flat().filter((value): value is number => value !== null);\n if (categories.length === 0 || values.length === 0) {\n return (\n <div\n className={cn(\n \"flex w-full items-center justify-center rounded-lg border border-dashed border-border px-6 py-10 text-sm text-muted-foreground\",\n className,\n )}\n >\n {emptyLabel}\n </div>\n );\n }\n\n // scales\n const rawMin = Math.min(0, ...values);\n const rawMax = Math.max(0, ...values);\n const ticks = niceTicks(rawMin, rawMax, yTickCount);\n const domainMin = ticks[0] ?? rawMin;\n const domainMax = ticks[ticks.length - 1] ?? rawMax;\n const domainSpan = domainMax - domainMin || 1;\n\n const plotWidth = width - MARGIN.left - MARGIN.right;\n const plotHeight = height - MARGIN.top - MARGIN.bottom;\n const yScale = (value: number): number =>\n MARGIN.top + ((domainMax - value) / domainSpan) * plotHeight;\n const bandWidth = plotWidth / categories.length;\n const bandCenter = (index: number): number => MARGIN.left + (index + 0.5) * bandWidth;\n const zeroY = yScale(Math.max(domainMin, Math.min(domainMax, 0)));\n\n // marks\n const seriesCount = Math.max(1, matrix.length);\n const groupWidth = bandWidth * 0.7;\n const barWidth = groupWidth / seriesCount;\n\n const marks = matrix.map((row, seriesIndex) => {\n if (kind === \"bar\") {\n return (\n <g key={seriesIndex} className={seriesClass(SERIES_FILL, seriesIndex)}>\n {row.map((value, categoryIndex) => {\n if (value === null) {\n return null;\n }\n const x = bandCenter(categoryIndex) - groupWidth / 2 + seriesIndex * barWidth;\n const y = Math.min(yScale(value), zeroY);\n const barHeight = Math.abs(yScale(value) - zeroY);\n return (\n <rect\n key={categoryIndex}\n x={x}\n y={y}\n width={Math.max(1, barWidth - 2)}\n height={barHeight}\n rx={2}\n />\n );\n })}\n </g>\n );\n }\n\n const points = row\n .map((value, categoryIndex) =>\n value === null ? null : ([bandCenter(categoryIndex), yScale(value)] as const),\n )\n .filter((point): point is readonly [number, number] => point !== null);\n\n return (\n <g key={seriesIndex}>\n <polyline\n className={seriesClass(SERIES_STROKE, seriesIndex)}\n fill=\"none\"\n strokeWidth={2}\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n points={points.map(([x, y]) => `${String(x)},${String(y)}`).join(\" \")}\n />\n {points.map(([x, y], pointIndex) => (\n <circle\n key={pointIndex}\n className={seriesClass(SERIES_FILL, seriesIndex)}\n cx={x}\n cy={y}\n r={3}\n />\n ))}\n </g>\n );\n });\n\n // tooltip geometry (percentages of the rendered box)\n const pct = (value: number, total: number): string => `${String((value / total) * 100)}%`;\n const hoveredPoints =\n hovered === null\n ? []\n : matrix\n .map((row, seriesIndex) => ({\n seriesName: seriesNames[seriesIndex] ?? \"\",\n value: row[hovered] ?? null,\n swatchClassName: seriesClass(SERIES_SWATCH, seriesIndex),\n }))\n .filter(\n (entry): entry is { seriesName: string; value: number; swatchClassName: string } =>\n entry.value !== null,\n );\n const hoveredLabel = hovered === null ? undefined : categories[hovered];\n\n const defaultLegend = seriesNames.length > 1;\n\n return (\n <div className={cn(\"w-full\", className)}>\n <div className=\"relative w-full\">\n <svg\n role=\"img\"\n aria-label={title}\n aria-labelledby={titleId}\n aria-describedby={description !== undefined ? descId : undefined}\n viewBox={`0 0 ${String(width)} ${String(height)}`}\n className=\"block h-auto w-full text-muted-foreground\"\n >\n <title id={titleId}>{title}</title>\n {description !== undefined && <desc id={descId}>{description}</desc>}\n\n {/* y grid + tick labels */}\n {ticks.map((tick) => (\n <g key={tick}>\n <line\n x1={MARGIN.left}\n x2={width - MARGIN.right}\n y1={yScale(tick)}\n y2={yScale(tick)}\n stroke=\"currentColor\"\n strokeOpacity={tick === 0 ? 0.6 : 0.2}\n />\n <text\n x={MARGIN.left - 6}\n y={yScale(tick)}\n textAnchor=\"end\"\n dominantBaseline=\"middle\"\n fontSize={10}\n fill=\"currentColor\"\n >\n {valueFormatter(tick)}\n </text>\n </g>\n ))}\n\n {/* x tick labels */}\n {categories.map((category, index) => (\n <text\n key={category}\n x={bandCenter(index)}\n y={height - MARGIN.bottom + 14}\n textAnchor=\"middle\"\n fontSize={10}\n fill=\"currentColor\"\n >\n {xTickFormatter ? xTickFormatter(category) : category}\n </text>\n ))}\n\n {marks}\n </svg>\n\n {/* Hover affordance + tooltip: visual only, OUTSIDE the role=\"img\"\n element and hidden from assistive tech (contract D10). */}\n {showTooltip && (\n <div aria-hidden=\"true\" className=\"absolute inset-0\">\n <div\n className=\"absolute flex\"\n style={{\n left: pct(MARGIN.left, width),\n width: pct(plotWidth, width),\n top: pct(MARGIN.top, height),\n height: pct(plotHeight, height),\n }}\n onMouseLeave={() => {\n setHovered(null);\n }}\n >\n {categories.map((category, index) => (\n <div\n key={category}\n data-karni-chart-hit={index}\n className=\"h-full flex-1\"\n onMouseEnter={() => {\n setHovered(index);\n }}\n />\n ))}\n </div>\n {hovered !== null && hoveredLabel !== undefined && hoveredPoints.length > 0 && (\n <div\n data-karni-chart-tooltip=\"\"\n className=\"pointer-events-none absolute z-10 min-w-24 -translate-x-1/2 rounded-md border border-border bg-popover px-2.5 py-1.5 text-xs text-popover-foreground shadow-md\"\n style={{\n left: pct(bandCenter(hovered), width),\n top: pct(MARGIN.top, height),\n }}\n >\n {renderTooltip ? (\n renderTooltip({ label: hoveredLabel, points: hoveredPoints })\n ) : (\n <>\n <p className=\"mb-1 font-medium\">{hoveredLabel}</p>\n {hoveredPoints.map((point) => (\n <p key={point.seriesName} className=\"flex items-center gap-1.5\">\n <span\n className={cn(\"h-2 w-2 shrink-0 rounded-full\", point.swatchClassName)}\n />\n <span className=\"text-muted-foreground\">{point.seriesName}</span>\n <span className=\"ml-auto font-medium\">{valueFormatter(point.value)}</span>\n </p>\n ))}\n </>\n )}\n </div>\n )}\n </div>\n )}\n </div>\n\n {(showLegend ?? defaultLegend) && (\n <div aria-hidden=\"true\" className=\"mt-2 flex flex-wrap items-center gap-x-4 gap-y-1\">\n {seriesNames.map((name, index) => (\n <span key={name} className=\"flex items-center gap-1.5 text-xs text-muted-foreground\">\n <span className={cn(\"h-2 w-2 rounded-full\", seriesClass(SERIES_SWATCH, index))} />\n {name}\n </span>\n ))}\n </div>\n )}\n\n {/* The accessible data surface (contract D10). */}\n <VisuallyHidden.Root asChild>\n <div>\n <table>\n <caption>{title}</caption>\n <thead>\n <tr>\n <th scope=\"col\">{categoryHeader}</th>\n {seriesNames.map((name) => (\n <th key={name} scope=\"col\">\n {name}\n </th>\n ))}\n </tr>\n </thead>\n <tbody>\n {categories.map((category, categoryIndex) => (\n <tr key={category}>\n <th scope=\"row\">{category}</th>\n {matrix.map((row, seriesIndex) => {\n const value = row[categoryIndex] ?? null;\n return (\n <td key={seriesIndex}>{value === null ? \"—\" : valueFormatter(value)}</td>\n );\n })}\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n </VisuallyHidden.Root>\n </div>\n );\n}\n"],"names":["cn","inputs","twMerge","clsx","registry","defaultHotDetector","meta","_a","_b","detectHot","registerComponentRole","role","component","options","reason","previous","existing","message","getRoleRegistry","variants","config","groupNames","props","className","rest","selection","chosen","classes","group","value","groupClasses","compound","compoundClassName","conditions","key","expected","buttonVariants","Button","React","variant","size","type","ref","jsx","Input","Textarea","baseProps","CheckIcon","ChevronDownIcon","ChevronUpIcon","KARNI_SELECT_EMPTY","SelectRoot","SelectPrimitive","SelectGroup","SelectValue","SelectTrigger","children","jsxs","SelectScrollUpButton","SelectScrollDownButton","SelectContent","position","SelectLabel","SelectItem","SelectSeparator","Select","onValueChange","placeholder","clearable","clearLabel","disabled","name","id","contentClassName","ariaLabel","safeOptions","filtered","option","radixValue","handleValueChange","next","Checkbox","CheckboxPrimitive","Switch","SwitchPrimitive","Label","LabelPrimitive","Tabs","TabsPrimitive","TabsList","TabsTrigger","TabsContent","DropdownMenu","DropdownMenuPrimitive","DropdownMenuTrigger","DropdownMenuGroup","DropdownMenuPortal","DropdownMenuContent","sideOffset","DropdownMenuItem","inset","DropdownMenuCheckboxItem","checked","DropdownMenuLabel","DropdownMenuSeparator","Skeleton","stringifyScalar","isScalarArray","buildListQuery","params","query","buildItemQuery","normalizeParams","out","normalized","normalizeValue","item","listPath","resource","detailPath","karniKeys","KarniClientContext","createContext","KarniProvider","client","queryClient","ownQueryClient","useState","QueryClient","QueryClientProvider","useKarniClient","useContext","useResourceList","useQuery","signal","isFileValue","isBlobValue","containsFile","values","appendFormValue","form","toFormData","encodeBody","fileFieldNames","cachedSchema","names","resources","entry","fields","field","kind","isStringOrStringArray","omitUnchangedFileUrls","fileFields","useResourceMutations","useQueryClient","invalidateKeys","invalidate","useCallback","queryKey","create","useMutation","update","prepared","remove","isRecord","humanize","spaced","REF_PREFIX","lookupRef","doc","resolveSchema","schema","seen","target","resolved","siblings","inner","normalizeType","t","relationFromExtension","ext","relationValueTypeOf","combineEnumMembers","members","nullable","description","member","CHOICE_LINE","choiceLabels","labels","line","match","text","applyChoiceLabels","info","isAnySchema","analyzeProperty","raw","relation","typeNullable","composition","combined","items","mergeField","responseInfo","requestInfo","requiredSet","hasCreateRequest","order","title","enumValues","fallback","enumLabels","maxLength","min","max","format","valueType","operationDef","path","method","op","queryParams","expandEnum","param","def","listItemSchema","response","media","_c","body","results","_d","createRequestSchema","content","METHODS","parseOpenApi","input","paths","rawAuthMode","authMode","listOps","get","listOp","itemEntry","candidate","itemPath","itemItem","operations","createOp","exportItem","exportOp","importItem","importOp","responseSchema","requestSchema","responseProps","requestProps","prop","requestProp","parsed","SCHEMA_QUERY_KEY","useParsedSchema","useSchema","known","EmptyState","icon","action","AUDIT_FIELDS","isAuditField","partitionAuditFields","domain","audit","a","b","LABEL_KEYS","displayLabel","obj","BulkActionsBar","selectedIds","bulkActions","onClear","index","sortingToOrdering","sorting","isNotFoundError","error","pageCountFor","count","pageSize","asRecord","errorMessage","data","detail","enumLabel","DEFAULT_SKIPPED_KINDS","UNSORTABLE_KINDS","EmptyValue","BooleanCell","IdCode","relationItem","label","RelationCell","Fragment","dateText","withTime","FileCell","event","JsonCell","shown","renderFieldCell","getRowLabel","headerTemplate","columnForField","override","customCell","row","ctx","deriveColumns","args","pending","column","defs","importDescribeKey","importJobKey","jobId","importPath","suffix","IN_FLIGHT","isImportInFlight","job","filenameFrom","header","downloadResourceExport","blob","filename","saveBlob","url","anchor","downloadImportTemplate","useImportDescribe","useImportJob","pollMs","useImportActions","store","upload","file","mapping","preview","commit","describe","ExportButtons","formats","busy","setBusy","setError","run","failure","useResourceItem","useDebouncedValue","delayMs","debounced","setDebounced","timer","idOf","optionDomId","listboxId","XIcon","ResourceSelect","onChange","multiple","getOptionLabel","filter","searchDebounceMs","reactId","inputId","open","setOpen","inputText","setInputText","activeIndex","setActiveIndex","cache","setCache","rootRef","contentRef","inputRef","debouncedSearch","selected","listParams","listQuery","rows","changed","unresolvedId","sel","itemQuery","resolvedItem","resolveError","labelOf","textOf","openPopover","closePopover","isSelected","optionId","toggleOption","clearSelection","singleText","inputValue","handleInputChange","handleKeyDown","handleBlur","listContent","optionSelected","PopoverPrimitive","chipText","other","toSelectValue","toRelationValue","EnumFilter","onFilterChange","BooleanFilter","FilterBar","searchEnabled","searchValue","onSearchChange","searchPlaceholder","filterFields","PaginationControls","page","pageCount","totalCount","hasPrevious","hasNext","onPageChange","DEFAULT_PAGE_SIZE","SEARCH_DEBOUNCE_MS","MAX_DERIVED_FILTERS","selectionColumn","table","DeleteRowButton","mutations","actionsColumn","rowActions","onEdit","enableDelete","TableSkeleton","_","ErrorPanel","SchemaErrorPanel","ResourceTable","columns","showAuditFields","extraColumns","columnsOverride","onRowClick","expand","initialSorting","filters","exportFormats","toolbar","empty","footer","schemaResult","setSorting","rowSelection","setRowSelection","setPage","searchInput","setSearchInput","filterValues","setFilterValues","effectivePageSize","lastSearch","handleSortingChange","updater","old","handleFilterChange","expandList","allowed","pinned","byName","declared","trimmedSearch","list","keepPreviousData","failureCount","clamping","current","hasBulkSelect","hasActions","columnDefs","leading","trailing","useReactTable","getCoreRowModel","hasActiveNarrowing","canSort","direction","flexRender","cell","_e","_f","exportList","exportEnabled","showFilterRow","REQUIRED_MESSAGE","LOCAL_DATETIME","toIsoWithOffset","date","enumSchema","literals","stringSchema","requireNonEmpty","numberSchema","integer","relationValueSchema","coerce","singleRelationSchema","fileSchema","baseSchemaFor","zodFor","mode","shape","fieldSchema","matchesAccept","accept","tokens","token","formatFileSize","bytes","fileBasename","segments","segment","UploadIcon","FileUpload","maxSize","onReject","dragging","setDragging","entries","acceptFiles","accepted","handleDrop","handleDragOver","removeEntry","remaining","i","files","humanizeValue","pad","n","toDatetimeLocal","HAS_ZONE","offsetMinutes","sign","abs","offset","isDirtyEntry","pkOf","initialFieldValue","buildFormValues","defaultValues","source","val","OMIT","emptied","coerceFieldValue","numeric","prepareSubmit","dirtyFields","jsonErrors","rawValue","result","stringInputType","DefaultFieldControl","control","describedBy","invalid","inputProps","aria","Controller","rhf","EDITABLE_KINDS","FormSkeleton","FormErrorPanel","applyServerErrors","knownNames","methods","maybe","rootMessages","messages","FormFieldRow","Component","errorId","descriptionId","part","ResourceFormInner","onSuccess","onError","fieldOverrides","extraFields","transformSubmit","actions","formFields","initialValues","resolver","base","zodResolver","omittable","context","cleaned","useForm","formState","submitting","onSubmit","jsonError","payload","rootError","fieldError","FormProvider","ResourceForm","isEdit","formatDate","formatDateTime","RelationEntry","RelationValue","DefaultValue","DetailSkeleton","DetailError","onRetry","DetailRow","muted","ResourceDetail","sections","recordHeadingId","visibleFields","section","changeHistoryKey","useChangeHistory","ACTION_LABEL","formatWhen","Value","Entry","before","after","ChangeHistory","errorText","Stats","created","updated","skipped","unchanged","errors","Problems","problem","Progress","percent","MappingTable","ResourceImport","onDone","setJobId","setMapping","remap","setRemap","templateError","setTemplateError","fileRef","jobQuery","seededFor","mutationError","handleUpload","handlePreview","handleTemplate","defaultMessage","status","KarniApiError","__publicField","splitBaseUrl","baseUrl","joinUrl","origin","basePath","appendQuery","qs","parseBody","createKarniClient","schemaUrl","fetchOption","hooks","perform","requestOptions","headers","hookHeaders","init","requestRaw","readAuthMode","record","normalizeUser","email","roles","readCookie","trimmed","separator","describeShape","keys","read2fa","AuthEngine","listener","user","document","refreshToken","access","rotated","password","twoFactor","refresh","loginPath","createLocalStorageTokenStorage","createMemoryTokenStorage","AuthContext","AuthProvider","tokenStorage","csrfCookieName","csrfHeaderName","authBasePath","storage","useMemo","engine","useEffect","snapshot","useSyncExternalStore","identity","previousIdentity","useRef","useAuth","AuthGuard","loading","LoginForm","on2FA","submitLabel","login","submit","usePermission","Page","headerClassName","MARK_VIEWBOX","MARK_PATHS","MARK_SIMPLE_BODY","KarniMark","simple","labelled","MenuIcon","CloseIcon","NAV_ITEM_CLASS","NAV_ITEM_ACTIVE_CLASS","SIDEBAR_ID","Layout","navItems","renderNavItem","sidebar","sidebarHeader","sidebarFooter","navLabel","sidebarClassName","mobileOpen","setMobileOpen","closeMobile","onKeyDown","navContent","defaultClassName","defaultNode","sidebarInner","ModalClose","DialogPrimitive","Modal","trigger","defaultOpen","onOpenChange","hideCloseButton","contentProps","clearDescribedBy","toasts","listeners","counter","emit","subscribeToToasts","getToasts","dismissToast","addToast","instance","makeShorthand","stableApi","useToast","toastVariants","Toaster","duration","swipeDirection","viewportClassName","toastClassName","ToastPrimitive","ArrowUpIcon","ArrowDownIcon","defaultFormatDelta","delta","formatted","Stat","formatDelta","deltaNode","down","SERIES_STROKE","SERIES_FILL","SERIES_SWATCH","seriesClass","MARGIN","niceNum","range","round","exponent","fraction","niceFraction","niceTicks","span","step","start","end","ticks","normalize","series","categories","point","matrix","byLabel","defaultValueFormatter","DataChart","valueFormatter","xTickFormatter","renderTooltip","width","height","yTickCount","showLegend","showTooltip","categoryHeader","emptyLabel","titleId","descId","hovered","setHovered","seriesNames","rawMin","rawMax","domainMin","domainMax","domainSpan","plotWidth","plotHeight","yScale","bandWidth","bandCenter","zeroY","seriesCount","groupWidth","barWidth","marks","seriesIndex","categoryIndex","x","y","barHeight","points","pointIndex","pct","total","hoveredPoints","hoveredLabel","defaultLegend","tick","category","VisuallyHidden"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;AASO,SAASA,KAAMC,GAA8B;AAClD,SAAOC,GAAQC,GAAKF,CAAM,CAAC;AAC7B;ACkBA,MAAMG,yBAAe,IAAA;AAOrB,SAASC,KAA8B;;AACrC,MAAI;AACF,UAAMC,IAAO;AAGb,WAFI,GAACA,EAAK,SACNC,IAAAD,EAAK,QAAL,gBAAAC,EAAU,UAAS,UACnB,OAAO,UAAY,SAAeC,IAAA,QAAQ,QAAR,gBAAAA,EAAa,YAAW;AAAA,EAEhE,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,IAAIC,KAA2BJ;AAuBxB,SAASK,GACdC,GACAC,GACAC,GACM;;AACN,MAAIA,KAAA,QAAAA,EAAS,SAAS;AACpB,UAAMC,MAASP,IAAAM,EAAQ,WAAR,gBAAAN,EAAgB,WAAU;AACzC,QAAIO,MAAW;AACb,YAAM,IAAI;AAAA,QACR,kDAAkDH,CAAI;AAAA,MAAA;AAI1D,UAAMI,IAAWX,GAAS,IAAIO,CAAI;AAClC,IAAII,MAAa,UAAaA,MAAaH,KACzC,QAAQ;AAAA,MACN,2BAA2BD,CAAI,gBAAgBI,CAAQ,SAASH,CAAS,MAAME,CAAM;AAAA,IAAA,GAGzFV,GAAS,IAAIO,GAAMC,CAAS;AAC5B;AAAA,EACF;AAEA,QAAMI,IAAWZ,GAAS,IAAIO,CAAI;AAClC,MAAIK,MAAa,UAAaA,MAAaJ,GAAW;AAEpD,IAAAR,GAAS,IAAIO,GAAMC,CAAS;AAC5B;AAAA,EACF;AAEA,QAAMK,IACJ,qCAAqCN,CAAI,6BAA6BK,CAAQ,sBAC/DJ,CAAS;AAG1B,MAAIH,MAAa;AAEf,YAAQ,MAAMQ,CAAO,GACrBb,GAAS,IAAIO,GAAMC,CAAS;AAC5B;AAAA,EACF;AACA,QAAM,IAAI,MAAMK,CAAO;AACzB;AAGO,SAASC,KAAoD;AAClE,SAAO,OAAO,OAAO,OAAO,YAAYd,EAAQ,CAAC;AACnD;AChFO,SAASe,GAAiCC,GAAyC;AACxF,QAAMC,IAAa,OAAO,KAAKD,EAAO,QAAQ;AAE9C,SAAO,CAACE,MAAU;;AAChB,UAAM,EAAE,WAAAC,GAAW,GAAGC,EAAA,IAASF,KAAS,CAAA,GAClCG,IAAYD,GACZE,IAA4D,CAAA,GAC5DC,IAAoB,CAAA;AAE1B,IAAIP,EAAO,QACTO,EAAQ,KAAKP,EAAO,IAAI;AAG1B,eAAWQ,KAASP,GAAY;AAC9B,YAAMQ,IAAQJ,EAAUG,CAAK,OAAKrB,IAAAa,EAAO,oBAAP,gBAAAb,EAAyBqB;AAC3D,UAAIC,KAAS;AACX;AAEF,MAAAH,EAAOE,CAAK,IAAIC;AAChB,YAAMC,IAAeV,EAAO,SAASQ,CAAK,EAAEC,CAAK;AACjD,MAAIC,KACFH,EAAQ,KAAKG,CAAY;AAAA,IAE7B;AAEA,eAAWC,KAAYX,EAAO,oBAAoB,CAAA,GAAI;AACpD,YAAM,EAAE,WAAWY,GAAmB,GAAGR,MAASO,GAG5CE,IAAaT;AAQnB,MALsB,OAAO,KAAKS,CAAU,EACd,MAAM,CAACC,MAAQ;AAC3C,cAAMC,IAAWF,EAAWC,CAAG;AAC/B,eAAOC,KAAY,QAAQT,EAAOQ,CAAG,MAAMC;AAAA,MAC7C,CAAC,KAECR,EAAQ,KAAKK,CAAiB;AAAA,IAElC;AAEA,WAAOhC,EAAG,GAAG2B,GAASJ,CAAS;AAAA,EACjC;AACF;AC3EO,MAAMa,KAAiBjB,GAAS;AAAA,EACrC,MAAM;AAAA,EACN,UAAU;AAAA,IACR,SAAS;AAAA,MACP,SAAS;AAAA,MACT,aAAa;AAAA,MACb,SAAS;AAAA,MACT,WAAW;AAAA,MACX,OAAO;AAAA,MACP,MAAM;AAAA,IAAA;AAAA,IAER,MAAM;AAAA,MACJ,SAAS;AAAA,MACT,IAAI;AAAA,MACJ,IAAI;AAAA,MACJ,MAAM;AAAA,IAAA;AAAA,EACR;AAAA,EAEF,iBAAiB;AAAA,IACf,SAAS;AAAA,IACT,MAAM;AAAA,EAAA;AAEV,CAAC,GAUYkB,IAASC,EAAM;AAAA,EAC1B,CAAC,EAAE,WAAAf,GAAW,SAAAgB,GAAS,MAAAC,GAAM,MAAAC,GAAM,GAAGnB,EAAA,GAASoB,MAC7C,gBAAAC;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,KAAAD;AAAA,MACA,MAAMD,KAAQ;AAAA,MACd,WAAWL,GAAe,EAAE,SAAAG,GAAS,MAAAC,GAAM,WAAAjB,GAAW;AAAA,MACrD,GAAGD;AAAA,IAAA;AAAA,EAAA;AAGV;AACAe,EAAO,cAAc;AC3Cd,MAAMO,KAAQN,EAAM;AAAA,EACzB,CAAC,EAAE,WAAAf,GAAW,GAAGD,EAAA,GAASoB,MACxB,gBAAAC;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,KAAAD;AAAA,MACA,WAAW1C;AAAA,QACT;AAAA,QACAuB;AAAA,MAAA;AAAA,MAED,GAAGD;AAAA,IAAA;AAAA,EAAA;AAGV;AACAsB,GAAM,cAAc;ACZb,MAAMC,KAAWP,EAAM;AAAA,EAC5B,CAAC,EAAE,WAAAf,GAAW,GAAGD,EAAA,GAASoB,MACxB,gBAAAC;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,KAAAD;AAAA,MACA,WAAW1C;AAAA,QACT;AAAA,QACAuB;AAAA,MAAA;AAAA,MAED,GAAGD;AAAA,IAAA;AAAA,EAAA;AAGV;AACAuB,GAAS,cAAc;ACRvB,SAASC,GAAUxB,GAA6B;AAC9C,SAAO;AAAA,IACL,SAAS;AAAA,IACT,MAAM;AAAA,IACN,QAAQ;AAAA,IACR,aAAa;AAAA,IACb,eAAe;AAAA,IACf,gBAAgB;AAAA,IAChB,eAAe;AAAA,IACf,WAAW;AAAA,IACX,GAAGA;AAAA,EAAA;AAEP;AAEO,SAASyB,GAAUzB,GAAsC;AAC9D,SACE,gBAAAqB,EAAC,OAAA,EAAK,GAAGG,GAAUxB,CAAK,GACtB,UAAA,gBAAAqB,EAAC,YAAA,EAAS,QAAO,iBAAA,CAAiB,EAAA,CACpC;AAEJ;AAEO,SAASK,GAAgB1B,GAAsC;AACpE,SACE,gBAAAqB,EAAC,OAAA,EAAK,GAAGG,GAAUxB,CAAK,GACtB,UAAA,gBAAAqB,EAAC,YAAA,EAAS,QAAO,iBAAA,CAAiB,EAAA,CACpC;AAEJ;AAEO,SAASM,GAAc3B,GAAsC;AAClE,SACE,gBAAAqB,EAAC,OAAA,EAAK,GAAGG,GAAUxB,CAAK,GACtB,UAAA,gBAAAqB,EAAC,YAAA,EAAS,QAAO,kBAAA,CAAkB,EAAA,CACrC;AAEJ;ACnCO,MAAMO,KAAqB,mBAOrBC,KAAaC,GAAgB,MAE7BC,KAAcD,GAAgB,OAE9BE,KAAcF,GAAgB,OAG9BG,KAAgBjB,EAAM,WAGjC,CAAC,EAAE,WAAAf,GAAW,UAAAiC,GAAU,GAAGlC,KAASoB,MACpC,gBAAAe;AAAA,EAACL,GAAgB;AAAA,EAAhB;AAAA,IACC,KAAAV;AAAA,IACA,WAAW1C;AAAA,MACT;AAAA,MACAuB;AAAA,IAAA;AAAA,IAED,GAAGD;AAAA,IAEH,UAAA;AAAA,MAAAkC;AAAA,MACD,gBAAAb,EAACS,GAAgB,MAAhB,EAAqB,SAAO,IAC3B,UAAA,gBAAAT,EAACK,IAAA,EAAgB,WAAU,8BAAA,CAA8B,EAAA,CAC3D;AAAA,IAAA;AAAA,EAAA;AACF,CACD;AACDO,GAAc,cAAc;AAE5B,MAAMG,KAAuBpB,EAAM,WAGjC,CAAC,EAAE,WAAAf,GAAW,GAAGD,EAAA,GAASoB,MAC1B,gBAAAC;AAAA,EAACS,GAAgB;AAAA,EAAhB;AAAA,IACC,KAAAV;AAAA,IACA,WAAW1C,EAAG,wDAAwDuB,CAAS;AAAA,IAC9E,GAAGD;AAAA,IAEJ,UAAA,gBAAAqB,EAACM,IAAA,EAAc,WAAU,UAAA,CAAU;AAAA,EAAA;AACrC,CACD;AACDS,GAAqB,cAAc;AAEnC,MAAMC,KAAyBrB,EAAM,WAGnC,CAAC,EAAE,WAAAf,GAAW,GAAGD,EAAA,GAASoB,MAC1B,gBAAAC;AAAA,EAACS,GAAgB;AAAA,EAAhB;AAAA,IACC,KAAAV;AAAA,IACA,WAAW1C,EAAG,wDAAwDuB,CAAS;AAAA,IAC9E,GAAGD;AAAA,IAEJ,UAAA,gBAAAqB,EAACK,IAAA,EAAgB,WAAU,UAAA,CAAU;AAAA,EAAA;AACvC,CACD;AACDW,GAAuB,cAAc;AAG9B,MAAMC,KAAgBtB,EAAM,WAGjC,CAAC,EAAE,WAAAf,GAAW,UAAAiC,GAAU,UAAAK,IAAW,UAAU,GAAGvC,KAASoB,MACzD,gBAAAC,EAACS,GAAgB,QAAhB,EACC,UAAA,gBAAAK;AAAA,EAACL,GAAgB;AAAA,EAAhB;AAAA,IACC,KAAAV;AAAA,IACA,UAAAmB;AAAA,IACA,WAAW7D;AAAA,MACT;AAAA,MACA6D,MAAa,YACX;AAAA,MACFtC;AAAA,IAAA;AAAA,IAED,GAAGD;AAAA,IAEJ,UAAA;AAAA,MAAA,gBAAAqB,EAACe,IAAA,EAAqB;AAAA,MACtB,gBAAAf;AAAA,QAACS,GAAgB;AAAA,QAAhB;AAAA,UACC,WAAWpD;AAAA,YACT;AAAA,YACA6D,MAAa,YACX;AAAA,UAAA;AAAA,UAGH,UAAAL;AAAA,QAAA;AAAA,MAAA;AAAA,wBAEFG,IAAA,CAAA,CAAuB;AAAA,IAAA;AAAA,EAAA;AAC1B,GACF,CACD;AACDC,GAAc,cAAc;AAGrB,MAAME,KAAcxB,EAAM,WAG/B,CAAC,EAAE,WAAAf,GAAW,GAAGD,EAAA,GAASoB,MAC1B,gBAAAC;AAAA,EAACS,GAAgB;AAAA,EAAhB;AAAA,IACC,KAAAV;AAAA,IACA,WAAW1C,EAAG,0CAA0CuB,CAAS;AAAA,IAChE,GAAGD;AAAA,EAAA;AACN,CACD;AACDwC,GAAY,cAAc;AAGnB,MAAMC,KAAazB,EAAM,WAG9B,CAAC,EAAE,WAAAf,GAAW,UAAAiC,GAAU,GAAGlC,KAASoB,MACpC,gBAAAe;AAAA,EAACL,GAAgB;AAAA,EAAhB;AAAA,IACC,KAAAV;AAAA,IACA,WAAW1C;AAAA,MACT;AAAA,MACAuB;AAAA,IAAA;AAAA,IAED,GAAGD;AAAA,IAEJ,UAAA;AAAA,MAAA,gBAAAqB,EAAC,QAAA,EAAK,WAAU,gEACd,UAAA,gBAAAA,EAACS,GAAgB,eAAhB,EACC,UAAA,gBAAAT,EAACI,IAAA,EAAU,WAAU,UAAA,CAAU,EAAA,CACjC,GACF;AAAA,MACA,gBAAAJ,EAACS,GAAgB,UAAhB,EAA0B,UAAAI,EAAA,CAAS;AAAA,IAAA;AAAA,EAAA;AACtC,CACD;AACDO,GAAW,cAAc;AAGlB,MAAMC,KAAkB1B,EAAM,WAGnC,CAAC,EAAE,WAAAf,GAAW,GAAGD,EAAA,GAASoB,MAC1B,gBAAAC;AAAA,EAACS,GAAgB;AAAA,EAAhB;AAAA,IACC,KAAAV;AAAA,IACA,WAAW1C,EAAG,4BAA4BuB,CAAS;AAAA,IAClD,GAAGD;AAAA,EAAA;AACN,CACD;AACD0C,GAAgB,cAAc;AA6CvB,MAAMC,KAAS3B,EAAM,WAA2C,CAAChB,GAAOoB,MAAQ;AACrF,QAAM;AAAA,IACJ,OAAAb;AAAA,IACA,eAAAqC;AAAA,IACA,SAAArD;AAAA,IACA,aAAAsD;AAAA,IACA,WAAAC,IAAY;AAAA,IACZ,YAAAC,IAAa;AAAA,IACb,UAAAC;AAAA,IACA,MAAAC;AAAA,IACA,IAAAC;AAAA,IACA,WAAAjD;AAAA,IACA,kBAAAkD;AAAA,IACA,UAAAjB;AAAA,IACA,cAAckB;AAAA,EAAA,IACZpD,GAEEqD,IAAcrC,EAAM,QAAQ,MAAM;AACtC,UAAMsC,IAAW/D,EAAQ;AAAA,MACvB,CAACgE,MAAWA,EAAO,UAAU,MAAMA,EAAO,UAAU3B;AAAA,IAAA;AAEtD,WAAI0B,EAAS,WAAW/D,EAAQ,UAC9B,QAAQ;AAAA,MACN,6CAA6CqC,EAAkB;AAAA,IAAA,GAG5D0B;AAAA,EACT,GAAG,CAAC/D,CAAO,CAAC,GAMNiE,IAJUjD,KAAS,QAAQA,MAAU,KAIbuC,IAAYlB,KAAqB,KAAMrB,GAE/DkD,IAAoBzC,EAAM;AAAA,IAC9B,CAAC0C,MAAiB;AAChB,MAAAd,KAAA,QAAAA,EAAgBc,MAAS9B,KAAqB,OAAO8B;AAAA,IACvD;AAAA,IACA,CAACd,CAAa;AAAA,EAAA;AAGhB,SACE,gBAAAT;AAAA,IAACN;AAAA,IAAA;AAAA,MACC,OAAO2B;AAAA,MACP,eAAeC;AAAA,MACf,UAAAT;AAAA,MACA,MAAAC;AAAA,MAEA,UAAA;AAAA,QAAA,gBAAA5B,EAACY,IAAA,EAAc,KAAAb,GAAU,IAAA8B,GAAQ,WAAAjD,GAAsB,cAAYmD,GACjE,UAAA,gBAAA/B,EAACW,IAAA,EAAY,aAAAa,EAAA,CAA0B,EAAA,CACzC;AAAA,QACA,gBAAAV,EAACG,IAAA,EAAc,WAAWa,GACvB,UAAA;AAAA,UAAAL,sBACEL,IAAA,EAAW,OAAOb,IAAoB,WAAU,yBAC9C,aACH,IACE;AAAA,UACHyB,EAAY,IAAI,CAACE,MAChB,gBAAAlC,EAACoB,MAA8B,OAAOc,EAAO,OAAO,UAAUA,EAAO,UAClE,UAAAA,EAAO,SADOA,EAAO,KAExB,CACD;AAAA,UACArB;AAAA,QAAA,EAAA,CACH;AAAA,MAAA;AAAA,IAAA;AAAA,EAAA;AAGN,CAAC;AACDS,GAAO,cAAc;AClQd,MAAMgB,KAAW3C,EAAM,WAG5B,CAAC,EAAE,WAAAf,GAAW,GAAGD,EAAA,GAASoB,MAC1B,gBAAAC;AAAA,EAACuC,GAAkB;AAAA,EAAlB;AAAA,IACC,KAAAxC;AAAA,IACA,WAAW1C;AAAA,MACT;AAAA,MACAuB;AAAA,IAAA;AAAA,IAED,GAAGD;AAAA,IAEJ,UAAA,gBAAAqB,EAACuC,GAAkB,WAAlB,EAA4B,WAAU,iDACrC,UAAA,gBAAAvC,EAACI,IAAA,EAAU,WAAU,cAAA,CAAc,EAAA,CACrC;AAAA,EAAA;AACF,CACD;AACDkC,GAAS,cAAc;AClBhB,MAAME,KAAS7C,EAAM;AAAA,EAC1B,CAAC,EAAE,WAAAf,GAAW,GAAGD,EAAA,GAASoB,MACxB,gBAAAC;AAAA,IAACyC,GAAgB;AAAA,IAAhB;AAAA,MACC,KAAA1C;AAAA,MACA,WAAW1C;AAAA,QACT;AAAA,QACAuB;AAAA,MAAA;AAAA,MAED,GAAGD;AAAA,MAEJ,UAAA,gBAAAqB,EAACyC,GAAgB,OAAhB,EAAsB,WAAU,6KAAA,CAA6K;AAAA,IAAA;AAAA,EAAA;AAGpN;AACAD,GAAO,cAAc;ACdd,MAAME,KAAQ/C,EAAM;AAAA,EACzB,CAAC,EAAE,WAAAf,GAAW,GAAGD,EAAA,GAASoB,MACxB,gBAAAC;AAAA,IAAC2C,GAAe;AAAA,IAAf;AAAA,MACC,KAAA5C;AAAA,MACA,WAAW1C;AAAA,QACT;AAAA,QACAuB;AAAA,MAAA;AAAA,MAED,GAAGD;AAAA,IAAA;AAAA,EAAA;AAGV;AACA+D,GAAM,cAAc;ACdb,MAAME,KAAOC,GAAc,MAGrBC,KAAWnD,EAAM,WAG5B,CAAC,EAAE,WAAAf,GAAW,GAAGD,EAAA,GAASoB,MAC1B,gBAAAC;AAAA,EAAC6C,GAAc;AAAA,EAAd;AAAA,IACC,KAAA9C;AAAA,IACA,WAAW1C;AAAA,MACT;AAAA,MACAuB;AAAA,IAAA;AAAA,IAED,GAAGD;AAAA,EAAA;AACN,CACD;AACDmE,GAAS,cAAc;AAGhB,MAAMC,KAAcpD,EAAM,WAG/B,CAAC,EAAE,WAAAf,GAAW,GAAGD,EAAA,GAASoB,MAC1B,gBAAAC;AAAA,EAAC6C,GAAc;AAAA,EAAd;AAAA,IACC,KAAA9C;AAAA,IACA,WAAW1C;AAAA,MACT;AAAA,MACAuB;AAAA,IAAA;AAAA,IAED,GAAGD;AAAA,EAAA;AACN,CACD;AACDoE,GAAY,cAAc;AAGnB,MAAMC,KAAcrD,EAAM,WAG/B,CAAC,EAAE,WAAAf,GAAW,GAAGD,EAAA,GAASoB,MAC1B,gBAAAC;AAAA,EAAC6C,GAAc;AAAA,EAAd;AAAA,IACC,KAAA9C;AAAA,IACA,WAAW1C;AAAA,MACT;AAAA,MACAuB;AAAA,IAAA;AAAA,IAED,GAAGD;AAAA,EAAA;AACN,CACD;AACDqE,GAAY,cAAc;AC/CnB,MAAMC,KAAeC,GAAsB,MAErCC,KAAsBD,GAAsB,SAE5CE,KAAoBF,GAAsB,OAE1CG,KAAqBH,GAAsB,QAG3CI,KAAsB3D,EAAM,WAGvC,CAAC,EAAE,WAAAf,GAAW,YAAA2E,IAAa,GAAG,GAAG5E,KAASoB,MAC1C,gBAAAC,EAACkD,GAAsB,QAAtB,EACC,UAAA,gBAAAlD;AAAA,EAACkD,GAAsB;AAAA,EAAtB;AAAA,IACC,KAAAnD;AAAA,IACA,YAAAwD;AAAA,IACA,WAAWlG;AAAA,MACT;AAAA,MACAuB;AAAA,IAAA;AAAA,IAED,GAAGD;AAAA,EAAA;AACN,GACF,CACD;AACD2E,GAAoB,cAAc;AAG3B,MAAME,KAAmB7D,EAAM,WAGpC,CAAC,EAAE,WAAAf,GAAW,OAAA6E,GAAO,GAAG9E,KAASoB,MACjC,gBAAAC;AAAA,EAACkD,GAAsB;AAAA,EAAtB;AAAA,IACC,KAAAnD;AAAA,IACA,WAAW1C;AAAA,MACT;AAAA,MACAoG,KAAS;AAAA,MACT7E;AAAA,IAAA;AAAA,IAED,GAAGD;AAAA,EAAA;AACN,CACD;AACD6E,GAAiB,cAAc;AAGxB,MAAME,KAA2B/D,EAAM,WAG5C,CAAC,EAAE,WAAAf,GAAW,UAAAiC,GAAU,SAAA8C,GAAS,GAAGhF,KAASoB,MAC7C,gBAAAe;AAAA,EAACoC,GAAsB;AAAA,EAAtB;AAAA,IACC,KAAAnD;AAAA,IACA,SAAA4D;AAAA,IACA,WAAWtG;AAAA,MACT;AAAA,MACAuB;AAAA,IAAA;AAAA,IAED,GAAGD;AAAA,IAEJ,UAAA;AAAA,MAAA,gBAAAqB,EAAC,QAAA,EAAK,WAAU,gEACd,UAAA,gBAAAA,EAACkD,GAAsB,eAAtB,EACC,UAAA,gBAAAlD,EAACI,IAAA,EAAU,WAAU,UAAA,CAAU,EAAA,CACjC,GACF;AAAA,MACCS;AAAA,IAAA;AAAA,EAAA;AACH,CACD;AACD6C,GAAyB,cAAc;AAGhC,MAAME,KAAoBjE,EAAM,WAGrC,CAAC,EAAE,WAAAf,GAAW,OAAA6E,GAAO,GAAG9E,KAASoB,MACjC,gBAAAC;AAAA,EAACkD,GAAsB;AAAA,EAAtB;AAAA,IACC,KAAAnD;AAAA,IACA,WAAW1C,EAAG,qCAAqCoG,KAAS,QAAQ7E,CAAS;AAAA,IAC5E,GAAGD;AAAA,EAAA;AACN,CACD;AACDiF,GAAkB,cAAc;AAGzB,MAAMC,KAAwBlE,EAAM,WAGzC,CAAC,EAAE,WAAAf,GAAW,GAAGD,EAAA,GAASoB,MAC1B,gBAAAC;AAAA,EAACkD,GAAsB;AAAA,EAAtB;AAAA,IACC,KAAAnD;AAAA,IACA,WAAW1C,EAAG,4BAA4BuB,CAAS;AAAA,IAClD,GAAGD;AAAA,EAAA;AACN,CACD;AACDkF,GAAsB,cAAc;AC5F7B,MAAMC,KAAWnE,EAAM;AAAA,EAC5B,CAAC,EAAE,WAAAf,GAAW,GAAGD,EAAA,GAASoB,MACxB,gBAAAC,EAAC,OAAA,EAAI,KAAAD,GAAU,WAAW1C,EAAG,qCAAqCuB,CAAS,GAAI,GAAGD,EAAA,CAAO;AAE7F;AACAmF,GAAS,cAAc;ACSvB,SAASC,GAAgB7E,GAA0C;AACjE,SAAO,OAAOA,KAAU,WAAWA,IAAQ,OAAOA,CAAK;AACzD;AAEA,SAAS8E,GAAc9E,GAAuE;AAC5F,SAAO,MAAM,QAAQA,CAAK;AAC5B;AAQO,SAAS+E,GACdC,GAC4C;AAC5C,QAAMC,IAAoD,CAAA;AAC1D,MAAID,MAAW,OAAW,QAAOC;AAEjC,MAAID,EAAO,YAAY;AACrB,eAAW,CAAC3E,GAAKL,CAAK,KAAK,OAAO,QAAQgF,EAAO,OAAO;AACtD,MAAIhF,KAAU,SACV8E,GAAc9E,CAAK,IACjBA,EAAM,SAAS,MAAGiF,EAAM5E,CAAG,IAAIL,EAAM,IAAI6E,EAAe,KAE5DI,EAAM5E,CAAG,IAAIwE,GAAgB7E,CAAK;AAKxC,SAAIgF,EAAO,SAAS,aAAiB,OAAO,OAAOA,EAAO,IAAI,IAC1DA,EAAO,aAAa,aAAiB,YAAY,OAAOA,EAAO,QAAQ,IACvEA,EAAO,aAAa,UAAaA,EAAO,aAAa,OAAIC,EAAM,WAAWD,EAAO,WACjFA,EAAO,WAAW,UAAaA,EAAO,WAAW,OAAIC,EAAM,SAASD,EAAO,SAC3EA,EAAO,WAAW,UAAaA,EAAO,OAAO,SAAS,MACxDC,EAAM,SAASD,EAAO,OAAO,KAAK,GAAG,IAEhCC;AACT;AAGO,SAASC,GAAeF,GAAqD;AAClF,QAAMC,IAAgC,CAAA;AACtC,UAAID,KAAA,gBAAAA,EAAQ,YAAW,UAAaA,EAAO,OAAO,SAAS,MACzDC,EAAM,SAASD,EAAO,OAAO,KAAK,GAAG,IAEhCC;AACT;AAOO,SAASE,GAAgBnF,GAAkD;AAChF,QAAMoF,IAA4C,CAAA;AAClD,aAAW/E,KAAO,OAAO,KAAKL,CAAK,EAAE,QAAQ;AAC3C,UAAMqF,IAAaC,GAAetF,EAAMK,CAAG,CAAC;AAC5C,IAAIgF,MAAe,WAAWD,EAAI/E,CAAG,IAAIgF;AAAA,EAC3C;AACA,SAAOD;AACT;AAEA,SAASE,GAAetF,GAAkD;AACxE,MAAIA,KAAU;AACd,WAAI,MAAM,QAAQA,CAAK,IACbA,EACL,OAAO,CAACuF,MAASA,KAAS,IAA0B,EACpD;AAAA,MAAI,CAACA,MACJ,OAAOA,KAAS,YAAYA,MAAS,OAAO,KAAK,UAAUA,CAAI,IAAI,OAAOA,CAAI;AAAA,IAAA,IAGhF,OAAOvF,KAAU,WACZmF,GAAgBnF,CAAgC,IAElD,OAAOA,CAAK;AACrB;AAGO,SAASwF,GAASC,GAA0B;AAEjD,SAAO,IADSA,EAAS,QAAQ,cAAc,EAAE,CAC/B;AACpB;AAGO,SAASC,GAAWD,GAAkB9C,GAA6B;AACxE,SAAO,GAAG6C,GAASC,CAAQ,CAAC,GAAG,mBAAmB,OAAO9C,CAAE,CAAC,CAAC;AAC/D;AClFO,MAAMgD,KAAY;AAAA;AAAA,EAEvB,SAA6B;AAC3B,WAAO,CAAC,SAAS,SAAS;AAAA,EAC5B;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,SAASF,GAAsC;AAC7C,WAAO,CAAC,SAASA,CAAQ;AAAA,EAC3B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,KAAKA,GAAkBT,GAAiD;AACtE,WAAO,CAAC,SAASS,GAAU,QAAQN,GAAgBJ,GAAeC,CAAM,CAAC,CAAC;AAAA,EAC5E;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,OAAOS,GAAkB9C,GAAqBqC,GAAiD;AAC7F,UAAMC,IAAQC,GAAeF,CAAM;AACnC,WAAI,OAAO,KAAKC,CAAK,EAAE,SAAS,IACvB,CAAC,SAASQ,GAAU,UAAU,OAAO9C,CAAE,GAAGwC,GAAgBF,CAAK,CAAC,IAElE,CAAC,SAASQ,GAAU,UAAU,OAAO9C,CAAE,CAAC;AAAA,EACjD;AACF,GClDMiD,KAAqBC,GAAkC,IAAI;AAU1D,SAASC,GAAcrG,GAAyC;AACrE,QAAM,EAAE,QAAAsG,GAAQ,aAAAC,GAAa,UAAArE,EAAA,IAAalC,GAGpC,CAACwG,CAAc,IAAIC,GAAS,MAAMF,KAAe,IAAIG,IAAa;AACxE,SACE,gBAAArF,EAACsF,IAAA,EAAoB,QAAQJ,KAAeC,GAC1C,UAAA,gBAAAnF,EAAC8E,GAAmB,UAAnB,EAA4B,OAAOG,GAAS,UAAApE,EAAA,CAAS,GACxD;AAEJ;AAGO,SAAS0E,KAA8B;AAC5C,QAAMN,IAASO,GAAWV,EAAkB;AAC5C,MAAIG,MAAW;AACb,UAAM,IAAI;AAAA,MACR;AAAA,IAAA;AAIJ,SAAOA;AACT;ACxBO,SAASQ,GACdd,GACAT,GACAhG,GAC8B;AAC9B,QAAM+G,IAASM,GAAA;AACf,SAAOG,GAAuB;AAAA,IAC5B,GAAGxH;AAAA,IACH,UAAU2G,GAAU,KAAKF,GAAUT,CAAM;AAAA,IACzC,SAAS,CAAC,EAAE,QAAAyB,QACVV,EAAO,QAAsBP,GAASC,CAAQ,GAAG,EAAE,OAAOV,GAAeC,CAAM,GAAG,QAAAyB,GAAQ;AAAA,EAAA,CAC7F;AACH;ACTA,SAASC,GAAY1G,GAA+B;AAClD,SAAO,OAAO,OAAS,OAAeA,aAAiB;AACzD;AAEA,SAAS2G,GAAY3G,GAA+B;AAClD,SAAO,OAAO,OAAS,OAAeA,aAAiB;AACzD;AAGO,SAAS4G,GAAaC,GAA0C;AACrE,SAAO,OAAO,OAAOA,CAAM,EAAE;AAAA,IAC3B,CAAC7G,MACC0G,GAAY1G,CAAK,KAAM,MAAM,QAAQA,CAAK,KAAKA,EAAM,KAAK,CAACuF,MAASmB,GAAYnB,CAAI,CAAC;AAAA,EAAA;AAE3F;AAEA,SAASuB,GAAgBC,GAAgB1G,GAAaL,GAAsB;AAC1E,MAAIA,KAAU,MACd;AAAA,QAAI0G,GAAY1G,CAAK,KAAK2G,GAAY3G,CAAK,GAAG;AAC5C,MAAA+G,EAAK,OAAO1G,GAAKL,CAAK;AACtB;AAAA,IACF;AACA,QAAI,OAAOA,KAAU,UAAU;AAC7B,MAAA+G,EAAK,OAAO1G,GAAK,KAAK,UAAUL,CAAK,CAAC;AACtC;AAAA,IACF;AACA,IAAA+G,EAAK,OAAO1G,GAAK,OAAOL,CAAK,CAAC;AAAA;AAChC;AAGO,SAASgH,GAAWH,GAA2C;AACpE,QAAME,IAAO,IAAI,SAAA;AACjB,aAAW,CAAC1G,GAAKL,CAAK,KAAK,OAAO,QAAQ6G,CAAM;AAC9C,QAAI7G,KAAU;AACd,UAAI,MAAM,QAAQA,CAAK;AACrB,mBAAWuF,KAAQvF,EAAO,CAAA8G,GAAgBC,GAAM1G,GAAKkF,CAAI;AAAA;AAEzD,QAAAuB,GAAgBC,GAAM1G,GAAKL,CAAK;AAGpC,SAAO+G;AACT;AAMO,SAASE,GAAWJ,GAAqE;AAC9F,SAAOD,GAAaC,CAAM,IAAIG,GAAWH,CAAM,IAAIA;AACrD;AAQO,SAASK,GAAeC,GAAuB1B,GAAuC;AAC3F,QAAM2B,wBAAY,IAAA;AAClB,MAAI,OAAOD,KAAiB,YAAYA,MAAiB,KAAM,QAAOC;AACtE,QAAMC,IAAaF,EAAyC;AAC5D,MAAI,OAAOE,KAAc,YAAYA,MAAc,KAAM,QAAOD;AAChE,QAAME,IAASD,EAAsC5B,CAAQ;AAC7D,MAAI,OAAO6B,KAAU,YAAYA,MAAU,KAAM,QAAOF;AACxD,QAAMG,IAAUD,EAAkC;AAClD,MAAI,CAAC,MAAM,QAAQC,CAAM,EAAG,QAAOH;AACnC,aAAWI,KAASD,GAA8B;AAChD,QAAI,OAAOC,KAAU,YAAYA,MAAU,KAAM;AACjD,UAAM,EAAE,MAAA9E,GAAM,MAAA+E,EAAA,IAASD;AACvB,IAAI,OAAO9E,KAAS,YAAY+E,MAAS,UAAQL,EAAM,IAAI1E,CAAI;AAAA,EACjE;AACA,SAAO0E;AACT;AAEA,SAASM,GAAsB1H,GAAyB;AACtD,SAAI,OAAOA,KAAU,WAAiB,KAC/B,MAAM,QAAQA,CAAK,KAAKA,EAAM,MAAM,CAACuF,MAAS,OAAOA,KAAS,QAAQ;AAC/E;AAOO,SAASoC,GACdd,GACAe,GACyB;AACzB,MAAIA,EAAW,SAAS,EAAG,QAAOf;AAClC,QAAMzB,IAA+B,CAAA;AACrC,aAAW,CAAC/E,GAAKL,CAAK,KAAK,OAAO,QAAQ6G,CAAM;AAC9C,IAAIe,EAAW,IAAIvH,CAAG,KAAKqH,GAAsB1H,CAAK,MACtDoF,EAAI/E,CAAG,IAAIL;AAEb,SAAOoF;AACT;ACxEO,SAASyC,GACdpC,GACAzG,GACsB;AACtB,QAAM+G,IAASM,GAAA,GACTL,IAAc8B,GAAA,GACdC,IAAiB/I,KAAA,gBAAAA,EAAS,gBAE1BgJ,IAAaC,GAAY,YAA2B;AACxD,UAAMjC,EAAY,kBAAkB,EAAE,UAAUL,GAAU,SAASF,CAAQ,GAAG,GAC1EsC,MAAmB,UACrB,MAAM,QAAQ;AAAA,MACZA,EAAe,IAAI,CAACG,MAAalC,EAAY,kBAAkB,EAAE,UAAAkC,GAAU,CAAC;AAAA,IAAA;AAAA,EAGlF,GAAG,CAAClC,GAAaP,GAAUsC,CAAc,CAAC,GAEpCI,IAASC,GAAiD;AAAA,IAC9D,YAAY,CAACvB,MACXd,EAAO,QAAWP,GAASC,CAAQ,GAAG,EAAE,QAAQ,QAAQ,MAAMwB,GAAWJ,CAAM,GAAG;AAAA,IACpF,WAAW,MAAMmB,EAAA;AAAA,EAAW,CAC7B,GAEKK,IAASD,GAAkF;AAAA,IAC/F,YAAY,CAAC,EAAE,IAAAzF,GAAI,QAAAkE,QAAa;AAC9B,YAAMe,IAAaV,GAAelB,EAAY,aAAaL,GAAU,OAAA,CAAQ,GAAGF,CAAQ,GAClF6C,IAAWX,GAAsBd,GAAQe,CAAU;AACzD,aAAO7B,EAAO,QAAWL,GAAWD,GAAU9C,CAAE,GAAG;AAAA,QACjD,QAAQ;AAAA,QACR,MAAMsE,GAAWqB,CAAQ;AAAA,MAAA,CAC1B;AAAA,IACH;AAAA,IACA,WAAW,MAAMN,EAAA;AAAA,EAAW,CAC7B,GAIKO,IAA4DH,GAAY;AAAA,IAC5E,YAAY,OAAOzF,MAAuC;AACxD,YAAMoD,EAAO,QAAQL,GAAWD,GAAU9C,CAAE,GAAG,EAAE,QAAQ,UAAU;AAAA,IACrE;AAAA,IACA,WAAW,MAAMqF,EAAA;AAAA,EAAW,CAC7B;AAED,SAAO,EAAE,QAAAG,GAAQ,QAAAE,GAAQ,QAAAE,EAAA;AAC3B;AC0BA,SAASC,EAASxI,GAAkD;AAClE,SAAO,OAAOA,KAAU,YAAYA,MAAU,QAAQ,CAAC,MAAM,QAAQA,CAAK;AAC5E;AAGO,SAASyI,GAAS/F,GAAsB;AAC7C,QAAMgG,IAAShG,EAAK,QAAQ,UAAU,GAAG,EAAE,KAAA;AAC3C,SAAOgG,EAAO,WAAW,IAAIhG,IAAOgG,EAAO,OAAO,CAAC,EAAE,YAAA,IAAgBA,EAAO,MAAM,CAAC;AACrF;AAEA,MAAMC,KAAa;AAEnB,SAASC,GAAUC,GAAsBhI,GAAuC;;AAC9E,MAAKA,EAAI,WAAW8H,EAAU;AAC9B,YAAOhK,KAAAD,IAAAmK,EAAI,eAAJ,gBAAAnK,EAAgB,YAAhB,gBAAAC,EAA0BkC,EAAI,MAAM8H,GAAW,MAAM;AAC9D;AAOO,SAASG,GACdD,GACAE,GACAC,IAA0B,CAAA,GACA;AAC1B,MAAID,MAAW,QAEf;AAAA,QAAI,OAAOA,EAAO,QAAS,UAAU;AACnC,UAAIC,EAAK,SAASD,EAAO,IAAI,UAAU,CAAA;AACvC,YAAME,IAASL,GAAUC,GAAKE,EAAO,IAAI;AACzC,UAAIE,MAAW,OAAW,QAAO,CAAA;AACjC,YAAMC,IAAWJ,GAAcD,GAAKI,GAAQ,CAAC,GAAGD,GAAMD,EAAO,IAAI,CAAC,KAAK,CAAA,GACjEI,IAAyB,EAAE,GAAGJ,EAAA;AACpC,oBAAOI,EAAS,MACT,EAAE,GAAGD,GAAU,GAAGC,EAAA;AAAA,IAC3B;AAEA,QAAI,MAAM,QAAQJ,EAAO,KAAK,KAAKA,EAAO,MAAM,WAAW,GAAG;AAC5D,YAAMK,IAAQN,GAAcD,GAAKE,EAAO,MAAM,CAAC,GAAGC,CAAI,KAAK,CAAA,GACrDG,IAAyB,EAAE,GAAGJ,EAAA;AACpC,oBAAOI,EAAS,OACT,EAAE,GAAGC,GAAO,GAAGD,EAAA;AAAA,IACxB;AAEA,WAAOJ;AAAA;AACT;AAwBA,SAASM,GAAcN,GAAuE;AAE5F,SAAI,MAAM,QAAQA,EAAO,IAAI,IAEpB,EAAE,MADOA,EAAO,KAAK,OAAO,CAACO,MAAMA,MAAM,MAAM,EAC/B,CAAC,GAAG,UAAUP,EAAO,KAAK,SAAS,MAAM,KAAKA,EAAO,aAAa,GAAA,IAEpF;AAAA,IACL,MAAM,OAAOA,EAAO,QAAS,WAAWA,EAAO,OAAO;AAAA,IACtD,UAAUA,EAAO,aAAa;AAAA,EAAA;AAElC;AAEA,SAASQ,GAAsBR,GAA+C;AAC5E,QAAMS,IAAMT,EAAO,kBAAkB;AACrC,MAAIP,EAASgB,CAAG,KAAK,OAAOA,EAAI,YAAa,YAAYA,EAAI,SAAS,SAAS;AAC7E,WAAO,EAAE,UAAUA,EAAI,UAAU,MAAMA,EAAI,SAAS,GAAA;AAGxD;AAEA,SAASC,GAAoBV,GAAqD;AAChF,QAAM,EAAE,MAAAnI,EAAA,IAASyI,GAAcN,CAAM;AACrC,SAAInI,MAAS,aAAaA,MAAS,WAAiB,YAChDmI,EAAO,WAAW,SAAe,SAC9B;AACT;AAOA,SAASW,GACPb,GACAc,GACAX,GACyF;AACzF,QAAMnC,IAAiC,CAAA;AACvC,MAAI+C,IAAW,IACXC;AACJ,aAAWC,KAAUH,GAAS;AAC5B,UAAMT,IAAWJ,GAAcD,GAAKiB,GAAQd,CAAI;AAChD,QAAIE,MAAa,UAAa,CAAC,MAAM,QAAQA,EAAS,IAAI,EAAG;AAC7D,IAAIW,MAAgB,UAAaX,EAAS,gBAAgB,UAAarC,EAAO,WAAW,MACvFgD,IAAcX,EAAS;AAEzB,eAAWlJ,KAASkJ,EAAS;AAC3B,MAAIlJ,MAAU,OACZ4J,IAAW,KACF5J,MAAU,MACnB6G,EAAO,KAAK7G,CAAK;AAAA,EAGvB;AACA,SAAO,EAAE,QAAA6G,GAAQ,UAAA+C,GAAU,aAAAC,EAAA;AAC7B;AAEA,MAAME,KAAc;AAQb,SAASC,GAAaH,GAG3B;AACA,MAAIA,MAAgB,OAAW,QAAO,CAAA;AACtC,QAAMI,IAAiC,CAAA,GACjCtK,IAAiB,CAAA;AACvB,aAAWuK,KAAQL,EAAY,MAAM;AAAA,CAAI,GAAG;AAC1C,UAAMM,IAAQJ,GAAY,KAAKG,EAAK,MAAM;AAC1C,IAAIC,MAAU,QAAQA,EAAM,CAAC,MAAM,UAAaA,EAAM,CAAC,MAAM,SAC3DF,EAAOE,EAAM,CAAC,CAAC,IAAIA,EAAM,CAAC,EAAE,KAAA,IAE5BxK,EAAK,KAAKuK,CAAI;AAAA,EAElB;AACA,QAAME,IAAOzK,EAAK,KAAK;AAAA,CAAI,EAAE,KAAA;AAC7B,SAAO;AAAA,IACL,GAAI,OAAO,KAAKsK,CAAM,EAAE,SAAS,IAAI,EAAE,QAAAA,EAAA,IAAW,CAAA;AAAA,IAClD,GAAIG,MAAS,KAAK,EAAE,MAAMA,EAAA,IAAS,CAAA;AAAA,EAAC;AAExC;AAEA,SAASC,GAAkBC,GAAoBT,GAAuC;AACpF,QAAM,EAAE,QAAAI,GAAQ,MAAAtK,MAASqK,GAAaH,CAAW;AACjD,EAAII,MAAW,WAAWK,EAAK,aAAaL,IAC5CK,EAAK,cAAc3K;AACrB;AAGA,SAAS4K,GAAYxB,GAA+B;AAClD,SACEA,EAAO,SAAS,UAChBA,EAAO,SAAS,UAChBA,EAAO,eAAe,UACtBA,EAAO,UAAU,UACjBA,EAAO,UAAU,UACjBA,EAAO,UAAU,UACjBA,EAAO,UAAU,UACjBA,EAAO,SAAS;AAEpB;AAEA,SAASyB,GAAgB3B,GAAsB4B,GAAiC;AAC9E,QAAMvB,IAAWJ,GAAcD,GAAK4B,CAAG,KAAK,CAAA,GACtCC,IAAWnB,GAAsBL,CAAQ,GACzC,EAAE,MAAAtI,GAAM,UAAU+J,EAAA,IAAiBtB,GAAcH,CAAQ,GAEzDoB,IAAqB;AAAA,IACzB,MAAM;AAAA,IACN,UAAUK;AAAA,IACV,QAAQzB,EAAS;AAAA,IACjB,aAAaA,EAAS;AAAA,IACtB,OAAOA,EAAS;AAAA,IAChB,SAASA,EAAS;AAAA,IAClB,UAAUA,EAAS,aAAa;AAAA,IAChC,WAAWA,EAAS,cAAc;AAAA,IAClC,WAAWA,EAAS;AAAA,IACpB,KAAKA,EAAS;AAAA,IACd,KAAKA,EAAS;AAAA,IACd,UAAAwB;AAAA,IACA,QAAQ;AAAA,EAAA,GAIJE,IAAc1B,EAAS,SAASA,EAAS;AAC/C,MAAI,MAAM,QAAQ0B,CAAW,GAAG;AAC9B,UAAMC,IAAWnB,GAAmBb,GAAK+B,GAAa,CAAA,CAAE;AACxD,WAAIC,MAAa,WACfP,EAAK,OAAO,QACZA,EAAK,aAAaO,EAAS,QAC3BP,EAAK,WAAWA,EAAK,YAAYO,EAAS,UAC1CR,GAAkBC,GAAMpB,EAAS,eAAe2B,EAAS,WAAW,IAC7DP;AAAA,EAGX;AAEA,MAAI,MAAM,QAAQpB,EAAS,IAAI;AAC7B,WAAAoB,EAAK,OAAO,QACZA,EAAK,WAAWA,EAAK,YAAYpB,EAAS,KAAK,SAAS,IAAI,GAC5DoB,EAAK,aAAapB,EAAS,KAAK;AAAA,MAC9B,CAAClJ,MAAoCA,MAAU,QAAQA,MAAU;AAAA,IAAA,GAEnEqK,GAAkBC,GAAMpB,EAAS,WAAW,GACrCoB;AAGT,MAAII,MAAa,UAAa,CAACA,EAAS;AACtC,WAAAJ,EAAK,OAAO,YACZA,EAAK,oBAAoBb,GAAoBP,CAAQ,GAC9CoB;AAGT,UAAQ1J,GAAA;AAAA,IACN,KAAK;AACH,aAAIsI,EAAS,WAAW,YACtBoB,EAAK,OAAO,QACZA,EAAK,SAAS,MACLpB,EAAS,WAAW,SAC7BoB,EAAK,OAAO,SACHpB,EAAS,WAAW,cAC7BoB,EAAK,OAAO,aACHpB,EAAS,WAAW,UAAaA,EAAS,cAAc,SAEjEoB,EAAK,OAAO,SAEZA,EAAK,OAAO,UAEPA;AAAA,IAET,KAAK;AACH,aAAAA,EAAK,OAAO,WACLA;AAAA,IACT,KAAK;AACH,aAAAA,EAAK,OAAO,UACLA;AAAA,IACT,KAAK;AACH,aAAAA,EAAK,OAAO,WACLA;AAAA,IACT,KAAK,SAAS;AACZ,UAAII,MAAa,QAAW;AAC1B,QAAAJ,EAAK,OAAO;AACZ,cAAMQ,IAAQhC,GAAcD,GAAKK,EAAS,KAAK,KAAK,CAAA;AACpD,QAAAoB,EAAK,oBAAoBb,GAAoBqB,CAAK;AAAA,MACpD;AACE,QAAAR,EAAK,OAAO;AAEd,aAAOA;AAAA,IACT;AAAA,IACA,KAAK;AACH,aAAAA,EAAK,OAAO,QACLA;AAAA,IACT;AACE,aAAII,MAAa,UAEfJ,EAAK,OAAO,YACZA,EAAK,oBAAoBb,GAAoBP,CAAQ,KAC5CqB,GAAYrB,CAAQ,MAE7BoB,EAAK,OAAO,SAEPA;AAAA,EACT;AAEJ;AAIA,SAASS,GACPrI,GACAsI,GACAC,GACAC,GACAC,GACAC,GACU;AAIV,MAAI3D;AACJ,GAAIwD,KAAA,gBAAAA,EAAa,YAAW,KAC1BxD,IAAO,SACEwD,MAAgB,UAAaA,EAAY,SAAS,YAC3DxD,IAAOwD,EAAY,OACVD,MAAiB,UAAaA,EAAa,SAAS,YAC7DvD,IAAOuD,EAAa,OAEpBvD,IAAO;AAGT,QAAMiD,KAAWO,KAAA,gBAAAA,EAAa,cAAYD,KAAA,gBAAAA,EAAc,WAClDK,KAAQJ,KAAA,gBAAAA,EAAa,WAASD,KAAA,gBAAAA,EAAc,QAE5CxD,IAAkB;AAAA,IACtB,MAAA9E;AAAA,IACA,OAAO2I,MAAU,UAAaA,EAAM,SAAS,IAAIA,IAAQ5C,GAAS/F,CAAI;AAAA,IACtE,MAAA+E;AAAA,IACA,UAAUyD,EAAY,IAAIxI,CAAI;AAAA,IAC9B,UACE,CAACyI,MACDH,KAAA,gBAAAA,EAAc,cAAa,OAC3BC,KAAA,gBAAAA,EAAa,cAAa,MACzBE,KAAoBH,MAAiB,UAAaC,MAAgB;AAAA,IACrE,YACEA,KAAA,gBAAAA,EAAa,eAAc,OAC3BD,KAAA,gBAAAA,EAAc,eAAc,MAC3BA,MAAiB,UAAaC,MAAgB;AAAA;AAAA;AAAA,IAGjD,UAAUA,MAAgB,SAAYA,EAAY,YAAYD,KAAA,gBAAAA,EAAc,aAAY;AAAA,IACxF,OAAAI;AAAA,EAAA,GAGIE,KAAaL,KAAA,gBAAAA,EAAa,gBAAcD,KAAA,gBAAAA,EAAc,aACtDO,KAAWN,KAAA,gBAAAA,EAAa,aAAWD,KAAA,gBAAAA,EAAc;AACvD,EAAIO,MAAa,WAAW/D,EAAM,UAAU+D,IACxCD,MAAe,WAAW9D,EAAM,aAAa8D;AACjD,QAAME,KAAaP,KAAA,gBAAAA,EAAa,gBAAcD,KAAA,gBAAAA,EAAc;AAC5D,EAAIQ,MAAe,WAAWhE,EAAM,aAAagE;AACjD,QAAMC,KAAYR,KAAA,gBAAAA,EAAa,eAAaD,KAAA,gBAAAA,EAAc;AAC1D,EAAIS,MAAc,WAAWjE,EAAM,YAAYiE;AAC/C,QAAMC,KAAMT,KAAA,gBAAAA,EAAa,SAAOD,KAAA,gBAAAA,EAAc;AAC9C,EAAIU,MAAQ,WAAWlE,EAAM,MAAMkE;AACnC,QAAMC,KAAMV,KAAA,gBAAAA,EAAa,SAAOD,KAAA,gBAAAA,EAAc;AAC9C,EAAIW,MAAQ,WAAWnE,EAAM,MAAMmE;AACnC,QAAMC,KAASX,KAAA,gBAAAA,EAAa,YAAUD,KAAA,gBAAAA,EAAc;AACpD,EAAIY,MAAW,WAAWpE,EAAM,SAASoE;AACzC,QAAM/B,KAAcmB,KAAA,gBAAAA,EAAc,iBAAeC,KAAA,gBAAAA,EAAa;AAE9D,MADIpB,MAAgB,WAAWrC,EAAM,cAAcqC,IAC/Ca,MAAa,QAAW;AAC1B,IAAAlD,EAAM,WAAWkD;AACjB,UAAMmB,KAAYZ,KAAA,gBAAAA,EAAa,uBAAqBD,KAAA,gBAAAA,EAAc;AAClE,IAAIa,MAAc,WAAWrE,EAAM,oBAAoBqE;AAAA,EACzD;AAEA,SAAOrE;AACT;AAIA,SAASsE,GACPjD,GACAkD,GACAC,GACAC,GACc;AACd,QAAMC,IAAwB,CAAA;AAC9B,MAAIC;AACJ,aAAWC,KAASH,EAAG,cAAc,CAAA;AACnC,QAAI,GAACzD,EAAS4D,CAAK,KAAKA,EAAM,OAAO,WAAW,OAAOA,EAAM,QAAS,cACtEF,EAAY,KAAKE,EAAM,IAAI,GACvBA,EAAM,SAAS,WAAU;AAC3B,YAAMrD,IAASD,GAAcD,GAAKuD,EAAM,MAAM,GACxCtB,IAAQhC,GAAcD,GAAKE,KAAA,gBAAAA,EAAQ,KAAK,GACxClC,KAASkC,KAAA,gBAAAA,EAAQ,UAAQ+B,KAAA,gBAAAA,EAAO;AACtC,MAAI,MAAM,QAAQjE,CAAM,MACtBsF,IAAatF,EAAO,OAAO,CAAC7G,MAA2B,OAAOA,KAAU,QAAQ;AAAA,IAEpF;AAEF,QAAMqM,IAAoB;AAAA,IACxB,MAAAN;AAAA,IACA,QAAAC;AAAA,IACA,aAAAE;AAAA,IACA,WAAWA,EAAY,SAAS,QAAQ;AAAA,EAAA;AAE1C,SAAI,OAAOD,EAAG,eAAgB,aAAUI,EAAI,cAAcJ,EAAG,cACzDE,MAAe,WAAWE,EAAI,aAAaF,IACxCE;AACT;AAGA,SAASC,GAAezD,GAAsBoD,GAA+C;;AAC3F,QAAMM,MACJ7N,IAAAuN,EAAG,cAAH,gBAAAvN,EAAe,aAAUC,IAAAsN,EAAG,cAAH,gBAAAtN,EAAe,WAAU,OAAO,OAAOsN,EAAG,aAAa,CAAA,CAAE,EAAE,CAAC,GACjFO,KAAQC,IAAAF,KAAA,gBAAAA,EAAU,YAAV,gBAAAE,EAAoB,qBAC5BC,IAAO5D,GAAcD,GAAK2D,KAAA,gBAAAA,EAAO,MAAM;AAC7C,MAAIE,MAAS,OAAW;AACxB,QAAMC,IAAU7D,GAAcD,IAAK+D,IAAAF,EAAK,eAAL,gBAAAE,EAAkB,OAAU;AAC/D,SAAID,MAAY,UAAaA,EAAQ,SAAS,UACrC7D,GAAcD,GAAK8D,EAAQ,KAAK,IAErCD,EAAK,SAAS,UAAgB5D,GAAcD,GAAK6D,EAAK,KAAK,IACxDA;AACT;AAEA,SAASG,GAAoBhE,GAAsBoD,GAA+C;;AAChG,QAAMa,KAAUpO,IAAAuN,EAAG,gBAAH,gBAAAvN,EAAgB;AAChC,MAAI,CAAC8J,EAASsE,CAAO,EAAG;AACxB,QAAMN,IACJM,EAAQ,kBAAkB,KAAKA,EAAQ,qBAAqB,KAAK,OAAO,OAAOA,CAAO,EAAE,CAAC;AAC3F,SAAOhE,GAAcD,GAAK2D,KAAA,gBAAAA,EAAO,MAAM;AACzC;AAIA,MAAMO,KAAU,CAAC,OAAO,QAAQ,OAAO,SAAS,QAAQ;AAQjD,SAASC,GAAaC,GAA8B;AACzD,QAAMpE,IAAuBL,EAASyE,CAAK,IAAKA,IAA4B,CAAA,GACtEC,IAAQ1E,EAASK,EAAI,KAAK,IAAIA,EAAI,QAAQ,CAAA,GAE1CxB,IAA4C,CAAA,GAC5C8F,IAActE,EAAI,mBAAmB,GACrCuE,IAAWD,MAAgB,SAASA,MAAgB,YAAYA,IAAc,QAG9EE,IAA2E,CAAA;AACjF,aAAW,CAACtB,GAAMxG,CAAI,KAAK,OAAO,QAAQ2H,CAAK,GAAG;AAChD,QAAI,CAAC1E,EAASjD,CAAI,EAAG;AACrB,UAAM+H,IAAM/H,EAAK;AACjB,IAAIiD,EAAS8E,CAAG,KAAK,OAAOA,EAAI,kBAAkB,KAAM,YACtDD,EAAQ,KAAK,EAAE,UAAUC,EAAI,kBAAkB,GAAG,MAAAvB,GAAM,MAAAxG,GAAM;AAAA,EAElE;AAEA,aAAW,EAAE,UAAAE,GAAU,MAAAsG,GAAM,MAAAxG,EAAA,KAAU8H,GAAS;AAC9C,UAAME,IAAShI,EAAK;AACpB,QAAI,CAACiD,EAAS+E,CAAM,EAAG;AAGvB,UAAMC,IAAY,OAAO,QAAQN,CAAK,EAAE,KAAK,CAAC,CAACO,CAAS,MAAM;AAC5D,UAAI,CAACA,EAAU,WAAW1B,CAAI,EAAG,QAAO;AACxC,YAAMpM,IAAO8N,EAAU,MAAM1B,EAAK,MAAM;AACxC,aAAO,mBAAmB,KAAKpM,CAAI;AAAA,IACrC,CAAC,GACK+N,IAAWF,KAAA,gBAAAA,EAAY,IACvBG,IAAWH,MAAc,UAAahF,EAASgF,EAAU,CAAC,CAAC,IAAIA,EAAU,CAAC,IAAI,QAE9EI,IAA2C;AAAA,MAC/C,MAAM9B,GAAajD,GAAKkD,GAAM,OAAOwB,CAAM;AAAA,IAAA,GAEvCM,IAAWrF,EAASjD,EAAK,IAAI,IAAIA,EAAK,OAAO;AACnD,IAAIsI,MAAa,WAAWD,EAAW,SAAS9B,GAAajD,GAAKkD,GAAM,QAAQ8B,CAAQ;AAExF,UAAMC,IAAaZ,EAAM,GAAGnB,CAAI,SAAS,GACnCgC,IAAWvF,EAASsF,CAAU,KAAKtF,EAASsF,EAAW,GAAG,IAAIA,EAAW,MAAM;AACrF,IAAIC,MAAa,WACfH,EAAW,SAAS9B,GAAajD,GAAK,GAAGkD,CAAI,WAAW,OAAOgC,CAAQ;AAEzE,UAAMC,IAAad,EAAM,GAAGnB,CAAI,SAAS,GACnCkC,IACJzF,EAASwF,CAAU,KAAKxF,EAASwF,EAAW,IAAI,IAAIA,EAAW,OAAO;AAIxE,QAHIC,MAAa,WACfL,EAAW,SAAS9B,GAAajD,GAAK,GAAGkD,CAAI,WAAW,QAAQkC,CAAQ,IAEtEP,MAAa,UAAaC,MAAa;AACzC,iBAAW3B,KAAUe,IAAS;AAC5B,cAAMd,IAAK0B,EAAS3B,CAAM;AAC1B,QAAKxD,EAASyD,CAAE,MACZD,MAAW,QAAO4B,EAAW,SAAS9B,GAAajD,GAAK6E,GAAU,OAAOzB,CAAE,IACtED,MAAW,UAAS4B,EAAW,SAAS9B,GAAajD,GAAK6E,GAAU,SAASzB,CAAE,IAC/ED,MAAW,SAAS4B,EAAW,WAAW,SACjDA,EAAW,SAAS9B,GAAajD,GAAK6E,GAAU,OAAOzB,CAAE,IAClDD,MAAW,aAAU4B,EAAW,SAAS9B,GAAajD,GAAK6E,GAAU,UAAUzB,CAAE;AAAA,MAC5F;AAIF,UAAMiC,IAAiB5B,GAAezD,GAAK0E,CAAM,GAC3CY,IAAgBN,MAAa,SAAYhB,GAAoBhE,GAAKgF,CAAQ,IAAI,QAC9E1C,IAAmBgD,MAAkB,QAErCC,IAAgB5F,EAAS0F,KAAA,gBAAAA,EAAgB,UAAU,IAAIA,EAAe,aAAa,CAAA,GACnFG,IAAe7F,EAAS2F,KAAA,gBAAAA,EAAe,UAAU,IAAIA,EAAc,aAAa,CAAA,GAEhFjD,IAAc,IAAI;AAAA,MACtB,MAAM,QAAQiD,KAAA,gBAAAA,EAAe,QAAQ,IAAIA,EAAc,WAAW,CAAA;AAAA,IAAC,GAG/D5G,IAAqB,CAAA;AAC3B,QAAI6D,IAAQ;AACZ,eAAW,CAAC1I,GAAM4L,CAAI,KAAK,OAAO,QAAQF,CAAa,GAAG;AACxD,YAAMpD,IAAeR,GAAgB3B,GAAKyF,CAAI,GACxCC,IAAcF,EAAa3L,CAAI,GAC/BuI,IAAcsD,MAAgB,SAAY/D,GAAgB3B,GAAK0F,CAAW,IAAI;AACpF,MAAAhH,EAAO;AAAA,QACLwD,GAAWrI,GAAMsI,GAAcC,GAAaC,GAAaC,GAAkBC,CAAK;AAAA,MAAA,GAElFA,KAAS;AAAA,IACX;AACA,eAAW,CAAC1I,GAAM4L,CAAI,KAAK,OAAO,QAAQD,CAAY,GAAG;AACvD,UAAI3L,KAAQ0L,EAAe;AAC3B,YAAMnD,IAAcT,GAAgB3B,GAAKyF,CAAI;AAC7C,MAAA/G,EAAO,KAAKwD,GAAWrI,GAAM,QAAWuI,GAAaC,GAAaC,GAAkBC,CAAK,CAAC,GAC1FA,KAAS;AAAA,IACX;AAEA,IAAA/D,EAAU5B,CAAQ,IAAI,EAAE,UAAAA,GAAU,YAAAmI,GAAY,QAAArG,EAAA;AAAA,EAChD;AAEA,QAAMiH,IAAuB,EAAE,WAAAnH,EAAA;AAC/B,SAAI+F,MAAa,WAAWoB,EAAO,WAAWpB,IACvCoB;AACT;ACnmBO,MAAMC,KAAmB,CAAC,SAAS,SAAS;AAO5C,SAASC,KAAgD;AAC9D,QAAM3I,IAASM,GAAA;AACf,SAAOG,GAAuB;AAAA,IAC5B,UAAUiI;AAAA,IACV,WAAW;AAAA,IACX,SAAS,YAAYzB,GAAa,MAAMjH,EAAO,QAAiBA,EAAO,SAAS,CAAC;AAAA,EAAA,CAClF;AACH;AASO,SAAS4I,GAAUlJ,GAAmC;AAC3D,QAAMR,IAAQyJ,GAAA;AAEd,MAAIzJ,EAAM,SAAS,QAAW;AAC5B,UAAM8D,IAAS9D,EAAM,KAAK,UAAUQ,CAAQ;AAC5C,QAAIsD,MAAW,QAAW;AACxB,YAAM6F,IAAQ,OAAO,KAAK3J,EAAM,KAAK,SAAS,EAAE,KAAA;AAChD,YAAM,IAAI;AAAA,QACR,qBAAqBQ,CAAQ,uBACxBmJ,EAAM,SAAS,IAAIA,EAAM,KAAK,IAAI,IAAI,mDAAmD;AAAA,MAAA;AAAA,IAElG;AACA,WAAO,EAAE,MAAM7F,GAAQ,WAAW,IAAO,OAAO9D,EAAM,MAAA;AAAA,EACxD;AAEA,SAAO,EAAE,MAAM,QAAW,WAAWA,EAAM,WAAW,OAAOA,EAAM,MAAA;AACrE;ACzDApG,GAAsB,eAAe,YAAY;AAqB1C,MAAMgQ,KAAapO,EAAM;AAAA,EAC9B,CAAC,EAAE,MAAAqO,GAAM,OAAAzD,GAAO,aAAAxB,GAAa,QAAAkF,GAAQ,WAAArP,GAAW,UAAAiC,GAAU,GAAGlC,KAASoB,MACpE,gBAAAe;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,KAAAf;AAAA,MACA,WAAW1C;AAAA,QACT;AAAA,QACAuB;AAAA,MAAA;AAAA,MAED,GAAGD;AAAA,MAEH,UAAA;AAAA,QAAAqP,KAAQ,QACP,gBAAAhO,EAAC,OAAA,EAAI,eAAY,QAAO,WAAU,wDAC/B,UAAAgO,EAAA,CACH;AAAA,QAEF,gBAAAhO,EAAC,MAAA,EAAG,WAAU,2CAA2C,UAAAuK,GAAM;AAAA,QAC9DxB,KAAe,QACd,gBAAA/I,EAAC,KAAA,EAAE,WAAU,0CAA0C,UAAA+I,GAAY;AAAA,QAEpEkF,KAAU,QAAQ,gBAAAjO,EAAC,OAAA,EAAI,WAAU,gCAAgC,UAAAiO,GAAO;AAAA,QACxEpN;AAAA,MAAA;AAAA,IAAA;AAAA,EAAA;AAGP;AACAkN,GAAW,cAAc;AClClB,MAAMG,KAAkC,OAAO,OAAO;AAAA,EAC3D;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AAOM,SAASC,GAAazH,GAAqD;AAChF,SAAOA,EAAM,YAAYwH,GAAa,SAASxH,EAAM,IAAI;AAC3D;AAMO,SAAS0H,GACd3H,GAC6B;AAC7B,QAAM4H,IAAc,CAAA,GACdC,IAAa,CAAA;AACnB,aAAW5H,KAASD;AAClB,KAAC0H,GAAazH,CAAK,IAAI4H,IAAQD,GAAQ,KAAK3H,CAAK;AAEnD,SAAA4H,EAAM,KAAK,CAACC,GAAGC,MAAMN,GAAa,QAAQK,EAAE,IAAI,IAAIL,GAAa,QAAQM,EAAE,IAAI,CAAC,GACzE,EAAE,QAAAH,GAAQ,OAAAC,EAAA;AACnB;ACtCA,MAAMG,KAAa,CAAC,QAAQ,SAAS,SAAS,SAAS,KAAK;AAMrD,SAASC,GAAaC,GAAsC;AACjE,aAAWpP,KAAOkP,IAAY;AAC5B,UAAMvP,IAAQyP,EAAIpP,CAAG;AACrB,QAAI,OAAOL,KAAU,YAAYA,EAAM,OAAO,SAAS,EAAG,QAAOA;AAAA,EACnE;AACA,QAAM2C,IAAK8M,EAAI;AACf,SAAI9M,KAAO,OAAiC,OAAOA,CAAE,IAC9C;AACT;ACEO,SAAS+M,GAAejQ,GAAgD;AAC7E,QAAM,EAAE,aAAAkQ,GAAa,aAAAC,GAAa,SAAAC,GAAS,WAAAnQ,MAAcD;AACzD,SACE,gBAAAmC;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,MAAK;AAAA,MACL,cAAW;AAAA,MACX,WAAWzD;AAAA,QACT;AAAA,QACAuB;AAAA,MAAA;AAAA,MAGF,UAAA;AAAA,QAAA,gBAAAkC,EAAC,KAAA,EAAE,WAAU,uCAAuC,UAAA;AAAA,UAAA+N,EAAY;AAAA,UAAO;AAAA,QAAA,GAAS;AAAA,QAChF,gBAAA7O,EAACN,KAAO,SAAQ,SAAQ,MAAK,MAAK,SAASqP,GAAS,UAAA,QAAA,CAEpD;AAAA,QACA,gBAAA/O,EAAC,SAAI,WAAU,6CACZ,YAAY,IAAI,CAACiO,GAAQe,MACxB,gBAAAhP;AAAA,UAACN;AAAA,UAAA;AAAA,YAEC,SAASuO,EAAO,gBAAgB,KAAO,gBAAgB;AAAA,YACvD,MAAK;AAAA,YACL,SAAS,MAAMA,EAAO,QAAQ,CAAC,GAAGY,CAAW,CAAC;AAAA,YAE7C,UAAAZ,EAAO;AAAA,UAAA;AAAA,UALHe;AAAA,QAAA,CAOR,EAAA,CACH;AAAA,MAAA;AAAA,IAAA;AAAA,EAAA;AAGN;AC1CO,SAASC,GAAkBC,GAA2C;AAC3E,MAAIA,EAAQ,WAAW;AACvB,WAAOA,EAAQ,IAAI,CAAC1I,MAAWA,EAAM,OAAO,IAAIA,EAAM,EAAE,KAAKA,EAAM,EAAG,EAAE,KAAK,GAAG;AAClF;AAOO,SAAS2I,GAAgBC,GAAyB;AACvD,SACE,OAAOA,KAAU,YACjBA,MAAU,QACV,YAAYA,KACXA,EAA8B,WAAW;AAE9C;AAEO,SAASC,GAAaC,GAA2BC,GAA0B;AAChF,SAAID,MAAU,UAAaA,KAAS,KAAKC,KAAY,IAAU,IACxD,KAAK,IAAI,GAAG,KAAK,KAAKD,IAAQC,CAAQ,CAAC;AAChD;AAGO,SAASC,GAAStQ,GAAyC;AAChE,SAAO,OAAOA,KAAU,YAAYA,MAAU,QAAQ,CAAC,MAAM,QAAQA,CAAK,IACrEA,IACD,CAAA;AACN;AAGO,SAASuQ,GAAaL,GAAwB;AACnD,MAAI,OAAOA,KAAU,YAAYA,MAAU,MAAM;AAC/C,UAAMM,IAAQN,EAA6B;AAC3C,QAAI,OAAOM,KAAS,YAAYA,MAAS,MAAM;AAC7C,YAAMC,IAAUD,EAA8B;AAC9C,UAAI,OAAOC,KAAW,YAAYA,EAAO,SAAS,EAAG,QAAOA;AAAA,IAC9D;AACA,UAAMrR,IAAW8Q,EAAgC;AACjD,QAAI,OAAO9Q,KAAY,YAAYA,EAAQ,SAAS,EAAG,QAAOA;AAAA,EAChE;AACA,SAAO;AACT;AAOO,SAASsR,GACd1Q,GACAiK,GACQ;AACR,QAAM2E,IAAQ3E,KAAA,gBAAAA,EAAS,OAAOjK,CAAK;AACnC,MAAI4O,MAAU,OAAW,QAAOA;AAChC,MAAI,OAAO5O,KAAU,SAAU,QAAO,OAAOA,CAAK;AAElD,MADe,mBAAmB,KAAKA,CAAK,MAC7BA,MAAUA,EAAM,YAAA,KAAiBA,MAAUA,EAAM,gBAAgB;AAC9E,UAAM0I,IAAS1I,EAAM,YAAA,EAAc,QAAQ,OAAO,GAAG,EAAE,KAAA;AACvD,WAAI0I,EAAO,WAAW,IAAU1I,IACzB0I,EAAO,OAAO,CAAC,EAAE,gBAAgBA,EAAO,MAAM,CAAC;AAAA,EACxD;AACA,SAAO1I;AACT;ACrCA,MAAM2Q,KAAgD,oBAAI,IAAI,CAAC,QAAQ,QAAQ,SAAS,CAAC,GACnFC,yBAA+C,IAAI;AAAA,EACvD;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AAED,SAASC,KAAiC;AACxC,2BACG,QAAA,EAAK,eAAY,QAAO,WAAU,yBAAwB,UAAA,KAE3D;AAEJ;AAEA,SAASC,GAAY,EAAE,OAAA9Q,KAAiD;AACtE,SAAOA,IACL,gBAAA4B,EAAC,QAAA,EAAK,WAAU,4CACd,UAAA;AAAA,IAAA,gBAAAd,EAACI,IAAA,EAAU,WAAU,UAAA,CAAU;AAAA,IAC/B,gBAAAJ,EAAC,QAAA,EAAK,WAAU,WAAU,UAAA,MAAA,CAAG;AAAA,EAAA,EAAA,CAC/B,IAEA,gBAAAc,EAAC,QAAA,EAAK,WAAU,kDACd,UAAA;AAAA,IAAA,gBAAAd,EAAC,QAAA,EAAK,eAAY,QAAO,UAAA,KAAC;AAAA,IAC1B,gBAAAA,EAAC,QAAA,EAAK,WAAU,WAAU,UAAA,KAAA,CAAE;AAAA,EAAA,GAC9B;AAEJ;AAEA,SAASiQ,GAAO,EAAE,OAAA/Q,KAAiD;AACjE,2BAAQ,QAAA,EAAK,WAAU,wCAAwC,UAAA,OAAOA,CAAK,GAAE;AAC/E;AAEA,SAASgR,GAAazL,GAAe0L,GAAoC;AACvE,SAAI1L,KAAS,yBAAoCsL,IAAA,EAAW,IACxD,OAAOtL,KAAS,YAAY,CAAC,MAAM,QAAQA,CAAI,IAAU0L,EAAMX,GAAS/K,CAAI,CAAC,IAC1E,gBAAAzE,EAACiQ,IAAA,EAAO,OAAOxL,EAAA,CAAM;AAC9B;AAEA,SAAS2L,GAAa,EAAE,OAAAlR,GAAO,OAAAiR,KAAoE;AACjG,SAAIjR,KAAU,yBAAqC6Q,IAAA,EAAW,IAC1D,MAAM,QAAQ7Q,CAAK,IACjBA,EAAM,WAAW,sBAAW6Q,IAAA,EAAW,sBAExC,QAAA,EAAK,WAAU,sDACb,UAAA7Q,EAAM,IAAI,CAACuF,GAAMuK,wBACfrP,EAAM,UAAN,EAA4B,UAAAuQ,GAAazL,GAAM0L,CAAK,EAAA,GAAhCnB,CAAkC,CACxD,GACH,IAGG,gBAAAhP,EAAAqQ,GAAA,EAAG,UAAAH,GAAahR,GAAOiR,CAAK,GAAE;AACvC;AAEA,SAASG,GAASpR,GAAgBqR,GAA2B;AAC3D,QAAM7C,IAAS,IAAI,KAAK,OAAOxO,CAAK,CAAC;AACrC,SAAI,OAAO,MAAMwO,EAAO,QAAA,CAAS,IAAU,OAAOxO,CAAK,IAChDqR,IAAW7C,EAAO,eAAA,IAAmBA,EAAO,mBAAA;AACrD;AAEA,SAAS8C,GAAS,EAAE,OAAAtR,KAAiD;AACnE,MAAI,OAAOA,KAAU,YAAYA,EAAM,SAAS,GAAG;AACjD,UAAM0C,IAAO1C,EAAM,MAAM,GAAG,EAAE,OAAO,OAAO,EAAE,IAAA,KAASA;AACvD,WACE,gBAAAc;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,MAAMd;AAAA,QACN,QAAO;AAAA,QACP,KAAI;AAAA,QACJ,WAAU;AAAA,QACV,SAAS,CAACuR,MAAUA,EAAM,gBAAA;AAAA,QAEzB,UAAA7O;AAAA,MAAA;AAAA,IAAA;AAAA,EAGP;AACA,SAAI,OAAO,OAAS,OAAe1C,aAAiB,OAAa,gBAAAc,EAAAqQ,GAAA,EAAG,YAAM,KAAA,CAAK,sBACvEN,IAAA,EAAW;AACrB;AAEA,SAASW,GAAS,EAAE,OAAAxR,KAAiD;AACnE,MAAIoK;AACJ,MAAI;AACF,IAAAA,IAAO,KAAK,UAAUpK,CAAK,KAAK,OAAOA,CAAK;AAAA,EAC9C,QAAQ;AACN,IAAAoK,IAAO,OAAOpK,CAAK;AAAA,EACrB;AACA,QAAMyR,IAAQrH,EAAK,SAAS,KAAK,GAAGA,EAAK,MAAM,GAAG,EAAE,CAAC,MAAMA;AAC3D,2BACG,QAAA,EAAK,WAAU,wCAAuC,OAAOA,GAC3D,UAAAqH,GACH;AAEJ;AAMO,SAASC,GACdlK,GACAxH,GACA2R,GACiB;AACjB,MAAI3R,KAAU,KAA6B,0BAAQ6Q,IAAA,EAAW;AAC9D,UAAQrJ,EAAM,MAAA;AAAA,IACZ,KAAK;AACH,aAAO,gBAAA1G,EAACgQ,IAAA,EAAY,OAAO9Q,MAAU,GAAA,CAAM;AAAA,IAC7C,KAAK;AACH,aAAOoR,GAASpR,GAAO,EAAK;AAAA,IAC9B,KAAK;AACH,aAAOoR,GAASpR,GAAO,EAAI;AAAA,IAC7B,KAAK;AACH,aAAO,OAAOA,KAAU,YAAY,OAAOA,KAAU,WACjD0Q,GAAU1Q,GAAOwH,EAAM,UAAU,IACjC,OAAOxH,CAAK;AAAA,IAClB,KAAK;AACH,aAAO,gBAAAc,EAACoQ,IAAA,EAAa,OAAAlR,GAAc,OAAO2R,KAAenC,IAAc;AAAA,IACzE,KAAK;AAAA,IACL,KAAK;AACH,aACE,gBAAA1O,EAAC,QAAA,EAAK,WAAU,gBACb,UAAA,OAAOd,KAAU,WAAWA,EAAM,eAAA,IAAmB,OAAOA,CAAK,EAAA,CACpE;AAAA,IAEJ,KAAK;AACH,aAAO,gBAAAc,EAACwQ,MAAS,OAAAtR,GAAc;AAAA,IACjC,KAAK;AACH,aAAO,gBAAAc,EAAC0Q,MAAS,OAAAxR,GAAc;AAAA,IACjC,KAAK;AACH,aAAO,MAAM,QAAQA,CAAK,IAAIA,EAAM,IAAI,CAACuF,MAAS,OAAOA,CAAI,CAAC,EAAE,KAAK,IAAI,IAAI,OAAOvF,CAAK;AAAA,IAC3F,KAAK;AACH,aACE,gBAAAc,EAAC,QAAA,EAAK,WAAU,2BAA0B,OAAO,OAAOd,CAAK,GAC1D,UAAA,OAAOA,CAAK,EAAA,CACf;AAAA,IAEJ;AACE,aAAO,OAAOA,CAAK;AAAA,EAAA;AAEzB;AAGA,SAAS4R,GAAkB9E,GAAkD;AAC3E,SAAO,OAAOA,KAAY,WAAWA,IAAU,MAAMA;AACvD;AAUA,SAAS+E,GACPrK,GACAsK,GACAH,GACc;AACd,QAAMI,IAAaD,KAAA,gBAAAA,EAAU;AAC7B,SAAO;AAAA,IACL,IAAItK,EAAM;AAAA,IACV,YAAY,CAACwK,MAAQ1B,GAAS0B,CAAG,EAAExK,EAAM,IAAI;AAAA,IAC7C,QAAQoK,IAAeE,KAAA,gBAAAA,EAAU,WAAUtK,EAAM,KAAK;AAAA,IACtD,MACEuK,MAAe,SACX,CAACE,MAAQF,EAAWE,EAAI,IAAI,QAAQ,IACpC,CAACA,MAAQP,GAAgBlK,GAAOyK,EAAI,SAAA,GAAYN,CAAW;AAAA,IACjE,gBAAeG,KAAA,gBAAAA,EAAU,aAAY,CAAClB,GAAiB,IAAIpJ,EAAM,IAAI;AAAA,EAAA;AAEzE;AASO,SAAS0K,GAAiBC,GAAiD;AAChF,QAAMC,IAAU,IAAI;AAAA,KACjBD,EAAK,WAAW,CAAA,GAAI,IAAI,CAACE,MAAW,CAACA,EAAO,OAAOA,CAAM,CAAC;AAAA,EAAA,GAEvDC,IAA4B,CAAA,GAC5B,EAAE,QAAAnD,GAAQ,OAAAC,EAAA,IAAUF,GAAqBiD,EAAK,MAAM;AAE1D,aAAW3K,KAAS,CAAC,GAAG2H,GAAQ,GAAGC,CAAK,GAAG;AACzC,UAAM0C,IAAWM,EAAQ,IAAI5K,EAAM,IAAI;AAEvC,IADA4K,EAAQ,OAAO5K,EAAM,IAAI,IACrBsK,KAAA,gBAAAA,EAAU,YAAW,OACrBA,MAAa,WACXtK,EAAM,aAAamJ,GAAsB,IAAInJ,EAAM,IAAI,KACvD2K,EAAK,oBAAoB,MAAQlD,GAAazH,CAAK,MAEzD8K,EAAK,KAAKT,GAAerK,GAAOsK,GAAUK,EAAK,WAAW,CAAC;AAAA,EAC7D;AAEA,aAAW,CAACzP,GAAMoP,CAAQ,KAAKM,GAAS;AACtC,QAAIN,EAAS,WAAW,GAAM;AAC9B,UAAMC,IAAaD,EAAS;AAC5B,IAAAQ,EAAK,KAAK;AAAA,MACR,IAAI5P;AAAA,MACJ,YAAY,CAACsP,MAAQ1B,GAAS0B,CAAG,EAAEtP,CAAI;AAAA,MACvC,QAAQkP,GAAeE,EAAS,UAAUrJ,GAAS/F,CAAI,CAAC;AAAA,MACxD,MACEqP,MAAe,SACX,CAACE,MAAQF,EAAWE,EAAI,IAAI,QAAQ,IACpC,CAACA,MAAQ;AACP,cAAMjS,IAAQiS,EAAI,SAAA;AAClB,eAAOjS,KAAU,yBAA+B6Q,IAAA,CAAA,CAAW,IAAK,OAAO7Q,CAAK;AAAA,MAC9E;AAAA,MACN,eAAe8R,EAAS,YAAY;AAAA,IAAA,CACrC;AAAA,EACH;AAEA,SAAOQ;AACT;AC9IO,SAASC,GAAkB9M,GAAsC;AACtE,SAAO,CAAC,GAAGE,GAAU,SAASF,CAAQ,GAAG,UAAU,UAAU;AAC/D;AAGO,SAAS+M,GAAa/M,GAAkBgN,GAAmC;AAChF,SAAO,CAAC,GAAG9M,GAAU,SAASF,CAAQ,GAAG,UAAU,OAAOgN,CAAK;AACjE;AAEA,SAASC,GAAWjN,GAAkBkN,IAAS,IAAY;AACzD,SAAO,GAAGnN,GAASC,CAAQ,CAAC,UAAUkN,CAAM;AAC9C;AAEA,MAAMC,KAAuC,oBAAI,IAAkB,CAAC,cAAc,YAAY,CAAC;AAGxF,SAASC,GAAiBC,GAAqC;AACpE,SAAOA,MAAQ,UAAaF,GAAU,IAAIE,EAAI,MAAM;AACtD;AAGA,SAASC,GAAaxG,GAAoBhB,GAA0B;AAClE,QAAMyH,IAASzG,EAAS,QAAQ,IAAI,qBAAqB,KAAK,IACxDpC,IAAQ,yBAAyB,KAAK6I,CAAM;AAClD,UAAO7I,KAAA,gBAAAA,EAAQ,OAAMoB;AACvB;AAQA,eAAsB0H,GACpBlN,GACAN,GACAT,GACA4G,IAAuB,OACN;AACjB,QAAM3G,IAAyC,EAAE,GAAGF,GAAeC,CAAM,GAAG,QAAA4G,EAAA;AAC5E,SAAO3G,EAAM,MACb,OAAOA,EAAM;AACb,QAAMsH,IAAW,MAAMxG,EAAO,WAAW,GAAGP,GAASC,CAAQ,CAAC,WAAW,EAAE,OAAAR,EAAA,CAAO,GAC5EiO,IAAO,MAAM3G,EAAS,KAAA,GACtB4G,IAAWJ,GAAaxG,GAAU,GAAG9G,CAAQ,IAAImG,CAAM,EAAE;AAC/D,SAAAwH,GAASF,GAAMC,CAAQ,GAChBA;AACT;AAGO,SAASC,GAASF,GAAYC,GAAwB;AAC3D,MAAI,OAAO,WAAa,OAAe,OAAO,IAAI,mBAAoB,WAAY;AAClF,QAAME,IAAM,IAAI,gBAAgBH,CAAI,GAC9BI,IAAS,SAAS,cAAc,GAAG;AACzC,EAAAA,EAAO,OAAOD,GACdC,EAAO,WAAWH,GAClB,SAAS,KAAK,YAAYG,CAAM,GAChCA,EAAO,MAAA,GACPA,EAAO,OAAA,GACP,IAAI,gBAAgBD,CAAG;AACzB;AAGA,eAAsBE,GACpBxN,GACAN,GACAmG,IAAuB,QACN;AACjB,QAAMW,IAAW,MAAMxG,EAAO,WAAW2M,GAAWjN,GAAU,WAAW,GAAG;AAAA,IAC1E,OAAO,EAAE,QAAAmG,EAAA;AAAA,EAAO,CACjB,GACKsH,IAAO,MAAM3G,EAAS,KAAA,GACtB4G,IAAWJ,GAAaxG,GAAU,GAAG9G,CAAQ,aAAamG,CAAM,EAAE;AACxE,SAAAwH,GAASF,GAAMC,CAAQ,GAChBA;AACT;AAGO,SAASK,GACd/N,GACAzG,GACmC;AACnC,QAAM+G,IAASM,GAAA;AACf,SAAOG,GAA4B;AAAA,IACjC,GAAGxH;AAAA,IACH,UAAUuT,GAAkB9M,CAAQ;AAAA,IACpC,SAAS,CAAC,EAAE,QAAAgB,EAAA,MAAaV,EAAO,QAA2B2M,GAAWjN,CAAQ,GAAG,EAAE,QAAAgB,EAAA,CAAQ;AAAA,EAAA,CAC5F;AACH;AAQO,SAASgN,GACdhO,GACAgN,GACAzT,GAC2B;AAC3B,QAAM+G,IAASM,GAAA,GACTqN,KAAS1U,KAAA,gBAAAA,EAAS,WAAU;AAClC,SAAOwH,GAAoB;AAAA,IACzB,UAAUgM,GAAa/M,GAAUgN,KAAS,EAAE;AAAA,IAC5C,SAASA,MAAU;AAAA,IACnB,SAAS,CAAC,EAAE,QAAAhM,EAAA,MACVV,EAAO,QAAmB2M,GAAWjN,GAAU,GAAG,mBAAmBgN,KAAS,EAAE,CAAC,GAAG,GAAG;AAAA,MACrF,QAAAhM;AAAA,IAAA,CACD;AAAA,IACH,iBAAiB,CAACxB,MAAW4N,GAAiB5N,EAAM,MAAM,IAAI,IAAIyO,IAAS;AAAA,EAAA,CAC5E;AACH;AAoBO,SAASC,GAAiBlO,GAAiC;AAChE,QAAMM,IAASM,GAAA,GACTL,IAAc8B,GAAA,GAEd8L,IAAQ,CAACd,OACb9M,EAAY,aAAawM,GAAa/M,GAAUqN,EAAI,EAAE,GAAGA,CAAG,GACrDA,IAGHe,IAASzL,GAAmD;AAAA,IAChE,YAAY,OAAO,EAAE,MAAA0L,GAAM,SAAAC,QAAc;AACvC,YAAMhN,IAAO,IAAI,SAAA;AACjB,aAAAA,EAAK,OAAO,QAAQ+M,CAAI,GACpBC,MAAY,UAAWhN,EAAK,OAAO,WAAW,KAAK,UAAUgN,CAAO,CAAC,GAClEH;AAAA,QACL,MAAM7N,EAAO,QAAmB2M,GAAWjN,CAAQ,GAAG,EAAE,QAAQ,QAAQ,MAAMsB,EAAA,CAAM;AAAA,MAAA;AAAA,IAExF;AAAA,EAAA,CACD,GAEKiN,IAAU5L,GAAoD;AAAA,IAClE,YAAY,OAAO,EAAE,OAAAqK,GAAO,SAAAsB,QAC1BH;AAAA,MACE,MAAM7N,EAAO;AAAA,QACX2M,GAAWjN,GAAU,GAAG,mBAAmBgN,CAAK,CAAC,WAAW;AAAA,QAC5D;AAAA,UACE,QAAQ;AAAA,UACR,MAAM,EAAE,SAAAsB,EAAA;AAAA,QAAQ;AAAA,MAClB;AAAA,IACF;AAAA,IAEJ,WAAW,MAAM;AACf,MAAK/N,EAAY,kBAAkB,EAAE,UAAUuM,GAAkB9M,CAAQ,GAAG;AAAA,IAC9E;AAAA,EAAA,CACD,GAEKwO,IAAS7L,GAAwC;AAAA,IACrD,YAAY,OAAOqK,MACjBmB;AAAA,MACE,MAAM7N,EAAO;AAAA,QACX2M,GAAWjN,GAAU,GAAG,mBAAmBgN,CAAK,CAAC,UAAU;AAAA,QAC3D;AAAA,UACE,QAAQ;AAAA,UACR,MAAM,CAAA;AAAA,QAAC;AAAA,MACT;AAAA,IACF;AAAA,IAEJ,WAAW,CAACK,MAAQ;AAClB,MAAIA,EAAI,WAAW,UACZ9M,EAAY,kBAAkB,EAAE,UAAUL,GAAU,SAASF,CAAQ,GAAG;AAAA,IAEjF;AAAA,EAAA,CACD;AAED,SAAO,EAAE,QAAAoO,GAAQ,SAAAG,GAAS,QAAAC,EAAA;AAC5B;ACzRA,SAASC,GAAShE,GAAwB;AACxC,MAAIA,aAAiB,OAAO;AAC1B,UAAMM,IAAQN,EAA6B;AAC3C,QAAI,OAAOM,KAAS,YAAYA,MAAS,QAAQ,YAAYA,GAAM;AACjE,YAAMC,IAAUD,EAA8B;AAC9C,UAAI,OAAOC,KAAW,SAAU,QAAOA;AAAA,IACzC;AACA,WAAOP,EAAM;AAAA,EACf;AACA,SAAO;AACT;AAEO,SAASiE,GAAc;AAAA,EAC5B,UAAA1O;AAAA,EACA,QAAAT;AAAA,EACA,SAAAoP;AACF,GAA2C;AACzC,QAAMrO,IAASM,GAAA,GACT,CAACgO,GAAMC,CAAO,IAAI7T,EAAM,SAA8B,IAAI,GAC1D,CAACyP,GAAOqE,CAAQ,IAAI9T,EAAM,SAAwB,IAAI,GAEtD+T,IAAM,CAAC5I,MAA+B;AAC1C,IAAA0I,EAAQ1I,CAAM,GACd2I,EAAS,IAAI,GACbtB,GAAuBlN,GAAQN,GAAUT,GAAQ4G,CAAM,EACpD,MAAM,CAAC6I,MAAqBF,EAASL,GAASO,CAAO,CAAC,CAAC,EACvD,QAAQ,MAAMH,EAAQ,IAAI,CAAC;AAAA,EAChC;AAEA,SACE,gBAAA1S,EAAC,OAAA,EAAI,WAAU,2BAA0B,eAAY,yBAClD,UAAA;AAAA,IAAAwS,EAAQ,IAAI,CAACxI,MACZ,gBAAA9K;AAAA,MAACN;AAAA,MAAA;AAAA,QAEC,MAAK;AAAA,QACL,SAAQ;AAAA,QACR,MAAK;AAAA,QACL,UAAU6T,MAAS;AAAA,QACnB,SAAS,MAAMG,EAAI5I,CAAM;AAAA,QACzB,cAAY,aAAaA,EAAO,YAAA,CAAa;AAAA,QAE5C,gBAASA,IAAS,eAAe,UAAUA,EAAO,aAAa;AAAA,MAAA;AAAA,MAR3DA;AAAA,IAAA,CAUR;AAAA,IACAsE,MAAU,QACT,gBAAApP,EAAC,QAAA,EAAK,MAAK,SAAQ,WAAU,4BAC1B,UAAAoP,EAAA,CACH;AAAA,EAAA,GAEJ;AAEJ;ACnDO,SAASwE,GACdjP,GACA9C,GACAqC,GACAhG,GACmB;AACnB,QAAM+G,IAASM,GAAA;AACf,SAAOG,GAAY;AAAA,IACjB,GAAGxH;AAAA,IACH,UAAU2G,GAAU,OAAOF,GAAU9C,GAAIqC,CAAM;AAAA,IAC/C,SAAS,CAAC,EAAE,QAAAyB,EAAA,MACVV,EAAO,QAAWL,GAAWD,GAAU9C,CAAE,GAAG,EAAE,OAAOuC,GAAeF,CAAM,GAAG,QAAAyB,GAAQ;AAAA,EAAA,CACxF;AACH;AC9BO,SAASkO,GAAqB3U,GAAU4U,GAAoB;AACjE,QAAM,CAACC,GAAWC,CAAY,IAAIrU,EAAM,SAAST,CAAK;AAEtD,SAAAS,EAAM,UAAU,MAAM;AACpB,QAAImU,KAAW,GAAG;AAChB,MAAAE,EAAa9U,CAAK;AAClB;AAAA,IACF;AACA,UAAM+U,IAAQ,WAAW,MAAMD,EAAa9U,CAAK,GAAG4U,CAAO;AAC3D,WAAO,MAAM,aAAaG,CAAK;AAAA,EACjC,GAAG,CAAC/U,GAAO4U,CAAO,CAAC,GAEZC;AACT;ACLAhW,GAAsB,gBAAgB,gBAAgB;AA2BtD,SAASmW,GAAKzP,GAA2C;AACvD,QAAMvF,IAAQuF,EAAK;AACnB,SAAI,OAAOvF,KAAU,YAAY,OAAOA,KAAU,WAAiBA,IAC5D,OAAOA,CAAK;AACrB;AAEA,SAASiV,GAAYC,GAAmBpF,GAAuB;AAC7D,SAAO,GAAGoF,CAAS,WAAWpF,CAAK;AACrC;AAEA,SAASqF,GAAM1V,GAA+D;AAC5E,SACE,gBAAAmC;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,SAAQ;AAAA,MACR,MAAK;AAAA,MACL,QAAO;AAAA,MACP,aAAa;AAAA,MACb,eAAc;AAAA,MACd,gBAAe;AAAA,MACf,eAAY;AAAA,MACZ,WAAW;AAAA,MACV,GAAGnC;AAAA,MAEJ,UAAA;AAAA,QAAA,gBAAAqB,EAAC,QAAA,EAAK,IAAG,MAAK,IAAG,KAAI,IAAG,KAAI,IAAG,KAAA,CAAK;AAAA,QACpC,gBAAAA,EAAC,UAAK,IAAG,KAAI,IAAG,KAAI,IAAG,MAAK,IAAG,KAAA,CAAK;AAAA,MAAA;AAAA,IAAA;AAAA,EAAA;AAG1C;AAcO,SAASsU,GAAe3V,GAAgD;;AAC7E,QAAM;AAAA,IACJ,UAAAgG;AAAA,IACA,OAAAzF;AAAA,IACA,UAAAqV;AAAA,IACA,UAAAC,IAAW;AAAA,IACX,UAAA7S,IAAW;AAAA,IACX,aAAAH;AAAA,IACA,gBAAAiT;AAAA,IACA,QAAAC;AAAA,IACA,IAAA7S;AAAA,IACA,WAAAjD;AAAA,IACA,UAAA2Q;AAAA,IACA,WAAA9N,IAAY;AAAA,IACZ,kBAAAkT,IAAmB;AAAA,EAAA,IACjBhW,GAEEiW,IAAUjV,EAAM,MAAA,GAChBkV,IAAUhT,KAAM+S,GAChBR,IAAY,GAAGS,CAAO,YAEtB,CAACC,GAAMC,CAAO,IAAIpV,EAAM,SAAS,EAAK,GACtC,CAACqV,GAAWC,CAAY,IAAItV,EAAM,SAAS,EAAE,GAC7C,CAACuV,GAAaC,CAAc,IAAIxV,EAAM,SAAS,CAAC,GAChD,CAACyV,GAAOC,CAAQ,IAAI1V,EAAM,SAA6C,CAAA,CAAE,GAEzE2V,IAAU3V,EAAM,OAAuB,IAAI,GAC3C4V,IAAa5V,EAAM,OAAuB,IAAI,GAC9C6V,IAAW7V,EAAM,OAAyB,IAAI,GAE9C8V,IAAkB5B,GAAkBmB,EAAU,KAAA,GAAQL,CAAgB,GAEtEe,IAA2C/V,EAAM,QAAQ,MACzDT,KAAS,OAAa,CAAA,IACnB,MAAM,QAAQA,CAAK,IAAIA,IAAQ,CAACA,CAAwB,GAC9D,CAACA,CAAK,CAAC,GAEJyW,IAAiChW,EAAM,QAAQ,MAAM;AACzD,UAAMuE,IAA6B,EAAE,MAAM,EAAA;AAC3C,WAAIqL,MAAa,WAAWrL,EAAO,WAAWqL,IAC1CkG,MAAoB,OAAIvR,EAAO,SAASuR,IACxCf,MAAW,WAAWxQ,EAAO,UAAUwQ,IACpCxQ;AAAA,EACT,GAAG,CAACqL,GAAUkG,GAAiBf,CAAM,CAAC,GAEhCkB,IAAYnQ,GAAgBd,GAAUgR,GAAY,EAAE,SAASb,KAAQ,CAACnT,GAAU,GAChFkK,MAAyCjO,KAAAgY,EAAU,SAAV,gBAAAhY,GAAgB,YAAW,CAAA;AAG1E,EAAA+B,EAAM,UAAU,MAAM;;AACpB,UAAMkW,KAAOjY,IAAAgY,EAAU,SAAV,gBAAAhY,EAAgB;AAC7B,IAAIiY,MAAS,UAAaA,EAAK,WAAW,KAC1CR,EAAS,CAACjX,MAAa;AACrB,UAAI0X,KAAU;AACd,YAAMzT,KAAO,EAAE,GAAGjE,EAAA;AAClB,iBAAW8S,MAAO2E,GAAM;AACtB,cAAMtW,KAAM,OAAO2U,GAAKhD,EAAG,CAAC;AAC5B,QAAM3R,MAAO8C,OACXA,GAAK9C,EAAG,IAAI2R,IACZ4E,KAAU;AAAA,MAEd;AACA,aAAOA,KAAUzT,KAAOjE;AAAA,IAC1B,CAAC;AAAA,EACH,GAAG,CAACwX,EAAU,IAAI,CAAC;AAInB,QAAMG,IAAeL,EAAS,KAAK,CAACM,MAAQ,EAAE,OAAOA,CAAG,KAAKZ,EAAM,GAC7Da,KAAYrC,GAAgBjP,GAAUoR,KAAgB,IAAI,QAAW;AAAA,IACzE,SAASA,MAAiB,UAAa,CAACpU;AAAA,IACxC,OAAO;AAAA,EAAA,CACR,GACKuU,KAAeD,GAAU,MACzBE,KAAeF,GAAU;AAE/B,EAAAtW,EAAM,UAAU,MAAM;AACpB,IAAIoW,MAAiB,WACjBG,OAAiB,SACnBb,EAAS,CAACjX,OAAc,EAAE,GAAGA,GAAU,CAAC,OAAO2X,CAAY,CAAC,GAAGG,GAAA,EAAe,IACrEC,MAAgB,QAGzBd,EAAS,CAACjX,OAAc,EAAE,GAAGA,GAAU,CAAC,OAAO2X,CAAY,CAAC,GAAG,EAAE,IAAIA,EAAA,IAAiB;AAAA,EAE1F,GAAG,CAACA,GAAcG,IAAcC,EAAY,CAAC;AAE7C,QAAMC,KAAUzW,EAAM;AAAA,IACpB,CAAC8E,MACCgQ,MAAmB,SAAYA,EAAehQ,CAAI,IAAIiK,GAAajK,CAAI;AAAA,IACzE,CAACgQ,CAAc;AAAA,EAAA,GAGX4B,KAAS1W,EAAM;AAAA,IACnB,CAACqW,MAAiC;AAChC,YAAMvR,IAAO2Q,EAAM,OAAOY,CAAG,CAAC;AAC9B,UAAIvR,MAAS,OAAW,QAAO,OAAOuR,CAAG;AACzC,YAAM7F,IAAQsE,MAAmB,SAAYA,EAAehQ,CAAI,IAAIiK,GAAajK,CAAI;AACrF,aAAI,OAAO0L,KAAU,WAAiBA,IAClC,OAAOA,KAAU,WAAiB,OAAOA,CAAK,IAC3CzB,GAAajK,CAAI;AAAA,IAC1B;AAAA,IACA,CAAC2Q,GAAOX,CAAc;AAAA,EAAA,GAGlB6B,KAAc3W,EAAM,YAAY,MAAM;AAC1C,IAAIgC,MACJsT,EAAa,EAAE,GACfE,EAAe,CAAC,GAChBJ,EAAQ,EAAI;AAAA,EACd,GAAG,CAACpT,CAAQ,CAAC,GAEP4U,IAAe5W,EAAM,YAAY,MAAM;AAC3C,IAAAoV,EAAQ,EAAK,GACbE,EAAa,EAAE;AAAA,EACjB,GAAG,CAAA,CAAE,GAECuB,KAAa7W,EAAM;AAAA,IACvB,CAAC8W,MACCf,EAAS,KAAK,CAACM,MAAQ,OAAOA,CAAG,MAAM,OAAOS,CAAQ,CAAC;AAAA,IACzD,CAACf,CAAQ;AAAA,EAAA,GAGLgB,KAAe,CAACjS,MAAmC;AACvD,UAAMgS,IAAWvC,GAAKzP,CAAI;AAI1B,QAHA4Q;AAAA,MAAS,CAACjX,MACR,OAAOqY,CAAQ,KAAKrY,IAAWA,IAAW,EAAE,GAAGA,GAAU,CAAC,OAAOqY,CAAQ,CAAC,GAAGhS,EAAA;AAAA,IAAK,GAEhF+P,GAAU;AACZ,YAAMnS,IAAOmU,GAAWC,CAAQ,IAC5Bf,EAAS,OAAO,CAACM,OAAQ,OAAOA,EAAG,MAAM,OAAOS,CAAQ,CAAC,IACzD,CAAC,GAAGf,GAAUe,CAAQ;AAC1B,MAAAlC,EAAS,CAAC,GAAGlS,CAAI,CAAC;AAAA,IACpB;AACE,MAAAkS,EAASkC,CAAQ,GACjBF,EAAA;AAAA,EAEJ,GAEMI,KAAiB,MAAY;;AACjC,IAAApC,EAAS,IAAI,GACbU,EAAa,EAAE,IACfrX,IAAA4X,EAAS,YAAT,QAAA5X,EAAkB;AAAA,EACpB,GAEMgZ,IAAa,CAACpC,KAAYkB,EAAS,SAAS,IAAIW,GAAOX,EAAS,CAAC,CAAC,IAAI,IACtEmB,IAAa/B,IAAOE,IAAYR,IAAW,KAAKoC,GAEhDE,KAAoB,CAACrG,MAAqD;AAC9E,UAAMpO,IAAOoO,EAAM,OAAO;AAC1B,QAAI,CAACqE,GAAM;AACT,UAAInT,EAAU;AACd,MAAAwT,EAAe,CAAC,GAChBJ,EAAQ,EAAI,GAGZE;AAAA,QACE2B,MAAe,MAAMvU,EAAK,WAAWuU,CAAU,IAAIvU,EAAK,MAAMuU,EAAW,MAAM,IAAIvU;AAAA,MAAA;AAErF;AAAA,IACF;AACA,IAAA8S,EAAe,CAAC,GAChBF,EAAa5S,CAAI;AAAA,EACnB,GAEM0U,IAAgB,CAACtG,MAAuD;AAC5E,QAAI,CAAA9O;AACJ,cAAQ8O,EAAM,KAAA;AAAA,QACZ,KAAK;AACH,UAAAA,EAAM,eAAA,GACDqE,IACIjJ,EAAQ,SAAS,KAAGsJ,EAAe,CAACnG,OAAWA,IAAQ,KAAKnD,EAAQ,MAAM,IADxEyK,GAAA;AAEX;AAAA,QACF,KAAK;AACH,UAAA7F,EAAM,eAAA,GACDqE,IACIjJ,EAAQ,SAAS,KACxBsJ,EAAe,CAACnG,OAAWA,IAAQ,IAAInD,EAAQ,UAAUA,EAAQ,MAAM,IAF9DyK,GAAA;AAIX;AAAA,QACF,KAAK;AACH,cAAIxB,GAAM;AACR,YAAArE,EAAM,eAAA;AACN,kBAAMhM,IAAOoH,EAAQqJ,CAAW;AAChC,YAAIzQ,MAAS,UAAWiS,GAAajS,CAAI;AAAA,UAC3C;AACA;AAAA,QACF,KAAK;AACH,UAAIqQ,MACFrE,EAAM,eAAA,GACNA,EAAM,gBAAA,GACN8F,EAAA;AAEF;AAAA,QACF,KAAK;AACH,UAAI/B,KAAYQ,MAAc,MAAMU,EAAS,SAAS,KACpDnB,EAAS,CAAC,GAAGmB,EAAS,MAAM,GAAG,EAAE,CAAC,CAAC;AAErC;AAAA,QACF,KAAK;AACH,UAAIZ,KAAMyB,EAAA;AACV;AAAA,MAEA;AAAA,EAEN,GAEMS,IAAa,CAACvG,MAAoD;;AACtE,UAAMpO,IAAOoO,EAAM;AACnB,IACEpO,MAAS,WACRzE,IAAA0X,EAAQ,YAAR,gBAAA1X,EAAiB,SAASyE,QAAU,QAAQxE,KAAA0X,EAAW,YAAX,gBAAA1X,GAAoB,SAASwE,QAAU,OAIlFyS,KAAMyB,EAAA;AAAA,EACZ,GAEMU,KACArB,EAAU,YACL,gBAAA5V,EAAC,OAAA,EAAI,WAAU,6CAA4C,UAAA,YAAQ,IAExE4V,EAAU,SAAS,yBAElB,OAAA,EAAI,MAAK,SAAQ,WAAU,wCAAuC,UAAA,2BAEnE,IAGA/J,EAAQ,WAAW,IACd,gBAAA7L,EAAC,OAAA,EAAI,WAAU,6CAA4C,UAAA,cAAU,IAEvE6L,EAAQ,IAAI,CAACpH,GAAMuK,MAAU;AAClC,UAAMyH,IAAWvC,GAAKzP,CAAI,GACpByS,KAAiBV,GAAWC,CAAQ;AAC1C,WACE,gBAAA3V;AAAA,MAAC;AAAA,MAAA;AAAA,QAEC,IAAIqT,GAAYC,GAAWpF,CAAK;AAAA,QAChC,MAAK;AAAA,QACL,iBAAekI;AAAA,QACf,oBAAkBlI,MAAUkG,IAAc,SAAS;AAAA,QACnD,WAAU;AAAA,QACV,aAAa,CAACzE,OAAUA,GAAM,eAAA;AAAA,QAC9B,aAAa,MAAM0E,EAAenG,CAAK;AAAA,QACvC,SAAS,MAAM0H,GAAajS,CAAI;AAAA,QAEhC,UAAA;AAAA,UAAA,gBAAAzE,EAAC,QAAA,EAAK,WAAU,YAAY,UAAAoW,GAAQ3R,CAAI,GAAE;AAAA,UACzCyS,KAAiB,gBAAAlX,EAACI,IAAA,EAAU,WAAU,oBAAmB,IAAK;AAAA,QAAA;AAAA,MAAA;AAAA,MAX1D,OAAOqW,CAAQ;AAAA,IAAA;AAAA,EAc1B,CAAC;AAGH,SACE,gBAAA3V;AAAA,IAACqW,GAAiB;AAAA,IAAjB;AAAA,MACC,MAAArC;AAAA,MACA,cAAc,CAACzS,MAAS;AACtB,QAAKA,KAAMkU,EAAA;AAAA,MACb;AAAA,MACA,OAAO;AAAA,MAEP,UAAA;AAAA,QAAA,gBAAAvW,EAACmX,GAAiB,QAAjB,EAAwB,SAAO,IAC9B,UAAA,gBAAArW;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,KAAKwU;AAAA,YACL,SAAS,MAAM;;AACb,cAAI3T,OACJ/D,IAAA4X,EAAS,YAAT,QAAA5X,EAAkB,SACbkX,KAAMwB,GAAA;AAAA,YACb;AAAA,YACA,WAAWjZ;AAAA,cACT;AAAA,cACAsE,KAAY;AAAA,cACZ/C;AAAA,YAAA;AAAA,YAGD,UAAA;AAAA,cAAA4V,IACGkB,EAAS,IAAI,CAACM,MAAQ;AACpB,sBAAMoB,IAAWf,GAAOL,CAAG;AAC3B,uBACE,gBAAAlV;AAAA,kBAAC;AAAA,kBAAA;AAAA,oBAEC,WAAU;AAAA,oBAET,UAAA;AAAA,sBAAAsW;AAAA,sBACCzV,IAYE,OAXF,gBAAA3B;AAAA,wBAAC;AAAA,wBAAA;AAAA,0BACC,MAAK;AAAA,0BACL,cAAY,UAAUoX,CAAQ;AAAA,0BAC9B,WAAU;AAAA,0BACV,SAAS,CAAC3G,MAAU;AAClB,4BAAAA,EAAM,gBAAA,GACN8D,EAAS,CAAC,GAAGmB,EAAS,OAAO,CAAC2B,OAAU,OAAOA,EAAK,MAAM,OAAOrB,CAAG,CAAC,CAAC,CAAC;AAAA,0BACzE;AAAA,0BAEA,UAAA,gBAAAhW,EAACqU,IAAA,EAAM,WAAU,UAAA,CAAU;AAAA,wBAAA;AAAA,sBAAA;AAAA,oBAE3B;AAAA,kBAAA;AAAA,kBAhBC,OAAO2B,CAAG;AAAA,gBAAA;AAAA,cAmBrB,CAAC,IACD;AAAA,cACJ,gBAAAhW;AAAA,gBAAC;AAAA,gBAAA;AAAA,kBACC,KAAKwV;AAAA,kBACL,IAAIX;AAAA,kBACJ,MAAK;AAAA,kBACL,MAAK;AAAA,kBACL,iBAAeC;AAAA,kBACf,iBAAeV;AAAA,kBACf,qBAAkB;AAAA,kBAClB,yBACEU,KAAQjJ,EAAQ,SAAS,IAAIsI,GAAYC,GAAWc,CAAW,IAAI;AAAA,kBAErE,cAAYvW,EAAM,YAAY;AAAA,kBAC9B,mBAAiBA,EAAM,iBAAiB;AAAA,kBACxC,cAAa;AAAA,kBACb,UAAAgD;AAAA,kBACA,aAAa+T,EAAS,WAAW,IAAIlU,IAAc;AAAA,kBACnD,OAAOqV;AAAA,kBACP,UAAUC;AAAA,kBACV,WAAWC;AAAA,kBACX,SAAS,MAAM;AACb,oBAAKjC,KAAMwB,GAAA;AAAA,kBACb;AAAA,kBACA,QAAQU;AAAA,kBACR,WAAU;AAAA,gBAAA;AAAA,cAAA;AAAA,cAEXvV,KAAaiU,EAAS,SAAS,KAAK,CAAC/T,IACpC,gBAAA3B;AAAA,gBAAC;AAAA,gBAAA;AAAA,kBACC,MAAK;AAAA,kBACL,cAAW;AAAA,kBACX,WAAU;AAAA,kBACV,aAAa,CAACyQ,MAAUA,EAAM,eAAA;AAAA,kBAC9B,SAAS,CAACA,MAAU;AAClB,oBAAAA,EAAM,gBAAA,GACNkG,GAAA;AAAA,kBACF;AAAA,kBAEA,UAAA,gBAAA3W,EAACqU,IAAA,EAAM,WAAU,UAAA,CAAU;AAAA,gBAAA;AAAA,cAAA,IAE3B;AAAA,cACJ,gBAAArU,EAACK,IAAA,EAAgB,WAAU,8BAAA,CAA8B;AAAA,YAAA;AAAA,UAAA;AAAA,QAAA,GAE7D;AAAA,QACA,gBAAAL,EAACmX,GAAiB,QAAjB,EACC,UAAA,gBAAAnX;AAAA,UAACmX,GAAiB;AAAA,UAAjB;AAAA,YACC,KAAK5B;AAAA,YACL,MAAK;AAAA,YACL,OAAM;AAAA,YACN,YAAY;AAAA,YACZ,iBAAiB,CAAC9E,MAAUA,EAAM,eAAA;AAAA,YAClC,kBAAkB,CAACA,MAAUA,EAAM,eAAA;AAAA,YACnC,mBAAmB,CAACA,MAAU;AAC5B,oBAAMtI,IAASsI,EAAM;AACrB,cACE6E,EAAQ,YAAY,QACpBnN,aAAkB,QAClBmN,EAAQ,QAAQ,SAASnN,CAAM,KAE/BsI,EAAM,eAAA;AAAA,YAEV;AAAA,YACA,WAAU;AAAA,YAEV,UAAA,gBAAAzQ,EAAC,SAAI,MAAK,WAAU,IAAIoU,GAAW,wBAAsBI,KAAY,QAClE,UAAAyC,GAAA,CACH;AAAA,UAAA;AAAA,QAAA,EACF,CACF;AAAA,MAAA;AAAA,IAAA;AAAA,EAAA;AAGN;AChaA,SAASK,GAAcpY,GAAmC;AACxD,SAAIA,KAAU,QAA+B,OAAOA,KAAU,WAAiB,OACxE,OAAOA,CAAK;AACrB;AAEA,SAASqY,GACPrY,GACyD;AACzD,SAAIA,KAAU,QAA+B,OAAOA,KAAU,YAAkB,OAC5E,MAAM,QAAQA,CAAK,IACdA,EAAM;AAAA,IACX,CAACuF,MAAkC,OAAOA,KAAS,YAAY,OAAOA,KAAS;AAAA,EAAA,IAG5EvF;AACT;AAEA,SAASsY,GAAW;AAAA,EAClB,OAAA9Q;AAAA,EACA,OAAAxH;AAAA,EACA,gBAAAuY;AACF,GAIuB;AACrB,QAAMvZ,KAAWwI,EAAM,cAAc,CAAA,GAAI,IAAI,CAACsC,OAAY;AAAA,IACxD,OAAO,OAAOA,CAAM;AAAA,IACpB,OAAO4G,GAAU5G,GAAQtC,EAAM,UAAU;AAAA,EAAA,EACzC;AACF,SACE,gBAAA1G;AAAA,IAACsB;AAAA,IAAA;AAAA,MACC,cAAYoF,EAAM;AAAA,MAClB,WAAU;AAAA,MACV,OAAO4Q,GAAcpY,CAAK;AAAA,MAC1B,SAAAhB;AAAA,MACA,aAAawI,EAAM;AAAA,MACnB,WAAS;AAAA,MACT,YAAW;AAAA,MACX,eAAe,CAACrE,MAAS;AACvB,YAAIA,MAAS,MAAM;AACjB,UAAAoV,EAAe/Q,GAAO,IAAI;AAC1B;AAAA,QACF;AAEA,cAAMsC,KAAUtC,EAAM,cAAc,CAAA,GAAI,KAAK,CAACiG,MAAc,OAAOA,CAAS,MAAMtK,CAAI;AACtF,QAAAoV,EAAe/Q,GAAOsC,KAAU3G,CAAI;AAAA,MACtC;AAAA,IAAA;AAAA,EAAA;AAGN;AAEA,SAASqV,GAAc;AAAA,EACrB,OAAAhR;AAAA,EACA,OAAAxH;AAAA,EACA,gBAAAuY;AACF,GAIuB;AACrB,SACE,gBAAAzX;AAAA,IAACsB;AAAA,IAAA;AAAA,MACC,cAAYoF,EAAM;AAAA,MAClB,WAAU;AAAA,MACV,OAAO,OAAOxH,KAAU,YAAY,OAAOA,CAAK,IAAI;AAAA,MACpD,SAAS;AAAA,QACP,EAAE,OAAO,QAAQ,OAAO,MAAA;AAAA,QACxB,EAAE,OAAO,SAAS,OAAO,KAAA;AAAA,MAAK;AAAA,MAEhC,aAAawH,EAAM;AAAA,MACnB,WAAS;AAAA,MACT,YAAW;AAAA,MACX,eAAe,CAACrE,MAASoV,EAAe/Q,GAAOrE,MAAS,OAAO,OAAOA,MAAS,MAAM;AAAA,IAAA;AAAA,EAAA;AAG3F;AAGO,SAASsV,GAAUhZ,GAA2C;AACnE,QAAM;AAAA,IACJ,eAAAiZ;AAAA,IACA,aAAAC;AAAA,IACA,gBAAAC;AAAA,IACA,mBAAAC,IAAoB;AAAA,IACpB,cAAAC;AAAA,IACA,QAAAjS;AAAA,IACA,gBAAA0R;AAAA,IACA,WAAA7Y;AAAA,EAAA,IACED;AAEJ,2BACG,OAAA,EAAI,WAAWtB,EAAG,qCAAqCuB,CAAS,GAC9D,UAAA;AAAA,IAAAgZ,KACC,gBAAA5X;AAAA,MAACC;AAAA,MAAA;AAAA,QACC,MAAK;AAAA,QACL,cAAW;AAAA,QACX,aAAa8X;AAAA,QACb,OAAOF;AAAA,QACP,UAAU,CAACpH,MAAUqH,EAAerH,EAAM,OAAO,KAAK;AAAA,QACtD,WAAU;AAAA,MAAA;AAAA,IAAA;AAAA,IAGbuH,EAAa,IAAI,CAACtR,MAAU;AAC3B,YAAMxH,IAAQ6G,EAAOW,EAAM,IAAI;AAC/B,aAAIA,EAAM,SAAS,SAEf,gBAAA1G;AAAA,QAACwX;AAAA,QAAA;AAAA,UAEC,OAAA9Q;AAAA,UACA,OAAAxH;AAAA,UACA,gBAAAuY;AAAA,QAAA;AAAA,QAHK/Q,EAAM;AAAA,MAAA,IAObA,EAAM,SAAS,YAEf,gBAAA1G;AAAA,QAAC0X;AAAA,QAAA;AAAA,UAEC,OAAAhR;AAAA,UACA,OAAAxH;AAAA,UACA,gBAAAuY;AAAA,QAAA;AAAA,QAHK/Q,EAAM;AAAA,MAAA,IAObA,EAAM,SAAS,cAAcA,EAAM,aAAa,SAEhD,gBAAA1G,EAAC,OAAA,EAAqB,WAAU,YAC9B,UAAA,gBAAAA;AAAA,QAACsU;AAAA,QAAA;AAAA,UACC,UAAU5N,EAAM,SAAS;AAAA,UACzB,UAAUA,EAAM,SAAS;AAAA,UACzB,OAAO6Q,GAAgBrY,CAAK;AAAA,UAC5B,aAAawH,EAAM;AAAA,UACnB,UAAU,CAACrE,MAASoV,EAAe/Q,GAAOrE,CAAI;AAAA,QAAA;AAAA,MAAA,EAChD,GAPQqE,EAAM,IAQhB,IAGG;AAAA,IACT,CAAC;AAAA,EAAA,GACH;AAEJ;AC1JO,SAASuR,GAAmBtZ,GAAoD;AACrF,QAAM,EAAE,MAAAuZ,GAAM,WAAAC,GAAW,YAAAC,GAAY,aAAAC,GAAa,SAAAC,GAAS,cAAAC,GAAc,WAAA3Z,MAAcD;AACvF,SACE,gBAAAmC;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,cAAW;AAAA,MACX,WAAWzD,EAAG,qDAAqDuB,CAAS;AAAA,MAE5E,UAAA;AAAA,QAAA,gBAAAkC,EAAC,KAAA,EAAE,WAAU,iCAAgC,UAAA;AAAA,UAAA;AAAA,UACrCoX;AAAA,UAAK;AAAA,UAAKC;AAAA,UAAU;AAAA,UAAIC;AAAA,UAAW;AAAA,UAAEA,MAAe,IAAI,SAAS;AAAA,QAAA,GACzE;AAAA,QACA,gBAAAtX,EAAC,OAAA,EAAI,WAAU,2BACb,UAAA;AAAA,UAAA,gBAAAd;AAAA,YAACN;AAAA,YAAA;AAAA,cACC,SAAQ;AAAA,cACR,MAAK;AAAA,cACL,UAAU,CAAC2Y;AAAA,cACX,SAAS,MAAME,EAAa,KAAK,IAAI,GAAGL,IAAO,CAAC,CAAC;AAAA,cAClD,UAAA;AAAA,YAAA;AAAA,UAAA;AAAA,UAGD,gBAAAlY;AAAA,YAACN;AAAA,YAAA;AAAA,cACC,SAAQ;AAAA,cACR,MAAK;AAAA,cACL,UAAU,CAAC4Y;AAAA,cACX,SAAS,MAAMC,EAAaL,IAAO,CAAC;AAAA,cACrC,UAAA;AAAA,YAAA;AAAA,UAAA;AAAA,QAED,EAAA,CACF;AAAA,MAAA;AAAA,IAAA;AAAA,EAAA;AAGN;AC9CO,SAASrE,GAAqB3U,GAAU4U,GAAoB;AACjE,QAAM,CAACC,GAAWC,CAAY,IAAIrU,EAAM,SAAST,CAAK;AACtD,SAAAS,EAAM,UAAU,MAAM;AACpB,UAAMsU,IAAQ,WAAW,MAAMD,EAAa9U,CAAK,GAAG4U,CAAO;AAC3D,WAAO,MAAM,aAAaG,CAAK;AAAA,EACjC,GAAG,CAAC/U,GAAO4U,CAAO,CAAC,GACZC;AACT;ACmDAhW,GAAsB,cAAc,eAAe;AAI5C,MAAMya,KAAoB,IAC3BC,KAAqB,KACrBC,KAAsB;AAmE5B,SAASC,KAAmC;AAC1C,SAAO;AAAA,IACL,IAAI;AAAA,IACJ,eAAe;AAAA,IACf,QAAQ,CAAC,EAAE,OAAAC,EAAA,MACT,gBAAA5Y;AAAA,MAACsC;AAAA,MAAA;AAAA,QACC,cAAW;AAAA,QACX,SACEsW,EAAM,6BACF,KACAA,EAAM,0BAAA,IACJ,kBACA;AAAA,QAER,iBAAiB,CAACjV,MAAYiV,EAAM,0BAA0BjV,MAAY,EAAI;AAAA,MAAA;AAAA,IAAA;AAAA,IAGlF,MAAM,CAAC,EAAE,KAAAuN,EAAA,MACP,gBAAAlR,EAAC,OAAA,EAAI,WAAU,qBAAoB,SAAS,CAACyQ,MAAUA,EAAM,mBAC3D,UAAA,gBAAAzQ;AAAA,MAACsC;AAAA,MAAA;AAAA,QACC,cAAW;AAAA,QACX,SAAS4O,EAAI,cAAA;AAAA,QACb,iBAAiB,CAACvN,MAAYuN,EAAI,eAAevN,MAAY,EAAI;AAAA,MAAA;AAAA,IAAA,EACnE,CACF;AAAA,EAAA;AAGN;AAEA,SAASkV,GAAgBla,GAIF;AACrB,QAAMma,IAAY/R,GAAqBpI,EAAM,QAAQ,GAC/CwR,KAASxR,EAAM,eAAe+P,IAAc/P,EAAM,GAAG;AAC3D,SACE,gBAAAqB;AAAA,IAACN;AAAA,IAAA;AAAA,MACC,SAAQ;AAAA,MACR,MAAK;AAAA,MACL,WAAU;AAAA,MACV,UAAUoZ,EAAU,OAAO;AAAA,MAC3B,SAAS,MAAM;AACb,cAAMjX,IAAKlD,EAAM,IAAI;AACrB,YAAIkD,KAAO,KAA0B;AAKrC,SAHE,OAAO,SAAW,OAClB,OAAO,OAAO,WAAY,cAC1B,OAAO,QAAQ,WAAWsO,CAAK,2BAA2B,MAC7C2I,EAAU,OAAO,OAAOjX,CAAqB;AAAA,MAC9D;AAAA,MACD,UAAA;AAAA,IAAA;AAAA,EAAA;AAIL;AAEA,SAASkX,GAAiB7a,GAMT;AACf,QAAM,EAAE,UAAAyG,GAAU,YAAAqU,GAAY,QAAAC,GAAQ,cAAAC,GAAc,aAAArI,MAAgB3S;AACpE,SAAO;AAAA,IACL,IAAI;AAAA,IACJ,eAAe;AAAA,IACf,QAAQ,MAAM,gBAAA8B,EAAC,QAAA,EAAK,WAAU,WAAU,UAAA,WAAO;AAAA,IAC/C,MAAM,CAAC,EAAE,KAAAkR,EAAA,MACP,gBAAApQ;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,WAAU;AAAA,QACV,SAAS,CAAC2P,MAAUA,EAAM,gBAAA;AAAA,QAEzB,UAAA;AAAA,UAAAwI,MAAW,UACV,gBAAAjZ,EAACN,GAAA,EAAO,SAAQ,SAAQ,MAAK,MAAK,SAAS,MAAMuZ,EAAO/H,EAAI,QAAQ,GAAG,UAAA,QAEvE;AAAA,UAED8H,KAAA,gBAAAA,EAAa9H,EAAI;AAAA,UACjBgI,MAAiB,MAChB,gBAAAlZ;AAAA,YAAC6Y;AAAA,YAAA;AAAA,cACC,UAAAlU;AAAA,cACA,KAAK6K,GAAS0B,EAAI,QAAQ;AAAA,cAC1B,aAAAL;AAAA,YAAA;AAAA,UAAA;AAAA,QACF;AAAA,MAAA;AAAA,IAAA;AAAA,EAEJ;AAGN;AAIA,SAASsI,GAAc,EAAE,MAAAtD,IAAO,KAA4C;AAC1E,SACE,gBAAA/U;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,MAAK;AAAA,MACL,aAAU;AAAA,MACV,WAAU;AAAA,MAEV,UAAA;AAAA,QAAA,gBAAAd,EAAC,QAAA,EAAK,WAAU,WAAU,UAAA,YAAQ;AAAA,QAClC,gBAAAA,EAAC8D,IAAA,EAAS,WAAU,YAAA,CAAY;AAAA,QAC/B,MAAM,KAAK,EAAE,QAAQ+R,KAAQ,CAACuD,GAAGpK,MAChC,gBAAAhP,EAAC8D,IAAA,EAAqB,WAAU,aAAA,GAAjBkL,CAA8B,CAC9C;AAAA,MAAA;AAAA,IAAA;AAAA,EAAA;AAGP;AAEA,SAASqK,GAAW1a,GAAqE;AACvF,SACE,gBAAAmC;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,MAAK;AAAA,MACL,WAAU;AAAA,MAEV,UAAA;AAAA,QAAA,gBAAAd,EAAC,OAAE,WAAU,wCAAwC,UAAAyP,GAAa9Q,EAAM,KAAK,GAAE;AAAA,QAC9EA,EAAM,YAAY,UACjB,gBAAAqB,EAACN,GAAA,EAAO,SAAQ,WAAU,MAAK,MAAK,SAASf,EAAM,SAAS,UAAA,QAAA,CAE5D;AAAA,MAAA;AAAA,IAAA;AAAA,EAAA;AAIR;AAGA,SAAS2a,GAAiB3a,GAA+C;AACvE,QAAMuG,IAAc8B,GAAA;AACpB,SACE,gBAAAhH;AAAA,IAACqZ;AAAA,IAAA;AAAA,MACC,OAAO1a,EAAM;AAAA,MACb,SAAS,MAAM;AACb,QAAKuG,EAAY,kBAAkB,EAAE,UAAUL,GAAU,OAAA,GAAU;AAAA,MACrE;AAAA,IAAA;AAAA,EAAA;AAGN;AAKO,SAAS0U,GACd5a,GACoB;;AACpB,QAAM;AAAA,IACJ,UAAAgG;AAAA,IACA,SAAA6U;AAAA,IACA,iBAAAC;AAAA,IACA,cAAAC;AAAA,IACA,iBAAAC;AAAA,IACA,YAAAX;AAAA,IACA,QAAAC;AAAA,IACA,cAAAC;AAAA,IACA,aAAApK;AAAA,IACA,YAAA8K;AAAA,IACA,QAAAC;AAAA,IACA,gBAAAC;AAAA,IACA,UAAAvK;AAAA,IACA,SAAAwK;AAAA,IACA,QAAA7V;AAAA,IACA,eAAA8V;AAAA,IACA,SAAAC;AAAA,IACA,OAAAC;AAAA,IACA,QAAAC;AAAA,IACA,aAAAtJ;AAAA,IACA,WAAAjS;AAAA,EAAA,IACED,GAEEyb,IAAevM,GAAUlJ,CAAQ,GACjCsD,IAASmS,EAAa,MAGtB,CAAClL,GAASmL,CAAU,IAAI1a,EAAM,SAAuBma,KAAkB,EAAE,GACzE,CAACQ,GAAcC,CAAe,IAAI5a,EAAM,SAA4B,CAAA,CAAE,GACtE,CAACuY,GAAMsC,CAAO,IAAI7a,EAAM,SAAS,CAAC,GAClC,CAAC8a,GAAaC,CAAc,IAAI/a,EAAM,SAAS,EAAE,GACjD,CAACgb,GAAcC,CAAe,IAAIjb,EAAM,SAAsC,CAAA,CAAE,GAEhFkb,KAAoBtL,KAAYiJ,IAChC/C,KAAkB5B,GAAkB4G,GAAahC,EAAkB,GAGnEqC,KAAanb,EAAM,OAAO8V,EAAe;AAC/C,EAAA9V,EAAM,UAAU,MAAM;AACpB,IAAImb,GAAW,YAAYrF,OACzBqF,GAAW,UAAUrF,IACrB+E,EAAQ,CAAC;AAAA,EAEb,GAAG,CAAC/E,EAAe,CAAC;AAEpB,QAAMsF,KAAsBpb,EAAM,YAAY,CAACqb,MAAmC;AAChF,IAAAX,EAAW,CAACY,MAAS,OAAOD,KAAY,aAAaA,EAAQC,CAAG,IAAID,CAAQ,GAC5ER,EAAQ,CAAC;AAAA,EACX,GAAG,CAAA,CAAE,GAECU,KAAqBvb,EAAM,YAAY,CAAC+G,GAAiBxH,MAAuB;AACpF,IAAA0b,EAAgB,CAACK,MAEb/b,KAAU,QAEVA,MAAU,MACT,MAAM,QAAQA,CAAK,KAAKA,EAAM,WAAW,IAEnC,OAAO,YAAY,OAAO,QAAQ+b,CAAG,EAAE,OAAO,CAAC,CAAC1b,EAAG,MAAMA,OAAQmH,EAAM,IAAI,CAAC,IAE9E,EAAE,GAAGuU,GAAK,CAACvU,EAAM,IAAI,GAAGxH,EAAA,CAChC,GACDsb,EAAQ,CAAC;AAAA,EACX,GAAG,CAAA,CAAE,GAGCW,KAAaxb,EAAM,QAA2B,MAAM;;AACxD,QAAIka,MAAW,OAAW,QAAOA;AACjC,UAAMuB,KAAUxd,IAAAqK,KAAA,gBAAAA,EAAQ,WAAW,SAAnB,gBAAArK,EAAyB;AACzC,WAAIqK,MAAW,UAAamT,MAAY,SAAkB,CAAA,IACnDnT,EAAO,OACX;AAAA,MACC,CAACvB,MACCA,EAAM,SAAS,cACfA,EAAM,aAAa,UACnB,CAACA,EAAM,SAAS,QAChB0U,EAAQ,SAAS1U,EAAM,IAAI;AAAA,IAAA,EAE9B,IAAI,CAACA,MAAUA,EAAM,IAAI;AAAA,EAC9B,GAAG,CAACmT,GAAQ5R,CAAM,CAAC,GAEboT,IAAS1b,EAAM,QAAQ,MAAM,IAAI,IAAI,OAAO,KAAKuE,KAAU,CAAA,CAAE,CAAC,GAAG,CAACA,CAAM,CAAC,GACzE8T,KAAerY,EAAM,QAA6B,MAAM;;AAC5D,QAAIoa,MAAY,MAAS9R,MAAW,eAAkB,CAAA;AACtD,QAAI8R,MAAY,QAAW;AACzB,YAAMuB,KAAS,IAAI,IAAIrT,EAAO,OAAO,IAAI,CAACvB,OAAU,CAACA,GAAM,MAAMA,EAAK,CAAC,CAAC;AACxE,aAAOqT,EACJ,OAAO,CAACnY,OAAS,CAACyZ,EAAO,IAAIzZ,EAAI,CAAC,EAClC,IAAI,CAACA,OAAS0Z,GAAO,IAAI1Z,EAAI,CAAC,EAC9B,OAAO,CAAC8E,OAA6BA,OAAU,MAAS;AAAA,IAC7D;AACA,UAAM6U,IAAW,IAAI,MAAI3d,KAAAqK,EAAO,WAAW,SAAlB,gBAAArK,GAAwB,gBAAe,EAAE,GAC5D,EAAE,QAAAyQ,GAAQ,OAAAC,EAAA,IAAUF,GAAqBnG,EAAO,MAAM;AAC5D,WAAO,CAAC,GAAGoG,GAAQ,GAAGC,CAAK,EACxB;AAAA,MACC,CAAC5H,OACC,CAACA,GAAM,aACP,CAAC2U,EAAO,IAAI3U,GAAM,IAAI,MACrB+S,MAAoB,MAAQ,CAACtL,GAAazH,EAAK,MAChD6U,EAAS,IAAI7U,GAAM,IAAI,MACtBA,GAAM,SAAS,UACdA,GAAM,SAAS,aACdA,GAAM,SAAS,cAAcA,GAAM,aAAa;AAAA,IAAA,EAEtD,MAAM,GAAGgS,EAAmB;AAAA,EACjC,GAAG,CAACqB,GAASsB,GAAQpT,GAAQwR,CAAe,CAAC,GAEvC7B,OAAgBha,KAAAqK,KAAA,gBAAAA,EAAQ,WAAW,SAAnB,gBAAArK,GAAyB,eAAc,IAGvD4d,KAAgB/F,GAAgB,KAAA,GAChCE,IAAahW,EAAM;AAAA,IACvB,OAAO;AAAA,MACL,MAAAuY;AAAA,MACA,UAAU2C;AAAA,MACV,UAAU5L,GAAkBC,CAAO;AAAA,MACnC,QAAQ0I,MAAiB4D,GAAc,SAAS,IAAIA,KAAgB;AAAA,MACpE,SACE,OAAO,KAAKb,CAAY,EAAE,SAAS,KAAKzW,MAAW,SAC/C,EAAE,GAAGyW,GAAc,GAAGzW,MACtB;AAAA,MACN,QAAQiX,GAAW,SAAS,IAAIA,KAAa;AAAA,IAAA;AAAA,IAE/C;AAAA,MACEjD;AAAA,MACA2C;AAAA,MACA3L;AAAA,MACA0I;AAAA,MACA4D;AAAA,MACAb;AAAA,MACAzW;AAAA,MACAiX;AAAA,IAAA;AAAA,EACF,GAGIM,IAAOhW,GAAmBd,GAAUgR,GAAY;AAAA,IACpD,SAAS1N,MAAW;AAAA,IACpB,iBAAiByT;AAAA;AAAA,IAEjB,OAAO,CAACC,GAAcvM,MAAU,CAACD,GAAgBC,CAAK,KAAKuM,IAAe;AAAA,EAAA,CAC3E,GAGKC,KAAWzM,GAAgBsM,EAAK,KAAK,KAAKvD,IAAO;AACvD,EAAAvY,EAAM,UAAU,MAAM;AACpB,IAAIic,QAAkB,CAACC,MAAY,KAAK,IAAI,GAAGA,IAAU,CAAC,CAAC;AAAA,EAC7D,GAAG,CAACD,IAAU1D,CAAI,CAAC;AAGnB,QAAM4D,IAAgBhN,MAAgB,UAAaA,EAAY,SAAS,GAClEiN,IAAa/C,MAAe,UAAaC,MAAW,UAAaC,MAAiB,IAElF8C,KAAarc,EAAM,QAA6B,MAAM;AAC1D,QAAIsI,MAAW,OAAW,QAAO,CAAA;AACjC,QAAIuJ,IAAOJ,GAAiB,EAAE,QAAQnJ,EAAO,QAAQ,SAAAuR,GAAS,aAAA3I,GAAa,iBAAA4I,GAAiB;AAC5F,IAAIC,MAAiB,WAAWlI,IAAO,CAAC,GAAGA,GAAM,GAAGkI,CAAY,IAC5DC,MAAoB,WAAWnI,IAAOmI,EAAgBnI,CAAI;AAC9D,UAAMyK,IAA+BH,IAAgB,CAACnD,GAAA,CAAoB,IAAI,CAAA,GACxEuD,IAAgCH,IAClC,CAAChD,GAAiB,EAAE,UAAApU,GAAU,YAAAqU,GAAY,QAAAC,GAAQ,cAAAC,GAAc,aAAArI,EAAA,CAAa,CAAC,IAC9E,CAAA;AACJ,WAAO,CAAC,GAAGoL,GAAS,GAAGzK,GAAM,GAAG0K,CAAQ;AAAA,EAC1C,GAAG;AAAA,IACDjU;AAAA,IACAuR;AAAA,IACA3I;AAAA,IACA4I;AAAA,IACAC;AAAA,IACAC;AAAA,IACAmC;AAAA,IACAC;AAAA,IACApX;AAAA,IACAqU;AAAA,IACAC;AAAA,IACAC;AAAA,EAAA,CACD,GAEKrD,KAAOlW,EAAM,QAAa;;AAAM,aAAA/B,IAAA6d,EAAK,SAAL,gBAAA7d,EAAW,YAAW,CAAA;AAAA,KAAI,CAAC6d,EAAK,IAAI,CAAC,GACrEnM,KAAQzR,KAAA4d,EAAK,SAAL,gBAAA5d,GAAW,OACnBsa,IAAY9I,GAAaC,GAAOuL,EAAiB,GAEjDjC,IAAQuD,GAAiB;AAAA,IAC7B,MAAMtG;AAAA,IACN,SAASmG;AAAA,IACT,OAAO,EAAE,SAAA9M,GAAS,cAAAoL,EAAA;AAAA,IAClB,eAAe;AAAA,IACf,kBAAkB;AAAA,IAClB,iBAAiB;AAAA,IACjB,WAAAnC;AAAA,IACA,oBAAoB2D;AAAA,IACpB,iBAAiBf;AAAA,IACjB,sBAAsBR;AAAA;AAAA;AAAA,IAGtB,UAAU,CAACrJ,MAAQ,OAAO1B,GAAS0B,CAAG,EAAE,EAAE;AAAA,IAC1C,iBAAiBkL,GAAA;AAAA,EAAgB,CAClC,GAEKvN,KAAclP,EAAM;AAAA,IACxB,MAAM,OAAO,KAAK2a,CAAY,EAAE,OAAO,CAACzY,MAAOyY,EAAazY,CAAE,CAAC;AAAA,IAC/D,CAACyY,CAAY;AAAA,EAAA,GAGT+B,KAAqBb,GAAc,SAAS,KAAK,OAAO,KAAKb,CAAY,EAAE,SAAS;AAG1F,MAAI/O;AACJ,EAAIwO,EAAa,UAAU,QAAQA,EAAa,UAAU,SACxDxO,KAAO,gBAAA5L,EAACsZ,IAAA,EAAiB,OAAOc,EAAa,OAAO,IAC3CA,EAAa,aAAanS,MAAW,UAAawT,EAAK,aAAaG,KAC7EhQ,uBAAQuN,IAAA,EAAc,IACbsC,EAAK,UAAU,QAAQA,EAAK,UAAU,SAC/C7P,KACE,gBAAA5L;AAAA,IAACqZ;AAAA,IAAA;AAAA,MACC,OAAOoC,EAAK;AAAA,MACZ,SAAS,MAAM;AACb,QAAKA,EAAK,QAAA;AAAA,MACZ;AAAA,IAAA;AAAA,EAAA,IAGK5F,GAAK,WAAW,IACzBjK,KACEsO,MACCmC,KACC,gBAAArc,EAAC+N,IAAA,EAAW,OAAM,cAAa,aAAY,wCAAA,CAAwC,IAEnF,gBAAA/N,EAAC+N,IAAA,EAAW,OAAM,oBAAmB,aAAY,yCAAA,CAAyC,KAG9FnC,KACE,gBAAA9K,EAAAuP,GAAA,EACE,UAAA;AAAA,IAAA,gBAAArQ;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,WAAW3C;AAAA,UACT;AAAA,UACAoe,EAAK,cAAc;AAAA,QAAA;AAAA,QAGrB,4BAAC,SAAA,EAAM,WAAU,iCAAgC,aAAWA,EAAK,YAC/D,UAAA;AAAA,UAAA,gBAAAzb,EAAC,SAAA,EAAM,WAAU,mCACf,UAAA,gBAAAA,EAAC,MAAA,EACE,YAAM,eAAA,EAAiB,IAAI,CAACkS,MAAW;AACtC,kBAAMoK,IAAUpK,EAAO,OAAO,WAAA,GACxBqK,IAAYrK,EAAO,OAAO,YAAA;AAChC,mBACE,gBAAAlS;AAAA,cAAC;AAAA,cAAA;AAAA,gBAEC,OAAM;AAAA,gBACN,aACEuc,MAAc,QACV,cACAA,MAAc,SACZ,eACA;AAAA,gBAER,WAAU;AAAA,gBAET,UAAArK,EAAO,gBAAgB,OAAOoK,IAC7B,gBAAAxb;AAAA,kBAAC;AAAA,kBAAA;AAAA,oBACC,MAAK;AAAA,oBACL,WAAU;AAAA,oBACV,SAAS,CAAC2P,OAAA;;AAAU,8BAAA7S,KAAAsU,EAAO,OAAO,wBAAA,MAAd,gBAAAtU,GAA0C6S;AAAA;AAAA,oBAE7D,UAAA;AAAA,sBAAA+L,GAAWtK,EAAO,OAAO,UAAU,QAAQA,EAAO,YAAY;AAAA,sBAC9DqK,MAAc,QACb,gBAAAvc,EAACM,IAAA,EAAc,WAAU,cAAA,CAAc,IACrCic,MAAc,SAChB,gBAAAvc,EAACK,IAAA,EAAgB,WAAU,eAAc,IACvC;AAAA,oBAAA;AAAA,kBAAA;AAAA,gBAAA,IAGNmc,GAAWtK,EAAO,OAAO,UAAU,QAAQA,EAAO,YAAY;AAAA,cAAA;AAAA,cAzB3DA,EAAO;AAAA,YAAA;AAAA,UA6BlB,CAAC,GACH,GACF;AAAA,UACA,gBAAAlS,EAAC,WACE,UAAA4Y,EAAM,YAAA,EAAc,KAAK,IAAI,CAAC1H,MAC7B,gBAAAlR;AAAA,YAAC;AAAA,YAAA;AAAA,cAEC,cAAYkR,EAAI,cAAA,IAAkB,aAAa;AAAA,cAC/C,SAAS0I,MAAe,SAAY,MAAMA,EAAW1I,EAAI,QAAQ,IAAI;AAAA,cACrE,WAAW7T;AAAA,gBACT;AAAA,gBACAuc,MAAe,UAAa;AAAA,cAAA;AAAA,cAG7B,UAAA1I,EAAI,kBAAkB,IAAI,CAACuL,MAC1B,gBAAAzc,EAAC,QAAiB,WAAU,0BACzB,aAAWyc,EAAK,OAAO,UAAU,MAAMA,EAAK,YAAY,EAAA,GADlDA,EAAK,EAEd,CACD;AAAA,YAAA;AAAA,YAZIvL,EAAI;AAAA,UAAA,CAcZ,EAAA,CACH;AAAA,QAAA,EAAA,CACF;AAAA,MAAA;AAAA,IAAA;AAAA,IAED5B,MAAU,UAAaA,IAAQ,KAC9B,gBAAAtP;AAAA,MAACiY;AAAA,MAAA;AAAA,QACC,MAAAC;AAAA,QACA,WAAAC;AAAA,QACA,YAAY7I;AAAA,QACZ,eAAa3D,KAAA8P,EAAK,SAAL,gBAAA9P,GAAW,cAAa,UAAQG,KAAA2P,EAAK,SAAL,gBAAA3P,GAAW,cAAa;AAAA,QACrE,WAAS4Q,KAAAjB,EAAK,SAAL,gBAAAiB,GAAW,UAAS,UAAQC,KAAAlB,EAAK,SAAL,gBAAAkB,GAAW,UAAS;AAAA,QACzD,cAAcnC;AAAA,MAAA;AAAA,IAAA;AAAA,EAChB,GAEJ;AAIJ,QAAMoC,KACJ5C,MAAkB,SAAY,CAAC,OAAO,MAAM,IAAIA,MAAkB,KAAQ,CAAA,IAAKA,GAC3E6C,KAAgBD,GAAW,SAAS,MAAK3U,KAAA,gBAAAA,EAAQ,WAAW,YAAW,QAEvE6U,KACJ7U,MAAW,WACV2P,MAAiBI,GAAa,SAAS,KAAKiC,MAAY,UAAa4C;AAExE,2BACG,OAAA,EAAI,WAAWxf,EAAG,8BAA8BuB,CAAS,GACvD,UAAA;AAAA,IAAAke,MACC,gBAAAhc,EAAC,OAAA,EAAI,WAAU,qDACb,UAAA;AAAA,MAAA,gBAAAd;AAAA,QAAC2X;AAAA,QAAA;AAAA,UACC,eAAAC;AAAA,UACA,aAAa6C;AAAA,UACb,gBAAgBC;AAAA,UAChB,cAAA1C;AAAA,UACA,QAAQ2C;AAAA,UACR,gBAAgBO;AAAA,UAChB,WAAU;AAAA,QAAA;AAAA,MAAA;AAAA,OAEVjB,MAAY,UAAa4C,OACzB,gBAAA/b,EAAC,OAAA,EAAI,WAAU,oCACZ,UAAA;AAAA,QAAA+b,wBACExJ,IAAA,EAAc,UAAA1O,GAAoB,QAAQgR,GAAY,SAASiH,IAAY;AAAA,QAE7E3C;AAAA,MAAA,EAAA,CACH;AAAA,IAAA,GAEJ;AAAA,IAED6B,KAAiBjN,GAAY,SAAS,KACrC,gBAAA7O;AAAA,MAAC4O;AAAA,MAAA;AAAA,QACC,aAAAC;AAAA,QACA,aAAAC;AAAA,QACA,SAAS,MAAMyL,EAAgB,CAAA,CAAE;AAAA,MAAA;AAAA,IAAA;AAAA,IAGpC3O;AAAA,IACAuO;AAAA,EAAA,GACH;AAEJ;AClmBA,MAAM4C,KAAmB,2BAGnBC,KAAiB;AAEvB,SAASC,GAAgB/d,GAAuB;AAC9C,MAAI,CAAC8d,GAAe,KAAK9d,CAAK,EAAG,QAAOA;AACxC,QAAMge,IAAO,IAAI,KAAKhe,CAAK;AAC3B,SAAI,OAAO,MAAMge,EAAK,QAAA,CAAS,IAAUhe,IAClCge,EAAK,YAAA;AACd;AAEA,SAASC,GAAWpX,GAAoD;AACtE,MAAIA,EAAO,WAAW,EAAG,QAAO,EAAE,MAAA;AAClC,MAAIA,EAAO,MAAM,CAAC7G,MAA2B,OAAOA,KAAU,QAAQ;AACpE,WAAO,EAAE,KAAK6G,CAA+B;AAE/C,QAAMqX,IAAWrX,EAAO,IAAI,CAAC7G,MAAU,EAAE,QAAQA,CAAK,CAAC;AACvD,SAAIke,EAAS,WAAW,IAAUA,EAAS,CAAC,IACrC,EAAE,MAAMA,CAAgE;AACjF;AAEA,SAASC,GAAa3W,GAAiB4W,GAAsC;AAC3E,MAAIrV,IAAS,EAAE,OAAA;AACf,SAAIvB,EAAM,WAAW,UAASuB,IAASA,EAAO,MAAA,IACrCvB,EAAM,WAAW,SAASA,EAAM,WAAW,QAAOuB,IAASA,EAAO,IAAA,IAClEvB,EAAM,WAAW,WAAQuB,IAASA,EAAO,KAAA,IAC9CvB,EAAM,cAAc,eAAoBuB,EAAO,IAAIvB,EAAM,SAAS,IAClE4W,MAAiBrV,IAASA,EAAO,IAAI,GAAG8U,EAAgB,IACrD9U;AACT;AAEA,SAASsV,GAAa7W,GAAiB8W,GAA8B;AACnE,MAAIvV,IAAS,EAAE,OAAO,OAAA;AACtB,SAAIuV,MAASvV,IAASA,EAAO,IAAA,IACzBvB,EAAM,QAAQ,eAAoBuB,EAAO,IAAIvB,EAAM,GAAG,IACtDA,EAAM,QAAQ,eAAoBuB,EAAO,IAAIvB,EAAM,GAAG,IACnDuB;AACT;AAEA,SAASwV,GAAoB/W,GAAiBgX,GAA6B;AACzE,UAAQhX,EAAM,mBAAA;AAAA,IACZ,KAAK;AACH,aAAO,EAAE,OAAO,EAAE,gBAAgBqW,GAAA,CAAkB,EAAE,KAAA;AAAA,IACxD,KAAK;AACH,aAAOW,IACH,EAAE,OAAO,OAAA,EAAS,IAAA,IAClB,EAAE,OAAO,EAAE,gBAAgBX,GAAA,CAAkB,EAAE,IAAA;AAAA,IACrD;AACE,aAAO,EAAE,OAAO,EAAE,gBAAgBA,IAAkB,EAAE,IAAI,GAAGA,EAAgB;AAAA,EAAA;AAEnF;AASA,SAASY,GAAqBjX,GAAiB4W,GAAsC;AACnF,QAAMpe,IAAQue,GAAoB/W,GAAO,EAAK;AAC9C,MAAIyB,IAAqBzB,EAAM,WAAWxH,EAAM,aAAaA;AAC7D,SAAKoe,MAAiBnV,IAASA,EAAO,SAAA,IAC/B,EAAE,WAAW,CAACwB,MAAQ;AAC3B,QAAIA,MAAQ,MAAMA,MAAQ,QAAQA,MAAQ,OAAW,QAAOjD,EAAM,WAAW,OAAO;AACpF,QAAIA,EAAM,sBAAsB,aAAa,OAAOiD,KAAQ,YAAYA,EAAI,KAAA,MAAW,IAAI;AACzF,YAAM+D,IAAS,OAAO/D,CAAG;AACzB,aAAO,OAAO,MAAM+D,CAAM,IAAI/D,IAAM+D;AAAA,IACtC;AACA,WAAO/D;AAAA,EACT,GAAGxB,CAAM;AACX;AAEA,SAASyV,KAAyB;AAChC,SAAI,OAAO,OAAS,MAAoB,EAAE,OAAA,IACnC,EAAE,MAAM,CAAC,EAAE,WAAW,IAAI,GAAG,EAAE,OAAA,CAAQ,CAAC;AACjD;AAEA,SAASC,GAAcnX,GAAiB4W,GAAsC;;AAC5E,UAAQ5W,EAAM,MAAA;AAAA,IACZ,KAAK;AAAA,IACL,KAAK;AACH,aAAO2W,GAAa3W,GAAO4W,CAAe;AAAA,IAC5C,KAAK;AACH,aAAOC,GAAa7W,GAAO,EAAI;AAAA,IACjC,KAAK;AACH,aAAO6W,GAAa7W,GAAO,EAAK;AAAA,IAClC,KAAK;AACH,aAAO,EAAE,QAAA;AAAA,IACX,KAAK,QAAQ;AACX,YAAMuB,IAAS,EAAE,OAAA;AACjB,aAAOqV,IAAkBrV,EAAO,IAAI,GAAG8U,EAAgB,IAAI9U;AAAA,IAC7D;AAAA,IACA,KAAK;AAEH,cADeqV,IAAkB,EAAE,OAAA,EAAS,IAAI,GAAGP,EAAgB,IAAI,EAAE,OAAA,GAC3D,UAAUE,EAAe;AAAA,IAEzC,KAAK;AACH,aAAOE,GAAWzW,EAAM,cAAc,EAAE;AAAA,IAC1C,KAAK;AACH,eAAI9I,IAAA8I,EAAM,aAAN,gBAAA9I,EAAgB,UAAS,KAAa,EAAE,MAAM6f,GAAoB/W,GAAO,EAAI,CAAC,IAC3EiX,GAAqBjX,GAAO4W,CAAe;AAAA,IAEpD,KAAK;AACH,aAAOM,GAAA;AAAA,IACT,KAAK;AACH,aAAO,EAAE,QAAA;AAAA,IACX,KAAK;AACH,aAAO,EAAE,MAAM,EAAE,QAAA,CAAS;AAAA,IAC5B,KAAK;AACH,aAAO,EAAE,QAAA;AAAA,EAAQ;AAEvB;AAGO,SAASE,GAAO7V,GAAwB8V,GAAmD;AAChG,QAAMC,IAAqB,CAAA;AAE3B,aAAWtX,KAASuB,EAAO,QAAQ;AACjC,QAAIvB,EAAM,SAAU;AAKpB,UAAM4W,IAAkB5W,EAAM;AAC9B,QAAIuX,IAAcJ,GAAcnX,GAAO4W,CAAe;AAEtD,IAAI5W,EAAM,aAAUuX,IAAcA,EAAY,SAAA,KAG1CF,MAAS,YAAY,CAACrX,EAAM,cAAUuX,IAAcA,EAAY,SAAA,IAEpED,EAAMtX,EAAM,IAAI,IAAIuX;AAAA,EACtB;AAEA,SAAO,EAAE,OAAOD,CAAK;AACvB;AChKAjgB,GAAsB,eAAe,YAAY;AAqCjD,SAASmgB,GAAclL,GAAYmL,GAAqC;AACtE,MAAIA,MAAW,UAAaA,EAAO,KAAA,MAAW,GAAI,QAAO;AACzD,QAAMC,IAASD,EACZ,MAAM,GAAG,EACT,IAAI,CAACE,MAAUA,EAAM,KAAA,EAAO,aAAa,EACzC,OAAO,CAACA,MAAUA,MAAU,EAAE;AACjC,MAAID,EAAO,WAAW,EAAG,QAAO;AAChC,QAAMxc,IAAOoR,EAAK,KAAK,YAAA,GACjBlT,IAAOkT,EAAK,KAAK,YAAA;AACvB,SAAOoL,EAAO,KAAK,CAACC,MACdA,EAAM,WAAW,GAAG,IAAUzc,EAAK,SAASyc,CAAK,IACjDA,EAAM,SAAS,IAAI,IAAUve,EAAK,WAAWue,EAAM,MAAM,GAAG,EAAE,CAAC,IAC5Dve,MAASue,CACjB;AACH;AAEA,SAASC,GAAeC,GAAuB;AAC7C,SAAIA,IAAQ,OAAa,GAAGA,CAAK,OAC7BA,IAAQ,OAAO,OAAa,GAAG,KAAK,MAAMA,IAAQ,IAAI,CAAC,QACpD,IAAIA,KAAS,OAAO,OAAO,QAAQ,CAAC,CAAC;AAC9C;AAEA,SAASC,GAAajM,GAAqB;AAEzC,QAAMkM,KADelM,EAAI,MAAM,QAAQ,CAAC,EAAE,CAAC,KAAKA,GAClB,MAAM,GAAG,EAAE,OAAO,CAACmM,MAAYA,MAAY,EAAE;AAC3E,SAAOD,EAASA,EAAS,SAAS,CAAC,KAAKlM;AAC1C;AAEA,SAASoM,GAAWhgB,GAA+D;AACjF,SACE,gBAAAmC;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,SAAQ;AAAA,MACR,MAAK;AAAA,MACL,QAAO;AAAA,MACP,aAAa;AAAA,MACb,eAAc;AAAA,MACd,gBAAe;AAAA,MACf,eAAY;AAAA,MACZ,WAAW;AAAA,MACV,GAAGnC;AAAA,MAEJ,UAAA;AAAA,QAAA,gBAAAqB,EAAC,QAAA,EAAK,GAAE,4CAAA,CAA4C;AAAA,QACpD,gBAAAA,EAAC,YAAA,EAAS,QAAO,gBAAA,CAAgB;AAAA,QACjC,gBAAAA,EAAC,UAAK,IAAG,MAAK,IAAG,KAAI,IAAG,MAAK,IAAG,KAAA,CAAK;AAAA,MAAA;AAAA,IAAA;AAAA,EAAA;AAG3C;AAEA,SAASqU,GAAM1V,GAA+D;AAC5E,SACE,gBAAAmC;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,SAAQ;AAAA,MACR,MAAK;AAAA,MACL,QAAO;AAAA,MACP,aAAa;AAAA,MACb,eAAc;AAAA,MACd,gBAAe;AAAA,MACf,eAAY;AAAA,MACZ,WAAW;AAAA,MACV,GAAGnC;AAAA,MAEJ,UAAA;AAAA,QAAA,gBAAAqB,EAAC,QAAA,EAAK,IAAG,MAAK,IAAG,KAAI,IAAG,KAAI,IAAG,KAAA,CAAK;AAAA,QACpC,gBAAAA,EAAC,UAAK,IAAG,KAAI,IAAG,KAAI,IAAG,MAAK,IAAG,KAAA,CAAK;AAAA,MAAA;AAAA,IAAA;AAAA,EAAA;AAG1C;AAWO,SAAS4e,GAAWjgB,GAA4C;AACrE,QAAM;AAAA,IACJ,OAAAO,IAAQ;AAAA,IACR,UAAAqV;AAAA,IACA,QAAA4J;AAAA,IACA,UAAA3J,IAAW;AAAA,IACX,UAAA7S,IAAW;AAAA,IACX,SAAAkd;AAAA,IACA,UAAAC;AAAA,IACA,IAAAjd;AAAA,IACA,MAAAD;AAAA,IACA,WAAAhD;AAAA,IACA,UAAAiC;AAAA,IACA,WAAAY,IAAY;AAAA,EAAA,IACV9C,GAEE6W,IAAW7V,EAAM,OAAyB,IAAI,GAC9C,CAACof,GAAUC,CAAW,IAAIrf,EAAM,SAAS,EAAK,GAE9Csf,IACJ/f,KAAS,OAAO,KAAK,MAAM,QAAQA,CAAK,IAAIA,IAAQ,CAACA,CAAsB,GAEvEggB,IAAc,CAACzD,MAAgC;AACnD,QAAI9Z,EAAU;AACd,UAAMwd,IAAmB,CAAA;AACzB,eAAWnM,KAAQ,MAAM,KAAKyI,CAAI,GAAG;AACnC,UAAI,CAACyC,GAAclL,GAAMmL,CAAM,GAAG;AAChC,QAAAW,KAAA,QAAAA,EAAW9L,GAAM;AACjB;AAAA,MACF;AACA,UAAI6L,MAAY,UAAa7L,EAAK,OAAO6L,GAAS;AAChD,QAAAC,KAAA,QAAAA,EAAW9L,GAAM;AACjB;AAAA,MACF;AACA,MAAAmM,EAAS,KAAKnM,CAAI;AAAA,IACpB;AACA,IAAImM,EAAS,WAAW,MACxB5K,KAAA,QAAAA,EAAWC,IAAW2K,IAAWA,EAAS,CAAC;AAAA,EAC7C,GAEMrI,IAAoB,CAACrG,MAAqD;AAC9E,IAAIA,EAAM,OAAO,UAAU,QAAMyO,EAAYzO,EAAM,OAAO,KAAK,GAE/DA,EAAM,OAAO,QAAQ;AAAA,EACvB,GAEM2O,IAAa,CAAC3O,MAAoD;AAGtE,IAFAA,EAAM,eAAA,GACNuO,EAAY,EAAK,GACb,CAAArd,KACJud,EAAYzO,EAAM,aAAa,KAAK;AAAA,EACtC,GAEM4O,IAAiB,CAAC5O,MAAoD;AAC1E,IAAAA,EAAM,eAAA,GACD9O,KAAUqd,EAAY,EAAI;AAAA,EACjC,GAEMM,IAAc,CAACtQ,MAAwB;AAC3C,QAAIuF,MAAa,OAAW;AAC5B,UAAMgL,IAAYN,EAAQ,OAAO,CAAC7F,GAAGoG,MAAMA,MAAMxQ,CAAK;AACtD,QAAIuQ,EAAU,WAAW,GAAG;AAC1B,MAAAhL,EAAS,IAAI;AACb;AAAA,IACF;AAGA,UAAMkL,IAAQF,EAAU,OAAO,CAAC/Y,MAAyB,OAAOA,KAAU,QAAQ;AAClF,IACE+N,EADEC,IACOiL,IAEAA,EAAM,CAAC,KAAK,IAFP;AAAA,EAIlB;AAEA,2BACG,OAAA,EAAI,WAAWpiB,EAAG,aAAauB,CAAS,GACvC,UAAA;AAAA,IAAA,gBAAAoB;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,MAAK;AAAA,QACL,IAAA6B;AAAA,QACA,UAAAF;AAAA,QACA,cAAYhD,EAAM,YAAY;AAAA,QAC9B,SAAS,MAAA;;AAAM,kBAAAf,IAAA4X,EAAS,YAAT,gBAAA5X,EAAkB;AAAA;AAAA,QACjC,YAAYyhB;AAAA,QACZ,aAAaA;AAAA,QACb,aAAa,MAAML,EAAY,EAAK;AAAA,QACpC,QAAQI;AAAA,QACR,iBAAeL,IAAW,SAAS;AAAA,QACnC,WAAU;AAAA,QAET,eACC,gBAAAje,EAAAuP,GAAA,EACE,UAAA;AAAA,UAAA,gBAAArQ,EAAC2e,IAAA,EAAW,WAAU,UAAA,CAAU;AAAA,UAChC,gBAAA3e,EAAC,QAAA,EACE,UAAAwU,IACG,iDACA,gDAAA,CACN;AAAA,QAAA,EAAA,CACF;AAAA,MAAA;AAAA,IAAA;AAAA,IAGJ,gBAAAxU;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,KAAKwV;AAAA,QACL,MAAK;AAAA,QACL,MAAA5T;AAAA,QACA,QAAAuc;AAAA,QACA,UAAA3J;AAAA,QACA,UAAA7S;AAAA,QACA,UAAUmV;AAAA,QACV,UAAU;AAAA,QACV,eAAY;AAAA,QACZ,WAAU;AAAA,MAAA;AAAA,IAAA;AAAA,IAEXmI,EAAQ,SAAS,IAChB,gBAAAjf,EAAC,MAAA,EAAG,WAAU,aACX,UAAAif,EAAQ,IAAI,CAACzY,GAAOwI,MAAU;AAC7B,YAAMmB,IAAQ,OAAO3J,KAAU,WAAWgY,GAAahY,CAAK,IAAIA,EAAM;AACtE,aACE,gBAAA1F;AAAA,QAAC;AAAA,QAAA;AAAA,UAEC,WAAU;AAAA,UAET,UAAA;AAAA,YAAA,OAAO0F,KAAU,WAChB,gBAAAxG;AAAA,cAAC;AAAA,cAAA;AAAA,gBACC,MAAMwG;AAAA,gBACN,QAAO;AAAA,gBACP,KAAI;AAAA,gBACJ,WAAU;AAAA,gBAET,UAAA2J;AAAA,cAAA;AAAA,YAAA,IAGH,gBAAArP,EAAC,QAAA,EAAK,WAAU,YACb,UAAA;AAAA,cAAA0F,EAAM;AAAA,gCACN,QAAA,EAAK,WAAU,sCACb,UAAA8X,GAAe9X,EAAM,IAAI,EAAA,CAC5B;AAAA,YAAA,GACF;AAAA,YAED/E,KAAa,CAACE,IACb,gBAAA3B;AAAA,cAAC;AAAA,cAAA;AAAA,gBACC,MAAK;AAAA,gBACL,cAAY,UAAUmQ,CAAK;AAAA,gBAC3B,SAAS,MAAMmP,EAAYtQ,CAAK;AAAA,gBAChC,WAAU;AAAA,gBAEV,UAAA,gBAAAhP,EAACqU,IAAA,EAAM,WAAU,UAAA,CAAU;AAAA,cAAA;AAAA,YAAA,IAE3B;AAAA,UAAA;AAAA,QAAA;AAAA,QA7BC,OAAO7N,KAAU,WAAW,OAAOA,CAAK,KAAK,QAAQA,EAAM,IAAI,IAAIwI,CAAK;AAAA,MAAA;AAAA,IAgCnF,CAAC,GACH,IACE;AAAA,EAAA,GACN;AAEJ;ACvQO,SAAS0Q,GAAcxgB,GAAuB;AACnD,QAAM0I,IAAS1I,EAAM,QAAQ,UAAU,GAAG,EAAE,KAAA;AAC5C,SAAI0I,MAAW,KAAW1I,IACnB0I,EAAO,OAAO,CAAC,EAAE,gBAAgBA,EAAO,MAAM,CAAC;AACxD;AAEA,SAAS+X,GAAIC,GAAmB;AAC9B,SAAO,OAAOA,CAAC,EAAE,SAAS,GAAG,GAAG;AAClC;AAGO,SAASC,GAAgB3gB,GAAuB;AACrD,QAAMge,IAAO,IAAI,KAAKhe,CAAK;AAC3B,SAAI,OAAO,MAAMge,EAAK,QAAA,CAAS,IAAUhe,IAClC,GAAGge,EAAK,YAAA,CAAa,IAAIyC,GAAIzC,EAAK,SAAA,IAAa,CAAC,CAAC,IAAIyC,GAAIzC,EAAK,QAAA,CAAS,CAAC,IAAIyC;AAAA,IACjFzC,EAAK,SAAA;AAAA,EAAS,CACf,IAAIyC,GAAIzC,EAAK,WAAA,CAAY,CAAC;AAC7B;AAEA,MAAM4C,KAAW;AAOV,SAAS7C,GAAgB/d,GAAuB;AACrD,MAAI4gB,GAAS,KAAK5gB,CAAK,EAAG,QAAOA;AACjC,QAAMge,IAAO,IAAI,KAAKhe,CAAK;AAC3B,MAAI,OAAO,MAAMge,EAAK,QAAA,CAAS,EAAG,QAAOhe;AACzC,QAAM6gB,IAAgB,CAAC7C,EAAK,kBAAA,GACtB8C,IAAOD,KAAiB,IAAI,MAAM,KAClCE,IAAM,KAAK,IAAIF,CAAa,GAC5BG,IAAS,GAAGF,CAAI,GAAGL,GAAI,KAAK,MAAMM,IAAM,EAAE,CAAC,CAAC,IAAIN,GAAIM,IAAM,EAAE,CAAC;AACnE,SAAO,GAAG/C,EAAK,YAAA,CAAa,IAAIyC,GAAIzC,EAAK,SAAA,IAAa,CAAC,CAAC,IAAIyC,GAAIzC,EAAK,QAAA,CAAS,CAAC,IAAIyC;AAAA,IACjFzC,EAAK,SAAA;AAAA,EAAS,CACf,IAAIyC,GAAIzC,EAAK,YAAY,CAAC,IAAIyC,GAAIzC,EAAK,WAAA,CAAY,CAAC,GAAGgD,CAAM;AAChE;AAOO,SAASC,GAAa3Z,GAAyB;AACpD,SAAIA,MAAU,KAAa,KACvB,MAAM,QAAQA,CAAK,IAAUA,EAAM,KAAK2Z,EAAY,IACpD3Z,MAAU,QAAQ,OAAOA,KAAU,WAC9B,OAAO,OAAOA,CAAK,EAAE,KAAK2Z,EAAY,IAExC;AACT;AAGA,SAASC,GAAKlhB,GAAyB;AACrC,SAAIA,MAAU,QAAQ,OAAOA,KAAU,YAAY,CAAC,MAAM,QAAQA,CAAK,KAAK,QAAQA,IAC1EA,EAA0B,KAE7BA;AACT;AASA,SAASmhB,GAAkB3Z,GAAiBxH,GAAyB;;AACnE,UAAQwH,EAAM,MAAA;AAAA,IACZ,KAAK;AAAA,IACL,KAAK;AACH,aAAOxH,KAAS,OAAO,KAAK,OAAOA,CAAK;AAAA,IAC1C,KAAK;AAAA,IACL,KAAK;AACH,aAAOA,KAAgB;AAAA,IACzB,KAAK;AACH,aAAO,EAAQA;AAAA,IACjB,KAAK;AACH,aAAOA,KAAS,QAAQA,MAAU,KAAK,KAAK,OAAOA,CAAK,EAAE,MAAM,GAAG,EAAE;AAAA,IACvE,KAAK;AACH,aAAOA,KAAS,QAAQA,MAAU,KAAK,KAAK2gB,GAAgB,OAAO3gB,CAAK,CAAC;AAAA,IAC3E,KAAK;AACH,aAAOA,KAAgB;AAAA,IACzB,KAAK;AACH,eAAItB,IAAA8I,EAAM,aAAN,gBAAA9I,EAAgB,UAAS,KACpB,MAAM,QAAQsB,CAAK,IAAIA,EAAM,IAAIkhB,EAAI,IAAI,CAAA,IAE3ClhB,KAAS,OAAO,OAAOkhB,GAAKlhB,CAAK;AAAA,IAC1C,KAAK;AACH,aAAOA,KAAgB;AAAA,IACzB,KAAK;AACH,aAAOA,KAAS,OAAO,KAAK,KAAK,UAAUA,GAAO,MAAM,CAAC;AAAA,IAC3D;AACE,aAAOA;AAAA,EAAA;AAEb;AAOO,SAASohB,GAAgB,EAAE,QAAA7Z,GAAQ,MAAAhC,GAAM,eAAA8b,KAAmD;AACjG,QAAMjc,IAAkB,CAAA;AACxB,aAAWoC,KAASD,GAAQ;AAC1B,QAAI+Z,IAAkBD,KAAA,gBAAAA,EAAgB7Z,EAAM;AAC5C,IAAI8Z,MAAW,WAAWA,IAAS9Z,EAAM,UACrCjC,MAAS,UAAaiC,EAAM,QAAQjC,MAAM+b,IAAS/b,EAAKiC,EAAM,IAAI,IACtEpC,EAAIoC,EAAM,IAAI,IAAI2Z,GAAkB3Z,GAAO8Z,CAAM;AAAA,EACnD;AACA,MAAID,MAAkB;AACpB,eAAW,CAAChhB,GAAKL,CAAK,KAAK,OAAO,QAAQqhB,CAAa;AACrD,MAAMhhB,KAAO+E,MAAMA,EAAI/E,CAAG,IAAIL;AAGlC,SAAOoF;AACT;AAKA,SAASmc,GAAIvhB,GAAgC;AAC3C,SAAO,EAAE,MAAM,SAAS,OAAAA,EAAA;AAC1B;AAEA,MAAMwhB,KAAuB,EAAE,MAAM,OAAA;AAGrC,SAASC,GAAQja,GAAiC;AAChD,SAAOA,EAAM,WAAW+Z,GAAI,IAAI,IAAIC;AACtC;AAEA,SAASE,GAAiBla,GAAiBxH,GAAgC;;AACzE,UAAQwH,EAAM,MAAA;AAAA,IACZ,KAAK;AAAA,IACL,KAAK,QAAQ;AACX,UAAIxH,KAAS,KAAM,QAAOyhB,GAAQja,CAAK;AACvC,YAAM4C,IAAO,OAAOpK,CAAK;AACzB,aAAIoK,MAAS,MAAM5C,EAAM,WAAiB+Z,GAAI,IAAI,IAC3CA,GAAInX,CAAI;AAAA,IACjB;AAAA,IACA,KAAK;AAAA,IACL,KAAK,WAAW;AACd,UAAIpK,KAAS,QAAQA,MAAU,GAAI,QAAOyhB,GAAQja,CAAK;AACvD,YAAMma,IAAU,OAAO3hB,KAAU,WAAWA,IAAQ,OAAOA,CAAK;AAChE,aAAK,OAAO,SAAS2hB,CAAO,IACrBJ,GAAII,CAAO,IADoBF,GAAQja,CAAK;AAAA,IAErD;AAAA,IACA,KAAK;AACH,aAAIxH,KAAS,OAAayhB,GAAQja,CAAK,IAChC+Z,GAAI,EAAQvhB,CAAM;AAAA,IAC3B,KAAK;AACH,aAAIA,KAAS,QAAQA,MAAU,KAAWyhB,GAAQja,CAAK,IAChD+Z,GAAI,OAAOvhB,CAAK,EAAE,MAAM,GAAG,EAAE,CAAC;AAAA,IACvC,KAAK;AACH,aAAIA,KAAS,QAAQA,MAAU,KAAWyhB,GAAQja,CAAK,IAChD+Z,GAAIxD,GAAgB,OAAO/d,CAAK,CAAC,CAAC;AAAA,IAC3C,KAAK,QAAQ;AACX,UAAIA,KAAS,QAAQA,MAAU,GAAI,QAAOyhB,GAAQja,CAAK;AACvD,YAAMsC,KAAUtC,EAAM,cAAc,CAAA,GAAI;AAAA,QACtC,CAACiG,MAAc,OAAOA,CAAS,MAAM,OAAOzN,CAAK;AAAA,MAAA;AAEnD,aAAOuhB,GAAIzX,KAAU9J,CAAK;AAAA,IAC5B;AAAA,IACA,KAAK;AACH,eAAItB,IAAA8I,EAAM,aAAN,gBAAA9I,EAAgB,UAAS,KAEvBsB,KAAS,OAAauhB,GAAI,CAAA,CAAE,IACzBA,GAAI,MAAM,QAAQvhB,CAAK,IAAIA,EAAM,IAAIkhB,EAAI,IAAI,CAACA,GAAKlhB,CAAK,CAAC,CAAC,IAE/DA,KAAS,QAAQA,MAAU,KAAWyhB,GAAQja,CAAK,IAChD+Z,GAAIL,GAAKlhB,CAAK,CAAC;AAAA,IAExB,KAAK;AACH,aAAIA,KAAS,OAAayhB,GAAQja,CAAK,IAEnC,OAAOxH,KAAU,WAAiBwhB,KAC/BD,GAAIvhB,CAAK;AAAA,IAElB,KAAK,QAAQ;AACX,UAAI,OAAOA,KAAU;AACnB,eAAOA,KAAS,OAAOyhB,GAAQja,CAAK,IAAI+Z,GAAIvhB,CAAK;AAEnD,UAAIA,EAAM,KAAA,MAAW,GAAI,QAAOyhB,GAAQja,CAAK;AAC7C,UAAI;AACF,eAAO+Z,GAAI,KAAK,MAAMvhB,CAAK,CAAC;AAAA,MAC9B,QAAQ;AACN,eAAO,EAAE,MAAM,SAAS,SAAS,oBAAA;AAAA,MACnC;AAAA,IACF;AAAA,IACA;AACE,aAAOuhB,GAAIvhB,CAAK;AAAA,EAAA;AAEtB;AA4BO,SAAS4hB,GAAc;AAAA,EAC5B,QAAAra;AAAA,EACA,KAAAkD;AAAA,EACA,MAAAoU;AAAA,EACA,aAAAgD;AACF,GAAuC;AACrC,QAAMzF,IAAS,IAAI,IAAI7U,EAAO,IAAI,CAACC,MAAU,CAACA,EAAM,MAAMA,CAAK,CAAC,CAAC,GAC3DX,IAAkC,CAAA,GAClCib,IAA+B,CAAA;AAErC,aAAW,CAACpf,GAAMqf,CAAQ,KAAK,OAAO,QAAQtX,CAAG,GAAG;AAClD,QAAIoU,MAAS,YAAY,CAACoC,GAAaY,KAAA,gBAAAA,EAAcnf,EAAK,EAAG;AAC7D,UAAM8E,IAAQ4U,EAAO,IAAI1Z,CAAI;AAC7B,QAAI8E,MAAU,QAAW;AACvB,MAAIua,MAAa,WAAWlb,EAAOnE,CAAI,IAAIqf;AAC3C;AAAA,IACF;AACA,UAAMC,IAASN,GAAiBla,GAAOua,CAAQ;AAC/C,IAAIC,EAAO,SAAS,UAClBF,EAAW,KAAK,EAAE,MAAApf,GAAM,SAASsf,EAAO,SAAS,IACxCA,EAAO,SAAS,WAAWA,EAAO,UAAU,WACrDnb,EAAOnE,CAAI,IAAIsf,EAAO;AAAA,EAE1B;AAEA,SAAO,EAAE,QAAAnb,GAAQ,YAAAib,EAAA;AACnB;ACrOA,SAASG,GAAgBza,GAAyB;AAChD,UAAQA,EAAM,QAAA;AAAA,IACZ,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AAAA,IACL,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT;AACE,aAAO;AAAA,EAAA;AAEb;AAEO,SAAS0a,GAAoB;AAAA,EAClC,OAAA1a;AAAA,EACA,SAAA2a;AAAA,EACA,SAAAxM;AAAA,EACA,aAAAyM;AAAA,EACA,SAAAC;AAAA,EACA,UAAA5f;AAAA,EACA,YAAA6f;AACF,GAAiD;AAC/C,QAAMC,IAAO;AAAA,IACX,gBAAgBF,KAAW;AAAA,IAC3B,oBAAoBD;AAAA,EAAA;AAGtB,SACE,gBAAAthB;AAAA,IAAC0hB;AAAA,IAAA;AAAA,MACC,SAAAL;AAAA,MACA,MAAM3a,EAAM;AAAA,MACZ,QAAQ,CAAC,EAAE,OAAOib,QAAU;AAC1B,gBAAQjb,EAAM,MAAA;AAAA,UACZ,KAAK;AACH,mBACE,gBAAA1G;AAAA,cAACE;AAAA,cAAA;AAAA,gBACC,IAAI2U;AAAA,gBACJ,MAAM;AAAA,gBACN,WAAWnO,EAAM;AAAA,gBACjB,UAAA/E;AAAA,gBACA,OAAOggB,EAAI,SAAS,OAAO,KAAK,OAAOA,EAAI,KAAK;AAAA,gBAChD,UAAU,CAAClR,MAAUkR,EAAI,SAASlR,EAAM,OAAO,KAAK;AAAA,gBACpD,QAAQkR,EAAI;AAAA,gBACX,GAAGF;AAAA,gBACH,GAAGD;AAAA,cAAA;AAAA,YAAA;AAAA,UAGV,KAAK;AAAA,UACL,KAAK;AACH,mBACE,gBAAAxhB;AAAA,cAACC;AAAA,cAAA;AAAA,gBACC,IAAI4U;AAAA,gBACJ,MAAK;AAAA,gBACL,WAAWnO,EAAM,SAAS,YAAY,YAAY;AAAA,gBAClD,MAAMA,EAAM,SAAS,YAAY,IAAI;AAAA,gBACrC,KAAKA,EAAM;AAAA,gBACX,KAAKA,EAAM;AAAA,gBACX,UAAA/E;AAAA,gBACA,OAAOggB,EAAI,SAAS,OAAO,KAAMA,EAAI;AAAA,gBACrC,UAAU,CAAClR,MAAUkR,EAAI,SAASlR,EAAM,OAAO,KAAK;AAAA,gBACpD,QAAQkR,EAAI;AAAA,gBACX,GAAGF;AAAA,gBACH,GAAGD;AAAA,cAAA;AAAA,YAAA;AAAA,UAGV,KAAK;AACH,mBACE,gBAAAxhB;AAAA,cAACwC;AAAA,cAAA;AAAA,gBACC,IAAIqS;AAAA,gBACJ,UAAAlT;AAAA,gBACA,SAAS,EAAQggB,EAAI;AAAA,gBACrB,iBAAiB,CAAChe,MAAYge,EAAI,SAAShe,CAAO;AAAA,gBAClD,QAAQge,EAAI;AAAA,gBACX,GAAGF;AAAA,gBACH,GAAGD;AAAA,cAAA;AAAA,YAAA;AAAA,UAGV,KAAK;AACH,mBACE,gBAAAxhB;AAAA,cAACC;AAAA,cAAA;AAAA,gBACC,IAAI4U;AAAA,gBACJ,MAAK;AAAA,gBACL,UAAAlT;AAAA,gBACA,OAAOggB,EAAI,SAAS,OAAO,KAAK,OAAOA,EAAI,KAAK;AAAA,gBAChD,UAAU,CAAClR,MAAUkR,EAAI,SAASlR,EAAM,OAAO,KAAK;AAAA,gBACpD,QAAQkR,EAAI;AAAA,gBACX,GAAGF;AAAA,gBACH,GAAGD;AAAA,cAAA;AAAA,YAAA;AAAA,UAGV,KAAK;AACH,mBACE,gBAAAxhB;AAAA,cAACC;AAAA,cAAA;AAAA,gBACC,IAAI4U;AAAA,gBACJ,MAAK;AAAA,gBACL,UAAAlT;AAAA,gBACA,OAAOggB,EAAI,SAAS,OAAO,KAAK,OAAOA,EAAI,KAAK;AAAA,gBAChD,UAAU,CAAClR,MAAUkR,EAAI,SAASlR,EAAM,OAAO,KAAK;AAAA,gBACpD,QAAQkR,EAAI;AAAA,gBACX,GAAGF;AAAA,gBACH,GAAGD;AAAA,cAAA;AAAA,YAAA;AAAA,UAGV,KAAK,QAAQ;AACX,kBAAM3Y,IAAUnC,EAAM,cAAc,CAAA,GAC9BxI,IAAU2K,EAAQ,IAAI,CAACG,MAAA;;AAAY;AAAA,gBACvC,OAAO,OAAOA,CAAM;AAAA,gBACpB,SAAOpL,IAAA8I,EAAM,eAAN,gBAAA9I,EAAmB,OAAOoL,CAAM,OAAM0W,GAAc,OAAO1W,CAAM,CAAC;AAAA,cAAA;AAAA,aACzE;AACF,mBACE,gBAAAhJ;AAAA,cAACsB;AAAA,cAAA;AAAA,gBACC,IAAIuT;AAAA,gBACJ,UAAAlT;AAAA,gBACA,OAAOggB,EAAI,SAAS,OAAO,OAAO,OAAOA,EAAI,KAAK;AAAA,gBAClD,SAAAzjB;AAAA,gBACA,WAAWwI,EAAM;AAAA,gBACjB,aAAY;AAAA,gBACZ,eAAe,CAACrE,MAAS;AACvB,sBAAIA,MAAS,MAAM;AACjB,oBAAAsf,EAAI,SAAS,IAAI;AACjB;AAAA,kBACF;AACA,wBAAM3Y,IAASH,EAAQ,KAAK,CAAC8D,MAAc,OAAOA,CAAS,MAAMtK,CAAI;AACrE,kBAAAsf,EAAI,SAAS3Y,KAAU3G,CAAI;AAAA,gBAC7B;AAAA,gBACC,GAAGmf;AAAA,cAAA;AAAA,YAAA;AAAA,UAGV;AAAA,UACA,KAAK,YAAY;AACf,kBAAM5X,IAAWlD,EAAM;AACvB,mBAAIkD,MAAa,SAGb,gBAAA5J;AAAA,cAACC;AAAA,cAAA;AAAA,gBACC,IAAI4U;AAAA,gBACJ,MAAK;AAAA,gBACL,UAAAlT;AAAA,gBACA,OAAOggB,EAAI,SAAS,OAAO,KAAK,OAAOA,EAAI,KAAK;AAAA,gBAChD,UAAU,CAAClR,MAAUkR,EAAI,SAASlR,EAAM,OAAO,KAAK;AAAA,gBACpD,QAAQkR,EAAI;AAAA,gBACX,GAAGF;AAAA,gBACH,GAAGD;AAAA,cAAA;AAAA,YAAA,IAKR,gBAAAxhB;AAAA,cAACsU;AAAA,cAAA;AAAA,gBACC,IAAIO;AAAA,gBACJ,UAAUjL,EAAS;AAAA,gBACnB,UAAUA,EAAS;AAAA,gBACnB,UAAAjI;AAAA,gBACA,OACGggB,EAAI,SAAS;AAAA,gBAEhB,UAAU,CAACtf,MAASsf,EAAI,SAAStf,CAAI;AAAA,gBACpC,GAAGmf;AAAA,cAAA;AAAA,YAAA;AAAA,UAGV;AAAA,UACA,KAAK;AACH,mBACE,gBAAAxhB;AAAA,cAAC4e;AAAA,cAAA;AAAA,gBACC,IAAI/J;AAAA,gBACJ,UAAAlT;AAAA,gBACA,OAAQggB,EAAI,SAAS;AAAA,gBACrB,UAAU,CAACtf,MAASsf,EAAI,SAAStf,CAAI;AAAA,gBACpC,GAAGmf;AAAA,cAAA;AAAA,YAAA;AAAA,UAGV,KAAK;AACH,mBACE,gBAAAxhB;AAAA,cAACE;AAAA,cAAA;AAAA,gBACC,IAAI2U;AAAA,gBACJ,MAAM;AAAA,gBACN,UAAAlT;AAAA,gBACA,WAAU;AAAA,gBACV,OACE,OAAOggB,EAAI,SAAU,WACjBA,EAAI,QACJA,EAAI,SAAS,OACX,KACA,KAAK,UAAUA,EAAI,OAAO,MAAM,CAAC;AAAA,gBAEzC,UAAU,CAAClR,MAAUkR,EAAI,SAASlR,EAAM,OAAO,KAAK;AAAA,gBACpD,QAAQkR,EAAI;AAAA,gBACX,GAAGF;AAAA,gBACH,GAAGD;AAAA,cAAA;AAAA,YAAA;AAAA,UAGV;AACE,mBACE,gBAAAxhB;AAAA,cAACC;AAAA,cAAA;AAAA,gBACC,IAAI4U;AAAA,gBACJ,MAAMsM,GAAgBza,CAAK;AAAA,gBAC3B,WAAWA,EAAM;AAAA,gBACjB,UAAA/E;AAAA,gBACA,OAAOggB,EAAI,SAAS,OAAO,KAAK,OAAOA,EAAI,KAAK;AAAA,gBAChD,UAAU,CAAClR,MAAUkR,EAAI,SAASlR,EAAM,OAAO,KAAK;AAAA,gBACpD,QAAQkR,EAAI;AAAA,gBACX,GAAGF;AAAA,gBACH,GAAGD;AAAA,cAAA;AAAA,YAAA;AAAA,QACN;AAAA,MAGR;AAAA,IAAA;AAAA,EAAA;AAGN;AC7NAzjB,GAAsB,iBAAiB,cAAc;AAuCrD,MAAM6jB,yBAA0C,IAAI;AAAA,EAClD;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AAED,SAASnS,GAAaL,GAAwB;AAC5C,SAAIA,aAAiB,QAAcA,EAAM,UAClC,OAAOA,CAAK;AACrB;AAEA,SAASyS,GAAa,EAAE,WAAAjjB,KAAyD;AAC/E,SACE,gBAAAkC,EAAC,OAAA,EAAI,MAAK,UAAS,cAAW,gBAAe,WAAWzD,EAAG,aAAauB,CAAS,GAC9E,UAAA;AAAA,IAAA,CAAC,GAAG,GAAG,CAAC,EAAE,IAAI,CAACsS,MACd,gBAAApQ,EAAC,OAAA,EAAc,WAAU,aACvB,UAAA;AAAA,MAAA,gBAAAd,EAAC8D,IAAA,EAAS,WAAU,WAAA,CAAW;AAAA,MAC/B,gBAAA9D,EAAC8D,IAAA,EAAS,WAAU,cAAA,CAAc;AAAA,IAAA,EAAA,GAF1BoN,CAGV,CACD;AAAA,IACD,gBAAAlR,EAAC8D,IAAA,EAAS,WAAU,YAAA,CAAY;AAAA,EAAA,GAClC;AAEJ;AAEA,SAASge,GAAe;AAAA,EACtB,OAAA1S;AAAA,EACA,WAAAxQ;AACF,GAGuB;AACrB,SACE,gBAAAoB;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,MAAK;AAAA,MACL,WAAW3C;AAAA,QACT;AAAA,QACAuB;AAAA,MAAA;AAAA,MAGD,aAAawQ,CAAK;AAAA,IAAA;AAAA,EAAA;AAGzB;AAOA,SAAS2S,GACP3S,GACA4S,GACAC,GACM;AACN,MAAI,OAAO7S,KAAU,YAAYA,MAAU,KAAM;AACjD,QAAM8S,IAAQ9S;AACd,MAAI8S,EAAM,WAAW,IAAK;AAC1B,QAAMxS,IAAOwS,EAAM;AACnB,MAAI,MAAM,QAAQxS,CAAI,GAAG;AACvB,IAAAuS,EAAQ,SAAS,eAAe,EAAE,MAAM,UAAU,SAASvS,EAAK,IAAI,MAAM,EAAE,KAAK,GAAG,GAAG;AACvF;AAAA,EACF;AACA,MAAI,OAAOA,KAAS,YAAYA,MAAS,KAAM;AAC/C,QAAMyS,IAAyB,CAAA;AAC/B,aAAW,CAAC5iB,GAAK6iB,CAAQ,KAAK,OAAO,QAAQ1S,CAA+B,GAAG;AAC7E,UAAMpR,IAAU,MAAM,QAAQ8jB,CAAQ,IAAIA,EAAS,IAAI,MAAM,EAAE,KAAK,GAAG,IAAI,OAAOA,CAAQ;AAC1F,IAAI7iB,MAAQ,sBAAsBA,MAAQ,WACxC4iB,EAAa,KAAK7jB,CAAO,IAChB0jB,EAAW,IAAIziB,CAAG,IAC3B0iB,EAAQ,SAAS1iB,GAAK,EAAE,MAAM,UAAU,SAAAjB,GAAS,IAEjD6jB,EAAa,KAAK,GAAG5iB,CAAG,KAAKjB,CAAO,EAAE;AAAA,EAE1C;AACA,EAAI6jB,EAAa,SAAS,KACxBF,EAAQ,SAAS,eAAe,EAAE,MAAM,UAAU,SAASE,EAAa,KAAK,GAAG,GAAG;AAEvF;AAUA,SAASE,GAAa;AAAA,EACpB,OAAA3b;AAAA,EACA,UAAAsK;AAAA,EACA,SAAAqQ;AAAA,EACA,OAAAjS;AAAA,EACA,UAAAzN;AACF,GAA0C;AACxC,QAAMkT,IAAUlV,EAAM,MAAA,GAChBwQ,KAAQa,KAAA,gBAAAA,EAAU,UAAStK,EAAM;AAEvC,OAAIsK,KAAA,gBAAAA,EAAU,eAAc,QAAW;AACrC,UAAMsR,IAAYtR,EAAS;AAC3B,WACE,gBAAAhR;AAAA,MAACsiB;AAAA,MAAA;AAAA,QACC,OAAA5b;AAAA,QACA,MAAMA,EAAM;AAAA,QACZ,OAAAyJ;AAAA,QACA,UAAUzJ,EAAM;AAAA,QAChB,SAAA2a;AAAA,QACA,OAAAjS;AAAA,QACA,UAAAzN;AAAA,QACA,OAAOqP,EAAS;AAAA,MAAA;AAAA,IAAA;AAAA,EAGtB;AAEA,QAAMuR,IAAU,GAAG1N,CAAO,UACpB2N,IAAgB,GAAG3N,CAAO,gBAC1ByM,IACJ,CAAC5a,EAAM,gBAAgB,SAAY8b,IAAgB,MAAMpT,MAAU,SAAYmT,IAAU,IAAI,EAC1F,OAAO,CAACE,MAAyBA,MAAS,IAAI,EAC9C,KAAK,GAAG,KAAK;AAElB,SACE,gBAAA3hB,EAAC,OAAA,EAAI,WAAU,aACb,UAAA;AAAA,IAAA,gBAAAA,EAAC4B,IAAA,EAAM,SAASmS,GACb,UAAA;AAAA,MAAA1E;AAAA,MACAzJ,EAAM,WACL,gBAAA1G,EAAC,QAAA,EAAK,eAAY,QAAO,WAAU,oBAChC,UAAA,KAAA,CACH,IACE;AAAA,IAAA,GACN;AAAA,IACA,gBAAAA;AAAA,MAACohB;AAAA,MAAA;AAAA,QACC,OAAA1a;AAAA,QACA,SAAA2a;AAAA,QACA,SAAAxM;AAAA,QACA,aAAAyM;AAAA,QACA,SAASlS,MAAU;AAAA,QACnB,UAAAzN;AAAA,QACA,YAAYqP,KAAA,gBAAAA,EAAU;AAAA,MAAA;AAAA,IAAA;AAAA,IAEvBtK,EAAM,gBAAgB,SACrB,gBAAA1G,EAAC,KAAA,EAAE,IAAIwiB,GAAe,WAAU,iCAC7B,UAAA9b,EAAM,YAAA,CACT,IACE;AAAA,IACH0I,MAAU,SACT,gBAAApP,EAAC,KAAA,EAAE,IAAIuiB,GAAS,WAAU,wCACvB,UAAAnT,EAAA,CACH,IACE;AAAA,EAAA,GACN;AAEJ;AAOA,SAASsT,GAAkB/jB,GAAmD;;AAC5E,QAAM;AAAA,IACJ,UAAAgG;AAAA,IACA,IAAA9C;AAAA,IACA,eAAA0e;AAAA,IACA,WAAAoC;AAAA,IACA,SAAAC;AAAA,IACA,QAAQC;AAAA,IACR,aAAAC;AAAA,IACA,iBAAAC;AAAA,IACA,SAAAC;AAAA,IACA,WAAApkB;AAAA,IACA,QAAAqJ;AAAA,IACA,MAAAxD;AAAA,EAAA,IACE9F,GACEof,IAAOlc,MAAO,SAAY,WAAW,UACrCiX,IAAY/R,GAAqBpC,CAAQ,GAEzCse,IAAatjB,EAAM;AAAA,IACvB,MACEsI,EAAO,OAAO;AAAA,MACZ,CAACvB,MAAA;;AACC,gBAACA,EAAM,aACNkb,GAAe,IAAIlb,EAAM,IAAI,OAAK9I,IAAAilB,KAAA,gBAAAA,EAAiBnc,EAAM,UAAvB,gBAAA9I,EAA8B,eAAc;AAAA;AAAA,IAAA;AAAA,IAErF,CAACqK,GAAQ4a,CAAc;AAAA,EAAA,GAGnBK,IAAgBvjB,EAAM;AAAA,IAC1B,MAAM2gB,GAAgB,EAAE,QAAQ2C,GAAY,MAAAxe,GAAM,eAAA8b,GAAe;AAAA,IACjE,CAAC0C,GAAYxe,GAAM8b,CAAa;AAAA,EAAA,GAG5B4C,IAAWxjB,EAAM,QAA+B,MAAM;AAC1D,UAAMyjB,IAAOC,GAAYvF,GAAO7V,GAAQ8V,CAAI,CAAC,GAIvCuF,IAAY,IAAI;AAAA,MACpBrb,EAAO,OACJ;AAAA,QACC,CAACvB,MAAA;;AACC,kBAACA,EAAM,YACP,CAACA,EAAM,YACP,EAAEA,EAAM,SAAS,gBAAc9I,IAAA8I,EAAM,aAAN,gBAAA9I,EAAgB,UAAS;AAAA;AAAA,MAAA,EAE3D,IAAI,CAAC8I,MAAUA,EAAM,IAAI;AAAA,IAAA;AAE9B,WAAO,CAACX,GAAQwd,GAASrlB,MAAY;AACnC,YAAMslB,IAAuB,OAAO;AAAA,QAClC,OAAO,QAAQzd,CAAM,EAAE,OAAO,CAAC,CAACnE,GAAM1C,EAAK,MAAM,EAAEA,OAAU,QAAQokB,EAAU,IAAI1hB,CAAI,EAAE;AAAA,MAAA;AAE3F,aAAOwhB,EAAKI,GAASD,GAASrlB,CAAO;AAAA,IACvC;AAAA,EACF,GAAG,CAAC+J,GAAQ8V,CAAI,CAAC,GAEXkE,IAAUwB,GAAqB;AAAA,IACnC,UAAAN;AAAA,IACA,QAAQD;AAAA,IACR,cAAc,EAAE,iBAAiB,GAAA;AAAA,EAAK,CACvC,GAEK,EAAE,WAAAQ,MAAczB,GAChB0B,IACJD,EAAU,gBAAgB5K,EAAU,OAAO,aAAaA,EAAU,OAAO,WAErE8K,IAAW3B,EAAQ,aAAa,OAAOtY,MAAQ;AACnD,IAAAsY,EAAQ,YAAY,aAAa;AACjC,UAAM,EAAE,QAAAlc,GAAQ,YAAAib,EAAA,IAAeF,GAAc;AAAA,MAC3C,QAAQmC;AAAA,MACR,KAAAtZ;AAAA,MACA,MAAAoU;AAAA,MACA,aAAakE,EAAQ,UAAU;AAAA,IAAA,CAChC;AACD,QAAIjB,EAAW,SAAS,GAAG;AACzB,iBAAW6C,KAAa7C;AACtB,QAAAiB,EAAQ,SAAS4B,EAAU,MAAM,EAAE,MAAM,YAAY,SAASA,EAAU,SAAS;AAEnF;AAAA,IACF;AACA,UAAMC,IAAUf,MAAoB,SAAYA,EAAgBhd,CAAM,IAAIA;AAC1E,QAAI;AACF,YAAMmb,IACJrf,MAAO,SACH,MAAMiX,EAAU,OAAO,YAAYgL,CAAO,IAC1C,MAAMhL,EAAU,OAAO,YAAY,EAAE,IAAAjX,GAAI,QAAQiiB,GAAS;AAChE,MAAIjiB,MAAO,SACTogB,EAAQ,MAAA,IAGRA,EAAQ,MAAM,QAAW,EAAE,YAAY,IAAM,GAE/CU,KAAA,QAAAA,EAAYzB;AAAA,IACd,SAAS9R,GAAO;AACd,YAAM4S,IAAa,oBAAI,IAAI,CAAC,GAAGiB,EAAW,IAAI,CAACvc,MAAUA,EAAM,IAAI,GAAG,GAAG,OAAO,KAAKiD,CAAG,CAAC,CAAC;AAC1F,MAAAoY,GAAkB3S,GAAO4S,GAAYC,CAAO,GAC5CW,KAAA,QAAAA,EAAUxT;AAAA,IACZ;AAAA,EACF,CAAC,GAEK2U,MAAYlmB,KAAAD,IAAA8lB,EAAU,OAAO,SAAjB,gBAAA9lB,EAAwB,WAAxB,gBAAAC,EAAmC,cAAW8N,IAAA+X,EAAU,OAAO,SAAjB,gBAAA/X,EAAuB,UAEjFqY,IAAa,CAACpiB,MAAqC;AACvD,UAAM4E,IAAQkd,EAAU,OAAO9hB,CAAI;AACnC,WAAO,QAAO4E,KAAA,gBAAAA,EAAO,YAAY,WAAWA,EAAM,UAAU;AAAA,EAC9D;AAEA,SACE,gBAAAxG,EAACikB,IAAA,EAAc,GAAGhC,GAChB,UAAA,gBAAAnhB;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,UAAU,CAAC2P,MAAU;AACnB,QAAKmT,EAASnT,CAAK;AAAA,MACrB;AAAA,MACA,YAAU;AAAA,MACV,aAAWkT,KAAc;AAAA,MACzB,WAAWtmB,EAAG,aAAauB,CAAS;AAAA,MAEnC,UAAA;AAAA,QAAA,OAAOmlB,KAAc,WACpB,gBAAA/jB;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,MAAK;AAAA,YACL,WAAU;AAAA,YAET,UAAA+jB;AAAA,UAAA;AAAA,QAAA,IAED;AAAA,QACHd,EAAW,IAAI,CAACvc,MAAU;AACzB,gBAAMsK,IAAW6R,KAAA,gBAAAA,EAAiBnc,EAAM;AACxC,kBAAIsK,KAAA,gBAAAA,EAAU,YAAW,KAAa,OAEpC,gBAAAhR;AAAA,YAACqiB;AAAA,YAAA;AAAA,cAEC,OAAA3b;AAAA,cACA,UAAAsK;AAAA,cACA,SAASiR,EAAQ;AAAA,cACjB,OAAO+B,EAAWtd,EAAM,IAAI;AAAA,cAC5B,UAAUid;AAAA,YAAA;AAAA,YALLjd,EAAM;AAAA,UAAA;AAAA,QAQjB,CAAC;AAAA,QACAoc;AAAA,QACAE,MAAY,SACXA,IAEA,gBAAAhjB,EAAC,OAAA,EAAI,WAAU,4CACb,UAAA,gBAAAA,EAACN,GAAA,EAAO,MAAK,UAAS,UAAUikB,GAC7B,gBAAO,SAAY,WAAW,gBACjC,EAAA,CACF;AAAA,MAAA;AAAA,IAAA;AAAA,EAAA,GAGN;AAEJ;AAeO,SAASO,GAAavlB,GAA8C;AACzE,QAAM,EAAE,UAAAgG,GAAU,IAAA9C,EAAA,IAAOlD,GACnByb,IAAevM,GAAUlJ,CAAQ,GACjCwf,IAAStiB,MAAO,QAChBoU,IAAYrC,GAAgBjP,GAAU9C,KAAM,IAAI,QAAW,EAAE,SAASsiB,GAAQ;AAEpF,SAAI/J,EAAa,SAAS,yBAChB0H,IAAA,EAAe,OAAO1H,EAAa,OAAO,WAAWzb,EAAM,WAAW,IAE5EwlB,KAAUlO,EAAU,SAAS,yBACvB6L,IAAA,EAAe,OAAO7L,EAAU,OAAO,WAAWtX,EAAM,WAAW,IAEzEyb,EAAa,SAAS,UAAc+J,KAAUlO,EAAU,SAAS,SAC5D,gBAAAjW,EAAC6hB,IAAA,EAAa,WAAWljB,EAAM,UAAA,CAAW,IAGjD,gBAAAqB;AAAA,IAAC0iB;AAAA,IAAA;AAAA,MACE,GAAG/jB;AAAA,MACJ,QAAQyb,EAAa;AAAA,MACrB,MAAM+J,IAASlO,EAAU,OAAO;AAAA,IAAA;AAAA,EAAA;AAGtC;AC/YAlY,GAAsB,eAAe,gBAAgB;AAoBrD,SAASygB,GAAajM,GAAqB;AAEzC,QAAMkM,KADelM,EAAI,MAAM,QAAQ,CAAC,EAAE,CAAC,KAAKA,GAClB,MAAM,GAAG,EAAE,OAAO,CAACmM,MAAYA,MAAY,EAAE;AAC3E,SAAOD,EAASA,EAAS,SAAS,CAAC,KAAKlM;AAC1C;AAEA,SAAS6R,GAAWllB,GAAuB;AACzC,QAAMmK,IAAQ,2BAA2B,KAAKnK,CAAK;AACnD,MAAImK,MAAU;AAEZ,WADa,IAAI,KAAK,OAAOA,EAAM,CAAC,CAAC,GAAG,OAAOA,EAAM,CAAC,CAAC,IAAI,GAAG,OAAOA,EAAM,CAAC,CAAC,CAAC,EAClE,mBAAA;AAEd,QAAM6T,IAAO,IAAI,KAAKhe,CAAK;AAC3B,SAAO,OAAO,MAAMge,EAAK,QAAA,CAAS,IAAIhe,IAAQge,EAAK,mBAAA;AACrD;AAEA,SAASmH,GAAenlB,GAAuB;AAC7C,QAAMge,IAAO,IAAI,KAAKhe,CAAK;AAC3B,SAAO,OAAO,MAAMge,EAAK,QAAA,CAAS,IAAIhe,IAAQge,EAAK,eAAA;AACrD;AAEA,SAASoH,GAAc,EAAE,OAAAplB,KAAiD;AACxE,SAAIA,MAAU,QAAQ,OAAOA,KAAU,WAC9B,gBAAAc,EAAAqQ,GAAA,EAAG,UAAA3B,GAAaxP,CAAgC,GAAE,sBAEnD,QAAA,EAAK,WAAU,kDAAkD,UAAA,OAAOA,CAAK,GAAE;AACzF;AAEA,SAASqlB,GAAc,EAAE,OAAArlB,KAAiD;AACxE,SAAI,MAAM,QAAQA,CAAK,IACjBA,EAAM,WAAW,sBAAW6Q,IAAA,EAAW,IAEzC,gBAAA/P,EAAC,UAAK,WAAU,0BACb,YAAM,IAAI,CAACwG,GAAOwI,MACjB,gBAAAhP;AAAA,IAAC;AAAA,IAAA;AAAA,MAEC,WAAU;AAAA,MAEV,UAAA,gBAAAA,EAACskB,IAAA,EAAc,OAAO9d,EAAA,CAAO;AAAA,IAAA;AAAA,IAHxBwI;AAAA,EAAA,CAKR,GACH,IAGG,gBAAAhP,EAACskB,MAAc,OAAAplB,GAAc;AACtC;AAEA,SAAS6Q,KAAiC;AACxC,SAAO,gBAAA/P,EAAC,QAAA,EAAK,WAAU,yBAAwB,UAAA,KAAC;AAClD;AAGA,SAASwkB,GAAa,EAAE,OAAA9d,GAAO,OAAAxH,KAAkE;;AAC/F,MAA2BA,KAAU,QAAQA,MAAU,GAAI,0BAAQ6Q,IAAA,EAAW;AAC9E,UAAQrJ,EAAM,MAAA;AAAA,IACZ,KAAK;AACH,aAAO,gBAAA1G,EAAAqQ,GAAA,EAAG,UAAAnR,IAAQ,QAAQ,MAAK;AAAA,IACjC,KAAK;AACH,aAAO,gBAAAc,EAAAqQ,GAAA,EAAG,UAAA+T,GAAW,OAAOllB,CAAK,CAAC,GAAE;AAAA,IACtC,KAAK;AACH,aAAO,gBAAAc,EAAAqQ,GAAA,EAAG,UAAAgU,GAAe,OAAOnlB,CAAK,CAAC,GAAE;AAAA,IAC1C,KAAK;AACH,aAAO,gBAAAc,EAAAqQ,GAAA,EAAG,YAAAzS,IAAA8I,EAAM,eAAN,gBAAA9I,EAAmB,OAAOsB,CAAK,OAAMwgB,GAAc,OAAOxgB,CAAK,CAAC,EAAA,CAAE;AAAA,IAC9E,KAAK;AACH,aAAO,gBAAAc,EAACukB,MAAc,OAAArlB,GAAc;AAAA,IACtC,KAAK;AACH,aACE,gBAAAc;AAAA,QAAC;AAAA,QAAA;AAAA,UACC,MAAM,OAAOd,CAAK;AAAA,UAClB,QAAO;AAAA,UACP,KAAI;AAAA,UACJ,WAAU;AAAA,UAET,UAAAsf,GAAa,OAAOtf,CAAK,CAAC;AAAA,QAAA;AAAA,MAAA;AAAA,IAGjC,KAAK;AACH,aACE,gBAAAc,EAAC,SAAI,WAAU,mDACZ,eAAK,UAAUd,GAAO,MAAM,CAAC,EAAA,CAChC;AAAA,IAEJ,KAAK;AAAA,IACL,KAAK;AACH,aAAO,gBAAAc,EAAAqQ,GAAA,EAAG,iBAAOnR,KAAU,WAAWA,EAAM,eAAA,IAAmB,OAAOA,CAAK,EAAA,CAAE;AAAA,IAC/E,KAAK;AACH,aAAO,gBAAAc,EAAAqQ,GAAA,EAAG,UAAA,MAAM,QAAQnR,CAAK,IAAIA,EAAM,IAAI,MAAM,EAAE,KAAK,IAAI,IAAI,OAAOA,CAAK,GAAE;AAAA,IAChF;AACE,aAAO,gBAAAc,EAAAqQ,GAAA,EAAG,UAAA,OAAOnR,CAAK,GAAE;AAAA,EAAA;AAE9B;AAEA,SAASulB,GAAe,EAAE,WAAA7lB,KAAyD;AACjF,SACE,gBAAAoB,EAAC,SAAI,MAAK,UAAS,cAAW,mBAAkB,WAAW3C,EAAG,aAAauB,CAAS,GACjF,WAAC,GAAG,GAAG,GAAG,CAAC,EAAE,IAAI,CAACsS,MACjB,gBAAApQ,EAAC,OAAA,EAAc,WAAU,kDACvB,UAAA;AAAA,IAAA,gBAAAd,EAAC8D,IAAA,EAAS,WAAU,WAAA,CAAW;AAAA,IAC/B,gBAAA9D,EAAC8D,IAAA,EAAS,WAAU,yBAAA,CAAyB;AAAA,EAAA,KAFrCoN,CAGV,CACD,GACH;AAEJ;AAEA,SAASwT,GAAY;AAAA,EACnB,OAAAtV;AAAA,EACA,SAAAuV;AAAA,EACA,WAAA/lB;AACF,GAIuB;AACrB,SACE,gBAAAkC;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,MAAK;AAAA,MACL,WAAWzD;AAAA,QACT;AAAA,QACAuB;AAAA,MAAA;AAAA,MAGF,UAAA;AAAA,QAAA,gBAAAoB,EAAC,OAAG,UAAAoP,aAAiB,QAAQA,EAAM,UAAU,OAAOA,CAAK,GAAE;AAAA,QAC3D,gBAAApP,EAACN,KAAO,SAAQ,WAAU,MAAK,MAAK,SAASilB,GAAS,UAAA,QAAA,CAEtD;AAAA,MAAA;AAAA,IAAA;AAAA,EAAA;AAGN;AAEA,SAASC,GAAUjmB,GAKI;AACrB,QAAM,EAAE,OAAA+H,GAAO,MAAAjC,GAAM,UAAAuM,GAAU,OAAA6T,MAAUlmB,GACnCO,IAAQuF,EAAKiC,EAAM,IAAI;AAC7B,SACE,gBAAA5F;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,WAAWzD;AAAA,QACT;AAAA,QACAwnB,IAAQ,iBAAiB;AAAA,MAAA;AAAA,MAG3B,UAAA;AAAA,QAAA,gBAAA7kB,EAAC,QAAG,WAAU,qCAAqC,WAAAgR,KAAA,gBAAAA,EAAU,UAAStK,EAAM,OAAM;AAAA,QAClF,gBAAA1G,EAAC,QAAG,WAAW3C,EAAG,iBAAiBwnB,IAAQ,0BAA0B,iBAAiB,GACnF,WAAA7T,KAAA,gBAAAA,EAAU,YAAW,SACpBA,EAAS,OAAO9R,GAAOuF,CAAI,IAE3B,gBAAAzE,EAACwkB,IAAA,EAAa,OAAA9d,GAAc,OAAAxH,EAAA,CAAc,EAAA,CAE9C;AAAA,MAAA;AAAA,IAAA;AAAA,EAAA;AAGN;AAcO,SAAS4lB,GAAenmB,GAAgD;AAC7E,QAAM,EAAE,UAAAgG,GAAU,IAAA9C,GAAI,QAAA4E,GAAQ,UAAAse,GAAU,QAAAlL,GAAQ,OAAAtP,GAAO,SAAAyY,GAAS,WAAApkB,EAAA,IAAcD,GACxEqmB,IAAkBrlB,EAAM,MAAA,GACxBya,IAAevM,GAAUlJ,CAAQ,GACjCT,IAAyCvE,EAAM;AAAA,IACnD,MAAOka,MAAW,UAAaA,EAAO,SAAS,IAAI,EAAE,QAAAA,MAAW;AAAA,IAChE,CAACA,CAAM;AAAA,EAAA,GAEH5D,IAAYrC,GAAgBjP,GAAU9C,GAAIqC,CAAM,GAEhDkL,IAAQgL,EAAa,SAASnE,EAAU;AAC9C,MAAI7G,KAAS;AACX,WACE,gBAAApP;AAAA,MAAC0kB;AAAA,MAAA;AAAA,QACC,OAAAtV;AAAA,QACA,SAAS,MAAM;AACb,UAAK6G,EAAU,QAAA;AAAA,QACjB;AAAA,QACA,WAAArX;AAAA,MAAA;AAAA,IAAA;AAIN,MAAIwb,EAAa,SAAS,UAAanE,EAAU,SAAS;AACxD,WAAO,gBAAAjW,EAACykB,MAAe,WAAA7lB,GAAsB;AAG/C,QAAM6F,IAAOwR,EAAU,MACjBgP,IAAgB7K,EAAa,KAAK,OAAO;AAAA,IAC7C,CAAC1T,MAAA;;AACC,cAACA,EAAM,aAAaA,EAAM,SAAS,eAAa9I,IAAA6I,KAAA,gBAAAA,EAASC,EAAM,UAAf,gBAAA9I,EAAsB,YAAW;AAAA;AAAA,EAAA,GAE/E,EAAE,QAAAyQ,GAAQ,OAAAC,MAAUF,GAAqB6W,CAAa;AAE5D,2BACG,OAAA,EAAI,WAAW5nB,EAAG,aAAauB,CAAS,GACtC,UAAA;AAAA,IAAA2L,MAAU,UAAayY,MAAY,SAClC,gBAAAliB,EAAC,OAAA,EAAI,WAAU,qDACZ,UAAA;AAAA,MAAAyJ,MAAU,2BACR,MAAA,EAAG,WAAU,wCAAwC,UAAAA,EAAA,CAAM,sBAE3D,OAAA,CAAA,CAAI;AAAA,MAENyY,MAAY,SAAY,gBAAAhjB,EAAC,SAAI,WAAU,2BAA2B,aAAQ,IAAS;AAAA,IAAA,EAAA,CACtF,IACE;AAAA,sBACH,MAAA,EAAG,WAAU,0BACX,UAAAqO,EAAO,IAAI,CAAC3H,MACX,gBAAA1G;AAAA,MAAC4kB;AAAA,MAAA;AAAA,QAEC,OAAAle;AAAA,QACA,MAAAjC;AAAA,QACA,UAAUgC,KAAA,gBAAAA,EAASC,EAAM;AAAA,QACzB,OAAO;AAAA,MAAA;AAAA,MAJFA,EAAM;AAAA,IAAA,CAMd,GACH;AAAA,IACC4H,EAAM,SAAS,IACd,gBAAAxN;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,mBAAiBkkB;AAAA,QACjB,WAAU;AAAA,QAEV,UAAA;AAAA,UAAA,gBAAAhlB;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,IAAIglB;AAAA,cACJ,WAAU;AAAA,cACX,UAAA;AAAA,YAAA;AAAA,UAAA;AAAA,4BAGA,MAAA,EAAG,WAAU,0BACX,UAAA1W,EAAM,IAAI,CAAC5H,MACV,gBAAA1G;AAAA,YAAC4kB;AAAA,YAAA;AAAA,cAEC,OAAAle;AAAA,cACA,MAAAjC;AAAA,cACA,UAAUgC,KAAA,gBAAAA,EAASC,EAAM;AAAA,cACzB,OAAK;AAAA,YAAA;AAAA,YAJAA,EAAM;AAAA,UAAA,CAMd,EAAA,CACH;AAAA,QAAA;AAAA,MAAA;AAAA,IAAA,IAEA;AAAA,IACHqe,MAAa,UAAaA,EAAS,SAAS,IAC3C,gBAAA/kB,EAAC,OAAA,EAAI,WAAU,aACZ,UAAA+kB,EAAS,IAAI,CAACG,GAASlW,MACtB,gBAAAhP,EAAC,OAAA,EAAiB,eAARgP,CAAgB,CAC3B,GACH,IACE;AAAA,EAAA,GACN;AAEJ;AC3PO,SAASmW,GACdxgB,GACA9C,GACAqC,GACoB;AACpB,SAAO,CAAC,GAAGW,GAAU,SAASF,CAAQ,GAAG,WAAW,OAAO9C,CAAE,GAAGqC,KAAU,EAAE;AAC9E;AAGO,SAASkhB,GACdzgB,GACA9C,GACAqC,GACAhG,GACmC;AACnC,QAAM+G,IAASM,GAAA;AACf,SAAOG,GAA4B;AAAA,IACjC,GAAGxH;AAAA,IACH,UAAUinB,GAAiBxgB,GAAU9C,GAAIqC,CAAM;AAAA,IAC/C,SAAS,CAAC,EAAE,QAAAyB,EAAA,MACVV,EAAO,QAA2B,GAAGL,GAAWD,GAAU9C,CAAE,CAAC,YAAY;AAAA,MACvE,OAAO,EAAE,WAAWqC,KAAA,gBAAAA,EAAQ,UAAU,MAAMA,KAAA,gBAAAA,EAAQ,KAAA;AAAA,MACpD,QAAAyB;AAAA,IAAA,CACD;AAAA,EAAA,CACJ;AACH;AC3DA5H,GAAsB,kBAAkB,eAAe;AAavD,MAAMsnB,KAAyD;AAAA,EAC7D,QAAQ;AAAA,EACR,QAAQ;AAAA,EACR,QAAQ;AAAA,EACR,SAAS;AACX;AAEA,SAASC,GAAWpmB,GAAuB;AACzC,QAAMge,IAAO,IAAI,KAAKhe,CAAK;AAC3B,SAAO,OAAO,MAAMge,EAAK,QAAA,CAAS,IAAIhe,IAAQge,EAAK,eAAA;AACrD;AAEA,SAASqI,GAAM,EAAE,OAAArmB,KAAiD;AAChE,MAAIA,KAAU,QAA+BA,MAAU;AACrD,WAAO,gBAAAc,EAAC,QAAA,EAAK,WAAU,yBAAwB,UAAA,KAAC;AAElD,MAAId,MAAU;AACZ,WAAO,gBAAAc,EAAC,QAAA,EAAK,WAAU,gCAA+B,UAAA,YAAQ;AAEhE,QAAMsJ,IAAO,OAAOpK,KAAU,WAAW,KAAK,UAAUA,CAAK,IAAI,OAAOA,CAAK;AAC7E,SAAO,gBAAAc,EAAC,QAAA,EAAK,WAAU,eAAe,UAAAsJ,GAAK;AAC7C;AAEA,SAASkc,GAAM,EAAE,OAAAhf,KAAwD;;AACvE,QAAMC,IAAS,OAAO,QAAQD,EAAM,IAAI;AACxC,2BACG,MAAA,EAAG,WAAU,yCAAwC,eAAaA,EAAM,QACvE,UAAA;AAAA,IAAA,gBAAA1F,EAAC,OAAA,EAAI,WAAU,iDACb,UAAA;AAAA,MAAA,gBAAAd,EAAC,QAAA,EAAK,WAAU,eAAe,UAAAqlB,GAAa7e,EAAM,MAAM,KAAKA,EAAM,OAAA,CAAO;AAAA,MAC1E,gBAAAxG,EAAC,QAAA,EAAK,UAAUwG,EAAM,WAAW,WAAU,yBACxC,UAAA8e,GAAW9e,EAAM,SAAS,EAAA,CAC7B;AAAA,wBACC,QAAA,EAAK,WAAU,yBAAyB,YAAA5I,IAAA4I,EAAM,UAAN,gBAAA5I,EAAa,UAAS,IAAA,CAAI;AAAA,IAAA,GACrE;AAAA,IACC6I,EAAO,SAAS,IACf,gBAAAzG,EAAC,QAAG,WAAU,yDACX,YAAO,IAAI,CAAC,CAAC4B,GAAM,CAAC6jB,GAAQC,CAAK,CAAC,MACjC,gBAAA5kB,EAACnB,EAAM,UAAN,EACC,UAAA;AAAA,MAAA,gBAAAK,EAAC,MAAA,EAAG,WAAU,2CAA2C,UAAA4B,GAAK;AAAA,MAC9D,gBAAAd,EAAC,MAAA,EAAG,WAAU,qCACZ,UAAA;AAAA,QAAA,gBAAAd,EAACulB,IAAA,EAAM,OAAOE,EAAA,CAAQ;AAAA,0BACrB,QAAA,EAAK,eAAY,QAAO,WAAU,yBAAwB,UAAA,KAE3D;AAAA,QACA,gBAAAzlB,EAACulB,IAAA,EAAM,OAAOG,EAAA,CAAO;AAAA,MAAA,EAAA,CACvB;AAAA,IAAA,EAAA,GARmB9jB,CASrB,CACD,EAAA,CACH,sBAEC,KAAA,EAAE,WAAU,8BAA6B,UAAA,4BAAA,CAAyB;AAAA,EAAA,GAEvE;AAEJ;AAQO,SAAS+jB,GAAc;AAAA,EAC5B,UAAAhhB;AAAA,EACA,IAAA9C;AAAA,EACA,UAAA0N;AAAA,EACA,OAAAhF,IAAQ;AAAA,EACR,OAAA2P,IAAQ;AAAA,EACR,WAAAtb;AACF,GAA2C;AACzC,QAAMuF,IAAQihB,GAAiBzgB,GAAU9C,GAAI0N,MAAa,SAAY,EAAE,UAAAA,EAAA,IAAa,MAAS;AAC9F,SACE,gBAAAzO,EAAC,aAAQ,WAAWzD,EAAG,aAAauB,CAAS,GAAG,cAAW,kBACxD,UAAA;AAAA,IAAA2L,MAAU,OAAO,gBAAAvK,EAAC,MAAA,EAAG,WAAU,2BAA2B,aAAM,IAAQ;AAAA,IACxEmE,EAAM,YACL,gBAAArD,EAAC,SAAI,WAAU,aAAY,eAAY,0BACrC,UAAA;AAAA,MAAA,gBAAAd,EAAC8D,IAAA,EAAS,WAAU,cAAA,CAAc;AAAA,MAClC,gBAAA9D,EAAC8D,IAAA,EAAS,WAAU,cAAA,CAAc;AAAA,IAAA,EAAA,CACpC,IACEK,EAAM,QACR,gBAAAnE,EAAC,OAAE,MAAK,SAAQ,WAAU,4BACvB,UAAAmE,EAAM,iBAAiB,QAAQA,EAAM,MAAM,UAAU,+BAAA,CACxD,IACEA,EAAM,KAAK,QAAQ,WAAW,sBAC/B,KAAA,EAAE,WAAU,iCAAiC,UAAA+V,EAAA,CAAM,sBAEnD,MAAA,EAAG,WAAU,aACX,UAAA/V,EAAM,KAAK,QAAQ,IAAI,CAACqC,MACvB,gBAAAxG,EAACwlB,IAAA,EAAqB,OAAAhf,KAAVA,EAAM,EAAkB,CACrC,EAAA,CACH;AAAA,EAAA,GAEJ;AAEJ;AChGAzI,GAAsB,mBAAmB,gBAAgB;AAUzD,SAAS6nB,GAAUxW,GAAwB;AACzC,MAAIA,aAAiB,OAAO;AAC1B,UAAMM,IAAQN,EAA6B;AAC3C,QAAI,OAAOM,KAAS,YAAYA,MAAS,QAAQ,YAAYA,GAAM;AACjE,YAAMC,IAAUD,EAA8B;AAC9C,UAAI,OAAOC,KAAW,SAAU,QAAOA;AAAA,IACzC;AACA,WAAOP,EAAM;AAAA,EACf;AACA,SAAO;AACT;AAEA,SAASyW,GAAM,EAAE,KAAA7T,KAAsD;AACrE,MAAIA,EAAI,WAAW,KAAM,QAAO;AAChC,QAAM,EAAE,SAAA8T,GAAS,SAAAC,GAAS,SAAAC,GAAS,WAAAC,GAAW,QAAAC,EAAA,IAAWlU,EAAI;AAC7D,SACE,gBAAAlR,EAAC,MAAA,EAAG,WAAU,wBAAuB,eAAY,gBAC/C,UAAA;AAAA,IAAA,gBAAAA,EAAC,OAAA,EACC,UAAA;AAAA,MAAA,gBAAAd,EAAC,MAAA,EAAG,WAAU,2CAA0C,UAAA,WAAO;AAAA,MAC/D,gBAAAA,EAAC,MAAA,EAAG,WAAU,0BAA0B,UAAA8lB,EAAA,CAAQ;AAAA,IAAA,GAClD;AAAA,sBACC,OAAA,EACC,UAAA;AAAA,MAAA,gBAAA9lB,EAAC,MAAA,EAAG,WAAU,2CAA0C,UAAA,WAAO;AAAA,MAC/D,gBAAAA,EAAC,MAAA,EAAG,WAAU,0BAA0B,UAAA+lB,EAAA,CAAQ;AAAA,IAAA,GAClD;AAAA,sBACC,OAAA,EACC,UAAA;AAAA,MAAA,gBAAA/lB,EAAC,MAAA,EAAG,WAAU,2CAA0C,UAAA,WAAO;AAAA,MAC/D,gBAAAc,EAAC,MAAA,EAAG,WAAU,0BACX,UAAA;AAAA,QAAAklB;AAAA,QAAS;AAAA,QACV,gBAAAllB,EAAC,QAAA,EAAK,WAAU,6CAA4C,UAAA;AAAA,UAAA;AAAA,UACxDmlB;AAAA,UAAU;AAAA,UAAaC;AAAA,UAAO;AAAA,QAAA,EAAA,CAClC;AAAA,MAAA,EAAA,CACF;AAAA,IAAA,EAAA,CACF;AAAA,EAAA,GACF;AAEJ;AAEA,SAASC,GAAS,EAAE,KAAAnU,KAAsD;AACxE,SAAIA,EAAI,SAAS,WAAW,IAAU,OAEpC,gBAAAhS,EAAC,SAAI,WAAU,mDACb,4BAAC,SAAA,EAAM,WAAU,kBAAiB,cAAW,oBAC3C,UAAA;AAAA,IAAA,gBAAAA,EAAC,SAAA,EAAM,WAAU,8DACf,UAAA,gBAAAc,EAAC,MAAA,EACC,UAAA;AAAA,MAAA,gBAAAd,EAAC,MAAA,EAAG,WAAU,aAAY,UAAA,OAAG;AAAA,MAC7B,gBAAAA,EAAC,MAAA,EAAG,WAAU,aAAY,UAAA,SAAK;AAAA,MAC/B,gBAAAA,EAAC,MAAA,EAAG,WAAU,aAAY,UAAA,UAAA,CAAO;AAAA,IAAA,EAAA,CACnC,EAAA,CACF;AAAA,IACA,gBAAAA,EAAC,SAAA,EACE,UAAAgS,EAAI,SAAS,IAAI,CAACoU,GAASpX,MAC1B,gBAAAlO,EAAC,MAAA,EAAoD,WAAU,0BAC7D,UAAA;AAAA,MAAA,gBAAAd,EAAC,MAAA,EAAG,WAAU,0BAA0B,UAAAomB,EAAQ,KAAI;AAAA,wBACnD,MAAA,EAAG,WAAU,+BAA+B,UAAAA,EAAQ,SAAS,KAAI;AAAA,MAClE,gBAAApmB,EAAC,MAAA,EAAG,WAAU,8BAA8B,YAAQ,QAAA,CAAQ;AAAA,IAAA,EAAA,GAHrD,GAAGomB,EAAQ,GAAG,IAAIA,EAAQ,KAAK,IAAIpX,CAAK,EAIjD,CACD,EAAA,CACH;AAAA,EAAA,EAAA,CACF,EAAA,CACF;AAEJ;AAEA,SAASqX,GAAS,EAAE,KAAArU,KAA+C;AACjE,QAAMsU,IAAUtU,EAAI,aAAa,IAAI,KAAK,MAAOA,EAAI,YAAY,MAAOA,EAAI,UAAU,IAAI;AAC1F,2BACG,OAAA,EAAI,WAAU,aAAY,MAAK,UAAS,aAAU,UACjD,UAAA;AAAA,IAAA,gBAAAlR,EAAC,KAAA,EAAE,WAAU,WACV,UAAA;AAAA,MAAAkR,EAAI,WAAW,eAAe,eAAe;AAAA,MAAa;AAAA,MAAGA,EAAI;AAAA,MAAU;AAAA,MAAG;AAAA,MAC9EA,EAAI;AAAA,MAAW;AAAA,IAAA,GAClB;AAAA,IACA,gBAAAhS,EAAC,OAAA,EAAI,WAAU,+CACb,4BAAC,OAAA,EAAI,WAAU,oCAAmC,OAAO,EAAE,OAAO,GAAGsmB,CAAO,IAAA,GAAO,EAAA,CACrF;AAAA,EAAA,GACF;AAEJ;AAEA,SAASC,GAAa5nB,GAKC;AACrB,QAAM,EAAE,KAAAqT,GAAK,QAAAvL,GAAQ,SAAAwM,GAAS,UAAAsB,MAAa5V,GACrCT,IAAUuI,EAAO,IAAI,CAACC,OAAW;AAAA,IACrC,OAAOA,EAAM;AAAA,IACb,OAAO,GAAGA,EAAM,IAAI,GAAGA,EAAM,WAAW,OAAO,EAAE,GAAGA,EAAM,MAAM,WAAW,EAAE;AAAA,EAAA,EAC7E;AACF,SACE,gBAAA1G,EAAC,SAAI,WAAU,mDACb,4BAAC,SAAA,EAAM,WAAU,kBAAiB,cAAW,kBAC3C,UAAA;AAAA,IAAA,gBAAAA,EAAC,SAAA,EAAM,WAAU,8DACf,UAAA,gBAAAc,EAAC,MAAA,EACC,UAAA;AAAA,MAAA,gBAAAd,EAAC,MAAA,EAAG,WAAU,aAAY,UAAA,sBAAkB;AAAA,MAC5C,gBAAAA,EAAC,MAAA,EAAG,WAAU,aAAY,UAAA,QAAA,CAAK;AAAA,IAAA,EAAA,CACjC,EAAA,CACF;AAAA,IACA,gBAAAA,EAAC,SAAA,EACE,UAAAgS,EAAI,QAAQ,IAAI,CAACE,MAChB,gBAAApR,EAAC,MAAA,EAAgB,WAAU,0BACzB,UAAA;AAAA,MAAA,gBAAAd,EAAC,MAAA,EAAG,WAAU,aAAa,UAAAkS,GAAO;AAAA,MAClC,gBAAAlS,EAAC,MAAA,EAAG,WAAU,aACZ,UAAA,gBAAAA;AAAA,QAACsB;AAAA,QAAA;AAAA,UACC,cAAY,aAAa4Q,CAAM;AAAA,UAC/B,WAAU;AAAA,UACV,OAAOe,EAAQf,CAAM,KAAK;AAAA,UAC1B,SAAAhU;AAAA,UACA,WAAS;AAAA,UACT,YAAW;AAAA,UACX,eAAe,CAACmE,MAASkS,EAASrC,GAAQ7P,KAAQ,EAAE;AAAA,QAAA;AAAA,MAAA,EACtD,CACF;AAAA,IAAA,EAAA,GAZO6P,CAaT,CACD,EAAA,CACH;AAAA,EAAA,EAAA,CACF,EAAA,CACF;AAEJ;AAUO,SAASsU,GAAe;AAAA,EAC7B,UAAA7hB;AAAA,EACA,OAAA4F,IAAQ;AAAA,EACR,QAAAkc;AAAA,EACA,WAAA7nB;AACF,GAA4C;;AAC1C,QAAMqG,IAASM,GAAA,GACT6N,IAAWV,GAAkB/N,CAAQ,GACrCqe,IAAUnQ,GAAiBlO,CAAQ,GACnC,CAACgN,GAAO+U,CAAQ,IAAI/mB,EAAM,SAA6B,MAAS,GAChE,CAACsT,GAAS0T,CAAU,IAAIhnB,EAAM,SAAiC,CAAA,CAAE,GACjE,CAACinB,GAAOC,CAAQ,IAAIlnB,EAAM,SAAS,EAAK,GACxC,CAACmnB,GAAeC,CAAgB,IAAIpnB,EAAM,SAAwB,IAAI,GACtEqnB,IAAUrnB,EAAM,OAAyB,IAAI,GAC7CsnB,IAAWtU,GAAahO,GAAUgN,CAAK,GACvCK,IAAMiV,EAAS,MAGfC,IAAYvnB,EAAM,OAA2B,MAAS;AAC5D,EAAAA,EAAM,UAAU,MAAM;AACpB,IAAIqS,MAAQ,UAAakV,EAAU,YAAYlV,EAAI,OACjDkV,EAAU,UAAUlV,EAAI,IACxB2U,EAAW3U,EAAI,OAAO;AAAA,EAE1B,GAAG,CAACA,CAAG,CAAC,GAERrS,EAAM,UAAU,MAAM;AACpB,KAAIqS,KAAA,gBAAAA,EAAK,YAAW,WAAQyU,KAAA,QAAAA,EAASzU;AAAA,EAEvC,GAAG,CAACA,KAAA,gBAAAA,EAAK,QAAQA,KAAA,gBAAAA,EAAK,EAAE,CAAC;AAEzB,QAAMvL,KAASuL,KAAA,gBAAAA,EAAK,aAAUpU,IAAAwV,EAAS,SAAT,gBAAAxV,EAAe,WAAU,CAAA,GACjD2V,IAAOyP,EAAQ,OAAO,aAAaA,EAAQ,QAAQ,aAAaA,EAAQ,OAAO,WAC/EmE,IAAgBnE,EAAQ,OAAO,SAASA,EAAQ,QAAQ,SAASA,EAAQ,OAAO,OAEhFoE,IAAe,CAAC3W,MAAkD;;AACtE,IAAAA,EAAM,eAAA;AACN,UAAMuC,KAAOnV,KAAAD,IAAAopB,EAAQ,YAAR,gBAAAppB,EAAiB,UAAjB,gBAAAC,EAAyB;AACtC,IAAImV,MAAS,WACb6T,EAAS,EAAK,GACd7D,EAAQ,OAAO,OAAO,EAAE,MAAAhQ,EAAA,GAAQ,EAAE,WAAW,CAAC8S,MAAYY,EAASZ,EAAQ,EAAE,GAAG;AAAA,EAClF,GAEMuB,IAAgB,MAAY;AAChC,IAAIrV,MAAQ,WACZ6U,EAAS,EAAK,GACd7D,EAAQ,QAAQ,OAAO,EAAE,OAAOhR,EAAI,IAAI,SAAAiB,GAAS;AAAA,EACnD,GAEMqU,IAAiB,CAACxc,MAAiC;AACvD,IAAAic,EAAiB,IAAI,GACrBtU,GAAuBxN,GAAQN,GAAUmG,CAAM,EAAE;AAAA,MAAM,CAACsE,MACtD2X,EAAiBnB,GAAUxW,CAAK,CAAC;AAAA,IAAA;AAAA,EAErC;AAEA,MAAIxD;AACJ,SAAIwH,EAAS,YACXxH,IAAO,gBAAA5L,EAAC8D,IAAA,EAAS,WAAU,eAAc,eAAY,2BAA0B,IACtEkO,MAAQ,UAAcL,MAAU,UAAasV,EAAS,YAC/Drb,IACE,gBAAA9K,EAAC,QAAA,EAAK,UAAUsmB,GAAc,WAAU,kCACtC,UAAA;AAAA,IAAA,gBAAAtmB,EAAC,SAAA,EAAM,WAAU,+BACf,UAAA;AAAA,MAAA,gBAAAd,EAAC,UAAK,UAAA,mBAAA,CAAgB;AAAA,MACtB,gBAAAA;AAAA,QAAC;AAAA,QAAA;AAAA,UACC,KAAKgnB;AAAA,UACL,MAAK;AAAA,UACL,MAAK;AAAA,UACL,QAAO;AAAA,UACP,UAAQ;AAAA,UACR,WAAU;AAAA,UACV,cAAW;AAAA,QAAA;AAAA,MAAA;AAAA,IACb,GACF;AAAA,sBACCtnB,GAAA,EAAO,MAAK,UAAS,UAAU6T,GAAM,UAAA,SAAA,CAEtC;AAAA,EAAA,GACF,IAEOxB,GAAiBC,CAAG,IAC7BpG,IAAO,gBAAA5L,EAACqmB,MAAS,KAAArU,EAAA,CAAU,IAClBA,EAAI,WAAW,cAAcA,EAAI,WAAW,YAAY4U,IACjEhb,IACE,gBAAA9K,EAAC,OAAA,EAAI,WAAU,aACZ,UAAA;AAAA,IAAAkR,EAAI,UAAU,QACb,gBAAAhS,EAAC,KAAA,EAAE,MAAK,SAAQ,WAAU,4BACvB,UAAAgS,EAAI,MAAA,CACP;AAAA,IAEF,gBAAAlR,EAAC,KAAA,EAAE,WAAU,iCACV,UAAA;AAAA,MAAAkR,EAAI;AAAA,MAAU;AAAA,MAAIA,EAAI;AAAA,MAAW;AAAA,IAAA,GAEpC;AAAA,IACA,gBAAAhS;AAAA,MAACumB;AAAA,MAAA;AAAA,QACC,KAAAvU;AAAA,QACA,QAAAvL;AAAA,QACA,SAAAwM;AAAA,QACA,UAAU,CAACf,GAAQxL,MAAUigB,EAAW,CAAC1L,OAAS,EAAE,GAAGA,GAAK,CAAC/I,CAAM,GAAGxL,IAAQ;AAAA,MAAA;AAAA,IAAA;AAAA,IAEhF,gBAAA5F,EAAC,OAAA,EAAI,WAAU,wBACb,UAAA;AAAA,MAAA,gBAAAd,EAACN,GAAA,EAAO,SAAS2nB,GAAe,UAAU9T,GAAM,UAAA,WAEhD;AAAA,MACA,gBAAAvT,EAACN,GAAA,EAAO,SAAQ,WAAU,SAAS,MAAMgnB,EAAS,MAAS,GAAG,UAAUnT,GAAM,UAAA,sBAAA,CAE9E;AAAA,IAAA,EAAA,CACF;AAAA,EAAA,GACF,IAGF3H,IACE,gBAAA9K,EAAC,OAAA,EAAI,WAAU,aACb,UAAA;AAAA,IAAA,gBAAAA,EAAC,KAAA,EAAE,WAAU,iCACV,UAAA;AAAA,MAAAkR,EAAI;AAAA,MAAU;AAAA,MAAIA,EAAI;AAAA,MAAW;AAAA,MAAO;AAAA,MACxCA,EAAI,WAAW,SAAS,cAAc;AAAA,IAAA,GACzC;AAAA,IACA,gBAAAhS,EAAC6lB,MAAM,KAAA7T,GAAU;AAAA,IACjB,gBAAAhS,EAACmmB,MAAS,KAAAnU,GAAU;AAAA,sBACnB,OAAA,EAAI,WAAU,wBACZ,UAAAA,EAAI,WAAW,cACd,gBAAAlR,EAAAuP,GAAA,EACE,UAAA;AAAA,MAAA,gBAAArQ,EAACN,GAAA,EAAO,SAAS,MAAMsjB,EAAQ,OAAO,OAAOhR,EAAI,EAAE,GAAG,UAAUuB,GAAM,UAAA,SAAA,CAEtE;AAAA,MACA,gBAAAvT,EAACN,GAAA,EAAO,SAAQ,WAAU,SAAS,MAAMmnB,EAAS,EAAI,GAAG,UAAUtT,GAAM,UAAA,qBAAA,CAEzE;AAAA,IAAA,EAAA,CACF,IAEA,gBAAAvT,EAACN,GAAA,EAAO,SAAQ,WAAU,SAAS,MAAMgnB,EAAS,MAAS,GAAG,UAAA,sBAAA,CAE9D,EAAA,CAEJ;AAAA,EAAA,GACF,GAKF,gBAAA5lB,EAAC,aAAQ,WAAWzD,EAAG,aAAauB,CAAS,GAAG,cAAW,UACzD,UAAA;AAAA,IAAA,gBAAAkC,EAAC,OAAA,EAAI,WAAU,uDACZ,UAAA;AAAA,MAAAyJ,MAAU,OAAO,gBAAAvK,EAAC,MAAA,EAAG,WAAU,2BAA2B,aAAM,IAAQ;AAAA,MACzE,gBAAAc,EAAC,OAAA,EAAI,WAAU,sBACb,UAAA;AAAA,QAAA,gBAAAd;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,MAAK;AAAA,YACL,WAAU;AAAA,YACV,SAAS,MAAMsnB,EAAe,MAAM;AAAA,YACrC,UAAA;AAAA,UAAA;AAAA,QAAA;AAAA,QAGD,gBAAAtnB;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,MAAK;AAAA,YACL,WAAU;AAAA,YACV,SAAS,MAAMsnB,EAAe,KAAK;AAAA,YACpC,UAAA;AAAA,UAAA;AAAA,QAAA;AAAA,MAED,EAAA,CACF;AAAA,IAAA,GACF;AAAA,IACClU,EAAS,UAAU,QAAQA,EAAS,UAAU,SAC7C,gBAAApT,EAAC,KAAA,EAAE,MAAK,SAAQ,WAAU,4BACvB,UAAA4lB,GAAUxS,EAAS,KAAK,GAC3B,IACE;AAAA,IACH+T,KAAkB,OACjB,gBAAAnnB,EAAC,KAAA,EAAE,MAAK,SAAQ,WAAU,4BACvB,UAAA4lB,GAAUuB,CAAa,GAC1B,IACE;AAAA,IACHL,MAAkB,OACjB,gBAAA9mB,EAAC,KAAA,EAAE,MAAK,SAAQ,WAAU,4BACvB,UAAA8mB,EAAA,CACH,IACE;AAAA,IACHlb;AAAA,EAAA,GACH;AAEJ;ACpQA,SAASlE,GAASxI,GAAkD;AAClE,SAAO,OAAOA,KAAU,YAAYA,MAAU,QAAQ,CAAC,MAAM,QAAQA,CAAK;AAC5E;AAEA,SAASqoB,GAAeC,GAAgB9X,GAAuB;AAC7D,SAAIhI,GAASgI,CAAI,KAAK,OAAOA,EAAK,UAAc,WAAiBA,EAAK,SAC/D,wCAAwC8X,CAAM;AACvD;AAGO,MAAMC,WAAsB,MAAM;AAAA,EAKvC,YAAYD,GAAgB9X,GAAepR,GAAkB;AAC3D,UAAMA,KAAWipB,GAAeC,GAAQ9X,CAAI,CAAC;AALtC,IAAAgY,EAAA;AAEA;AAAA,IAAAA,EAAA;AAIP,SAAK,OAAO,iBACZ,KAAK,SAASF,GACd,KAAK,OAAO9X;AAAA,EACd;AACF;AAkBA,SAASiY,GAAaC,GAAuD;AAC3E,QAAMve,IAAQ,8BAA8B,KAAKue,CAAO;AACxD,SAAIve,MAAU,OACL,EAAE,QAAQA,EAAM,CAAC,KAAK,IAAI,WAAWA,EAAM,CAAC,KAAK,IAAI,QAAQ,QAAQ,EAAE,EAAA,IAEzE,EAAE,QAAQ,IAAI,UAAUue,EAAQ,QAAQ,QAAQ,EAAE,EAAA;AAC3D;AAEA,SAASC,GAAQD,GAAiB3c,GAAsB;AACtD,MAAI,eAAe,KAAKA,CAAI,EAAG,QAAOA;AACtC,QAAM,EAAE,QAAA6c,GAAQ,UAAAC,MAAaJ,GAAaC,CAAO,GAC3CrjB,IAAa0G,EAAK,WAAW,GAAG,IAAIA,IAAO,IAAIA,CAAI;AACzD,SAAI8c,MAAa,OAAOxjB,MAAewjB,KAAYxjB,EAAW,WAAW,GAAGwjB,CAAQ,GAAG,KAC9ED,IAASvjB,IAEXujB,IAASC,IAAWxjB;AAC7B;AAEA,SAASyjB,GAAYzV,GAAapO,GAA4D;AAC5F,MAAIA,MAAU,OAAW,QAAOoO;AAChC,QAAMrO,IAAS,IAAI,gBAAA;AACnB,aAAW,CAAC3E,GAAKL,CAAK,KAAK,OAAO,QAAQiF,CAAK;AAC7C,QAAIjF,KAAU;AACd,UAAI,MAAM,QAAQA,CAAK;AACrB,mBAAWuF,KAAQvF,EAAO,CAAAgF,EAAO,OAAO3E,GAAK,OAAOkF,CAAI,CAAC;AAAA;AAEzD,QAAAP,EAAO,OAAO3E,GAAK,OAAOL,CAAK,CAAC;AAGpC,QAAM+oB,IAAK/jB,EAAO,SAAA;AAClB,SAAI+jB,MAAO,KAAW1V,IACfA,EAAI,SAAS,GAAG,IAAI,GAAGA,CAAG,IAAI0V,CAAE,KAAK,GAAG1V,CAAG,IAAI0V,CAAE;AAC1D;AAIA,eAAeC,GAAUzc,GAAsC;AAC7D,MAAIA,EAAS,WAAW,OAAOA,EAAS,WAAW,IAAK;AACxD,QAAMnC,IAAO,MAAMmC,EAAS,KAAA;AAC5B,MAAInC,MAAS,GAAI;AAEjB,OADoBmC,EAAS,QAAQ,IAAI,cAAc,KAAK,IAC5C,SAAS,MAAM;AAC7B,QAAI;AACF,aAAO,KAAK,MAAMnC,CAAI;AAAA,IACxB,QAAQ;AACN,aAAOA;AAAA,IACT;AAEF,SAAOA;AACT;AAKO,SAAS6e,GAAkBjqB,GAA0C;AAC1E,QAAM,EAAE,SAAA0pB,GAAS,WAAAQ,IAAY,gBAAgB,OAAOC,MAAgBnqB;AAEpE,MAAIoqB,IAAwB,CAAA;AAC5B,EAAIpqB,EAAQ,mBAAmB,WAC7BoqB,IAAQ,EAAE,gBAAgBpqB,EAAQ,eAAA;AAGpC,iBAAeqqB,EAAQhW,GAAaiW,GAAwD;;AAC1F,UAAMC,IAAU,IAAI,QAAQ,EAAE,QAAQ,oBAAoB,GACpDC,KAAc9qB,IAAA0qB,EAAM,eAAN,gBAAA1qB,EAAA,KAAA0qB;AACpB,QAAII,MAAgB;AAClB,iBAAW,CAAC9mB,GAAM1C,CAAK,KAAK,OAAO,QAAQwpB,CAAW,EAAG,CAAAD,EAAQ,IAAI7mB,GAAM1C,CAAK;AAElF,QAAIspB,EAAe,YAAY;AAC7B,iBAAW,CAAC5mB,GAAM1C,CAAK,KAAK,OAAO,QAAQspB,EAAe,OAAO;AAC/D,QAAAC,EAAQ,IAAI7mB,GAAM1C,CAAK;AAG3B,UAAMmf,MAAQxgB,IAAAyqB,EAAM,mBAAN,gBAAAzqB,EAAA,KAAAyqB,OAA4B;AAC1C,IAAIjK,MAAU,QAAQA,MAAU,QAAY,IAAI,iBAAiB,UAAUA,CAAK,EAAE;AAElF,QAAIzS;AACJ,IAAI,OAAO,WAAa,OAAe4c,EAAe,gBAAgB,WACpE5c,IAAO4c,EAAe,OACbA,EAAe,SAAS,WACjC5c,IAAO,KAAK,UAAU4c,EAAe,IAAI,GACpCC,EAAQ,IAAI,cAAc,KAAGA,EAAQ,IAAI,gBAAgB,kBAAkB;AAGlF,UAAME,IAAoB,EAAE,QAAQH,EAAe,UAAU,OAAO,SAAAC,EAAA;AACpE,WAAI7c,MAAS,WAAW+c,EAAK,OAAO/c,IAChC4c,EAAe,WAAW,WAAWG,EAAK,SAASH,EAAe,SAClEF,EAAM,gBAAgB,WAAWK,EAAK,cAAcL,EAAM,eAE5CD,KAAe,WAAW,OAC3B9V,GAAKoW,CAAI;AAAA,EAC5B;AAEA,iBAAeC,EACb3d,GACAud,IAAsC,IACnB;AACnB,UAAMjW,IAAMyV,GAAYH,GAAQD,GAAS3c,CAAI,GAAGud,EAAe,KAAK;AAEpE,QAAI/c,IAAW,MAAM8c,EAAQhW,GAAKiW,CAAc;AAChD,QAAI/c,EAAS,GAAI,QAAOA;AAExB,UAAM2D,IAAQ,IAAIqY,GAAchc,EAAS,QAAQ,MAAMyc,GAAUzc,CAAQ,CAAC;AAC1E,QACEA,EAAS,WAAW,OACpB6c,EAAM,mBAAmB,UACzBE,EAAe,oBAAoB,MAEf,MAAMF,EAAM,eAAelZ,CAAK,GACnC;AAEf,UADA3D,IAAW,MAAM8c,EAAQhW,GAAKiW,CAAc,GACxC/c,EAAS,GAAI,QAAOA;AAGxB,YAAM,IAAIgc,GAAchc,EAAS,QAAQ,MAAMyc,GAAUzc,CAAQ,CAAC;AAAA,IACpE;AAEF,UAAM2D;AAAA,EACR;AAEA,SAAO;AAAA,IACL,SAAAwY;AAAA,IACA,WAAAQ;AAAA,IAEA,MAAM,QAAWnd,GAAcud,IAAsC,IAAgB;AACnF,YAAM/c,IAAW,MAAMmd,EAAW3d,GAAMud,CAAc;AACtD,aAAQ,MAAMN,GAAUzc,CAAQ;AAAA,IAClC;AAAA,IAEA,YAAAmd;AAAA,IAEA,aAAavmB,GAA4B;AACvC,MAAAimB,IAAQ,EAAE,GAAGA,GAAO,GAAGjmB,EAAA;AAAA,IACzB;AAAA,EAAA;AAEJ;ACnKO,SAASwmB,GAAa3pB,GAAsC;AACjE,MAAI,OAAOA,KAAU,YAAYA,MAAU,KAAM;AACjD,QAAM4pB,IAAS5pB,GACTyN,IAAYmc,EAAO,YAAeA,EAAO,mBAAmB;AAClE,SAAOnc,MAAc,SAASA,MAAc,YAAYA,IAAY;AACtE;AAGO,SAASoc,GAAc7pB,GAAkC;AAC9D,MAAI,OAAOA,KAAU,YAAYA,MAAU,KAAM,QAAO;AACxD,QAAM4pB,IAAS5pB,GACT,EAAE,IAAA2C,GAAI,OAAAmnB,EAAA,IAAUF;AAEtB,MADI,OAAOjnB,KAAO,YAAY,OAAOA,KAAO,YACxC,OAAOmnB,KAAU,SAAU,QAAO;AACtC,QAAMC,IAAQ,MAAM,QAAQH,EAAO,KAAK,IACpCA,EAAO,MAAM,OAAO,CAAC9qB,MAAyB,OAAOA,KAAS,QAAQ,IACtE,CAAA;AACJ,SAAO,EAAE,GAAG8qB,GAAQ,IAAAjnB,GAAI,OAAAmnB,GAAO,OAAAC,EAAA;AACjC;AAEA,SAASC,GAAWtnB,GAA6B;AAC/C,MAAI,OAAO,WAAa,IAAa,QAAO;AAC5C,MAAI;AACF,eAAW6gB,KAAQ,SAAS,OAAO,MAAM,GAAG,GAAG;AAC7C,YAAM0G,IAAU1G,EAAK,KAAA,GACf2G,IAAYD,EAAQ,QAAQ,GAAG;AACrC,UAAIC,MAAc,MACdD,EAAQ,MAAM,GAAGC,CAAS,MAAMxnB;AAClC,eAAO,mBAAmBunB,EAAQ,MAAMC,IAAY,CAAC,CAAC;AAAA,IAE1D;AAAA,EACF,QAAQ;AAAA,EAER;AACA,SAAO;AACT;AAEA,SAASC,GAAcnqB,GAAwB;AAC7C,MAAI,OAAOA,KAAU,YAAYA,MAAU,KAAM,QAAO,KAAK,OAAOA,CAAK;AACzE,QAAMoqB,IAAO,OAAO,KAAKpqB,CAAK;AAC9B,SAAOoqB,EAAK,WAAW,IAAI,oBAAoB,wBAAwBA,EAAK,KAAK,IAAI,CAAC;AACxF;AAEA,SAASC,GAAQrqB,GAAmD;AAClE,MAAI,OAAOA,KAAU,YAAYA,MAAU,KAAM,QAAO;AACxD,QAAM4pB,IAAS5pB;AACf,SAAI4pB,EAAO,iBAAiB,KAAa,OAClC,OAAOA,EAAO,mBAAoB,WACrC,EAAE,gBAAgBA,EAAO,oBACzB;AACN;AAEO,MAAMU,GAAW;AAAA,EAgBtB,YAAYtrB,GAA4B;AAfvB,IAAAwpB,EAAA;AACA,IAAAA,EAAA;AACA,IAAAA,EAAA;AACA,IAAAA,EAAA;AACA,IAAAA,EAAA;AACA,IAAAA,EAAA;AACA,IAAAA,EAAA;AAET,IAAAA,EAAA;AACA,IAAAA,EAAA,qBAA6B;AAC7B,IAAAA,EAAA,wBAA0C;AAC1C,IAAAA,EAAA,qBAAoC;AAC3B,IAAAA,EAAA,uCAAgB,IAAA;AACzB,IAAAA,EAAA;AAqEC;AAAA,IAAAA,EAAA,mBAAY,CAAC+B,OACpB,KAAK,UAAU,IAAIA,CAAQ,GACpB,MAAM;AACX,WAAK,UAAU,OAAOA,CAAQ;AAAA,IAChC;AAGO,IAAA/B,EAAA,qBAAc,MAAoB,KAAK;AAzE9C,SAAK,SAASxpB,EAAQ,QACtB,KAAK,eAAeA,EAAQ,cAC5B,KAAK,eAAeA,EAAQ,cAC5B,KAAK,iBAAiBA,EAAQ,kBAAkB,aAChD,KAAK,iBAAiBA,EAAQ,kBAAkB,eAChD,KAAK,gBAAgBA,EAAQ,gBAAgB,SAAS,QAAQ,QAAQ,EAAE,GACxE,KAAK,mBAAmBA,EAAQ,kBAChC,KAAK,OAAOA,EAAQ,gBAAgB,MACpC,KAAK,QAAQ,EAAE,QAAQ,WAAW,MAAM,MAAM,MAAM,KAAK,KAAA,GAKzD,KAAK,OAAA;AAAA,EACP;AAAA;AAAA;AAAA,EAKA,SAAe;AACb,SAAK,OAAO,aAAa;AAAA,MACvB,gBAAgB,MAAM,KAAK;AAAA,MAC3B,gBAAgB,MAAM,KAAK,mBAAA;AAAA,MAC3B,YAAY,MAAM,KAAK,YAAA;AAAA,MACvB,GAAI,KAAK,SAAS,YAAY,EAAE,aAAa,UAAA,IAAoC,CAAA;AAAA,IAAC,CACnF;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,SAAe;AACb,SAAK,OAAO,aAAa;AAAA,MACvB,gBAAgB;AAAA,MAChB,gBAAgB;AAAA,MAChB,YAAY;AAAA,MACZ,aAAa;AAAA,IAAA,CACd;AAAA,EACH;AAAA,EAEQ,cAAsC;AAC5C,QAAI,KAAK,SAAS,UAAW,QAAO,CAAA;AACpC,UAAMmgB,IAAQ6K,GAAW,KAAK,cAAc;AAC5C,WAAO7K,MAAU,OAAO,CAAA,IAAK,EAAE,CAAC,KAAK,cAAc,GAAGA,EAAA;AAAA,EACxD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAc,qBAAuC;AAEnD,WADA,MAAM,KAAK,kBAAA,GACP,KAAK,SAAS,SAEZ,KAAK,MAAM,WAAW,mBAAiB,KAAK,SAAS,aAAa,IAAI,GACnE,MAEL,KAAK,aAAa,IAAA,MAAU,OAAa,KACtC,KAAK,cAAA;AAAA,EACd;AAAA,EAaQ,SAASmJ,GAAoBkC,GAA8B;AACjE,SAAK,QAAQ,EAAE,QAAAlC,GAAQ,MAAAkC,GAAM,MAAM,KAAK,KAAA;AACxC,eAAWD,KAAY,KAAK,UAAW,CAAAA,EAAA;AAAA,EACzC;AAAA;AAAA;AAAA,EAKA,oBAAmC;AACjC,gBAAK,gBAAL,KAAK,cAAgB,KAAK,WAAA,IACnB,KAAK;AAAA,EACd;AAAA,EAEA,MAAc,aAA4B;;AACxC,QAAI;AAMF,UALA,KAAK,OACH,KAAK,gBACLZ,IAAajrB,IAAA,KAAK,qBAAL,gBAAAA,EAAA,UAAyB,KACrC,MAAM,KAAK,oBAAA,KACZ,OACE,KAAK,SAAS,WAAW;AAC3B,aAAK,OAAO,aAAa,EAAE,aAAa,WAAW,GACnD,MAAM,KAAK,gBAAA,GACX,MAAM,KAAK,SAAA;AACX;AAAA,MACF;AACA,UAAI,KAAK,aAAa,IAAA,MAAU,MAAM;AACpC,aAAK,SAAS,aAAa,IAAI;AAC/B;AAAA,MACF;AAEA,UAAI,CADc,MAAM,KAAK,cAAA,EACb;AAChB,YAAM,KAAK,SAAA;AAAA,IACb,QAAQ;AACN,WAAK,SAAS,aAAa,IAAI;AAAA,IACjC;AAAA,EACF;AAAA,EAEA,MAAc,sBAAqD;AACjE,QAAI;AAGF,YAAM+rB,IAAW,MAAM,KAAK,OAAO,QAAiB,KAAK,OAAO,WAAW;AAAA,QACzE,iBAAiB;AAAA,MAAA,CAClB;AACD,aAAOd,GAAac,CAAQ;AAAA,IAC9B,QAAQ;AACN;AAAA,IACF;AAAA,EACF;AAAA;AAAA,EAGA,MAAc,WAA0B;AACtC,QAAI;AACF,YAAMja,IAAO,MAAM,KAAK,OAAO,QAAiB,GAAG,KAAK,YAAY,QAAQ;AAAA,QAC1E,iBAAiB;AAAA,MAAA,CAClB,GACKga,IAAOX,GAAcrZ,CAAI;AAC/B,MAAIga,MAAS,OACX,KAAK,SAAS,aAAa,IAAI,IAE/B,KAAK,SAAS,iBAAiBA,CAAI;AAAA,IAEvC,QAAQ;AACN,WAAK,SAAS,aAAa,IAAI;AAAA,IACjC;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAc,kBAA0C;AACtD,QAAIrL,IAAQ6K,GAAW,KAAK,cAAc;AAC1C,QAAI7K,MAAU,MAAM;AAClB,UAAI;AACF,cAAM,KAAK,OAAO,QAAiB,GAAG,KAAK,YAAY,UAAU;AAAA,UAC/D,QAAQ;AAAA,UACR,iBAAiB;AAAA,QAAA,CAClB;AAAA,MACH,QAAQ;AAAA,MAER;AACA,MAAAA,IAAQ6K,GAAW,KAAK,cAAc;AAAA,IACxC;AACA,WAAO7K;AAAA,EACT;AAAA;AAAA;AAAA,EAKQ,gBAAkC;AACxC,WAAI,KAAK,mBAAmB,SAC1B,KAAK,iBAAiB,KAAK,eAAA,EAAiB,QAAQ,MAAM;AACxD,WAAK,iBAAiB;AAAA,IACxB,CAAC,IAEI,KAAK;AAAA,EACd;AAAA,EAEA,MAAc,iBAAmC;AAC/C,UAAMuL,IAAe,KAAK,aAAa,IAAA;AACvC,QAAIA,MAAiB;AACnB,kBAAK,cAAc,MACnB,KAAK,SAAS,aAAa,IAAI,GACxB;AAKT,SAAK,cAAc;AACnB,QAAI;AACF,YAAMla,IAAO,MAAM,KAAK,OAAO,QAAiB,GAAG,KAAK,YAAY,aAAa;AAAA,QAC/E,QAAQ;AAAA,QACR,MAAM,EAAE,SAASka,EAAA;AAAA,QACjB,iBAAiB;AAAA;AAAA,MAAA,CAClB,GACKd,IACJ,OAAOpZ,KAAS,YAAYA,MAAS,OAAQA,IAAmC,CAAA,GAC5Ema,IAASf,EAAO;AACtB,UAAI,OAAOe,KAAW,YAAYA,MAAW;AAC3C,cAAM,IAAI;AAAA,UACR,eAAe,KAAK,YAAY,sBAAsBR,GAAc3Z,CAAI,CAAC;AAAA,QAAA;AAM7E,YAAMoa,IAAUhB,EAAO;AACvB,aAAI,OAAOgB,KAAY,YAAYA,MAAY,MAC7C,KAAK,aAAa,IAAIA,CAAO,GAE/B,KAAK,cAAcD,GACZ;AAAA,IACT,QAAQ;AACN,kBAAK,aAAa,MAAA,GAClB,KAAK,cAAc,MACnB,KAAK,SAAS,aAAa,IAAI,GACxB;AAAA,IACT;AAAA,EACF;AAAA;AAAA,EAIA,MAAM,MAAMb,GAAee,GAAwC;AACjE,UAAM,KAAK,kBAAA;AACX,UAAM9e,IAAO,GAAG,KAAK,YAAY;AACjC,QAAI,KAAK,SAAS,WAAW;AAC3B,YAAM,KAAK,gBAAA;AACX,YAAMyE,IAAO,MAAM,KAAK,OAAO,QAAiBzE,GAAM;AAAA,QACpD,QAAQ;AAAA,QACR,MAAM,EAAE,OAAA+d,GAAO,UAAAe,EAAA;AAAA,QACf,iBAAiB;AAAA,MAAA,CAClB,GACKC,IAAYT,GAAQ7Z,CAAI;AAC9B,UAAIsa,MAAc;AAChB,eAAO,EAAE,aAAa,IAAM,gBAAgBA,EAAU,eAAA;AAExD,YAAMN,IAAOX,GAAcrZ,CAAI,KAAM,MAAM,KAAK,QAAQzE,CAAI;AAC5D,kBAAK,SAAS,iBAAiBye,CAAI,GAC5B,EAAE,IAAI,IAAM,MAAAA,EAAAA;AAAAA,IACrB;AAEA,UAAMha,IAAO,MAAM,KAAK,OAAO,QAAiBzE,GAAM;AAAA,MACpD,QAAQ;AAAA,MACR,MAAM,EAAE,OAAA+d,GAAO,UAAAe,EAAA;AAAA,MACf,iBAAiB;AAAA,IAAA,CAClB,GACKC,IAAYT,GAAQ7Z,CAAI;AAC9B,QAAIsa,MAAc;AAChB,aAAO,EAAE,aAAa,IAAM,gBAAgBA,EAAU,eAAA;AAExD,UAAMlB,IACJ,OAAOpZ,KAAS,YAAYA,MAAS,OAAQA,IAAmC,CAAA,GAC5E,EAAE,QAAAma,GAAQ,SAAAI,EAAA,IAAYnB;AAC5B,QAAI,OAAOe,KAAW,YAAY,OAAOI,KAAY;AACnD,YAAM,IAAI;AAAA,QACR,6CAA6Chf,CAAI,wFAE5Coe,GAAc3Z,CAAI,CAAC;AAAA,MAAA;AAI5B,SAAK,aAAa,IAAIua,CAAO,GAC7B,KAAK,cAAcJ;AACnB,UAAMH,IAAOX,GAAcD,EAAO,IAAI,KAAM,MAAM,KAAK,QAAQ7d,CAAI;AACnE,gBAAK,SAAS,iBAAiBye,CAAI,GAC5B,EAAE,IAAI,IAAM,MAAAA,EAAA;AAAA,EACrB;AAAA,EAEA,MAAc,QAAQQ,GAAuC;AAC3D,UAAMxa,IAAO,MAAM,KAAK,OAAO,QAAiB,GAAG,KAAK,YAAY,QAAQ;AAAA,MAC1E,iBAAiB;AAAA,IAAA,CAClB,GACKga,IAAOX,GAAcrZ,CAAI;AAC/B,QAAIga,MAAS;AACX,YAAM,IAAI;AAAA,QACR,oBAAoBQ,CAAS,kBAAkB,KAAK,YAAY,iBAC3Db,GAAc3Z,CAAI,CAAC;AAAA,MAAA;AAG5B,WAAOga;AAAA,EACT;AAAA;AAAA,EAGA,MAAM,SAAwB;AAC5B,UAAM,KAAK,kBAAA;AACX,QAAI;AACF,UAAI,KAAK,SAAS;AAChB,cAAM,KAAK,gBAAA,GACX,MAAM,KAAK,OAAO,QAAiB,GAAG,KAAK,YAAY,YAAY;AAAA,UACjE,QAAQ;AAAA,UACR,iBAAiB;AAAA,QAAA,CAClB;AAAA,WACI;AACL,cAAMO,IAAU,KAAK,aAAa,IAAA;AAClC,QAAIA,MAAY,QACd,MAAM,KAAK,OAAO,QAAiB,GAAG,KAAK,YAAY,YAAY;AAAA,UACjE,QAAQ;AAAA,UACR,MAAM,EAAE,SAAAA,EAAA;AAAA,UACR,iBAAiB;AAAA,QAAA,CAClB;AAAA,MAEL;AAAA,IACF,QAAQ;AAAA,IAER;AACA,SAAK,cAAc,MACnB,KAAK,aAAa,MAAA,GAClB,KAAK,SAAS,aAAa,IAAI;AAAA,EACjC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,YAAYJ,GAAuBI,GAAuC;AAC9E,UAAM,KAAK,kBAAA,GACP,KAAK,SAAS,UACZ,OAAOA,KAAY,YAAYA,MAAY,MAAI,KAAK,aAAa,IAAIA,CAAO,GAC5E,OAAOJ,KAAW,YAAYA,MAAW,YAAS,cAAcA,KAEtE,MAAM,KAAK,SAAA;AAAA,EACb;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,UAAyB;AAE7B,IADA,MAAM,KAAK,kBAAA,GACP,OAAK,SAAS,SAEZ,CADc,MAAM,KAAK,cAAA,MAG/B,MAAM,KAAK,SAAA;AAAA,EACb;AACF;ACpdO,SAASM,GAA+B5qB,IAAM,sBAAoC;AACvF,SAAO;AAAA,IACL,MAAqB;AACnB,UAAI;AACF,eAAO,WAAW,aAAa,QAAQA,CAAG;AAAA,MAC5C,QAAQ;AACN,eAAO;AAAA,MACT;AAAA,IACF;AAAA,IACA,IAAI8e,GAAqB;AACvB,UAAI;AACF,mBAAW,aAAa,QAAQ9e,GAAK8e,CAAK;AAAA,MAC5C,QAAQ;AAAA,MAER;AAAA,IACF;AAAA,IACA,QAAc;AACZ,UAAI;AACF,mBAAW,aAAa,WAAW9e,CAAG;AAAA,MACxC,QAAQ;AAAA,MAER;AAAA,IACF;AAAA,EAAA;AAEJ;AAMO,SAAS6qB,KAAyC;AACvD,MAAI/L,IAAuB;AAC3B,SAAO;AAAA,IACL,KAAK,MAAMA;AAAA,IACX,KAAK,CAAChc,MAAiB;AACrB,MAAAgc,IAAQhc;AAAA,IACV;AAAA,IACA,OAAO,MAAM;AACX,MAAAgc,IAAQ;AAAA,IACV;AAAA,EAAA;AAEJ;ACyBO,MAAMgM,KAActlB,GAAuC,IAAI;AAG/D,SAASulB,GAAa;AAAA,EAC3B,MAAAvM;AAAA,EACA,cAAAwM;AAAA,EACA,gBAAAC;AAAA,EACA,gBAAAC;AAAA,EACA,cAAAC;AAAA,EACA,UAAA7pB;AACF,GAAoC;;AAClC,QAAMoE,IAASM,GAAA,GACTL,IAAc8B,GAAA,GACd2jB,IAAUC,GAAQ,MAAML,KAAgBJ,MAAkC,CAACI,CAAY,CAAC,GAKxFM,IAASD;AAAA,IACb,MACE,IAAIpB,GAAW;AAAA,MACb,QAAAvkB;AAAA,MACA,cAAc0lB;AAAA,MACd,GAAI5M,MAAS,SAAY,EAAE,cAAcA,EAAA,IAAS,CAAA;AAAA,MAClD,GAAIyM,MAAmB,SAAY,EAAE,gBAAAA,EAAA,IAAmB,CAAA;AAAA,MACxD,GAAIC,MAAmB,SAAY,EAAE,gBAAAA,EAAA,IAAmB,CAAA;AAAA,MACxD,GAAIC,MAAiB,SAAY,EAAE,cAAAA,EAAA,IAAiB,CAAA;AAAA,MACpD,kBAAkB,MAAMxlB,EAAY,aAAaL,GAAU,QAAQ;AAAA,IAAA,CACpE;AAAA,IACH,CAACI,GAAQC,GAAaylB,GAAS5M,GAAMyM,GAAgBC,GAAgBC,CAAY;AAAA,EAAA;AAGnF,EAAAI,GAAU,OACRD,EAAO,OAAA,GACFA,EAAO,kBAAA,GACL,MAAM;AACX,IAAAA,EAAO,OAAA;AAAA,EACT,IACC,CAACA,CAAM,CAAC;AAEX,QAAME,IAAWC,GAAqBH,EAAO,WAAWA,EAAO,aAAaA,EAAO,WAAW,GAGxFI,MAAWrtB,IAAAmtB,EAAS,SAAT,gBAAAntB,EAAe,OAAM,MAChCstB,IAAmBC,GAAOF,CAAQ;AACxC,EAAAH,GAAU,MAAM;AACd,IAAII,EAAiB,YAAYD,MACjCC,EAAiB,UAAUD,GACtB/lB,EAAY,kBAAkB,EAAE,UAAUL,GAAU,OAAA,GAAU;AAAA,EACrE,GAAG,CAAComB,GAAU/lB,CAAW,CAAC;AAE1B,QAAMhG,IAAQ0rB;AAAA,IACZ,MAAA;;AAAO;AAAA,QACL,MAAMG,EAAS;AAAA,QACf,SAAOntB,IAAAmtB,EAAS,SAAT,gBAAAntB,EAAe,UAAS,CAAA;AAAA,QAC/B,QAAQmtB,EAAS;AAAA,QACjB,OAAO,CAAC/B,GAAOe,MAAac,EAAO,MAAM7B,GAAOe,CAAQ;AAAA,QACxD,QAAQ,MAAMc,EAAO,OAAA;AAAA,QACrB,SAAS,MAAMA,EAAO,QAAA;AAAA,QACtB,aAAa,CAAChB,GAAQI,MAAYY,EAAO,YAAYhB,GAAQI,CAAO;AAAA,MAAA;AAAA;AAAA,IAEtE,CAACY,GAAQE,CAAQ;AAAA,EAAA;AAGnB,SAAO,gBAAA/qB,EAACqqB,GAAY,UAAZ,EAAqB,OAAAnrB,GAAe,UAAA2B,EAAA,CAAS;AACvD;AAGO,SAASuqB,KAA4B;AAC1C,QAAMlsB,IAAQsG,GAAW6kB,EAAW;AACpC,MAAInrB,MAAU;AACZ,UAAM,IAAI;AAAA,MACR;AAAA,IAAA;AAIJ,SAAOA;AACT;ACxJAnB,GAAsB,cAAc,WAAW;AAaxC,SAASstB,GAAU;AAAA,EACxB,OAAApC;AAAA,EACA,UAAAxe,IAAW;AAAA,EACX,SAAA6gB,IAAU;AAAA,EACV,UAAAzqB;AACF,GAAwC;AACtC,QAAM,EAAE,QAAA2mB,GAAQ,MAAAkC,EAAA,IAAS0B,GAAA;AACzB,SAAI5D,MAAW,YAAkB,gBAAAxnB,EAAAqQ,GAAA,EAAG,UAAAib,GAAQ,IACxC9D,MAAW,mBAAmBkC,MAAS,8BAAgB,UAAAjf,GAAS,IAChEwe,MAAU,UAAaA,EAAM,SAAS,KAAK,CAACA,EAAM,KAAK,CAACjrB,MAAS0rB,EAAK,MAAM,SAAS1rB,CAAI,CAAC,2BAClF,UAAAyM,EAAA,CAAS,2BAEX,UAAA5J,GAAS;AACrB;ACpBA9C,GAAsB,cAAc,WAAW;AAmBxC,SAASwtB,GAAU;AAAA,EACxB,WAAA5I;AAAA,EACA,OAAA6I;AAAA,EACA,OAAAjhB,IAAQ;AAAA,EACR,aAAAxB;AAAA,EACA,aAAA0iB,IAAc;AAAA,EACd,UAAA9pB,IAAW;AAAA,EACX,WAAA/C;AACF,GAAmB;AACjB,QAAM,EAAE,OAAA8sB,EAAA,IAAUN,GAAA,GACZvpB,IAAKlC,EAAM,MAAA,GACX,CAAC4T,GAAMC,CAAO,IAAI7T,EAAM,SAAS,EAAK,GACtC,CAACyP,GAAOqE,CAAQ,IAAI9T,EAAM,SAAwB,IAAI;AAE5D,iBAAegsB,EAAOlb,GAAyC;AAC7D,IAAAA,EAAM,eAAA;AACN,UAAMf,IAAO,IAAI,SAASe,EAAM,aAAa;AAC7C,IAAA+C,EAAQ,EAAI,GACZC,EAAS,IAAI;AACb,QAAI;AACF,YAAMyN,IAAS,MAAMwK;AAAA,QACnB,OAAOhc,EAAK,IAAI,OAAO,KAAK,EAAE;AAAA,QAC9B,OAAOA,EAAK,IAAI,UAAU,KAAK,EAAE;AAAA,MAAA;AAEnC,MAAI,QAAQwR,IACVyB,KAAA,QAAAA,EAAYzB,EAAO,QACVsK,MAAU,SACnBA,EAAMtK,EAAO,cAAc,IAE3BzN,EAAS,0EAA0E;AAAA,IAEvF,QAAQ;AACN,MAAAA,EAAS,uCAAuC;AAAA,IAClD,UAAA;AACE,MAAAD,EAAQ,EAAK;AAAA,IACf;AAAA,EACF;AAEA,SACE,gBAAA1S;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,WAAWzD,EAAG,aAAauB,CAAS;AAAA,MACpC,UAAU,CAAC6R,MAAU,KAAKkb,EAAOlb,CAAK;AAAA,MACtC,aAAW8C;AAAA,MACX,YAAY;AAAA,MAEX,UAAA;AAAA,QAAAhJ,MAAU,OAAO,gBAAAvK,EAAC,MAAA,EAAG,WAAU,yBAAyB,aAAM,IAAQ;AAAA,QACtE+I,MAAgB,SACf,gBAAA/I,EAAC,OAAE,WAAU,iCAAiC,aAAY,IACxD;AAAA,QACJ,gBAAAc,EAAC,OAAA,EAAI,WAAU,aACb,UAAA;AAAA,UAAA,gBAAAd,EAAC0C,IAAA,EAAM,SAAS,GAAGb,CAAE,UAAU,UAAA,SAAK;AAAA,UACpC,gBAAA7B;AAAA,YAACC;AAAA,YAAA;AAAA,cACC,IAAI,GAAG4B,CAAE;AAAA,cACT,MAAK;AAAA,cACL,MAAK;AAAA,cACL,cAAa;AAAA,cACb,UAAQ;AAAA,cACR,UAAUF,KAAY4R;AAAA,YAAA;AAAA,UAAA;AAAA,QACxB,GACF;AAAA,QACA,gBAAAzS,EAAC,OAAA,EAAI,WAAU,aACb,UAAA;AAAA,UAAA,gBAAAd,EAAC0C,IAAA,EAAM,SAAS,GAAGb,CAAE,aAAa,UAAA,YAAQ;AAAA,UAC1C,gBAAA7B;AAAA,YAACC;AAAA,YAAA;AAAA,cACC,IAAI,GAAG4B,CAAE;AAAA,cACT,MAAK;AAAA,cACL,MAAK;AAAA,cACL,cAAa;AAAA,cACb,UAAQ;AAAA,cACR,UAAUF,KAAY4R;AAAA,YAAA;AAAA,UAAA;AAAA,QACxB,GACF;AAAA,QACCnE,MAAU,OACT,gBAAApP,EAAC,KAAA,EAAE,MAAK,SAAQ,WAAU,4BACvB,UAAAoP,EAAA,CACH,IACE;AAAA,0BACH1P,GAAA,EAAO,MAAK,UAAS,UAAUiC,KAAY4R,GACzC,UAAAkY,EAAA,CACH;AAAA,MAAA;AAAA,IAAA;AAAA,EAAA;AAGN;ACzGO,SAASG,KAAmC;AACjD,QAAM,EAAE,OAAA3C,GAAO,QAAAzB,EAAA,IAAW4D,GAAA;AAC1B,SAAOR;AAAA,IACL,OAAO;AAAA,MACL,iBAAiBpD,MAAW;AAAA,MAC5B,SAAS,IAAIlhB,MACXkhB,MAAW,mBAAmBlhB,EAAM,KAAK,CAAC1E,MAASqnB,EAAM,SAASrnB,CAAI,CAAC;AAAA,IAAA;AAAA,IAE3E,CAACqnB,GAAOzB,CAAM;AAAA,EAAA;AAElB;ACpBAzpB,GAAsB,cAAc,MAAM;AA8BnC,MAAM8tB,KAAOlsB,EAAM;AAAA,EACxB,CACE;AAAA,IACE,OAAA4K;AAAA,IACA,aAAAxB;AAAA,IACA,SAAAia;AAAA,IACA,QAAA9Q;AAAA,IACA,iBAAA4Z;AAAA,IACA,kBAAAhqB;AAAA,IACA,WAAAlD;AAAA,IACA,UAAAiC;AAAA,IACA,GAAGlC;AAAA,EAAA,GAELoB,MAEA,gBAAAe,EAAC,WAAA,EAAQ,KAAAf,GAAU,WAAW1C,EAAG,8BAA8BuB,CAAS,GAAI,GAAGD,GAC5E,UAAA;AAAA,IAAAuT,uBACE,UAAA,EAAO,WAAW7U,EAAG,oDAAoDyuB,CAAe,GACvF,UAAA;AAAA,MAAA,gBAAAhrB,EAAC,OAAA,EAAI,WAAU,cACb,UAAA;AAAA,QAAA,gBAAAd,EAAC,MAAA,EAAG,WAAU,yDAAyD,UAAAuK,GAAM;AAAA,QAC5ExB,KAAe,QAAQ,gBAAA/I,EAAC,KAAA,EAAE,WAAU,iCAAiC,UAAA+I,EAAA,CAAY;AAAA,MAAA,GACpF;AAAA,MACCia,KAAW,QAAQ,gBAAAhjB,EAAC,OAAA,EAAI,WAAU,oCAAoC,UAAAgjB,EAAA,CAAQ;AAAA,IAAA,GACjF;AAAA,sBAED,OAAA,EAAI,WAAW3lB,EAAG,uBAAuByE,CAAgB,GAAI,UAAAjB,EAAA,CAAS;AAAA,EAAA,EAAA,CACzE;AAEJ;AACAgrB,GAAK,cAAc;AC9DZ,MAAME,KAAe,iBAEfC,KAA2E;AAAA,EACtF;AAAA,IACE,MAAQ;AAAA,IACR,GAAK;AAAA,EAAA;AAAA,EAEP;AAAA,IACE,MAAQ;AAAA,IACR,GAAK;AAAA,EAAA;AAAA,EAEP;AAAA,IACE,MAAQ;AAAA,IACR,GAAK;AAAA,EAAA;AAET,GAEaC,KAAmB;AAAA;AAAA;AAAA;AAAA;AAAA,8ECMnBC,KAAYvsB,EAAM;AAAA,EAC7B,CAAC,EAAE,MAAAE,IAAO,IAAI,SAAAD,IAAU,QAAQ,OAAA2K,IAAQ,SAAS,WAAA3L,GAAW,GAAGD,EAAA,GAASoB,MAAQ;AAC9E,UAAMosB,IAASvsB,MAAY,YAAaA,MAAY,UAAUC,KAAQ,IAChEusB,IAAW7hB,MAAU;AAC3B,WACE,gBAAAvK;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,KAAAD;AAAA,QACA,SAASgsB;AAAA,QACT,OAAOlsB;AAAA,QACP,QAAQA;AAAA,QACR,MAAMusB,IAAW,QAAQ;AAAA,QACzB,eAAaA,IAAW,SAAY;AAAA,QACpC,cAAYA,IAAW7hB,IAAQ;AAAA,QAC/B,WAAWlN,EAAG,YAAYuB,CAAS;AAAA,QAClC,GAAGD;AAAA,QACH,GAAIwtB,IAAS,EAAE,yBAAyB,EAAE,QAAQF,GAAA,EAAiB,IAAM,CAAA;AAAA,QAEzE,cACG,OACAD,GAAW,IAAI,CAAC/gB,wBACb,QAAA,EAAqC,MAAMA,EAAK,MAAM,GAAGA,EAAK,EAAA,GAApDA,EAAK,OAAOA,EAAK,EAAE,MAAoC,CACnE;AAAA,MAAA;AAAA,IAAA;AAAA,EAGX;AACF;AACAihB,GAAU,cAAc;AC7CxBnuB,GAAsB,gBAAgB,QAAQ;AAI9C,SAASsuB,GAAS1tB,GAAsC;AACtD,SACE,gBAAAmC;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,SAAQ;AAAA,MACR,MAAK;AAAA,MACL,QAAO;AAAA,MACP,aAAa;AAAA,MACb,eAAc;AAAA,MACd,gBAAe;AAAA,MACf,eAAY;AAAA,MACZ,WAAW;AAAA,MACV,GAAGnC;AAAA,MAEJ,UAAA;AAAA,QAAA,gBAAAqB,EAAC,QAAA,EAAK,IAAG,KAAI,IAAG,KAAI,IAAG,MAAK,IAAG,IAAA,CAAI;AAAA,QACnC,gBAAAA,EAAC,UAAK,IAAG,KAAI,IAAG,MAAK,IAAG,MAAK,IAAG,KAAA,CAAK;AAAA,QACrC,gBAAAA,EAAC,UAAK,IAAG,KAAI,IAAG,MAAK,IAAG,MAAK,IAAG,KAAA,CAAK;AAAA,MAAA;AAAA,IAAA;AAAA,EAAA;AAG3C;AAEA,SAASssB,GAAU3tB,GAAsC;AACvD,SACE,gBAAAmC;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,SAAQ;AAAA,MACR,MAAK;AAAA,MACL,QAAO;AAAA,MACP,aAAa;AAAA,MACb,eAAc;AAAA,MACd,gBAAe;AAAA,MACf,eAAY;AAAA,MACZ,WAAW;AAAA,MACV,GAAGnC;AAAA,MAEJ,UAAA;AAAA,QAAA,gBAAAqB,EAAC,QAAA,EAAK,IAAG,MAAK,IAAG,KAAI,IAAG,KAAI,IAAG,KAAA,CAAK;AAAA,QACpC,gBAAAA,EAAC,UAAK,IAAG,KAAI,IAAG,KAAI,IAAG,MAAK,IAAG,KAAA,CAAK;AAAA,MAAA;AAAA,IAAA;AAAA,EAAA;AAG1C;AA+CA,MAAMusB,KACJ,iLACIC,KAAwB,oCAExBC,KAAa,wBAYNC,KAAS/sB,EAAM;AAAA,EAC1B,CACE;AAAA,IACE,UAAAgtB,IAAW,CAAA;AAAA,IACX,eAAAC;AAAA,IACA,SAAAC;AAAA,IACA,eAAAC,IAAgB,gBAAA9sB,EAACksB,IAAA,EAAU,WAAU,OAAA,CAAO;AAAA,IAC5C,eAAAa;AAAA,IACA,QAAA7a;AAAA,IACA,UAAA8a,IAAW;AAAA,IACX,kBAAAC;AAAA,IACA,iBAAAnB;AAAA,IACA,kBAAAhqB;AAAA,IACA,WAAAlD;AAAA,IACA,UAAAiC;AAAA,IACA,GAAGlC;AAAA,EAAA,GAELoB,MACG;AACH,UAAM,CAACmtB,GAAYC,CAAa,IAAIxtB,EAAM,SAAS,EAAK,GAElDytB,IAAcztB,EAAM,YAAY,MAAM;AAC1C,MAAAwtB,EAAc,EAAK;AAAA,IACrB,GAAG,CAAA,CAAE;AAEL,IAAAxtB,EAAM,UAAU,MAAM;AACpB,UAAI,CAACutB;AACH;AAEF,YAAMG,IAAY,CAAC5c,MAA+B;AAChD,QAAIA,EAAM,QAAQ,YAChB0c,EAAc,EAAK;AAAA,MAEvB;AACA,sBAAS,iBAAiB,WAAWE,CAAS,GACvC,MAAM;AACX,iBAAS,oBAAoB,WAAWA,CAAS;AAAA,MACnD;AAAA,IACF,GAAG,CAACH,CAAU,CAAC;AAEf,UAAMI,IAAaT,KACjB,gBAAA7sB,EAAC,OAAA,EAAI,cAAYgtB,GAAU,WAAU,cAClC,UAAAL,EAAS,IAAI,CAACloB,MAAS;AACtB,YAAM8oB,IAAmBlwB;AAAA,QACvBkvB;AAAA,QACA9nB,EAAK,WAAW,MAAQ+nB;AAAA,MAAA,GAEpBgB,IACJ,gBAAA1sB;AAAA,QAAC;AAAA,QAAA;AAAA,UACC,MAAM2D,EAAK;AAAA,UACX,gBAAcA,EAAK,WAAW,KAAO,SAAS;AAAA,UAC9C,WAAW8oB;AAAA,UACX,SAASH;AAAA,UAER,UAAA;AAAA,YAAA3oB,EAAK,QAAQ,QAAQ,gBAAAzE,EAAC,UAAK,eAAY,QAAQ,YAAK,KAAA,CAAK;AAAA,YACzDyE,EAAK;AAAA,UAAA;AAAA,QAAA;AAAA,MAAA;AAGV,+BACG9E,EAAM,UAAN,EACE,UAAAitB,IAAgBA,EAAcnoB,GAAM,EAAE,aAAA+oB,GAAa,kBAAAD,EAAA,CAAkB,IAAIC,EAAA,GADvD/oB,EAAK,OAAOA,EAAK,IAEtC;AAAA,IAEJ,CAAC,EAAA,CACH,GAGIgpB,IACJ,gBAAA3sB,EAAAuP,GAAA,EACG,UAAA;AAAA,MAAAyc,KAAiB,QAAQ,gBAAA9sB,EAAC,OAAA,EAAI,WAAU,QAAQ,UAAA8sB,GAAc;AAAA,MAC/D,gBAAA9sB,EAAC,OAAA,EAAI,WAAU,0BAA0B,UAAAstB,GAAW;AAAA,MACnDP,KAAiB,QAAQ,gBAAA/sB,EAAC,OAAA,EAAI,WAAU,QAAQ,UAAA+sB,EAAA,CAAc;AAAA,IAAA,GACjE;AAGF,WACE,gBAAAjsB;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,KAAAf;AAAA,QACA,WAAW1C,EAAG,0DAA0DuB,CAAS;AAAA,QAChF,GAAGD;AAAA,QAGJ,UAAA;AAAA,UAAA,gBAAAqB;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,WAAW3C;AAAA,gBACT;AAAA,gBACA4vB;AAAA,cAAA;AAAA,cAGD,UAAAQ;AAAA,YAAA;AAAA,UAAA;AAAA,UAIFP,KACC,gBAAApsB,EAAC,OAAA,EAAI,WAAU,gCACb,UAAA;AAAA,YAAA,gBAAAd;AAAA,cAAC;AAAA,cAAA;AAAA,gBACC,eAAY;AAAA,gBACZ,eAAY;AAAA,gBACZ,WAAU;AAAA,gBACV,SAASotB;AAAA,cAAA;AAAA,YAAA;AAAA,YAEX,gBAAAtsB;AAAA,cAAC;AAAA,cAAA;AAAA,gBACC,IAAI2rB;AAAA,gBACJ,WAAWpvB;AAAA,kBACT;AAAA,kBACA4vB;AAAA,gBAAA;AAAA,gBAGF,UAAA;AAAA,kBAAA,gBAAAjtB,EAAC,OAAA,EAAI,WAAU,yBACb,UAAA,gBAAAc;AAAA,oBAAC;AAAA,oBAAA;AAAA,sBACC,MAAK;AAAA,sBACL,SAASssB;AAAA,sBACT,WAAU;AAAA,sBAEV,UAAA;AAAA,wBAAA,gBAAAptB,EAACssB,IAAA,EAAU,WAAU,UAAA,CAAU;AAAA,wBAC/B,gBAAAtsB,EAAC,QAAA,EAAK,WAAU,WAAU,UAAA,mBAAA,CAAgB;AAAA,sBAAA;AAAA,oBAAA;AAAA,kBAAA,GAE9C;AAAA,kBACCytB;AAAA,gBAAA;AAAA,cAAA;AAAA,YAAA;AAAA,UACH,GACF;AAAA,UAGF,gBAAA3sB,EAAC,OAAA,EAAI,WAAU,gCACb,UAAA;AAAA,YAAA,gBAAAA;AAAA,cAAC;AAAA,cAAA;AAAA,gBACC,WAAWzD;AAAA,kBACT;AAAA,kBACAyuB;AAAA,gBAAA;AAAA,gBAGF,UAAA;AAAA,kBAAA,gBAAAhrB;AAAA,oBAAC;AAAA,oBAAA;AAAA,sBACC,MAAK;AAAA,sBACL,iBAAeosB;AAAA,sBACf,iBAAeT;AAAA,sBACf,SAAS,MAAM;AACb,wBAAAU,EAAc,CAACrY,MAAS,CAACA,CAAI;AAAA,sBAC/B;AAAA,sBACA,WAAU;AAAA,sBAEV,UAAA;AAAA,wBAAA,gBAAA9U,EAACqsB,IAAA,EAAS,WAAU,UAAA,CAAU;AAAA,wBAC9B,gBAAArsB,EAAC,QAAA,EAAK,WAAU,WAAU,UAAA,kBAAA,CAAe;AAAA,sBAAA;AAAA,oBAAA;AAAA,kBAAA;AAAA,kBAE1CkS,KAAU,QACT,gBAAAlS,EAAC,OAAA,EAAI,WAAU,0CAA0C,UAAAkS,EAAA,CAAO;AAAA,gBAAA;AAAA,cAAA;AAAA,YAAA;AAAA,8BAGnE,QAAA,EAAK,WAAW7U,EAAG,cAAcyE,CAAgB,GAAI,UAAAjB,EAAA,CAAS;AAAA,UAAA,EAAA,CACjE;AAAA,QAAA;AAAA,MAAA;AAAA,IAAA;AAAA,EAGN;AACF;AACA6rB,GAAO,cAAc;AC/PrB3uB,GAAsB,SAAS,OAAO;AAItC,SAASuuB,GAAU3tB,GAAsC;AACvD,SACE,gBAAAmC;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,SAAQ;AAAA,MACR,MAAK;AAAA,MACL,QAAO;AAAA,MACP,aAAa;AAAA,MACb,eAAc;AAAA,MACd,gBAAe;AAAA,MACf,eAAY;AAAA,MACZ,WAAW;AAAA,MACV,GAAGnC;AAAA,MAEJ,UAAA;AAAA,QAAA,gBAAAqB,EAAC,QAAA,EAAK,IAAG,MAAK,IAAG,KAAI,IAAG,KAAI,IAAG,KAAA,CAAK;AAAA,QACpC,gBAAAA,EAAC,UAAK,IAAG,KAAI,IAAG,KAAI,IAAG,MAAK,IAAG,KAAA,CAAK;AAAA,MAAA;AAAA,IAAA;AAAA,EAAA;AAG1C;AAMO,MAAM0tB,KAAaC,GAAgB;AA2CnC,SAASC,GAAM;AAAA,EACpB,OAAArjB;AAAA,EACA,aAAAxB;AAAA,EACA,UAAAlI;AAAA,EACA,QAAAsZ;AAAA,EACA,SAAA0T;AAAA,EACA,MAAA/Y;AAAA,EACA,aAAAgZ;AAAA,EACA,cAAAC;AAAA,EACA,iBAAAC,IAAkB;AAAA,EAClB,WAAApvB;AAAA,EACA,cAAAqvB;AACF,GAAmC;AAIjC,QAAMC,IACJnlB,KAAe,SAAQklB,KAAA,gBAAAA,EAAe,yBAAwB,SAC1D,EAAE,oBAAoB,OAAA,IACtB,CAAA;AACN,2BACGN,GAAgB,MAAhB,EAAqB,MAAA7Y,GAAY,aAAAgZ,GAA0B,cAAAC,GACzD,UAAA;AAAA,IAAAF,KAAW,QAAQ,gBAAA7tB,EAAC2tB,GAAgB,SAAhB,EAAwB,SAAO,IAAE,UAAAE,GAAQ;AAAA,IAC9D,gBAAA/sB,EAAC6sB,GAAgB,QAAhB,EACC,UAAA;AAAA,MAAA,gBAAA3tB,EAAC2tB,GAAgB,SAAhB,EAAwB,WAAU,sCAAA,CAAsC;AAAA,MACzE,gBAAA7sB;AAAA,QAAC6sB,GAAgB;AAAA,QAAhB;AAAA,UACE,GAAGM;AAAA,UACH,GAAGC;AAAA,UACJ,WAAW7wB;AAAA,YACT;AAAA,YACAuB;AAAA,UAAA;AAAA,UAGF,UAAA;AAAA,YAAA,gBAAAkC,EAAC,OAAA,EAAI,WAAU,gBACb,UAAA;AAAA,cAAA,gBAAAd,EAAC2tB,GAAgB,OAAhB,EAAsB,WAAU,qDAC9B,UAAApjB,GACH;AAAA,cACCxB,KAAe,QACd,gBAAA/I,EAAC2tB,GAAgB,aAAhB,EAA4B,WAAU,iCACpC,UAAA5kB,EAAA,CACH;AAAA,YAAA,GAEJ;AAAA,YACClI;AAAA,YACAsZ,KAAU,QACT,gBAAAna,EAAC,OAAA,EAAI,WAAU,0DAA0D,UAAAma,GAAO;AAAA,YAEjF,CAAC6T,KACA,gBAAAltB,EAAC6sB,GAAgB,OAAhB,EAAsB,WAAU,4OAC/B,UAAA;AAAA,cAAA,gBAAA3tB,EAACssB,IAAA,EAAU,WAAU,UAAA,CAAU;AAAA,cAC/B,gBAAAtsB,EAAC,QAAA,EAAK,WAAU,WAAU,UAAA,QAAA,CAAK;AAAA,YAAA,EAAA,CACjC;AAAA,UAAA;AAAA,QAAA;AAAA,MAAA;AAAA,IAEJ,EAAA,CACF;AAAA,EAAA,GACF;AAEJ;AC7FA,IAAImuB,KAAmC,CAAA;AACvC,MAAMC,yBAAgB,IAAA;AACtB,IAAIC,KAAU;AAEd,SAASC,KAAa;AACpB,aAAW7E,KAAY2E;AACrB,IAAA3E,EAAA;AAEJ;AAEO,SAAS8E,GAAkB9E,GAAgC;AAChE,SAAA2E,GAAU,IAAI3E,CAAQ,GACf,MAAM;AACX,IAAA2E,GAAU,OAAO3E,CAAQ;AAAA,EAC3B;AACF;AAEO,SAAS+E,KAAsC;AACpD,SAAOL;AACT;AAEO,SAASM,GAAa5sB,GAAmB;AAC9C,QAAMQ,IAAOR,MAAO,SAAY,KAAKssB,GAAO,OAAO,CAAC1pB,MAASA,EAAK,OAAO5C,CAAE;AAC3E,EAAIQ,EAAK,WAAW8rB,GAAO,WACzBA,KAAS9rB,GACTisB,GAAA;AAEJ;AAEO,SAASI,GAASxwB,GAAoC;AAC3D,EAAAmwB,MAAW;AACX,QAAMxsB,IAAK3D,EAAQ,MAAM,eAAe,OAAOmwB,EAAO,CAAC,IACjDM,IAA0B;AAAA,IAC9B,GAAGzwB;AAAA,IACH,IAAA2D;AAAA,IACA,SAAS3D,EAAQ,WAAW;AAAA,EAAA;AAE9B,SAAAiwB,KAAS,CAAC,GAAGA,GAAO,OAAO,CAAC1pB,MAASA,EAAK,OAAO5C,CAAE,GAAG8sB,CAAQ,EAAE,MAAM,EAAY,GAClFL,GAAA,GACO;AAAA,IACL,IAAAzsB;AAAA,IACA,SAAS,MAAM;AACb,MAAA4sB,GAAa5sB,CAAE;AAAA,IACjB;AAAA,EAAA;AAEJ;AC1DA,SAAS+sB,GACPhvB,GACkF;AAClF,SAAO,CAAC2K,GAAOrM,MAAYwwB,GAAS,EAAE,GAAGxwB,GAAS,OAAAqM,GAAO,SAAA3K,GAAS;AACpE;AAEA,MAAMivB,KAAY;AAAA,EAChB,OAAOH;AAAA,EACP,SAASE,GAAc,SAAS;AAAA,EAChC,OAAOA,GAAc,OAAO;AAAA,EAC5B,MAAMA,GAAc,MAAM;AAAA,EAC1B,SAASH;AACX;AASO,SAASK,KAA2B;AACzC,QAAMX,IAASxuB,EAAM,qBAAqB4uB,IAAmBC,IAAWA,EAAS;AACjF,SAAO7uB,EAAM,QAAQ,OAAO,EAAE,QAAAwuB,GAAQ,GAAGU,GAAA,IAAc,CAACV,CAAM,CAAC;AACjE;AC1CApwB,GAAsB,SAAS,SAAS;AAIxC,SAASuuB,GAAU3tB,GAAsC;AACvD,SACE,gBAAAmC;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,SAAQ;AAAA,MACR,MAAK;AAAA,MACL,QAAO;AAAA,MACP,aAAa;AAAA,MACb,eAAc;AAAA,MACd,gBAAe;AAAA,MACf,eAAY;AAAA,MACZ,WAAW;AAAA,MACV,GAAGnC;AAAA,MAEJ,UAAA;AAAA,QAAA,gBAAAqB,EAAC,QAAA,EAAK,IAAG,MAAK,IAAG,KAAI,IAAG,KAAI,IAAG,KAAA,CAAK;AAAA,QACpC,gBAAAA,EAAC,UAAK,IAAG,KAAI,IAAG,KAAI,IAAG,MAAK,IAAG,KAAA,CAAK;AAAA,MAAA;AAAA,IAAA;AAAA,EAAA;AAG1C;AAMO,MAAM+uB,KAAgBvwB,GAAS;AAAA,EACpC,MAAM;AAAA,EACN,UAAU;AAAA,IACR,SAAS;AAAA,MACP,SAAS;AAAA,MACT,SAAS;AAAA,MACT,OAAO;AAAA,MACP,MAAM;AAAA,IAAA;AAAA,EACR;AAAA,EAEF,iBAAiB;AAAA,IACf,SAAS;AAAA,EAAA;AAEb,CAAC;AAsBM,SAASwwB,GAAQ;AAAA,EACtB,UAAAC,IAAW;AAAA,EACX,gBAAAC,IAAiB;AAAA,EACjB,OAAA/e,IAAQ;AAAA,EACR,mBAAAgf;AAAA,EACA,gBAAAC;AACF,GAAqC;AACnC,QAAM,EAAE,QAAAjB,EAAA,IAAWW,GAAA;AAEnB,2BACGO,GAAe,UAAf,EAAwB,UAAAJ,GAAoB,gBAAAC,GAAgC,OAAA/e,GAC1E,UAAA;AAAA,IAAAge,EAAO,IAAI,CAAC1pB,MACX,gBAAA3D;AAAA,MAACuuB,GAAe;AAAA,MAAf;AAAA,QAEC,UAAU5qB,EAAK;AAAA,QACf,gBAAcA,EAAK;AAAA,QACnB,cAAc,CAACqQ,MAAS;AACtB,UAAKA,KACH2Z,GAAahqB,EAAK,EAAE;AAAA,QAExB;AAAA,QACA,WAAWsqB,GAAc,EAAE,SAAStqB,EAAK,SAAS,WAAW2qB,GAAgB;AAAA,QAE7E,UAAA;AAAA,UAAA,gBAAAtuB,EAAC,OAAA,EAAI,WAAU,qBACZ,UAAA;AAAA,YAAA2D,EAAK,SAAS,QACb,gBAAAzE,EAACqvB,GAAe,OAAf,EAAqB,WAAU,yBAC7B,UAAA5qB,EAAK,MAAA,CACR;AAAA,YAEDA,EAAK,eAAe,QACnB,gBAAAzE,EAACqvB,GAAe,aAAf,EAA2B,WAAU,sBACnC,UAAA5qB,EAAK,YAAA,CACR;AAAA,UAAA,GAEJ;AAAA,UACCA,EAAK,UAAU,QAAQ,gBAAAzE,EAAC,SAAI,WAAU,8BAA8B,YAAK,OAAA,CAAO;AAAA,UACjF,gBAAAA;AAAA,YAACqvB,GAAe;AAAA,YAAf;AAAA,cACC,cAAW;AAAA,cACX,WAAU;AAAA,cAEV,UAAA,gBAAArvB,EAACssB,IAAA,EAAU,WAAU,UAAA,CAAU;AAAA,YAAA;AAAA,UAAA;AAAA,QACjC;AAAA,MAAA;AAAA,MA5BK7nB,EAAK;AAAA,IAAA,CA8Bb;AAAA,IACD,gBAAAzE;AAAA,MAACqvB,GAAe;AAAA,MAAf;AAAA,QACC,WAAWhyB;AAAA,UACT;AAAA,UACA8xB;AAAA,QAAA;AAAA,MACF;AAAA,IAAA;AAAA,EACF,GACF;AAEJ;ACtHApxB,GAAsB,QAAQ,MAAM;AAIpC,SAASuxB,GAAY3wB,GAAuC;AAC1D,SACE,gBAAAmC;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,SAAQ;AAAA,MACR,MAAK;AAAA,MACL,QAAO;AAAA,MACP,aAAa;AAAA,MACb,eAAc;AAAA,MACd,gBAAe;AAAA,MACf,eAAY;AAAA,MACZ,WAAW;AAAA,MACV,GAAGnC;AAAA,MAEJ,UAAA;AAAA,QAAA,gBAAAqB,EAAC,QAAA,EAAK,IAAG,MAAK,IAAG,MAAK,IAAG,MAAK,IAAG,IAAA,CAAI;AAAA,QACrC,gBAAAA,EAAC,YAAA,EAAS,QAAO,kBAAA,CAAkB;AAAA,MAAA;AAAA,IAAA;AAAA,EAAA;AAGzC;AAEA,SAASuvB,GAAc5wB,GAAuC;AAC5D,SACE,gBAAAmC;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,SAAQ;AAAA,MACR,MAAK;AAAA,MACL,QAAO;AAAA,MACP,aAAa;AAAA,MACb,eAAc;AAAA,MACd,gBAAe;AAAA,MACf,eAAY;AAAA,MACZ,WAAW;AAAA,MACV,GAAGnC;AAAA,MAEJ,UAAA;AAAA,QAAA,gBAAAqB,EAAC,QAAA,EAAK,IAAG,MAAK,IAAG,KAAI,IAAG,MAAK,IAAG,KAAA,CAAK;AAAA,QACrC,gBAAAA,EAAC,YAAA,EAAS,QAAO,mBAAA,CAAmB;AAAA,MAAA;AAAA,IAAA;AAAA,EAAA;AAG1C;AAmBA,SAASwvB,GAAmBC,GAAuB;AACjD,QAAMC,IAAY,KAAK,IAAID,CAAK,EAAE,eAAA;AAClC,SAAOA,KAAS,IAAI,IAAIC,CAAS,KAAK,IAAIA,CAAS;AACrD;AAQO,MAAMC,KAAOhwB,EAAM;AAAA,EACxB,CAAC,EAAE,OAAAwQ,GAAO,OAAAjR,GAAO,OAAAuwB,GAAO,aAAAG,IAAcJ,IAAoB,MAAAxhB,GAAM,WAAApP,GAAW,GAAGD,EAAA,GAASoB,MAAQ;AAC7F,QAAI8vB,IAA6B;AACjC,QAAI,OAAOJ,KAAU,YAAY,OAAO,SAASA,CAAK,GAAG;AACvD,YAAMK,IAAOL,IAAQ;AACrB,MAAAI,IACE,gBAAA/uB;AAAA,QAAC;AAAA,QAAA;AAAA,UACC,WAAWzD;AAAA,YACT;AAAA,YACAyyB,IAAO,qBAAqB;AAAA,UAAA;AAAA,UAG7B,UAAA;AAAA,YAAAA,IACC,gBAAA9vB,EAACuvB,MAAc,WAAU,cAAA,CAAc,IAEvC,gBAAAvvB,EAACsvB,IAAA,EAAY,WAAU,cAAA,CAAc;AAAA,YAEvC,gBAAAxuB,EAAC,QAAA,EAAK,WAAU,WAAW,UAAA;AAAA,cAAAgvB,IAAO,iBAAiB;AAAA,cAAe;AAAA,YAAA,GAAC;AAAA,YAClEF,EAAYH,CAAK;AAAA,UAAA;AAAA,QAAA;AAAA,MAAA;AAAA,IAGxB,MAAA,CAAWA,KAAS,SAClBI,IAAY,gBAAA7vB,EAAC,OAAA,EAAI,WAAU,iCAAiC,UAAAyvB,GAAM;AAGpE,WACE,gBAAA3uB;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,KAAAf;AAAA,QACA,WAAW1C;AAAA,UACT;AAAA,UACAuB;AAAA,QAAA;AAAA,QAED,GAAGD;AAAA,QAEJ,UAAA;AAAA,UAAA,gBAAAmC,EAAC,OAAA,EAAI,WAAU,0CACb,UAAA;AAAA,YAAA,gBAAAd,EAAC,KAAA,EAAE,WAAU,6CAA6C,UAAAmQ,GAAM;AAAA,YAC/DnC,KAAQ,QACP,gBAAAhO,EAAC,QAAA,EAAK,eAAY,QAAO,WAAU,iDAChC,UAAAgO,EAAA,CACH;AAAA,UAAA,GAEJ;AAAA,UACA,gBAAAhO,EAAC,KAAA,EAAE,WAAU,yCAAyC,UAAAd,GAAM;AAAA,UAC3D2wB;AAAA,QAAA;AAAA,MAAA;AAAA,IAAA;AAAA,EAGP;AACF;AACAF,GAAK,cAAc;ACrHnB5xB,GAAsB,SAAS,WAAW;AAoE1C,MAAMgyB,KAAgB;AAAA,EACpB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAEMC,KAAc;AAAA,EAClB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAEMC,KAAgB;AAAA,EACpB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAEA,SAASC,GAAYlxB,GAA4BgQ,GAAuB;AAItE,SAHchQ,EAAQgQ,IAAQhQ,EAAQ,MAAM,KAG5BA,EAAQ,CAAC,KAAK;AAChC;AAEA,MAAMmxB,KAAS,EAAE,KAAK,GAAG,OAAO,IAAI,QAAQ,IAAI,MAAM,GAAA;AAEtD,SAASC,GAAQC,GAAeC,GAAwB;AACtD,QAAMC,IAAW,KAAK,MAAM,KAAK,MAAMF,CAAK,CAAC,GACvCG,IAAWH,IAAQ,MAAME;AAC/B,MAAIE;AACJ,SAAIH,IACFG,IAAeD,IAAW,MAAM,IAAIA,IAAW,IAAI,IAAIA,IAAW,IAAI,IAAI,KAE1EC,IAAeD,KAAY,IAAI,IAAIA,KAAY,IAAI,IAAIA,KAAY,IAAI,IAAI,IAEtEC,IAAe,MAAMF;AAC9B;AAEA,SAASG,GAAU9lB,GAAaC,GAAayE,GAAyB;AACpE,QAAMqhB,IAAO9lB,IAAMD,IAAMC,IAAMD,IAAM,GAC/BgmB,IAAOR,GAAQA,GAAQO,GAAM,EAAK,IAAI,KAAK,IAAI,GAAGrhB,CAAK,GAAG,EAAI,GAC9DuhB,IAAQ,KAAK,MAAMjmB,IAAMgmB,CAAI,IAAIA,GACjCE,IAAM,KAAK,KAAKjmB,IAAM+lB,CAAI,IAAIA,GAC9BG,IAAkB,CAAA;AACxB,WAAS7xB,IAAQ2xB,GAAO3xB,KAAS4xB,IAAMF,IAAO,GAAG1xB,KAAS0xB;AAExD,IAAAG,EAAM,KAAK,OAAO7xB,EAAM,QAAQ,EAAE,CAAC,CAAC;AAEtC,SAAO6xB;AACT;AASA,SAASC,GACPthB,GACAuhB,GACiB;AACjB,QAAM7oB,IACJ6oB,MAAWvhB,MAAS,SAAY,CAAC,EAAE,MAAM,SAAS,MAAAA,GAAM,IAAI,KAExDwhB,IAAuB,CAAA,GACvBhpB,wBAAW,IAAA;AACjB,aAAW,KAAKE;AACd,eAAW+oB,KAAS,EAAE;AACpB,MAAKjpB,EAAK,IAAIipB,EAAM,KAAK,MACvBjpB,EAAK,IAAIipB,EAAM,KAAK,GACpBD,EAAW,KAAKC,EAAM,KAAK;AAKjC,QAAMC,IAAShpB,EAAS,IAAI,CAAC,MAAM;AACjC,UAAMipB,wBAAc,IAAA;AACpB,eAAWF,KAAS,EAAE;AACpB,MAAI,OAAO,SAASA,EAAM,KAAK,KAC7BE,EAAQ,IAAIF,EAAM,OAAOA,EAAM,KAAK;AAGxC,WAAOD,EAAW,IAAI,CAAC/gB,MAAUkhB,EAAQ,IAAIlhB,CAAK,KAAK,IAAI;AAAA,EAC7D,CAAC;AAED,SAAO,EAAE,YAAA+gB,GAAY,aAAa9oB,EAAS,IAAI,CAAC,MAAM,EAAE,IAAI,GAAG,QAAAgpB,EAAA;AACjE;AAEA,SAASE,GAAsBpyB,GAAuB;AACpD,SAAOA,EAAM,eAAA;AACf;AAUO,SAASqyB,GAAU;AAAA,EACxB,MAAA5qB;AAAA,EACA,MAAA+I;AAAA,EACA,QAAAuhB;AAAA,EACA,OAAA1mB;AAAA,EACA,aAAAxB;AAAA,EACA,gBAAAyoB,IAAiBF;AAAA,EACjB,gBAAAG;AAAA,EACA,eAAAC;AAAA,EACA,OAAAC,IAAQ;AAAA,EACR,QAAAC,IAAS;AAAA,EACT,YAAAC,IAAa;AAAA,EACb,YAAAC;AAAA,EACA,aAAAC,IAAc;AAAA,EACd,gBAAAC,IAAiB;AAAA,EACjB,YAAAC,IAAa;AAAA,EACb,WAAArzB;AACF,GAAuC;AACrC,QAAMszB,IAAUvyB,EAAM,MAAA,GAChBwyB,IAASxyB,EAAM,MAAA,GACf,CAACyyB,GAASC,CAAU,IAAI1yB,EAAM,SAAwB,IAAI,GAE1D,EAAE,YAAAuxB,GAAY,aAAAoB,GAAa,QAAAlB,EAAA,IAAWzxB,EAAM;AAAA,IAChD,MAAMqxB,GAAUthB,GAAMuhB,CAAM;AAAA,IAC5B,CAACvhB,GAAMuhB,CAAM;AAAA,EAAA,GAGTlrB,IAASqrB,EAAO,KAAA,EAAO,OAAO,CAAClyB,MAA2BA,MAAU,IAAI;AAC9E,MAAIgyB,EAAW,WAAW,KAAKnrB,EAAO,WAAW;AAC/C,WACE,gBAAA/F;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,WAAW3C;AAAA,UACT;AAAA,UACAuB;AAAA,QAAA;AAAA,QAGD,UAAAqzB;AAAA,MAAA;AAAA,IAAA;AAMP,QAAMM,IAAS,KAAK,IAAI,GAAG,GAAGxsB,CAAM,GAC9BysB,IAAS,KAAK,IAAI,GAAG,GAAGzsB,CAAM,GAC9BgrB,IAAQL,GAAU6B,GAAQC,GAAQX,CAAU,GAC5CY,IAAY1B,EAAM,CAAC,KAAKwB,GACxBG,IAAY3B,EAAMA,EAAM,SAAS,CAAC,KAAKyB,GACvCG,IAAaD,IAAYD,KAAa,GAEtCG,IAAYjB,IAAQxB,GAAO,OAAOA,GAAO,OACzC0C,IAAajB,IAASzB,GAAO,MAAMA,GAAO,QAC1C2C,IAAS,CAAC5zB,MACdixB,GAAO,OAAQuC,IAAYxzB,KAASyzB,IAAcE,GAC9CE,IAAYH,IAAY1B,EAAW,QACnC8B,KAAa,CAAChkB,MAA0BmhB,GAAO,QAAQnhB,IAAQ,OAAO+jB,GACtEE,KAAQH,EAAO,KAAK,IAAIL,GAAW,KAAK,IAAIC,GAAW,CAAC,CAAC,CAAC,GAG1DQ,KAAc,KAAK,IAAI,GAAG9B,EAAO,MAAM,GACvC+B,KAAaJ,IAAY,KACzBK,KAAWD,KAAaD,IAExBG,KAAQjC,EAAO,IAAI,CAAClgB,GAAKoiB,MAAgB;AAC7C,QAAI3sB,MAAS;AACX,aACE,gBAAA3G,EAAC,KAAA,EAAoB,WAAWkwB,GAAYF,IAAasD,CAAW,GACjE,UAAApiB,EAAI,IAAI,CAAChS,GAAOq0B,MAAkB;AACjC,YAAIr0B,MAAU;AACZ,iBAAO;AAET,cAAMs0B,KAAIR,GAAWO,CAAa,IAAIJ,KAAa,IAAIG,IAAcF,IAC/DK,KAAI,KAAK,IAAIX,EAAO5zB,CAAK,GAAG+zB,EAAK,GACjCS,IAAY,KAAK,IAAIZ,EAAO5zB,CAAK,IAAI+zB,EAAK;AAChD,eACE,gBAAAjzB;AAAA,UAAC;AAAA,UAAA;AAAA,YAEC,GAAAwzB;AAAA,YACA,GAAAC;AAAA,YACA,OAAO,KAAK,IAAI,GAAGL,KAAW,CAAC;AAAA,YAC/B,QAAQM;AAAA,YACR,IAAI;AAAA,UAAA;AAAA,UALCH;AAAA,QAAA;AAAA,MAQX,CAAC,KAlBKD,CAmBR;AAIJ,UAAMK,KAASziB,EACZ;AAAA,MAAI,CAAChS,GAAOq0B,MACXr0B,MAAU,OAAO,OAAQ,CAAC8zB,GAAWO,CAAa,GAAGT,EAAO5zB,CAAK,CAAC;AAAA,IAAA,EAEnE,OAAO,CAACiyB,MAA8CA,MAAU,IAAI;AAEvE,6BACG,KAAA,EACC,UAAA;AAAA,MAAA,gBAAAnxB;AAAA,QAAC;AAAA,QAAA;AAAA,UACC,WAAWkwB,GAAYH,IAAeuD,CAAW;AAAA,UACjD,MAAK;AAAA,UACL,aAAa;AAAA,UACb,eAAc;AAAA,UACd,gBAAe;AAAA,UACf,QAAQK,GAAO,IAAI,CAAC,CAACH,GAAGC,CAAC,MAAM,GAAG,OAAOD,CAAC,CAAC,IAAI,OAAOC,CAAC,CAAC,EAAE,EAAE,KAAK,GAAG;AAAA,QAAA;AAAA,MAAA;AAAA,MAErEE,GAAO,IAAI,CAAC,CAACH,GAAGC,CAAC,GAAGG,OACnB,gBAAA5zB;AAAA,QAAC;AAAA,QAAA;AAAA,UAEC,WAAWkwB,GAAYF,IAAasD,CAAW;AAAA,UAC/C,IAAIE;AAAA,UACJ,IAAIC;AAAA,UACJ,GAAG;AAAA,QAAA;AAAA,QAJEG;AAAA,MAAA,CAMR;AAAA,IAAA,EAAA,GAjBKN,CAkBR;AAAA,EAEJ,CAAC,GAGKO,IAAM,CAAC30B,GAAe40B,MAA0B,GAAG,OAAQ50B,IAAQ40B,IAAS,GAAG,CAAC,KAChFC,KACJ3B,MAAY,OACR,CAAA,IACAhB,EACG,IAAI,CAAClgB,GAAKoiB,OAAiB;AAAA,IAC1B,YAAYhB,EAAYgB,CAAW,KAAK;AAAA,IACxC,OAAOpiB,EAAIkhB,CAAO,KAAK;AAAA,IACvB,iBAAiBlC,GAAYD,IAAeqD,CAAW;AAAA,EAAA,EACvD,EACD;AAAA,IACC,CAAC9sB,MACCA,EAAM,UAAU;AAAA,EAAA,GAEtBwtB,KAAe5B,MAAY,OAAO,SAAYlB,EAAWkB,CAAO,GAEhE6B,KAAgB3B,EAAY,SAAS;AAE3C,2BACG,OAAA,EAAI,WAAWj1B,EAAG,UAAUuB,CAAS,GACpC,UAAA;AAAA,IAAA,gBAAAkC,EAAC,OAAA,EAAI,WAAU,mBACb,UAAA;AAAA,MAAA,gBAAAA;AAAA,QAAC;AAAA,QAAA;AAAA,UACC,MAAK;AAAA,UACL,cAAYyJ;AAAA,UACZ,mBAAiB2nB;AAAA,UACjB,oBAAkBnpB,MAAgB,SAAYopB,IAAS;AAAA,UACvD,SAAS,OAAO,OAAOR,CAAK,CAAC,IAAI,OAAOC,CAAM,CAAC;AAAA,UAC/C,WAAU;AAAA,UAEV,UAAA;AAAA,YAAA,gBAAA5xB,EAAC,SAAA,EAAM,IAAIkyB,GAAU,UAAA3nB,GAAM;AAAA,YAC1BxB,MAAgB,UAAa,gBAAA/I,EAAC,QAAA,EAAK,IAAImyB,GAAS,UAAAppB,GAAY;AAAA,YAG5DgoB,EAAM,IAAI,CAACmD,wBACT,KAAA,EACC,UAAA;AAAA,cAAA,gBAAAl0B;AAAA,gBAAC;AAAA,gBAAA;AAAA,kBACC,IAAImwB,GAAO;AAAA,kBACX,IAAIwB,IAAQxB,GAAO;AAAA,kBACnB,IAAI2C,EAAOoB,CAAI;AAAA,kBACf,IAAIpB,EAAOoB,CAAI;AAAA,kBACf,QAAO;AAAA,kBACP,eAAeA,MAAS,IAAI,MAAM;AAAA,gBAAA;AAAA,cAAA;AAAA,cAEpC,gBAAAl0B;AAAA,gBAAC;AAAA,gBAAA;AAAA,kBACC,GAAGmwB,GAAO,OAAO;AAAA,kBACjB,GAAG2C,EAAOoB,CAAI;AAAA,kBACd,YAAW;AAAA,kBACX,kBAAiB;AAAA,kBACjB,UAAU;AAAA,kBACV,MAAK;AAAA,kBAEJ,YAAeA,CAAI;AAAA,gBAAA;AAAA,cAAA;AAAA,YACtB,EAAA,GAlBMA,CAmBR,CACD;AAAA,YAGAhD,EAAW,IAAI,CAACiD,GAAUnlB,MACzB,gBAAAhP;AAAA,cAAC;AAAA,cAAA;AAAA,gBAEC,GAAGgzB,GAAWhkB,CAAK;AAAA,gBACnB,GAAG4iB,IAASzB,GAAO,SAAS;AAAA,gBAC5B,YAAW;AAAA,gBACX,UAAU;AAAA,gBACV,MAAK;AAAA,gBAEJ,UAAAsB,IAAiBA,EAAe0C,CAAQ,IAAIA;AAAA,cAAA;AAAA,cAPxCA;AAAA,YAAA,CASR;AAAA,YAEAd;AAAA,UAAA;AAAA,QAAA;AAAA,MAAA;AAAA,MAKFtB,KACC,gBAAAjxB,EAAC,OAAA,EAAI,eAAY,QAAO,WAAU,oBAChC,UAAA;AAAA,QAAA,gBAAAd;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,WAAU;AAAA,YACV,OAAO;AAAA,cACL,MAAM6zB,EAAI1D,GAAO,MAAMwB,CAAK;AAAA,cAC5B,OAAOkC,EAAIjB,GAAWjB,CAAK;AAAA,cAC3B,KAAKkC,EAAI1D,GAAO,KAAKyB,CAAM;AAAA,cAC3B,QAAQiC,EAAIhB,GAAYjB,CAAM;AAAA,YAAA;AAAA,YAEhC,cAAc,MAAM;AAClB,cAAAS,EAAW,IAAI;AAAA,YACjB;AAAA,YAEC,UAAAnB,EAAW,IAAI,CAACiD,GAAUnlB,MACzB,gBAAAhP;AAAA,cAAC;AAAA,cAAA;AAAA,gBAEC,wBAAsBgP;AAAA,gBACtB,WAAU;AAAA,gBACV,cAAc,MAAM;AAClB,kBAAAqjB,EAAWrjB,CAAK;AAAA,gBAClB;AAAA,cAAA;AAAA,cALKmlB;AAAA,YAAA,CAOR;AAAA,UAAA;AAAA,QAAA;AAAA,QAEF/B,MAAY,QAAQ4B,OAAiB,UAAaD,GAAc,SAAS,KACxE,gBAAA/zB;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,4BAAyB;AAAA,YACzB,WAAU;AAAA,YACV,OAAO;AAAA,cACL,MAAM6zB,EAAIb,GAAWZ,CAAO,GAAGT,CAAK;AAAA,cACpC,KAAKkC,EAAI1D,GAAO,KAAKyB,CAAM;AAAA,YAAA;AAAA,YAG5B,UAAAF,IACCA,EAAc,EAAE,OAAOsC,IAAc,QAAQD,GAAA,CAAe,IAE5D,gBAAAjzB,EAAAuP,GAAA,EACE,UAAA;AAAA,cAAA,gBAAArQ,EAAC,KAAA,EAAE,WAAU,oBAAoB,UAAAg0B,IAAa;AAAA,cAC7CD,GAAc,IAAI,CAAC5C,MAClB,gBAAArwB,EAAC,KAAA,EAAyB,WAAU,6BAClC,UAAA;AAAA,gBAAA,gBAAAd;AAAA,kBAAC;AAAA,kBAAA;AAAA,oBACC,WAAW3C,EAAG,iCAAiC8zB,EAAM,eAAe;AAAA,kBAAA;AAAA,gBAAA;AAAA,gBAEtE,gBAAAnxB,EAAC,QAAA,EAAK,WAAU,yBAAyB,YAAM,YAAW;AAAA,kCACzD,QAAA,EAAK,WAAU,uBAAuB,UAAAwxB,EAAeL,EAAM,KAAK,EAAA,CAAE;AAAA,cAAA,EAAA,GAL7DA,EAAM,UAMd,CACD;AAAA,YAAA,EAAA,CACH;AAAA,UAAA;AAAA,QAAA;AAAA,MAEJ,EAAA,CAEJ;AAAA,IAAA,GAEJ;AAAA,KAEEW,KAAcmC,OACd,gBAAAj0B,EAAC,OAAA,EAAI,eAAY,QAAO,WAAU,oDAC/B,UAAAsyB,EAAY,IAAI,CAAC1wB,GAAMoN,MACtB,gBAAAlO,EAAC,QAAA,EAAgB,WAAU,2DACzB,UAAA;AAAA,MAAA,gBAAAd,EAAC,QAAA,EAAK,WAAW3C,EAAG,wBAAwB6yB,GAAYD,IAAejhB,CAAK,CAAC,GAAG;AAAA,MAC/EpN;AAAA,IAAA,KAFQA,CAGX,CACD,GACH;AAAA,IAIF,gBAAA5B,EAACo0B,GAAe,MAAf,EAAoB,SAAO,IAC1B,UAAA,gBAAAp0B,EAAC,OAAA,EACC,UAAA,gBAAAc,EAAC,SAAA,EACC,UAAA;AAAA,MAAA,gBAAAd,EAAC,aAAS,UAAAuK,EAAA,CAAM;AAAA,MAChB,gBAAAvK,EAAC,SAAA,EACC,UAAA,gBAAAc,EAAC,MAAA,EACC,UAAA;AAAA,QAAA,gBAAAd,EAAC,MAAA,EAAG,OAAM,OAAO,UAAAgyB,GAAe;AAAA,QAC/BM,EAAY,IAAI,CAAC1wB,MAChB,gBAAA5B,EAAC,QAAc,OAAM,OAClB,UAAA4B,EAAA,GADMA,CAET,CACD;AAAA,MAAA,EAAA,CACH,EAAA,CACF;AAAA,MACA,gBAAA5B,EAAC,WACE,UAAAkxB,EAAW,IAAI,CAACiD,GAAUZ,wBACxB,MAAA,EACC,UAAA;AAAA,QAAA,gBAAAvzB,EAAC,MAAA,EAAG,OAAM,OAAO,UAAAm0B,GAAS;AAAA,QACzB/C,EAAO,IAAI,CAAClgB,IAAKoiB,MAAgB;AAChC,gBAAMp0B,IAAQgS,GAAIqiB,CAAa,KAAK;AACpC,iBACE,gBAAAvzB,EAAC,QAAsB,UAAAd,MAAU,OAAO,MAAMsyB,EAAetyB,CAAK,KAAzDo0B,CAA2D;AAAA,QAExE,CAAC;AAAA,MAAA,EAAA,GAPMa,CAQT,CACD,EAAA,CACH;AAAA,IAAA,EAAA,CACF,GACF,EAAA,CACF;AAAA,EAAA,GACF;AAEJ;"}
|