@coolms/image-editor-angular 2.0.0-alpha.2

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.
@@ -0,0 +1 @@
1
+ {"version":3,"file":"coolms-image-editor-angular.mjs","sources":["../../src/types/layer.types.ts","../../src/engine/command/command-stack.ts","../../src/engine/fabric-engine.adapter.ts","../../src/services/image-editor-state.service.ts","../../src/components/top-toolbar/top-toolbar.component.ts","../../src/components/top-toolbar/top-toolbar.component.html","../../src/components/canvas-mount/canvas-mount.component.ts","../../src/components/canvas-mount/canvas-mount.component.html","../../src/tools/tool-registry.service.ts","../../src/components/right-sidebar/right-sidebar.component.ts","../../src/components/right-sidebar/right-sidebar.component.html","../../src/tools/crop/crop-tool.component.ts","../../src/tools/crop/crop-tool.component.html","../../src/tools/rotate/rotate-tool.component.ts","../../src/tools/rotate/rotate-tool.component.html","../../src/tools/flip/flip-tool.component.ts","../../src/tools/flip/flip-tool.component.html","../../src/tools/resize/resize-tool.component.ts","../../src/tools/resize/resize-tool.component.html","../../src/tools/mask/svg-mask.util.ts","../../src/tools/mask/mask-tool.component.ts","../../src/tools/filter/slider-filter.component.ts","../../src/tools/filter/slider-filter.component.html","../../src/tools/filter/toggle-filter.component.ts","../../src/tools/filter/toggle-filter.component.html","../../src/tools/shape/shape-tool.component.ts","../../src/tools/text/text-tool.component.ts","../../src/tools/layers/layers-panel.component.ts","../../src/components/coolms-image-editor.component.ts","../../src/components/coolms-image-editor.component.html","../../src/host/overwrite-confirm-dialog.component.ts","../../src/host/save-as-dialog.component.ts","../../src/services/image-editor-http.service.ts","../../src/host/coolms-image-editor-host.component.ts","../../src/host/coolms-image-editor-host.component.html","../../src/index.ts","../../src/coolms-image-editor-angular.ts"],"sourcesContent":["/**\n * Object / layer model for the image editor (Track C.1).\n *\n * The editor was historically single-image (one `FabricImage`, flat\n * bitmap). C.1 introduces an **objects-as-layers** model: the base\n * image is the bottom layer; every shape / text the author adds is a\n * layer stacked on top. Fabric's canvas is already an ordered object\n * stack, so a \"layer\" is just a canvas object carrying a stable id.\n *\n * Resize / filters still operate on the base image only — they're\n * pixel-baking ops, meant to run before annotations. C.1c makes\n * **rotate / flip** target the selected non-image layer (falling back\n * to the base image) and adds **masking** (a clip-path on the target;\n * see {@link MaskSpec}); C.1e makes **crop** composition-aware — the\n * annotation layers shift with the cropped content and clip at the new\n * edges, so a crop after annotating stays aligned.\n */\n\n/** What a layer is. `image` is the immovable-from-the-stack base. */\nexport type LayerKind = 'image' | 'shape' | 'text';\n\n/** The shape primitives the Shapes tool can insert. */\nexport type ShapeKind = 'rect' | 'ellipse' | 'line' | 'arrow' | 'triangle';\n\n/**\n * Canvas-space geometry of an annotation shape — the round-trippable\n * subset consumers that author geometry (e.g. the ImageMap region\n * page) read and write via `addShapeAt()` / `getShapeGeometry()`.\n * Coordinates are SCENE space (viewport zoom/pan factored out), the\n * same space `getImageBounds()` reports in.\n */\nexport type ShapeGeometry =\n | { kind: 'rect'; rect: { x: number; y: number; width: number; height: number } }\n | { kind: 'ellipse'; center: { x: number; y: number }; rx: number; ry: number }\n | { kind: 'polygon'; points: { x: number; y: number }[] };\n\n/**\n * Options for `addShapeAt()`. Style keys mirror {@link ShapeOptions};\n * the extras tune the shape for geometry-authoring use:\n * - `name`: layer display name (defaults to the shape kind).\n * - `lockRotation`: hide the rotate handle — authored geometry is\n * axis-aligned (rect regions have no rotation representation).\n * - `lockNonUniformScaling`: hide the edge handles so corner drags\n * scale uniformly (keeps a circle circular).\n */\nexport interface AnnotationShapeOptions {\n fill?: string;\n stroke?: string;\n strokeWidth?: number;\n name?: string;\n lockRotation?: boolean;\n lockNonUniformScaling?: boolean;\n}\n\n/**\n * How a shape / text layer is filled (C.1b).\n *\n * - `solid` : a single flat colour.\n * - `linear` : a linear gradient from `color` -> `color2` along `angle`.\n * - `radial` : a radial gradient from `color` (centre) -> `color2` (edge).\n */\nexport type FillType = 'solid' | 'linear' | 'radial';\n\n/**\n * UI-friendly, serialisable description of a fill. The engine\n * translates this to / from a fabric solid colour or `Gradient`, so the\n * tool components never import fabric. Colours are `#rrggbb` hex (what\n * `<input type=\"color\">` reads / writes); `angle` is in degrees\n * (0 = left->right, 90 = top->bottom) and only meaningful for `linear`.\n */\nexport interface FillSpec {\n type: FillType;\n color: string;\n color2: string;\n angle: number;\n}\n\n/**\n * A read-only view of one layer, surfaced to the Layers panel. The\n * engine owns the fabric objects; this is the serialisable projection\n * the UI binds to (never a live fabric handle).\n */\nexport interface LayerInfo {\n readonly id: string;\n readonly kind: LayerKind;\n readonly name: string;\n readonly visible: boolean;\n /** 0..1. */\n readonly opacity: number;\n /**\n * True for the base image: it can't be deleted or reordered below\n * itself (it's the canvas floor). Shapes / text are never locked.\n */\n readonly locked: boolean;\n}\n\n/** Style options for an inserted shape. */\nexport interface ShapeOptions {\n fill: string;\n stroke: string;\n strokeWidth: number;\n /**\n * Richer fill description (solid colour or gradient). When present\n * it takes precedence over the flat `fill` string. The Shapes tool\n * always sends this; `fill` stays a plain-colour fallback for any\n * caller that doesn't. (C.1b)\n */\n fillSpec?: FillSpec;\n}\n\n/** Style options for inserted text. */\nexport interface TextOptions {\n text: string;\n fontFamily: string;\n fontSize: number;\n fill: string;\n fontWeight: 'normal' | 'bold';\n fontStyle: 'normal' | 'italic';\n textAlign: 'left' | 'center' | 'right';\n /** Gradient-capable fill; see {@link ShapeOptions.fillSpec}. (C.1b) */\n fillSpec?: FillSpec;\n}\n\n/**\n * Generic property bag the style panels read/write against the active\n * object. Keys are fabric property names (`fill`, `stroke`,\n * `strokeWidth`, `opacity`, `fontFamily`, …); the engine reads them off\n * / sets them on the active object without the UI importing fabric.\n */\nexport type ObjectProps = Record<string, string | number>;\n\nexport const DEFAULT_SHAPE_OPTIONS: ShapeOptions = {\n fill: '#4f8cff',\n stroke: '#1b1f24',\n strokeWidth: 2,\n};\n\n/** Starting fill for the Shapes / Text tools (solid, blue accent). (C.1b) */\nexport const DEFAULT_FILL_SPEC: FillSpec = {\n type: 'solid',\n color: DEFAULT_SHAPE_OPTIONS.fill,\n // Literal on purpose — this is a CANVAS fill, not CSS: Fabric resolves no\n // custom properties, so a `var()` here renders as nothing.\n color2: '#ffffff',\n angle: 0,\n};\n\nexport const DEFAULT_TEXT_OPTIONS: TextOptions = {\n text: 'Text',\n fontFamily: 'Arial',\n fontSize: 48,\n fill: '#1b1f24',\n fontWeight: 'normal',\n fontStyle: 'normal',\n textAlign: 'left',\n};\n\n/** Font families offered in the Text tool (web-safe set). */\nexport const TEXT_FONT_FAMILIES = [\n 'Arial',\n 'Helvetica',\n 'Times New Roman',\n 'Georgia',\n 'Courier New',\n 'Verdana',\n 'Trebuchet MS',\n 'Impact',\n] as const;\n\n/**\n * Mask / clip shapes a layer can be cut to (C.1c / C.1d).\n *\n * `none` clears the mask. `rect` / `rounded` / `ellipse` / `triangle`\n * are geometric primitives; `star` / `heart` / `hexagon` are SVG-path\n * presets. `custom` (C.1d) clips to arbitrary path geometry the user\n * pasted or uploaded as an SVG — see {@link MaskSpec.svgPath}. The\n * engine builds the matching fabric `clipPath` against the target's own\n * box, so the mask tracks the object through scale / move, and the\n * export flatten bakes it in (the clip is part of the object's normal\n * render path).\n */\nexport type MaskShape =\n | 'none' | 'rect' | 'rounded' | 'ellipse' | 'triangle'\n | 'star' | 'heart' | 'hexagon' | 'custom';\n\n/**\n * UI-friendly description of a layer mask. The engine translates it to /\n * from a fabric `clipPath`, so the tool component never imports fabric.\n *\n * - `inset` : 0..40, percent each edge is pulled in from the box (a\n * symmetric margin around the clip).\n * - `radius` : 0..50, corner radius for `rounded` only, as a percent of\n * the clip's shorter half-dimension (50 = pill / circle).\n * - `svgPath` : SVG path `d` data for `shape: 'custom'` (C.1d). Sanitised\n * geometry extracted from a pasted path string or uploaded\n * SVG file — every drawable element is flattened to a single\n * combined path (paths only, no script / external refs). The\n * engine scales its bounding box to the clip box exactly\n * like the built-in path presets, so it tracks scale / move\n * and round-trips through the `coolmsMask` stamp.\n */\nexport interface MaskSpec {\n shape: MaskShape;\n inset: number;\n radius: number;\n svgPath?: string;\n}\n\n/** Starting mask for the Mask tool (no clip). (C.1c) */\nexport const DEFAULT_MASK_SPEC: MaskSpec = {\n shape: 'none',\n inset: 0,\n radius: 30,\n};\n\n/**\n * SVG path data for the path-preset masks, normalised to a 0..100 box.\n * The engine scales each to the target's clip box. (C.1c)\n */\nexport const MASK_PATHS: Readonly<Record<'star' | 'heart' | 'hexagon', string>> = {\n star: 'M50 3 L61 38 L98 38 L68 60 L79 96 L50 73 L21 96 L32 60 L2 38 L39 38 Z',\n heart: 'M50 90 C18 66 4 46 4 28 C4 14 16 6 28 6 C39 6 47 13 50 22 C53 13 61 6 72 6 C84 6 96 14 96 28 C96 46 82 66 50 90 Z',\n hexagon: 'M50 3 L93 27 L93 73 L50 97 L7 73 L7 27 Z',\n} as const;\n","import type { EngineCommand } from './engine-command.types';\n\n/**\n * Two-array undo / redo stack for engine operations. The adapter pushes\n * each command after running its forward op; pushing clears the redo\n * stack, mirroring the convention every desktop editor uses (a fresh\n * branch invalidates the previous redo timeline).\n */\nexport class CommandStack {\n private undoStack: EngineCommand[] = [];\n private redoStack: EngineCommand[] = [];\n\n push(cmd: EngineCommand): void {\n this.undoStack.push(cmd);\n this.redoStack = [];\n }\n\n async undo(): Promise<void> {\n const cmd = this.undoStack.pop();\n if (cmd === undefined) return;\n await cmd.undo();\n this.redoStack.push(cmd);\n }\n\n async redo(): Promise<void> {\n const cmd = this.redoStack.pop();\n if (cmd === undefined) return;\n await cmd.do();\n this.undoStack.push(cmd);\n }\n\n canUndo(): boolean { return this.undoStack.length > 0; }\n canRedo(): boolean { return this.redoStack.length > 0; }\n\n clearRedo(): void { this.redoStack = []; }\n\n clear(): void {\n this.undoStack = [];\n this.redoStack = [];\n }\n}\n"," \nimport {\n Canvas, FabricImage, Point, Rect as FabricRect, filters,\n config as fabricConfig, initFilterBackend, setFilterBackend,\n Ellipse, Line, Triangle, Polygon, Textbox, Gradient, Path,\n Control, util,\n} from 'fabric/es';\nimport type { FabricObject, Transform } from 'fabric/es';\nimport type { ImageEditorEngine } from './image-editor-engine.interface';\nimport type { Point as PointType, Rect, Size } from '../types/geometry.types';\nimport type { FilterName, FilterParams } from '../types/filter.types';\nimport type {\n LayerInfo, LayerKind, ShapeKind, ShapeOptions, TextOptions, ObjectProps, FillSpec, MaskSpec,\n ShapeGeometry, AnnotationShapeOptions,\n} from '../types/layer.types';\nimport { DEFAULT_SHAPE_OPTIONS, DEFAULT_TEXT_OPTIONS, DEFAULT_MASK_SPEC, MASK_PATHS } from '../types/layer.types';\nimport type {\n EngineEventType, EngineEventHandler, EngineEvents,\n} from './engine-events';\nimport { CommandStack } from './command/command-stack';\nimport type { EngineCommand } from './command/engine-command.types';\n\ninterface FabricEngineCreateOptions {\n container: HTMLElement;\n}\n\ninterface ImageTransformState {\n angle: number;\n scaleX: number;\n scaleY: number;\n flipX: boolean;\n flipY: boolean;\n left: number;\n top: number;\n}\n\ninterface VertexEditSnapshot {\n points: PointType[];\n left: number;\n top: number;\n}\n\ninterface VertexEditState {\n obj: Polygon;\n savedControls: Record<string, Control>;\n savedProps: {\n hasBorders: boolean;\n lockMovementX: boolean;\n lockMovementY: boolean;\n cornerStyle: 'rect' | 'circle';\n cornerColor: string;\n cornerStrokeColor: string;\n transparentCorners: boolean;\n };\n /** Non-null while a vertex drag is in flight (snapshot for undo). */\n pointsBefore: VertexEditSnapshot | null;\n}\n\ntype SliderFilterCtor = new (params: Record<string, number>) => any;\ntype ToggleFilterCtor = new (params?: Record<string, number>) => any;\ntype ConvoluteFilterCtor = new (params: { matrix: number[]; opaque?: boolean }) => any;\n\nconst SHARPEN_KERNEL: readonly number[] = [0, -1, 0, -1, 5, -1, 0, -1, 0];\n\n/**\n * Pin the loaded image to v6's `left`/`top` origin so the\n * captureTransform snapshot/restore path and frame-overlay math\n * keep treating `image.left/image.top` as visual top-left\n * coordinates (fabric 7 default flipped to `center`/`center`).\n */\nconst IMAGE_ORIGIN_OPTIONS = { originX: 'left', originY: 'top' } as const;\n\n/**\n * fabric.js v7 adapter for the CoolMS image editor.\n *\n * Mounts a fresh `<canvas>` element inside the consumer-provided\n * container and takes ownership of canvas backstore + CSS dimensions\n * so viewport zoom is the single source of truth for visual scale.\n * No vendor CSS auto-fit layer in front of fabric, so small images\n * (sub-viewport) zoom predictably and large images shrink-to-fit\n * through the same `setZoom` path.\n *\n * fabric 7 flipped the FabricObject default origin from 'left'/'top'\n * (v6) to 'center'/'center'. The crop overlay's `bounds.left/top`\n * positioning math assumes 'left'/'top' semantics, and we keep\n * `image.left/image.top` referring to the visual top-left corner so\n * the snapshot/restore captureTransform path stays a no-op. Image\n * and crop-overlay constructors below pass explicit `originX: 'left',\n * originY: 'top'` to preserve v6 behavior bit-for-bit. The frame\n * overlay mirrors `image.originX/originY` so it follows whatever the\n * image uses.\n *\n * Use `FabricEngineAdapter.create(options)` rather than `new`. The\n * factory wires up the canvas element and seeds initial dimensions\n * from the container's measured size.\n */\nexport class FabricEngineAdapter implements ImageEditorEngine {\n private static readonly TOGGLE_FILTERS: Partial<Record<FilterName, ToggleFilterCtor>> = {\n sepia: filters.Sepia,\n grayscale: filters.Grayscale,\n invert: filters.Invert,\n };\n\n private static readonly SLIDER_FILTERS: Partial<Record<FilterName, SliderFilterCtor>> = {\n brightness: filters.Brightness,\n contrast: filters.Contrast,\n saturation: filters.Saturation,\n blur: filters.Blur,\n noise: filters.Noise,\n pixelate: filters.Pixelate,\n };\n\n private readonly canvas: Canvas;\n private readonly canvasEl: HTMLCanvasElement;\n private readonly container: HTMLElement;\n /** The default annotation-shape fill; `setLayerFill(id, null)` restores it. */\n private static readonly DEFAULT_SHAPE_FILL = 'rgba(37, 99, 235, 0.20)';\n\n private readonly listeners = new Map<EngineEventType, Set<(data: any) => void>>();\n private readonly commandStack = new CommandStack();\n\n private image: FabricImage | null = null;\n private vertexEdit: VertexEditState | null = null;\n private originalSource: { url: string; name: string } | { blob: Blob; name: string } | null = null;\n private cropOverlay: FabricRect | null = null;\n private frameOverlay: FabricRect | null = null;\n private mouseTransformSnapshot: ImageTransformState | null = null;\n\n // --- C.1 layer model -------------------------------------------\n /** Monotonic id source for shape / text layers. */\n private nextLayerId = 1;\n /**\n * Transform snapshot for a non-image object captured on\n * `mouse:down`, so `object:modified` can build the inverse for\n * undo (mirrors `mouseTransformSnapshot` but for shapes / text).\n */\n private objTransformSnapshot: { obj: FabricObject; state: Record<string, number> } | null = null;\n\n private constructor(canvas: Canvas, canvasEl: HTMLCanvasElement, container: HTMLElement) {\n this.canvas = canvas;\n this.canvasEl = canvasEl;\n this.container = container;\n this.attachVendorListeners();\n }\n\n /**\n * Build an adapter against the given container element. Creates a\n * `<canvas>` child sized to the container and constructs a fabric\n * Canvas around it.\n */\n static async create(options: FabricEngineCreateOptions): Promise<FabricEngineAdapter> {\n const container = options.container;\n const canvasEl = document.createElement('canvas');\n canvasEl.width = Math.max(1, container.clientWidth);\n canvasEl.height = Math.max(1, container.clientHeight);\n container.appendChild(canvasEl);\n\n const canvas = new Canvas(canvasEl, {\n preserveObjectStacking: true,\n selection: true,\n backgroundColor: 'transparent',\n renderOnAddRemove: true,\n });\n\n return new FabricEngineAdapter(canvas, canvasEl, container);\n }\n\n async loadImage(source: string | Blob, name = 'image'): Promise<Size> {\n const url = typeof source === 'string'\n ? source\n : URL.createObjectURL(source);\n const ownsUrl = typeof source !== 'string';\n\n try {\n const image = await FabricImage.fromURL(url, { crossOrigin: 'anonymous' }, IMAGE_ORIGIN_OPTIONS);\n if (this.image !== null) {\n this.canvas.remove(this.image);\n }\n // A fresh load / reset wipes annotation layers too, so the\n // canvas returns to a truly pristine single-image state.\n this.removeLayerObjects();\n this.removeFrameOverlay();\n this.image = image;\n this.stampLayer(image, 'image', 'Background');\n this.canvas.add(image);\n this.canvas.centerObject(image);\n // Reset viewport to identity so the canvas-mount's\n // imageLoaded -> applyFitZoom path computes its\n // zoomToPoint anchor from a known centered baseline.\n // Without this a prior zoom + pan persists across the\n // load and centerObject puts the image at canvas-center\n // in canvas coords but off-screen in viewport pixels.\n this.canvas.setViewportTransform([1, 0, 0, 1, 0, 0]);\n this.addFrameOverlay();\n this.canvas.requestRenderAll();\n this.commandStack.clear();\n\n this.originalSource = typeof source === 'string'\n ? { url: source, name }\n : { blob: source, name };\n\n const size: Size = { width: image.width, height: image.height };\n this.emit('imageLoaded', size);\n this.emit('imageChanged', undefined);\n this.emit('historyStateChanged', { canUndo: false, canRedo: false });\n this.emit('layersChanged', undefined);\n this.emit('activeObjectChanged', { id: null, kind: null });\n return size;\n } finally {\n if (ownsUrl) URL.revokeObjectURL(url);\n }\n }\n\n async reset(): Promise<void> {\n if (this.originalSource === null) return;\n const src = this.originalSource;\n const source = 'url' in src ? src.url : src.blob;\n await this.loadImage(source, src.name);\n }\n\n async crop(canvasSpaceRect: Rect): Promise<void> {\n const image = this.requireImage();\n const imageBounds = image.getBoundingRect();\n\n // Bake current transform state (rotation, flip, filters, prior\n // crop) into a canvas at the image's bounding-rect dimensions.\n // The cropped output is then a sub-rectangle of THAT baked\n // canvas, which is what the user sees and selects with the\n // overlay. Applying the crop in image-local coordinates instead\n // would crop an axis-aligned rectangle of the un-rotated image\n // and then re-apply the rotation, producing the diamond-shaped\n // output that the engine swap surfaced.\n const baked = image.toCanvasElement({ multiplier: 1 });\n\n const ox = Math.max(0, canvasSpaceRect.x - imageBounds.left);\n const oy = Math.max(0, canvasSpaceRect.y - imageBounds.top);\n const ow = Math.max(1, Math.min(canvasSpaceRect.width, imageBounds.width - ox));\n const oh = Math.max(1, Math.min(canvasSpaceRect.height, imageBounds.height - oy));\n\n const target = document.createElement('canvas');\n target.width = Math.round(ow);\n target.height = Math.round(oh);\n const ctx = target.getContext('2d');\n if (ctx === null) {\n throw new Error('FabricEngineAdapter: 2d context unavailable for crop');\n }\n ctx.drawImage(baked, ox, oy, ow, oh, 0, 0, target.width, target.height);\n const newDataUrl = target.toDataURL('image/png');\n\n // Capture the previous image's PIXEL state via a self-contained\n // data URL so undo can re-create the image without depending on\n // `getSrc()`. For blob-sourced loads we revoke the Object URL\n // after FabricImage.fromURL resolves, so getSrc() would return\n // an unreachable URL by the time the user clicks Undo. The\n // baked snapshot already has rotation/flip/filters applied to\n // its pixels (toCanvasElement bakes transforms by default), so\n // the restored image starts at angle 0 / no flips and still\n // looks identical to the pre-crop view.\n const prevSnapshotDataUrl = baked.toDataURL('image/png');\n\n // C.1e — composition-aware crop. Annotation layers must shift\n // with the cropped content so they stay aligned (and clip at the\n // new edges). Capture each layer's offset from the ORIGINAL\n // image's content top-left (`imageBounds` = image-pixel space,\n // scale 1), then re-place it relative to whatever image is\n // mounted, minus the crop offset. `placeLayers(0, 0)` (no crop\n // drop) restores the pre-crop layout on undo. Anything left of /\n // above the crop lands at a negative offset and is clipped by the\n // smaller canvas + the export flatten — no need to delete it.\n const offsets = this.layerObjects()\n .filter(o => this.layerKind(o) !== 'image')\n .map(o => ({\n obj: o,\n left: (o.left ?? 0) - imageBounds.left,\n top: (o.top ?? 0) - imageBounds.top,\n }));\n const placeLayers = (originLeft: number, originTop: number, dropX: number, dropY: number): void => {\n for (const { obj, left, top } of offsets) {\n obj.set({ left: originLeft + left - dropX, top: originTop + top - dropY });\n obj.setCoords();\n }\n };\n\n const newImage = await FabricImage.fromURL(newDataUrl, undefined, IMAGE_ORIGIN_OPTIONS);\n this.canvas.remove(image);\n this.replaceImage(newImage);\n placeLayers(newImage.left ?? 0, newImage.top ?? 0, ox, oy);\n this.canvas.requestRenderAll();\n\n this.pushCommand({\n name: 'crop',\n do: async () => {\n if (this.image === newImage) return;\n this.canvas.remove(this.requireImage());\n const replay = await FabricImage.fromURL(newDataUrl, undefined, IMAGE_ORIGIN_OPTIONS);\n this.replaceImage(replay);\n placeLayers(replay.left ?? 0, replay.top ?? 0, ox, oy);\n this.canvas.requestRenderAll();\n },\n undo: async () => {\n this.canvas.remove(this.requireImage());\n const restored = await FabricImage.fromURL(prevSnapshotDataUrl, undefined, IMAGE_ORIGIN_OPTIONS);\n this.replaceImage(restored);\n placeLayers(restored.left ?? 0, restored.top ?? 0, 0, 0);\n this.canvas.requestRenderAll();\n },\n });\n }\n\n async enterCropMode(): Promise<void> {\n const image = this.requireImage();\n if (this.cropOverlay !== null) return;\n\n // Lock the image so the user can only interact with the crop\n // overlay's handles. Without this, clicking the image inside\n // the crop region would steal the active object from the\n // overlay and turn the gesture into a stray image drag. Lock\n // the annotation layers too (C.1e) so a stray click on a shape\n // can't hijack the crop gesture.\n image.selectable = false;\n image.evented = false;\n this.setLayersInteractive(false);\n\n // Hide the canvas frame so the crop overlay's dashed outline\n // is the only rectangle competing for the user's attention.\n if (this.frameOverlay !== null) {\n this.frameOverlay.visible = false;\n }\n\n const bounds = image.getBoundingRect();\n const overlay = new FabricRect({\n // Pin to v6 left/top origin so `bounds.left/top` place\n // the overlay's visual top-left at the image AABB corner\n // (fabric 7's default center/center would offset it by\n // half the overlay's size).\n originX: 'left',\n originY: 'top',\n left: bounds.left,\n top: bounds.top,\n width: bounds.width,\n height: bounds.height,\n fill: 'rgba(0,0,0,0)',\n stroke: '#ffffff',\n strokeDashArray: [4, 4],\n strokeUniform: true,\n cornerStyle: 'circle',\n // Literal on purpose: Fabric paints to a CANVAS, which resolves no\n // CSS custom properties — `var(--cms-text-inverse)` would render as\n // nothing. A tokenising pass swapped this once and it had\n // to be put back; keep it a literal, or thread the resolved value\n // through `getComputedStyle` if it ever needs to follow the theme.\n cornerColor: '#ffffff',\n cornerStrokeColor: '#000000',\n transparentCorners: false,\n lockRotation: true,\n hasRotatingPoint: false,\n centeredScaling: false,\n objectCaching: false,\n } as any);\n this.cropOverlay = overlay;\n this.canvas.add(overlay);\n this.canvas.setActiveObject(overlay);\n this.canvas.requestRenderAll();\n }\n\n async exitCropMode(): Promise<void> {\n if (this.cropOverlay !== null) {\n this.canvas.remove(this.cropOverlay);\n this.cropOverlay = null;\n }\n if (this.image !== null) {\n this.image.selectable = true;\n this.image.evented = true;\n }\n this.setLayersInteractive(true);\n if (this.frameOverlay !== null) {\n this.frameOverlay.visible = true;\n this.syncFrameOverlay();\n }\n this.canvas.discardActiveObject();\n this.canvas.requestRenderAll();\n }\n\n /** Toggle selectability of the annotation layers (used by crop mode). */\n private setLayersInteractive(enabled: boolean): void {\n for (const o of this.layerObjects()) {\n if (this.layerKind(o) === 'image') continue;\n o.selectable = enabled;\n o.evented = enabled;\n }\n }\n\n setCropAspectRatio(ratio: number | null): void {\n const overlay = this.cropOverlay;\n const image = this.image;\n if (overlay === null || image === null) return;\n\n if (ratio === null) {\n (overlay as any).lockUniScaling = false;\n this.canvas.requestRenderAll();\n return;\n }\n\n const bounds = image.getBoundingRect();\n const fitW = Math.min(bounds.width, bounds.height * ratio);\n const fitH = fitW / ratio;\n overlay.set({\n left: bounds.left + (bounds.width - fitW) / 2,\n top: bounds.top + (bounds.height - fitH) / 2,\n width: fitW,\n height: fitH,\n scaleX: 1,\n scaleY: 1,\n });\n (overlay as any).lockUniScaling = true;\n overlay.setCoords();\n this.canvas.requestRenderAll();\n }\n\n getCropRect(): Rect | null {\n const overlay = this.cropOverlay;\n if (overlay === null) return null;\n // Return the overlay's axis-aligned bounding box in canvas\n // coordinate space (no viewport zoom/pan). `crop()` consumes\n // this directly: it bakes the rotated/flipped image to a\n // canvas at its bounding-rect dimensions, then extracts the\n // sub-region the overlay covers within that baked canvas.\n const bounds = overlay.getBoundingRect();\n if (bounds.width <= 0 || bounds.height <= 0) return null;\n return {\n x: bounds.left,\n y: bounds.top,\n width: bounds.width,\n height: bounds.height,\n };\n }\n\n async rotate(degrees: number): Promise<void> {\n // C.1c: a selected shape / text layer is the rotate target;\n // otherwise the base image (the original whole-image behaviour).\n const layer = this.activeNonImageLayer();\n if (layer !== null) {\n this.rotateLayer(layer, degrees);\n return;\n }\n const image = this.requireImage();\n const previousAngle = image.angle ?? 0;\n const targetAngle = previousAngle + degrees;\n const applyForward = (): void => {\n image.rotate(targetAngle);\n image.setCoords();\n this.canvas.requestRenderAll();\n this.emitImageTransformed(image, 'sidebar');\n };\n applyForward();\n this.pushCommand({\n name: 'rotate',\n do: () => { applyForward(); },\n undo: () => {\n image.rotate(previousAngle);\n image.setCoords();\n this.canvas.requestRenderAll();\n this.emitImageTransformed(image, 'sidebar');\n },\n });\n }\n\n async flip(axis: 'horizontal' | 'vertical'): Promise<void> {\n // C.1c: flip the selected non-image layer when one is active,\n // else the base image.\n const layer = this.activeNonImageLayer();\n if (layer !== null) {\n this.flipLayer(layer, axis);\n return;\n }\n const image = this.requireImage();\n const prop: 'flipX' | 'flipY' = axis === 'horizontal' ? 'flipX' : 'flipY';\n const previous = image[prop] ?? false;\n const applyForward = (): void => {\n image[prop] = !previous;\n image.setCoords();\n this.canvas.requestRenderAll();\n this.emitImageTransformed(image, 'sidebar');\n };\n applyForward();\n this.pushCommand({\n name: `flip-${axis}`,\n do: () => { applyForward(); },\n undo: () => {\n image[prop] = previous;\n image.setCoords();\n this.canvas.requestRenderAll();\n this.emitImageTransformed(image, 'sidebar');\n },\n });\n }\n\n async resize(size: Size): Promise<void> {\n const image = this.requireImage();\n const imageBounds = image.getBoundingRect();\n const baked = image.toCanvasElement({ multiplier: 1 });\n\n const target = document.createElement('canvas');\n target.width = Math.max(1, Math.round(size.width));\n target.height = Math.max(1, Math.round(size.height));\n const ctx = target.getContext('2d');\n if (ctx === null) {\n throw new Error('FabricEngineAdapter: 2d context unavailable for resize');\n }\n ctx.drawImage(baked, 0, 0, target.width, target.height);\n const newDataUrl = target.toDataURL('image/png');\n\n // Self-contained snapshot of the pre-resize state so undo\n // doesn't depend on the original source URL (which may have\n // been a revoked blob URL for VFS-loaded images).\n const prevSnapshotDataUrl = baked.toDataURL('image/png');\n\n // C.1f — composition-aware resize. Like crop (C.1e), annotation\n // layers must move with the base image so they stay aligned; but\n // resize ALSO scales the image, so a shape / text layer has to\n // grow or shrink in step (crop is a pure translation, resize is a\n // translation *and* a scale). Capture each layer's offset from the\n // ORIGINAL image's content top-left (`imageBounds` = displayed\n // canvas-space) plus its own scaleX/scaleY, and the resize factor\n // (new pixel size ÷ old displayed size). `scaleLayers(originLeft,\n // originTop, sx, sy)` re-places each layer at\n // `image-top-left + offset*factor` and multiplies its scaleX/scaleY\n // by the factor (origin-center, so it grows about its own centre —\n // matching a handle-resize). `scaleLayers(…, 1, 1)` on undo\n // restores the captured pre-resize position + size verbatim.\n const sx = target.width / Math.max(1, imageBounds.width);\n const sy = target.height / Math.max(1, imageBounds.height);\n const offsets = this.layerObjects()\n .filter(o => this.layerKind(o) !== 'image')\n .map(o => ({\n obj: o,\n left: (o.left ?? 0) - imageBounds.left,\n top: (o.top ?? 0) - imageBounds.top,\n scaleX: o.scaleX ?? 1,\n scaleY: o.scaleY ?? 1,\n }));\n const scaleLayers = (originLeft: number, originTop: number, factorX: number, factorY: number): void => {\n for (const { obj, left, top, scaleX, scaleY } of offsets) {\n obj.set({\n left: originLeft + left * factorX,\n top: originTop + top * factorY,\n scaleX: scaleX * factorX,\n scaleY: scaleY * factorY,\n });\n obj.setCoords();\n }\n };\n\n const newImage = await FabricImage.fromURL(newDataUrl, undefined, IMAGE_ORIGIN_OPTIONS);\n this.canvas.remove(image);\n this.replaceImage(newImage);\n scaleLayers(newImage.left ?? 0, newImage.top ?? 0, sx, sy);\n this.canvas.requestRenderAll();\n\n this.pushCommand({\n name: 'resize',\n do: async () => {\n if (this.image === newImage) return;\n this.canvas.remove(this.requireImage());\n const replay = await FabricImage.fromURL(newDataUrl, undefined, IMAGE_ORIGIN_OPTIONS);\n this.replaceImage(replay);\n scaleLayers(replay.left ?? 0, replay.top ?? 0, sx, sy);\n this.canvas.requestRenderAll();\n },\n undo: async () => {\n this.canvas.remove(this.requireImage());\n const restored = await FabricImage.fromURL(prevSnapshotDataUrl, undefined, IMAGE_ORIGIN_OPTIONS);\n this.replaceImage(restored);\n scaleLayers(restored.left ?? 0, restored.top ?? 0, 1, 1);\n this.canvas.requestRenderAll();\n },\n });\n }\n\n async applyFilter(name: FilterName, params: FilterParams = {}): Promise<void> {\n const image = this.requireImage();\n this.ensureFilterBackendFitsImage(image);\n const ctorTag = this.resolveFilterCtor(name);\n const newFilter = this.instantiateFilter(name, params);\n\n const existingIndex = image.filters.findIndex(f => (f as any) instanceof ctorTag);\n const previousFilter = existingIndex >= 0 ? image.filters[existingIndex] : null;\n\n const applyForward = (): void => {\n if (existingIndex >= 0) {\n image.filters[existingIndex] = newFilter;\n } else {\n image.filters.push(newFilter);\n }\n image.applyFilters();\n this.canvas.requestRenderAll();\n };\n applyForward();\n\n this.pushCommand({\n name: `filter-${name}`,\n do: () => { applyForward(); },\n undo: () => {\n if (previousFilter !== null) {\n const idx = image.filters.indexOf(newFilter);\n if (idx >= 0) image.filters[idx] = previousFilter;\n } else {\n const idx = image.filters.indexOf(newFilter);\n if (idx >= 0) image.filters.splice(idx, 1);\n }\n image.applyFilters();\n this.canvas.requestRenderAll();\n },\n });\n }\n\n async removeFilter(name: FilterName): Promise<void> {\n const image = this.requireImage();\n this.ensureFilterBackendFitsImage(image);\n const ctorTag = this.resolveFilterCtor(name);\n const idx = image.filters.findIndex(f => (f as any) instanceof ctorTag);\n if (idx < 0) return;\n\n const removed = image.filters[idx];\n const applyForward = (): void => {\n const at = image.filters.indexOf(removed);\n if (at >= 0) image.filters.splice(at, 1);\n image.applyFilters();\n this.canvas.requestRenderAll();\n };\n applyForward();\n\n this.pushCommand({\n name: `filter-remove-${name}`,\n do: () => { applyForward(); },\n undo: () => {\n if (!image.filters.includes(removed)) {\n image.filters.splice(idx, 0, removed);\n }\n image.applyFilters();\n this.canvas.requestRenderAll();\n },\n });\n }\n\n hasFilter(name: FilterName): boolean {\n if (this.image === null) return false;\n const ctorTag = this.resolveFilterCtor(name);\n return this.image.filters.some(f => (f as any) instanceof ctorTag);\n }\n\n // --- Layers / objects (C.1) -------------------------------------\n\n addShape(kind: ShapeKind, opts: Partial<ShapeOptions> = {}): void {\n const o: ShapeOptions = { ...DEFAULT_SHAPE_OPTIONS, ...opts };\n this.placeAndAdd(this.createShape(kind, o), 'shape', this.shapeLabel(kind));\n }\n\n addText(opts: Partial<TextOptions> = {}): void {\n const o: TextOptions = { ...DEFAULT_TEXT_OPTIONS, ...opts };\n const text = new Textbox(o.text, {\n width: Math.min(420, (this.image?.width ?? 600) * 0.6),\n fontFamily: o.fontFamily,\n fontSize: o.fontSize,\n fill: this.resolveFill(o.fillSpec, o.fill),\n fontWeight: o.fontWeight,\n fontStyle: o.fontStyle,\n textAlign: o.textAlign,\n });\n this.placeAndAdd(text, 'text', 'Text');\n }\n\n // --- Annotation-authoring seams ---------------------------------\n\n getImageBounds(): Rect | null {\n if (this.image === null) return null;\n const b = this.image.getBoundingRect();\n return { x: b.left, y: b.top, width: b.width, height: b.height };\n }\n\n addShapeAt(geometry: ShapeGeometry, opts: AnnotationShapeOptions = {}): string {\n const style = {\n fill: opts.fill ?? FabricEngineAdapter.DEFAULT_SHAPE_FILL,\n stroke: opts.stroke ?? '#2563eb',\n strokeWidth: opts.strokeWidth ?? 2,\n // Keep the border width constant under interactive scaling —\n // geometry consumers read the shape's box, not its stroke.\n strokeUniform: true,\n };\n let obj: FabricObject;\n switch (geometry.kind) {\n case 'rect':\n obj = new FabricRect({\n ...style,\n left: geometry.rect.x,\n top: geometry.rect.y,\n width: geometry.rect.width,\n height: geometry.rect.height,\n originX: 'left',\n originY: 'top',\n });\n break;\n case 'ellipse':\n obj = new Ellipse({\n ...style,\n left: geometry.center.x,\n top: geometry.center.y,\n rx: geometry.rx,\n ry: geometry.ry,\n originX: 'center',\n originY: 'center',\n });\n break;\n case 'polygon':\n obj = new Polygon(geometry.points.map(p => ({ x: p.x, y: p.y })), { ...style });\n break;\n }\n if (opts.lockRotation === true) {\n obj.setControlsVisibility({ mtr: false });\n }\n if (opts.lockNonUniformScaling === true) {\n obj.setControlsVisibility({ ml: false, mr: false, mt: false, mb: false });\n }\n obj.setCoords();\n\n const name = opts.name ?? geometry.kind;\n this.stampLayer(obj, 'shape', name);\n this.canvas.add(obj);\n this.keepImageAtBack();\n this.canvas.setActiveObject(obj);\n this.canvas.requestRenderAll();\n\n this.pushCommand({\n name: `add ${name}`,\n do: () => {\n this.canvas.add(obj);\n this.keepImageAtBack();\n this.canvas.setActiveObject(obj);\n this.canvas.requestRenderAll();\n this.afterLayerMutation();\n },\n undo: () => {\n this.canvas.remove(obj);\n this.canvas.discardActiveObject();\n this.canvas.requestRenderAll();\n this.afterLayerMutation();\n },\n });\n this.afterLayerMutation();\n return this.layerId(obj);\n }\n\n getShapeGeometry(id: string): ShapeGeometry | null {\n const obj = this.findLayer(id);\n if (obj === null || this.layerKind(obj) !== 'shape') return null;\n\n if (obj instanceof Ellipse) {\n const c = obj.getCenterPoint();\n return {\n kind: 'ellipse',\n center: { x: c.x, y: c.y },\n rx: (obj.rx ?? 0) * (obj.scaleX ?? 1),\n ry: (obj.ry ?? 0) * (obj.scaleY ?? 1),\n };\n }\n if (obj instanceof Polygon) {\n const m = obj.calcTransformMatrix();\n const points = (obj.points ?? [])\n .map(p => new Point(p.x - obj.pathOffset.x, p.y - obj.pathOffset.y).transform(m))\n .map(p => ({ x: p.x, y: p.y }));\n return { kind: 'polygon', points };\n }\n if (obj instanceof FabricRect) {\n // Axis-aligned box from the center point, ignoring rotation\n // (annotation rects ship lockRotation — see the interface).\n const w = (obj.width ?? 0) * (obj.scaleX ?? 1);\n const h = (obj.height ?? 0) * (obj.scaleY ?? 1);\n const c = obj.getCenterPoint();\n return { kind: 'rect', rect: { x: c.x - w / 2, y: c.y - h / 2, width: w, height: h } };\n }\n return null;\n }\n\n setVertexEditing(id: string, enabled: boolean): boolean {\n const obj = this.findLayer(id);\n if (obj === null || !(obj instanceof Polygon) || this.layerKind(obj) !== 'shape') return false;\n if (enabled) {\n if (this.vertexEdit?.obj === obj) return true;\n if (this.vertexEdit !== null) this.exitVertexEdit();\n this.enterVertexEdit(obj);\n } else if (this.vertexEdit?.obj === obj) {\n this.exitVertexEdit();\n }\n this.canvas.requestRenderAll();\n return true;\n }\n\n /**\n * Swap the polygon's default handles for one draggable Control per\n * vertex — the official fabric \"custom polygon controls\" pattern:\n * `positionHandler` projects `points[i]` through viewport × object\n * transform; `actionHandler` writes the pointer back into\n * `points[i]` (object-local, stroke-compensated) and re-anchors the\n * polygon on a neighbouring vertex after `setDimensions()` so the\n * shape doesn't jump while its bounding box is recomputed.\n */\n private enterVertexEdit(polygon: Polygon): void {\n const savedControls = polygon.controls;\n const savedProps = {\n hasBorders: polygon.hasBorders,\n lockMovementX: polygon.lockMovementX,\n lockMovementY: polygon.lockMovementY,\n cornerStyle: polygon.cornerStyle,\n cornerColor: polygon.cornerColor,\n cornerStrokeColor: polygon.cornerStrokeColor,\n transparentCorners: polygon.transparentCorners,\n };\n\n this.rebuildVertexControls(polygon);\n polygon.hasBorders = false;\n // Vertices are the ONLY interaction in edit mode — whole-shape\n // dragging would fight the per-point handles.\n polygon.lockMovementX = true;\n polygon.lockMovementY = true;\n // Filled white dots with a blue ring — fabric's default\n // transparentCorners renders outline-only handles that vanish\n // against same-hue shapes.\n polygon.cornerStyle = 'circle';\n polygon.transparentCorners = false;\n polygon.cornerColor = '#ffffff';\n polygon.cornerStrokeColor = '#2563eb';\n polygon.setCoords();\n this.canvas.setActiveObject(polygon);\n this.vertexEdit = { obj: polygon, savedControls, savedProps, pointsBefore: null };\n }\n\n private exitVertexEdit(): void {\n const edit = this.vertexEdit;\n if (edit === null) return;\n const obj = edit.obj;\n obj.controls = edit.savedControls;\n obj.hasBorders = edit.savedProps.hasBorders;\n obj.lockMovementX = edit.savedProps.lockMovementX;\n obj.lockMovementY = edit.savedProps.lockMovementY;\n obj.cornerStyle = edit.savedProps.cornerStyle;\n obj.cornerColor = edit.savedProps.cornerColor;\n obj.cornerStrokeColor = edit.savedProps.cornerStrokeColor;\n obj.transparentCorners = edit.savedProps.transparentCorners;\n obj.setCoords();\n this.vertexEdit = null;\n }\n\n private vertexControlPosition(polygon: Polygon, index: number): Point {\n const p = (polygon.points ?? [])[index] ?? { x: 0, y: 0 };\n return new Point(p.x - polygon.pathOffset.x, p.y - polygon.pathOffset.y).transform(\n util.multiplyTransformMatrices(\n polygon.canvas?.viewportTransform ?? [1, 0, 0, 1, 0, 0],\n polygon.calcTransformMatrix(),\n ),\n );\n }\n\n private moveVertex(transform: Transform, index: number, x: number, y: number): boolean {\n const polygon = transform.target;\n if (!(polygon instanceof Polygon)) return false;\n const points = polygon.points ?? [];\n if (points.length < 3 || index >= points.length) return false;\n\n // Anchor: keep a NEIGHBOURING vertex visually fixed across the\n // setDimensions() bounding-box recompute.\n const anchorIndex = index > 0 ? index - 1 : points.length - 1;\n const anchorAbs = new Point(\n points[anchorIndex].x - polygon.pathOffset.x,\n points[anchorIndex].y - polygon.pathOffset.y,\n ).transform(polygon.calcTransformMatrix());\n\n // Scene -> object-center-local (v7 dropped toLocalPoint; the\n // inverse of calcTransformMatrix is its center-origin equivalent).\n const local = new Point(x, y).transform(util.invertTransform(polygon.calcTransformMatrix()));\n const size = this.polygonSizeWithStroke(polygon);\n points[index] = {\n x: local.x * ((polygon.width ?? 0) / size.x) + polygon.pathOffset.x,\n y: local.y * ((polygon.height ?? 0) / size.y) + polygon.pathOffset.y,\n };\n polygon.setDimensions();\n\n const sizeAfter = this.polygonSizeWithStroke(polygon);\n const newX = (points[anchorIndex].x - polygon.pathOffset.x) / sizeAfter.x;\n const newY = (points[anchorIndex].y - polygon.pathOffset.y) / sizeAfter.y;\n polygon.setPositionByOrigin(anchorAbs, newX + 0.5, newY + 0.5);\n polygon.setCoords();\n return true;\n }\n\n /**\n * (Re)build one draggable Control per vertex — used on entering vertex\n * edit AND after a topology change (add/remove) so the `vertexN` controls\n * stay index-aligned with the current `points` array.\n */\n private rebuildVertexControls(polygon: Polygon): void {\n const controls: Record<string, Control> = {};\n (polygon.points ?? []).forEach((_, i) => {\n controls['vertex' + i] = new Control({\n actionName: 'modifyPolygonVertex',\n positionHandler: (dim, finalMatrix, fabricObject) =>\n this.vertexControlPosition(fabricObject as Polygon, i),\n actionHandler: (eventData, transform, x, y) => this.moveVertex(transform, i, x, y),\n mouseDownHandler: () => { this.vertexDragStart(polygon); return true; },\n mouseUpHandler: () => { this.vertexDragEnd(polygon); return true; },\n });\n });\n polygon.controls = controls;\n }\n\n addVertexAt(id: string, sceneX: number, sceneY: number): boolean {\n const polygon = this.findLayer(id);\n if (this.vertexEdit === null || !(polygon instanceof Polygon) || this.vertexEdit.obj !== polygon) return false;\n const points = polygon.points ?? [];\n if (points.length < 3) return false;\n\n // Scene -> object-local point-space (mirrors moveVertex).\n const local = new Point(sceneX, sceneY).transform(util.invertTransform(polygon.calcTransformMatrix()));\n const size = this.polygonSizeWithStroke(polygon);\n const target = {\n x: local.x * ((polygon.width ?? 0) / size.x) + polygon.pathOffset.x,\n y: local.y * ((polygon.height ?? 0) / size.y) + polygon.pathOffset.y,\n };\n\n // Project onto the NEAREST edge (segment i->i+1) and insert the\n // projected point after i — a collinear insert, so the polygon's\n // outline is unchanged; it just gains a handle to drag.\n let bestIndex = 0;\n let bestDistSq = Infinity;\n let bestPoint: PointType = { x: points[0].x, y: points[0].y };\n for (let i = 0; i < points.length; i++) {\n const proj = this.projectOnSegment(target, points[i], points[(i + 1) % points.length]);\n const dx = proj.x - target.x;\n const dy = proj.y - target.y;\n const distSq = dx * dx + dy * dy;\n if (distSq < bestDistSq) { bestDistSq = distSq; bestIndex = i; bestPoint = proj; }\n }\n\n const before = points.map(p => ({ x: p.x, y: p.y }));\n const after = before.slice();\n after.splice(bestIndex + 1, 0, bestPoint);\n\n this.applyVertexTopology(polygon, after);\n this.pushCommand({\n name: 'add vertex',\n do: () => this.applyVertexTopology(polygon, after),\n undo: () => this.applyVertexTopology(polygon, before),\n });\n this.canvas.requestRenderAll();\n return true;\n }\n\n removeVertexAt(id: string, sceneX: number, sceneY: number): boolean {\n const polygon = this.findLayer(id);\n if (this.vertexEdit === null || !(polygon instanceof Polygon) || this.vertexEdit.obj !== polygon) return false;\n const points = polygon.points ?? [];\n // A polygon needs at least 3 vertices — never remove past that floor.\n if (points.length <= 3) return false;\n\n // Scene -> object-local point-space (mirrors addVertexAt / moveVertex).\n const local = new Point(sceneX, sceneY).transform(util.invertTransform(polygon.calcTransformMatrix()));\n const size = this.polygonSizeWithStroke(polygon);\n const target = {\n x: local.x * ((polygon.width ?? 0) / size.x) + polygon.pathOffset.x,\n y: local.y * ((polygon.height ?? 0) / size.y) + polygon.pathOffset.y,\n };\n\n // Nearest vertex to the click.\n let bestIndex = 0;\n let bestDistSq = Infinity;\n for (let i = 0; i < points.length; i++) {\n const dx = points[i].x - target.x;\n const dy = points[i].y - target.y;\n const distSq = dx * dx + dy * dy;\n if (distSq < bestDistSq) { bestDistSq = distSq; bestIndex = i; }\n }\n\n // Only remove when the click landed ON a handle — within a fraction\n // of the polygon's own size. Otherwise return false so the caller\n // falls through to addVertexAt (which targets the OUTLINE). Scaling\n // the threshold to the shape keeps it zoom- and size-independent.\n const w = polygon.width ?? 0;\n const h = polygon.height ?? 0;\n const threshold = 0.10 * Math.hypot(w, h);\n if (Math.sqrt(bestDistSq) > threshold) return false;\n\n const before = points.map(p => ({ x: p.x, y: p.y }));\n const after = before.slice();\n after.splice(bestIndex, 1);\n // The surviving anchor vertex: after[0] is before[fromIdx] — removing\n // vertex 0 shifts everyone down, so it lives at before-index 1 then.\n const fromIdx = bestIndex === 0 ? 1 : 0;\n\n this.applyVertexTopology(polygon, after, fromIdx, 0);\n this.pushCommand({\n name: 'remove vertex',\n do: () => this.applyVertexTopology(polygon, after, fromIdx, 0),\n undo: () => this.applyVertexTopology(polygon, before, 0, fromIdx),\n });\n this.canvas.requestRenderAll();\n return true;\n }\n\n /** Closest point on segment `a->b` to `p` (all object-local coords). */\n private projectOnSegment(p: PointType, a: PointType, b: PointType): PointType {\n const abx = b.x - a.x;\n const aby = b.y - a.y;\n const denom = abx * abx + aby * aby;\n let t = denom === 0 ? 0 : ((p.x - a.x) * abx + (p.y - a.y) * aby) / denom;\n t = Math.max(0, Math.min(1, t));\n return { x: a.x + t * abx, y: a.y + t * aby };\n }\n\n /**\n * Replace the polygon's `points` and re-index its vertex controls,\n * keeping one SURVIVING vertex visually fixed across the\n * `setDimensions()` bbox recompute so the shape never jumps.\n *\n * `fromIndex` is the anchor vertex's index in the CURRENT points,\n * `toIndex` its index in the NEW `pts` — the two must be the SAME\n * vertex. For an insert (add) or the identity case both are 0 (the\n * defaults). A removal that drops vertex 0 shifts every later vertex\n * down one, so its surviving anchor lives at different indices before\n * vs after — hence the explicit pair.\n */\n private applyVertexTopology(polygon: Polygon, pts: PointType[], fromIndex = 0, toIndex = 0): void {\n const current = polygon.points ?? [];\n const anchorAbs = new Point(\n (current[fromIndex]?.x ?? 0) - polygon.pathOffset.x,\n (current[fromIndex]?.y ?? 0) - polygon.pathOffset.y,\n ).transform(polygon.calcTransformMatrix());\n\n polygon.points = pts.map(p => ({ x: p.x, y: p.y }));\n polygon.setDimensions();\n\n const sizeAfter = this.polygonSizeWithStroke(polygon);\n const newX = ((polygon.points[toIndex]?.x ?? 0) - polygon.pathOffset.x) / sizeAfter.x;\n const newY = ((polygon.points[toIndex]?.y ?? 0) - polygon.pathOffset.y) / sizeAfter.y;\n polygon.setPositionByOrigin(anchorAbs, newX + 0.5, newY + 0.5);\n\n this.rebuildVertexControls(polygon);\n polygon.setCoords();\n }\n\n private polygonSizeWithStroke(polygon: Polygon): Point {\n const strokeWidth = polygon.strokeWidth ?? 0;\n const sx = polygon.strokeUniform === true ? strokeWidth / (polygon.scaleX ?? 1) : strokeWidth;\n const sy = polygon.strokeUniform === true ? strokeWidth / (polygon.scaleY ?? 1) : strokeWidth;\n return new Point((polygon.width ?? 0) + sx, (polygon.height ?? 0) + sy);\n }\n\n private vertexDragStart(polygon: Polygon): void {\n if (this.vertexEdit?.obj !== polygon) return;\n this.vertexEdit.pointsBefore = {\n points: (polygon.points ?? []).map(p => ({ x: p.x, y: p.y })),\n left: polygon.left ?? 0,\n top: polygon.top ?? 0,\n };\n }\n\n private vertexDragEnd(polygon: Polygon): void {\n const edit = this.vertexEdit;\n if (edit?.obj !== polygon || edit.pointsBefore === null) return;\n const before = edit.pointsBefore;\n edit.pointsBefore = null;\n\n const after = {\n points: (polygon.points ?? []).map(p => ({ x: p.x, y: p.y })),\n left: polygon.left ?? 0,\n top: polygon.top ?? 0,\n };\n const unchanged = before.points.length === after.points.length\n && before.points.every((p, i) => p.x === after.points[i].x && p.y === after.points[i].y);\n if (unchanged) return;\n\n // The drag already happened — record it for undo/redo only\n // (pushCommand does not invoke do()), like addShapeAt.\n const apply = (state: VertexEditSnapshot) => {\n polygon.points = state.points.map(p => ({ x: p.x, y: p.y }));\n polygon.setDimensions();\n polygon.set({ left: state.left, top: state.top });\n polygon.setCoords();\n this.canvas.requestRenderAll();\n };\n this.pushCommand({\n name: 'move vertex',\n do: () => apply(after),\n undo: () => apply(before),\n });\n }\n\n getLayers(): LayerInfo[] {\n // Canvas order is bottom->top; the panel lists top->bottom.\n return this.layerObjects()\n .slice()\n .reverse()\n .map(o => ({\n id: this.layerId(o),\n kind: this.layerKind(o),\n name: this.layerName(o),\n visible: o.visible !== false,\n opacity: o.opacity ?? 1,\n locked: this.layerKind(o) === 'image',\n }));\n }\n\n getActiveLayerId(): string | null {\n const active = this.canvas.getActiveObject();\n return active ? (this.layerId(active) || null) : null;\n }\n\n selectLayer(id: string | null): void {\n if (id === null) {\n this.canvas.discardActiveObject();\n this.canvas.requestRenderAll();\n this.emitActiveFromCanvas();\n return;\n }\n const obj = this.findLayer(id);\n if (obj === null) return;\n this.canvas.setActiveObject(obj);\n this.canvas.requestRenderAll();\n this.emitActiveFromCanvas();\n }\n\n setLayerFill(id: string, fill: string | null): void {\n const obj = this.findLayer(id);\n if (obj === null || this.layerKind(obj) === 'image') return;\n // A transient PREVIEW tint (status overlay etc.) — NOT recorded as an\n // undoable command and NOT part of getShapeGeometry (fill is style, not\n // geometry), so it never touches what the save-diff persists. Passing\n // null restores the default region fill.\n obj.set('fill', fill ?? FabricEngineAdapter.DEFAULT_SHAPE_FILL);\n this.canvas.requestRenderAll();\n }\n\n removeLayer(id: string): void {\n const obj = this.findLayer(id);\n if (obj === null || this.layerKind(obj) === 'image') return;\n\n const wasActive = this.canvas.getActiveObject() === obj;\n this.canvas.remove(obj);\n if (wasActive) this.canvas.discardActiveObject();\n this.canvas.requestRenderAll();\n\n this.pushCommand({\n name: 'delete layer',\n do: () => {\n this.canvas.remove(obj);\n this.canvas.discardActiveObject();\n this.afterLayerMutation();\n },\n undo: () => {\n this.canvas.add(obj);\n this.keepImageAtBack();\n this.afterLayerMutation();\n },\n });\n this.afterLayerMutation();\n }\n\n setLayerVisibility(id: string, visible: boolean): void {\n const obj = this.findLayer(id);\n if (obj === null) return;\n const before = obj.visible !== false;\n if (before === visible) return;\n obj.visible = visible;\n this.canvas.requestRenderAll();\n this.pushCommand({\n name: 'toggle visibility',\n do: () => { obj.visible = visible; this.afterLayerMutation(); },\n undo: () => { obj.visible = before; this.afterLayerMutation(); },\n });\n this.afterLayerMutation();\n }\n\n setLayerOpacity(id: string, opacity: number): void {\n const obj = this.findLayer(id);\n if (obj === null) return;\n const next = Math.min(1, Math.max(0, opacity));\n const before = obj.opacity ?? 1;\n if (before === next) return;\n obj.set({ opacity: next });\n this.canvas.requestRenderAll();\n this.pushCommand({\n name: 'opacity',\n do: () => { obj.set({ opacity: next }); this.afterLayerMutation(); },\n undo: () => { obj.set({ opacity: before }); this.afterLayerMutation(); },\n });\n this.afterLayerMutation();\n }\n\n reorderLayer(id: string, direction: 'up' | 'down' | 'front' | 'back'): void {\n const obj = this.findLayer(id);\n if (obj === null || this.layerKind(obj) === 'image') return;\n\n const beforeIndex = this.canvas.getObjects().indexOf(obj);\n switch (direction) {\n case 'up': this.canvas.bringObjectForward(obj); break;\n case 'down': this.canvas.sendObjectBackwards(obj); break;\n case 'front': this.canvas.bringObjectToFront(obj); break;\n case 'back': this.canvas.sendObjectToBack(obj); break;\n }\n // The base image is the canvas floor; a \"send to back\" lands a\n // shape just above it, never below.\n this.keepImageAtBack();\n const afterIndex = this.canvas.getObjects().indexOf(obj);\n this.canvas.requestRenderAll();\n if (afterIndex === beforeIndex) { this.afterLayerMutation(); return; }\n\n this.pushCommand({\n name: 'reorder layer',\n do: () => { this.canvas.moveObjectTo(obj, afterIndex); this.keepImageAtBack(); this.afterLayerMutation(); },\n undo: () => { this.canvas.moveObjectTo(obj, beforeIndex); this.keepImageAtBack(); this.afterLayerMutation(); },\n });\n this.afterLayerMutation();\n }\n\n getActiveObjectProps(): ObjectProps | null {\n const active = this.canvas.getActiveObject();\n if (active === undefined || active === null) return null;\n const kind = this.layerKind(active);\n if (kind === 'image' || this.layerId(active) === '') return null;\n\n if (kind === 'text') {\n const t = active as Textbox;\n return {\n text: t.text ?? '',\n fontFamily: t.fontFamily ?? 'Arial',\n fontSize: t.fontSize ?? 48,\n fill: this.fillToHex(t.fill),\n fontWeight: t.fontWeight ?? 'normal',\n fontStyle: t.fontStyle ?? 'normal',\n textAlign: t.textAlign ?? 'left',\n opacity: active.opacity ?? 1,\n };\n }\n return {\n fill: this.fillToHex(active.fill),\n stroke: (active.stroke as string) ?? '',\n strokeWidth: active.strokeWidth ?? 0,\n opacity: active.opacity ?? 1,\n };\n }\n\n getActiveObjectFill(): FillSpec | null {\n const active = this.canvas.getActiveObject();\n if (active === undefined || active === null) return null;\n if (this.layerKind(active) === 'image' || this.layerId(active) === '') return null;\n return this.readFill(active.fill);\n }\n\n setActiveObjectFill(spec: FillSpec): void {\n const active = this.canvas.getActiveObject();\n if (active === undefined || active === null) return;\n if (this.layerKind(active) === 'image' || this.layerId(active) === '') return;\n\n const before = active.get('fill');\n const next = this.buildFill(spec);\n const apply = (val: unknown): void => {\n active.set('fill', val as any);\n active.setCoords();\n this.canvas.requestRenderAll();\n };\n apply(next);\n\n this.pushCommand({\n name: 'fill layer',\n do: () => { apply(next); this.afterLayerMutation(); },\n undo: () => { apply(before); this.afterLayerMutation(); },\n });\n this.afterLayerMutation();\n }\n\n // --- Per-layer transforms + masking (C.1c) ----------------------\n\n getActiveLayerTransform(): { angle: number; flipX: boolean; flipY: boolean } | null {\n const layer = this.activeNonImageLayer();\n if (layer === null) return null;\n return {\n angle: layer.angle ?? 0,\n flipX: layer.flipX ?? false,\n flipY: layer.flipY ?? false,\n };\n }\n\n setMask(spec: MaskSpec): void {\n const target = this.maskTarget();\n if (target === null) return;\n\n // fabric types `clipPath` with a looser object generic than the\n // default `FabricObject`; cast so the restore-path assignment\n // type-checks against `buildClipPath`'s return.\n const before = (target.clipPath ?? null) as FabricObject | null;\n const beforeStamp = (target as unknown as Record<string, unknown>)['coolmsMask'] ?? null;\n const apply = (clip: FabricObject | null, stamp: unknown): void => {\n // fabric reads `clipPath` directly; `dirty` busts the object\n // cache so the new clip actually re-renders.\n (target as unknown as Record<string, unknown>)['clipPath'] = clip ?? undefined;\n (target as unknown as Record<string, unknown>)['coolmsMask'] = stamp ?? undefined;\n target.set({ dirty: true });\n target.setCoords();\n this.canvas.requestRenderAll();\n };\n\n const nextStamp = spec.shape === 'none' ? null : { ...spec };\n apply(this.buildClipPath(target, spec), nextStamp);\n\n this.pushCommand({\n name: 'mask',\n do: () => { apply(this.buildClipPath(target, spec), nextStamp); this.afterLayerMutation(); },\n undo: () => { apply(before, beforeStamp); this.afterLayerMutation(); },\n });\n this.afterLayerMutation();\n }\n\n getMask(): MaskSpec | null {\n const target = this.maskTarget();\n if (target === null) return null;\n const stamp = (target as unknown as Record<string, unknown>)['coolmsMask'];\n if (stamp !== null && typeof stamp === 'object') {\n return { ...DEFAULT_MASK_SPEC, ...(stamp as Partial<MaskSpec>) };\n }\n return { ...DEFAULT_MASK_SPEC };\n }\n\n updateActiveObject(props: ObjectProps): void {\n const active = this.canvas.getActiveObject();\n if (active === undefined || active === null) return;\n if (this.layerKind(active) === 'image' || this.layerId(active) === '') return;\n\n const before: ObjectProps = {};\n for (const key of Object.keys(props)) {\n before[key] = (active.get(key) as string | number) ?? '';\n }\n active.set(props);\n active.setCoords();\n this.canvas.requestRenderAll();\n\n this.pushCommand({\n name: 'style layer',\n do: () => { active.set(props); active.setCoords(); this.canvas.requestRenderAll(); this.afterLayerMutation(); },\n undo: () => { active.set(before); active.setCoords(); this.canvas.requestRenderAll(); this.afterLayerMutation(); },\n });\n this.afterLayerMutation();\n }\n\n async undo(): Promise<void> {\n await this.commandStack.undo();\n this.emit('imageChanged', undefined);\n this.emit('historyStateChanged', {\n canUndo: this.commandStack.canUndo(),\n canRedo: this.commandStack.canRedo(),\n });\n }\n\n async redo(): Promise<void> {\n await this.commandStack.redo();\n this.emit('imageChanged', undefined);\n this.emit('historyStateChanged', {\n canUndo: this.commandStack.canUndo(),\n canRedo: this.commandStack.canRedo(),\n });\n }\n\n canUndo(): boolean { return this.commandStack.canUndo(); }\n canRedo(): boolean { return this.commandStack.canRedo(); }\n\n clearRedoStack(): void {\n this.commandStack.clearRedo();\n this.emit('historyStateChanged', {\n canUndo: this.commandStack.canUndo(),\n canRedo: this.commandStack.canRedo(),\n });\n }\n\n async export(format: 'png' | 'jpeg' | 'webp' = 'png', quality = 0.92): Promise<Blob> {\n const flat = this.renderFlattened();\n const blob = await new Promise<Blob | null>(resolve =>\n flat.toBlob(b => resolve(b), `image/${format}`, quality),\n );\n if (blob === null) {\n throw new Error('FabricEngineAdapter: export produced null blob');\n }\n return blob;\n }\n\n exportDataUrl(format: 'png' | 'jpeg' | 'webp' = 'png', quality = 0.92): string {\n return this.renderFlattened().toDataURL(`image/${format}`, quality);\n }\n\n hasAlpha(): boolean {\n if (this.image === null) return false;\n\n // Cheap structural check first: a mask / clipPath on the base\n // image (or any visible layer) cuts pixels to transparent. This\n // is the masking case (C.1c) — the verified source of opaque\n // black corners on a JPEG save — and returns without a scan.\n if (this.objectHasClip(this.image)) return true;\n for (const o of this.layerObjects()) {\n if (o.visible !== false && this.objectHasClip(o)) return true;\n }\n\n // Fall back to a pixel scan to catch a transparent source image\n // (PNG / WebP / GIF with alpha) or partial-opacity compositing\n // that leaves the flattened result non-opaque. Early-exits on the\n // first transparent pixel; a fully-opaque image scans in full,\n // which is acceptable for an infrequent save action.\n try {\n const flat = this.renderFlattened();\n const ctx = flat.getContext('2d', { willReadFrequently: true });\n if (ctx === null) return false;\n const { data } = ctx.getImageData(0, 0, flat.width, flat.height);\n for (let i = 3; i < data.length; i += 4) {\n if (data[i] < 255) return true;\n }\n } catch {\n // A tainted canvas (cross-origin source) would throw here as\n // it does for `toBlob`; assume opaque and let the caller fall\n // back to the source-derived format.\n return false;\n }\n return false;\n }\n\n /** True when `obj` carries a fabric `clipPath` (a mask). */\n private objectHasClip(obj: FabricObject | null): boolean {\n return obj !== null\n && (obj as unknown as Record<string, unknown>)['clipPath'] != null;\n }\n\n /**\n * Render the base image plus every visible annotation layer into a\n * single bitmap (the export-time flatten). With no annotations the\n * fast path returns the image baked at its own resolution; with\n * annotations we composite each object onto a canvas sized to the\n * image's bounding box, offsetting every object by its position\n * relative to the image (both in canvas-space px, multiplier 1).\n *\n * C.1 keeps transforms whole-image, so the common authoring flow\n * (edit pixels -> annotate -> save) lands annotations at full\n * resolution; a base image the user manually scaled with handles\n * exports at its displayed size (a documented limitation).\n */\n private renderFlattened(): HTMLCanvasElement {\n const image = this.requireImage();\n const extras = this.layerObjects().filter(\n o => this.layerKind(o) !== 'image' && o.visible !== false,\n );\n\n const baseEl = image.toCanvasElement({ multiplier: 1 });\n if (extras.length === 0) {\n return baseEl;\n }\n\n const base = image.getBoundingRect();\n const out = document.createElement('canvas');\n out.width = Math.max(1, Math.round(base.width));\n out.height = Math.max(1, Math.round(base.height));\n const ctx = out.getContext('2d');\n if (ctx === null) {\n throw new Error('FabricEngineAdapter: 2d context unavailable for export');\n }\n ctx.drawImage(baseEl, 0, 0);\n for (const obj of extras) {\n const bounds = obj.getBoundingRect();\n const el = obj.toCanvasElement({ multiplier: 1 });\n ctx.drawImage(el, Math.round(bounds.left - base.left), Math.round(bounds.top - base.top));\n }\n return out;\n }\n\n getCanvasSize(): Size {\n if (this.image === null) return { width: 0, height: 0 };\n return { width: this.image.width, height: this.image.height };\n }\n\n setZoom(scale: number): void {\n const center = new Point(this.canvas.getWidth() / 2, this.canvas.getHeight() / 2);\n this.canvas.zoomToPoint(center, scale);\n this.syncFrameOverlay();\n this.canvas.requestRenderAll();\n }\n\n getZoom(): number {\n return this.canvas.getZoom();\n }\n\n resetZoom(): void {\n this.canvas.setViewportTransform([1, 0, 0, 1, 0, 0]);\n this.syncFrameOverlay();\n this.canvas.requestRenderAll();\n }\n\n pan(dx: number, dy: number): void {\n this.canvas.relativePan(new Point(dx, dy));\n this.canvas.requestRenderAll();\n }\n\n getPanOffset(): PointType {\n const vt = this.canvas.viewportTransform ?? [1, 0, 0, 1, 0, 0];\n return { x: vt[4] ?? 0, y: vt[5] ?? 0 };\n }\n\n setPanOffset(offset: PointType): void {\n const zoom = this.canvas.getZoom();\n this.canvas.setViewportTransform([zoom, 0, 0, zoom, offset.x, offset.y]);\n this.canvas.requestRenderAll();\n }\n\n resetPan(): void {\n const zoom = this.canvas.getZoom();\n this.canvas.setViewportTransform([zoom, 0, 0, zoom, 0, 0]);\n this.canvas.requestRenderAll();\n }\n\n getFitZoom(viewportSize: Size): number {\n if (this.image === null) return 1;\n const margin = 0.95;\n const w = this.image.width;\n const h = this.image.height;\n if (w <= 0 || h <= 0) return 1;\n const widthRatio = (viewportSize.width * margin) / w;\n const heightRatio = (viewportSize.height * margin) / h;\n return Math.min(widthRatio, heightRatio);\n }\n\n setCursor(cursor: 'default' | 'grab' | 'grabbing' | 'crosshair'): void {\n this.canvas.defaultCursor = cursor;\n this.canvas.hoverCursor = cursor;\n this.canvas.moveCursor = cursor;\n }\n\n setSelectionEnabled(enabled: boolean): void {\n this.canvas.selection = enabled;\n this.canvas.skipTargetFind = !enabled;\n if (!enabled) {\n this.canvas.discardActiveObject();\n this.canvas.requestRenderAll();\n }\n }\n\n setCanvasDimensions(viewport: Size): void {\n const width = Math.max(1, Math.round(viewport.width));\n const height = Math.max(1, Math.round(viewport.height));\n this.canvas.setDimensions({ width, height });\n if (this.image !== null) {\n this.canvas.centerObject(this.image);\n // Re-anchor the viewport transform around the NEW canvas\n // centre while preserving the current zoom level.\n // `setDimensions` updates `canvas.width/height`, and\n // `centerObject` moves the image to the new canvas centre\n // in canvas coords — but the existing viewportTransform's\n // translate term still anchors to the OLD canvas centre.\n // Without re-anchoring, the image drifts off-centre\n // (most visibly vertically when the dialog grows or\n // shrinks) on every container resize. `zoomToPoint(p, s)`\n // is a no-op when `s` equals the current zoom (it's\n // designed to change zoom while keeping `p` fixed on\n // screen), so we rewrite vt[4]/vt[5] directly: at\n // zoom `s` anchored at canvas centre `(cx, cy)`, the\n // identity for \"vt maps cx,cy -> cx,cy on screen\" is\n // `tx = cx * (1 - s)`, `ty = cy * (1 - s)`.\n const zoom = this.canvas.getZoom();\n const c = this.canvas.getCenterPoint();\n this.canvas.setViewportTransform([zoom, 0, 0, zoom, c.x * (1 - zoom), c.y * (1 - zoom)]);\n }\n this.syncFrameOverlay();\n this.canvas.requestRenderAll();\n }\n\n on<T extends EngineEventType>(event: T, handler: EngineEventHandler<T>): void {\n let set = this.listeners.get(event);\n if (set === undefined) {\n set = new Set();\n this.listeners.set(event, set);\n }\n set.add(handler as (data: any) => void);\n }\n\n off<T extends EngineEventType>(event: T, handler?: EngineEventHandler<T>): void {\n const set = this.listeners.get(event);\n if (set === undefined) return;\n if (handler === undefined) {\n set.clear();\n } else {\n set.delete(handler as (data: any) => void);\n }\n }\n\n destroy(): void {\n if (this.cropOverlay !== null) {\n this.canvas.remove(this.cropOverlay);\n this.cropOverlay = null;\n }\n this.removeFrameOverlay();\n this.commandStack.clear();\n this.listeners.clear();\n this.image = null;\n // Canvas.dispose is async in v6; fire-and-forget so a sync\n // destroy from ngOnDestroy doesn't block teardown. Internal\n // listeners detach synchronously inside dispose itself.\n void this.canvas.dispose();\n if (this.canvasEl.parentElement === this.container) {\n this.container.removeChild(this.canvasEl);\n }\n }\n\n get canvasElement(): HTMLCanvasElement | null {\n return this.canvasEl;\n }\n\n private requireImage(): FabricImage {\n if (this.image === null) {\n throw new Error('FabricEngineAdapter: no image loaded');\n }\n return this.image;\n }\n\n /**\n * Add a thin orange rectangle that mirrors the image's transform\n * so the user can see exactly where the image edge is against the\n * dark canvas background. Sent to the back so the image renders\n * on top of the inner half of the stroke; the outer half stays\n * visible just outside the image bounds. `strokeWidth = 2 / zoom`\n * keeps that outer band a constant 1 visual pixel regardless of\n * viewport zoom. Excluded from export by both convention and\n * construction: our `export` / `exportDataUrl` paths render only\n * the FabricImage object, not the canvas.\n */\n private addFrameOverlay(): void {\n if (this.image === null) return;\n if (this.frameOverlay !== null) {\n this.canvas.remove(this.frameOverlay);\n this.frameOverlay = null;\n }\n const image = this.image;\n const zoom = this.canvas.getZoom() || 1;\n const frame = new FabricRect({\n left: image.left ?? 0,\n top: image.top ?? 0,\n width: image.width,\n height: image.height,\n angle: image.angle ?? 0,\n scaleX: image.scaleX ?? 1,\n scaleY: image.scaleY ?? 1,\n flipX: image.flipX ?? false,\n flipY: image.flipY ?? false,\n originX: image.originX,\n originY: image.originY,\n fill: 'transparent',\n stroke: 'rgba(245, 166, 35, 0.5)',\n strokeWidth: 2 / zoom,\n strokeUniform: false,\n selectable: false,\n evented: false,\n excludeFromExport: true,\n objectCaching: false,\n hoverCursor: 'default',\n } as any);\n this.frameOverlay = frame;\n this.canvas.add(frame);\n this.canvas.sendObjectToBack(frame);\n this.canvas.requestRenderAll();\n }\n\n /**\n * Refresh the frame to mirror the image's current transform and\n * keep the stroke at a constant 1 visual pixel. Called whenever\n * the image moves, scales, rotates, or flips, and after viewport\n * zoom changes (since the latter only matters for the stroke\n * width). Hidden frame stays hidden but its geometry still\n * updates so the next show is in sync.\n */\n private syncFrameOverlay(): void {\n const frame = this.frameOverlay;\n const image = this.image;\n if (frame === null || image === null) return;\n const zoom = this.canvas.getZoom() || 1;\n frame.set({\n left: image.left ?? 0,\n top: image.top ?? 0,\n width: image.width,\n height: image.height,\n angle: image.angle ?? 0,\n scaleX: image.scaleX ?? 1,\n scaleY: image.scaleY ?? 1,\n flipX: image.flipX ?? false,\n flipY: image.flipY ?? false,\n strokeWidth: 2 / zoom,\n });\n frame.setCoords();\n this.canvas.requestRenderAll();\n }\n\n private removeFrameOverlay(): void {\n if (this.frameOverlay !== null) {\n this.canvas.remove(this.frameOverlay);\n this.frameOverlay = null;\n }\n }\n\n /**\n * Install a new FabricImage as the active image after a crop or\n * resize replacement. Adds it to the canvas, centers it in canvas\n * coordinates, drops any leftover viewport zoom/pan from the\n * previous image (otherwise the new, smaller image lands\n * off-screen because the user was zoomed into the corner of the\n * old one), and re-emits `imageLoaded` so consumers refit the\n * view to the new dimensions.\n */\n private replaceImage(newImage: FabricImage): void {\n this.removeFrameOverlay();\n this.image = newImage;\n this.canvas.add(newImage);\n // Keep the base image the canvas floor: a crop / resize that runs\n // after annotations were added must not stack the fresh image on\n // top of them (C.1e). No-op when there are no annotation layers.\n this.keepImageAtBack();\n this.canvas.centerObject(newImage);\n this.canvas.setViewportTransform([1, 0, 0, 1, 0, 0]);\n this.addFrameOverlay();\n this.canvas.requestRenderAll();\n this.emit('imageLoaded', { width: newImage.width, height: newImage.height });\n }\n\n /**\n * Make sure fabric's WebGL filter backend has a GL canvas large\n * enough to hold the image's full pixel area. Fabric defaults\n * `config.textureSize` to 4096 and constructs a 4096×4096 GL\n * canvas; rendering a 4608×3456 image into that backend leaves\n * a ~512 px right-edge band un-rendered (the WebGL viewport is\n * set to image dims but the GL canvas can't hold them), which\n * `copyGLTo2D` then reads as transparent. That surfaced as the\n * right-side crop the user reported on Sharpen.\n *\n * Fix: bump `config.textureSize` to the next power-of-two that\n * fits the image, capped at 16384, then drop the cached backend\n * so `getFilterBackend()` re-initialises with the new tile size.\n * The probe inside `initFilterBackend` falls back to the Canvas2D\n * backend automatically if the GPU can't support the new size,\n * so this is safe on low-end hardware.\n */\n private ensureFilterBackendFitsImage(image: FabricImage): void {\n const required = Math.max(image.width, image.height);\n if (required <= fabricConfig.textureSize) return;\n const nextPow2 = 1 << Math.ceil(Math.log2(required));\n fabricConfig.textureSize = Math.min(16384, nextPow2);\n setFilterBackend(initFilterBackend());\n }\n\n private pushCommand(cmd: EngineCommand): void {\n this.commandStack.push(cmd);\n this.emit('imageChanged', undefined);\n this.emit('historyStateChanged', {\n canUndo: this.commandStack.canUndo(),\n canRedo: this.commandStack.canRedo(),\n });\n }\n\n private resolveFilterCtor(name: FilterName): any {\n if (name === 'sharpen') return filters.Convolute;\n const slider = FabricEngineAdapter.SLIDER_FILTERS[name];\n if (slider !== undefined) return slider;\n const toggle = FabricEngineAdapter.TOGGLE_FILTERS[name];\n if (toggle !== undefined) return toggle;\n throw new Error(`FabricEngineAdapter: unknown filter \"${name}\"`);\n }\n\n private instantiateFilter(name: FilterName, params: FilterParams): any {\n if (name === 'sharpen') {\n const Ctor = filters.Convolute as ConvoluteFilterCtor;\n return new Ctor({ matrix: [...SHARPEN_KERNEL], opaque: false });\n }\n if (name === 'pixelate') {\n const Ctor = filters.Pixelate as SliderFilterCtor;\n const blocksize = Math.max(2, Math.round(params.pixelate ?? 2));\n return new Ctor({ blocksize });\n }\n const slider = FabricEngineAdapter.SLIDER_FILTERS[name];\n if (slider !== undefined) {\n const value = (params as Record<string, number | undefined>)[name] ?? 0;\n return new slider({ [name]: value });\n }\n const toggle = FabricEngineAdapter.TOGGLE_FILTERS[name];\n if (toggle !== undefined) {\n return new toggle();\n }\n throw new Error(`FabricEngineAdapter: unknown filter \"${name}\"`);\n }\n\n private attachVendorListeners(): void {\n // Keep the canvas frame in sync with every image transform.\n // All transform paths (rotate, flip, mouse drag, undo/redo)\n // funnel through `imageTransformed`, so a single subscription\n // is enough to catch them.\n this.on('imageTransformed', () => this.syncFrameOverlay());\n\n this.canvas.on('selection:created', (e: any) => {\n const target = e.selected?.[0] ?? null;\n this.emit('objectActivated', { objectType: target?.type ?? '' });\n this.emitActiveFromCanvas();\n });\n this.canvas.on('selection:updated', (e: any) => {\n const target = e.selected?.[0] ?? null;\n this.emit('objectActivated', { objectType: target?.type ?? '' });\n this.emitActiveFromCanvas();\n });\n this.canvas.on('selection:cleared', () => {\n this.emit('objectDeactivated', undefined);\n this.emit('activeObjectChanged', { id: null, kind: null });\n });\n\n // Snapshot the image's transform when the user starts a drag\n // gesture on it. fabric fires `object:modified` once the gesture\n // ends, with the final state on the target; without the\n // snapshot we'd have no way to build the inverse for undo.\n // Filtered to the image only so the crop overlay's drags don't\n // poison the snapshot. Shape / text layers get a parallel\n // snapshot so their moves / resizes are undoable too (C.1).\n this.canvas.on('mouse:down', (e: any) => {\n const target = e.target as FabricObject | undefined;\n if (this.image !== null && target === this.image) {\n this.mouseTransformSnapshot = this.captureTransform(this.image);\n } else if (target && this.layerId(target) !== '' && this.layerKind(target) !== 'image') {\n this.objTransformSnapshot = { obj: target, state: this.captureObjectState(target) };\n }\n });\n\n this.canvas.on('object:modified', (e: any) => {\n // Shape / text layer moved / resized / rotated with the\n // mouse handles — push a generic transform command.\n const tgt = e.target as FabricObject | undefined;\n if (tgt && this.layerId(tgt) !== '' && this.layerKind(tgt) !== 'image') {\n const snap = this.objTransformSnapshot;\n this.objTransformSnapshot = null;\n if (snap !== null && snap.obj === tgt) {\n const before = snap.state;\n const after = this.captureObjectState(tgt);\n if (JSON.stringify(before) !== JSON.stringify(after)) {\n this.commandStack.push({\n name: 'move layer',\n do: () => { tgt.set(after); tgt.setCoords(); this.canvas.requestRenderAll(); this.afterLayerMutation(); },\n undo: () => { tgt.set(before); tgt.setCoords(); this.canvas.requestRenderAll(); this.afterLayerMutation(); },\n });\n this.emit('imageChanged', undefined);\n this.emit('historyStateChanged', {\n canUndo: this.commandStack.canUndo(),\n canRedo: this.commandStack.canRedo(),\n });\n }\n }\n // Refresh the active-layer transform mirror so the\n // Rotate / Flip tools pick up a handle-drag rotation /\n // flip as their next baseline (C.1c).\n this.emitActiveFromCanvas();\n return;\n }\n\n if (this.image === null || e.target !== this.image) return;\n const before = this.mouseTransformSnapshot;\n this.mouseTransformSnapshot = null;\n if (before === null) return;\n const after = this.captureTransform(this.image);\n if (this.transformsEqual(before, after)) return;\n\n const image = this.image;\n this.commandStack.push({\n name: 'transform',\n do: () => {\n image.set(after);\n image.setCoords();\n this.canvas.requestRenderAll();\n this.emitImageTransformed(image, 'sidebar');\n },\n undo: () => {\n image.set(before);\n image.setCoords();\n this.canvas.requestRenderAll();\n this.emitImageTransformed(image, 'sidebar');\n },\n });\n this.emit('imageChanged', undefined);\n this.emit('historyStateChanged', {\n canUndo: this.commandStack.canUndo(),\n canRedo: this.commandStack.canRedo(),\n });\n this.emitImageTransformed(image, 'mouse');\n });\n\n // Annotation seam: raw pointer stream in SCENE coordinates so\n // consumers can implement draw-by-drag interactions without\n // touching fabric (see EngineEvents.scenePointer).\n const emitScenePointer = (phase: 'down' | 'move' | 'up' | 'dblclick') => (e: any) => {\n const p = this.canvas.getScenePoint(e.e);\n const target = e.target as FabricObject | undefined;\n this.emit('scenePointer', {\n phase,\n x: p.x,\n y: p.y,\n targetLayerId: target ? (this.layerId(target) || null) : null,\n });\n };\n this.canvas.on('mouse:down', emitScenePointer('down'));\n this.canvas.on('mouse:move', emitScenePointer('move'));\n this.canvas.on('mouse:up', emitScenePointer('up'));\n this.canvas.on('mouse:dblclick', emitScenePointer('dblclick'));\n }\n\n private captureTransform(image: FabricImage): ImageTransformState {\n return {\n angle: image.angle ?? 0,\n scaleX: image.scaleX ?? 1,\n scaleY: image.scaleY ?? 1,\n flipX: image.flipX ?? false,\n flipY: image.flipY ?? false,\n left: image.left ?? 0,\n top: image.top ?? 0,\n };\n }\n\n private transformsEqual(a: ImageTransformState, b: ImageTransformState): boolean {\n return a.angle === b.angle\n && a.scaleX === b.scaleX\n && a.scaleY === b.scaleY\n && a.flipX === b.flipX\n && a.flipY === b.flipY\n && a.left === b.left\n && a.top === b.top;\n }\n\n private emitImageTransformed(image: FabricImage, source: 'mouse' | 'sidebar'): void {\n const t = this.captureTransform(image);\n this.emit('imageTransformed', { ...t, source });\n }\n\n // --- C.1 layer helpers -----------------------------------------\n\n /** A filled right-pointing arrow, drawn as a single polygon. */\n private static readonly ARROW_POINTS: readonly { x: number; y: number }[] = [\n { x: 0, y: 14 }, { x: 150, y: 14 }, { x: 150, y: 0 },\n { x: 200, y: 28 }, { x: 150, y: 56 }, { x: 150, y: 42 }, { x: 0, y: 42 },\n ];\n\n private createShape(kind: ShapeKind, o: ShapeOptions): FabricObject {\n const base = { fill: this.resolveFill(o.fillSpec, o.fill), stroke: o.stroke, strokeWidth: o.strokeWidth };\n switch (kind) {\n case 'rect': return new FabricRect({ ...base, width: 220, height: 140 });\n case 'ellipse': return new Ellipse({ ...base, rx: 120, ry: 80 });\n case 'triangle': return new Triangle({ ...base, width: 200, height: 170 });\n case 'line': return new Line([0, 0, 240, 0], { stroke: o.stroke, strokeWidth: Math.max(3, o.strokeWidth) });\n case 'arrow': return new Polygon([...FabricEngineAdapter.ARROW_POINTS], { ...base });\n }\n }\n\n // --- C.1b fill (solid / gradient) ------------------------------\n\n /** A fabric fill value: a flat colour string or a `Gradient`. */\n private resolveFill(spec: FillSpec | undefined, fallback: string): string | Gradient<'linear'> | Gradient<'radial'> {\n return spec === undefined ? fallback : this.buildFill(spec);\n }\n\n /**\n * Build a fabric solid colour or `Gradient` from a {@link FillSpec}.\n * Gradients use `gradientUnits: 'percentage'`, so coords are 0..1 of\n * the object's bounding box (origin top-left) and the gradient\n * tracks the object through resize / text reflow — fabric applies\n * `ctx.transform(width, 0, 0, height, …)` at paint time, including\n * the `toCanvasElement` flatten the export composites.\n */\n private buildFill(spec: FillSpec): string | Gradient<'linear'> | Gradient<'radial'> {\n if (spec.type === 'solid') return spec.color;\n\n const colorStops = [\n { offset: 0, color: spec.color },\n { offset: 1, color: spec.color2 },\n ];\n\n if (spec.type === 'radial') {\n // Centre -> edge ellipse spanning the object box.\n return new Gradient<'radial'>({\n type: 'radial',\n gradientUnits: 'percentage',\n coords: { x1: 0.5, y1: 0.5, r1: 0, x2: 0.5, y2: 0.5, r2: 0.5 },\n colorStops,\n });\n }\n\n // Linear: a line through the box centre at `angle` degrees.\n const rad = (spec.angle * Math.PI) / 180;\n const dx = Math.cos(rad) / 2;\n const dy = Math.sin(rad) / 2;\n return new Gradient<'linear'>({\n type: 'linear',\n gradientUnits: 'percentage',\n coords: { x1: 0.5 - dx, y1: 0.5 - dy, x2: 0.5 + dx, y2: 0.5 + dy },\n colorStops,\n });\n }\n\n /** Resolve a fabric fill (string or `Gradient`) back to a {@link FillSpec}. */\n private readFill(fill: unknown): FillSpec {\n if (this.isGradient(fill)) {\n const stops = fill.colorStops ?? [];\n const color = this.colorStopHex(stops[0]?.color, '#000000');\n const color2 = this.colorStopHex(stops[stops.length - 1]?.color, '#ffffff');\n if (fill.type === 'radial') {\n return { type: 'radial', color, color2, angle: 0 };\n }\n const c = fill.coords;\n const deg = (Math.atan2((c.y2 ?? 0) - (c.y1 ?? 0), (c.x2 ?? 1) - (c.x1 ?? 0)) * 180) / Math.PI;\n return { type: 'linear', color, color2, angle: Math.round((deg + 360) % 360) };\n }\n const color = typeof fill === 'string' && fill !== '' ? fill : '#000000';\n return { type: 'solid', color, color2: '#ffffff', angle: 0 };\n }\n\n /** Best-effort solid-colour hex for the generic prop bag (gradients collapse to their first stop). */\n private fillToHex(fill: unknown): string {\n if (typeof fill === 'string') return fill;\n return this.readFill(fill).color;\n }\n\n private isGradient(v: unknown): v is {\n type: 'linear' | 'radial';\n colorStops: { color: string; offset: number }[];\n coords: { x1: number; y1: number; x2: number; y2: number };\n } {\n return v !== null && typeof v === 'object'\n && Array.isArray((v as { colorStops?: unknown }).colorStops);\n }\n\n /** Coerce a colour-stop value to an `<input type=color>`-safe 6-digit hex. */\n private colorStopHex(color: string | undefined, fallback: string): string {\n return typeof color === 'string' && /^#[0-9a-fA-F]{6}$/.test(color) ? color : fallback;\n }\n\n private shapeLabel(kind: ShapeKind): string {\n const labels: Record<ShapeKind, string> = {\n rect: 'Rectangle', ellipse: 'Ellipse', triangle: 'Triangle', line: 'Line', arrow: 'Arrow',\n };\n return labels[kind];\n }\n\n /**\n * Centre `obj` on the image, stamp it as a layer, add + select it,\n * and push an add/remove undo command. Shared by addShape/addText.\n */\n private placeAndAdd(obj: FabricObject, kind: LayerKind, name: string): void {\n const center = this.image !== null\n ? this.image.getCenterPoint()\n : new Point(this.canvas.getWidth() / 2, this.canvas.getHeight() / 2);\n obj.set({ originX: 'center', originY: 'center', left: center.x, top: center.y });\n obj.setCoords();\n this.stampLayer(obj, kind, name);\n this.canvas.add(obj);\n this.keepImageAtBack();\n this.canvas.setActiveObject(obj);\n this.canvas.requestRenderAll();\n\n this.pushCommand({\n name: `add ${name}`,\n do: () => {\n this.canvas.add(obj);\n this.keepImageAtBack();\n this.canvas.setActiveObject(obj);\n this.canvas.requestRenderAll();\n this.afterLayerMutation();\n },\n undo: () => {\n this.canvas.remove(obj);\n this.canvas.discardActiveObject();\n this.canvas.requestRenderAll();\n this.afterLayerMutation();\n },\n });\n this.afterLayerMutation();\n }\n\n private stampLayer(obj: FabricObject, kind: LayerKind, name: string): void {\n const o = obj as unknown as Record<string, unknown>;\n o['coolmsId'] = kind === 'image' ? 'layer-bg' : `layer-${this.nextLayerId++}`;\n o['coolmsKind'] = kind;\n o['coolmsName'] = name;\n }\n\n /** Every stamped layer object on the canvas (base image + extras). */\n private layerObjects(): FabricObject[] {\n return this.canvas.getObjects().filter(o => (o as unknown as Record<string, unknown>)['coolmsId'] !== undefined);\n }\n\n /** Drop every non-image layer (used by load / reset). */\n private removeLayerObjects(): void {\n for (const o of this.layerObjects()) {\n if (this.layerKind(o) !== 'image') this.canvas.remove(o);\n }\n this.nextLayerId = 1;\n }\n\n private findLayer(id: string): FabricObject | null {\n return this.layerObjects().find(o => this.layerId(o) === id) ?? null;\n }\n\n private layerId(o: FabricObject): string {\n return (o as unknown as Record<string, unknown>)['coolmsId'] as string ?? '';\n }\n\n private layerKind(o: FabricObject): LayerKind {\n return (o as unknown as Record<string, unknown>)['coolmsKind'] as LayerKind ?? 'shape';\n }\n\n private layerName(o: FabricObject): string {\n return (o as unknown as Record<string, unknown>)['coolmsName'] as string ?? 'Layer';\n }\n\n /** Keep the base image pinned to the canvas floor (z-index 0). */\n private keepImageAtBack(): void {\n if (this.image !== null && this.canvas.getObjects().length > 1) {\n this.canvas.sendObjectToBack(this.image);\n }\n }\n\n /** Notify consumers a layer changed + re-broadcast the active layer. */\n private afterLayerMutation(): void {\n this.emit('layersChanged', undefined);\n this.emitActiveFromCanvas();\n }\n\n private emitActiveFromCanvas(): void {\n const active = this.canvas.getActiveObject();\n if (active === undefined || active === null) {\n this.emit('activeObjectChanged', { id: null, kind: null });\n return;\n }\n const id = this.layerId(active);\n this.emit('activeObjectChanged', {\n id: id === '' ? null : id,\n kind: id === '' ? null : this.layerKind(active),\n });\n }\n\n private captureObjectState(o: FabricObject): Record<string, number> {\n return {\n left: o.left ?? 0,\n top: o.top ?? 0,\n scaleX: o.scaleX ?? 1,\n scaleY: o.scaleY ?? 1,\n angle: o.angle ?? 0,\n skewX: o.skewX ?? 0,\n skewY: o.skewY ?? 0,\n width: o.width ?? 0,\n height: o.height ?? 0,\n };\n }\n\n // --- C.1c per-layer transforms + masking helpers ---------------\n\n /**\n * The active object when it's a selectable shape / text layer (not\n * the base image, not nothing). The rotate / flip / mask targeting\n * keys off this: a non-null result means \"operate on this layer\".\n */\n private activeNonImageLayer(): FabricObject | null {\n const active = this.canvas.getActiveObject();\n if (active === undefined || active === null) return null;\n if (this.layerId(active) === '' || this.layerKind(active) === 'image') return null;\n return active;\n }\n\n /**\n * The mask target: the active non-image layer if one is selected,\n * else the base image (which may be `null` before any load).\n */\n private maskTarget(): FabricObject | null {\n return this.activeNonImageLayer() ?? this.image;\n }\n\n private rotateLayer(obj: FabricObject, degrees: number): void {\n const prev = obj.angle ?? 0;\n const next = prev + degrees;\n const apply = (angle: number): void => {\n obj.rotate(angle);\n obj.setCoords();\n this.canvas.requestRenderAll();\n this.afterLayerMutation();\n };\n apply(next);\n this.pushCommand({\n name: 'rotate layer',\n do: () => { apply(next); },\n undo: () => { apply(prev); },\n });\n }\n\n private flipLayer(obj: FabricObject, axis: 'horizontal' | 'vertical'): void {\n const prop: 'flipX' | 'flipY' = axis === 'horizontal' ? 'flipX' : 'flipY';\n const prev = obj[prop] ?? false;\n const apply = (value: boolean): void => {\n obj.set(prop, value);\n obj.setCoords();\n this.canvas.requestRenderAll();\n this.afterLayerMutation();\n };\n apply(!prev);\n this.pushCommand({\n name: `flip layer ${axis}`,\n do: () => { apply(!prev); },\n undo: () => { apply(prev); },\n });\n }\n\n /**\n * Build a fabric `clipPath` for `spec` against `target`'s own box.\n * The clip is centred on the object (originX/Y = 'center', left/top\n * = 0): fabric renders clipPaths in the object's centred local space\n * before applying the object's own scale, so the mask tracks the\n * object through scale / move and bakes into `toCanvasElement`.\n * Returns `null` for `shape: 'none'` (clears the mask).\n */\n private buildClipPath(target: FabricObject, spec: MaskSpec): FabricObject | null {\n if (spec.shape === 'none') return null;\n\n const w = target.width ?? 0;\n const h = target.height ?? 0;\n const mx = w * (spec.inset / 100);\n const my = h * (spec.inset / 100);\n const cw = Math.max(1, w - 2 * mx);\n const ch = Math.max(1, h - 2 * my);\n const common = { originX: 'center', originY: 'center', left: 0, top: 0 } as const;\n\n switch (spec.shape) {\n case 'rect':\n return new FabricRect({ ...common, width: cw, height: ch });\n case 'rounded': {\n const r = (Math.min(cw, ch) / 2) * (spec.radius / 100);\n return new FabricRect({ ...common, width: cw, height: ch, rx: r, ry: r });\n }\n case 'ellipse':\n return new Ellipse({ ...common, rx: cw / 2, ry: ch / 2 });\n case 'triangle':\n return new Triangle({ ...common, width: cw, height: ch });\n case 'custom':\n // Arbitrary path geometry from a pasted / uploaded SVG\n // (C.1d). The tool has already sanitised it to a single\n // combined path `d` string (paths only).\n return this.buildPathClip(spec.svgPath ?? '', cw, ch, common);\n default:\n // SVG-path presets (star / heart / hexagon), normalised to\n // a 0..100 box and scaled to the clip box.\n return this.buildPathClip(MASK_PATHS[spec.shape], cw, ch, common);\n }\n }\n\n /**\n * Build a `Path` clip from raw SVG path `d` data, scaling its\n * bounding box to the `cw × ch` clip box (centred via `common`).\n * Shared by the built-in path presets and arbitrary `custom` masks\n * (C.1d) — fabric computes the path's intrinsic bbox, and the\n * `scaleX/Y` maps it onto the target's clip box, so any path tracks\n * scale / move and bakes into `toCanvasElement` like the presets.\n * Returns `null` for empty / unparseable data (clears the mask).\n */\n private buildPathClip(\n d: string,\n cw: number,\n ch: number,\n common: { originX: 'center'; originY: 'center'; left: number; top: number },\n ): FabricObject | null {\n if (d.trim() === '') return null;\n let path: Path;\n try {\n path = new Path(d, { ...common });\n } catch {\n // Defensive: fabric throws on path data it can't tokenise.\n // The tool validates before sending, so this is a backstop.\n return null;\n }\n const pw = path.width || 100;\n const ph = path.height || 100;\n path.set({ scaleX: cw / pw, scaleY: ch / ph });\n path.setCoords();\n return path;\n }\n\n private emit<T extends EngineEventType>(event: T, data: EngineEvents[T]): void {\n const set = this.listeners.get(event);\n if (set === undefined) return;\n for (const handler of set) {\n handler(data);\n }\n }\n}\n","import { Injectable, computed, signal } from '@angular/core';\nimport { FabricEngineAdapter } from '../engine/fabric-engine.adapter';\nimport type { ImageEditorEngine } from '../engine/image-editor-engine.interface';\nimport type { Size } from '../types/geometry.types';\nimport type { LayerInfo, LayerKind } from '../types/layer.types';\n\n/**\n * Lifecycle states the shell renders against.\n *\n * `uninitialized` — fresh service instance, no engine yet.\n * `loading` — engine creation or initial image load is in flight.\n * `ready` — engine is mounted and the image is on the canvas.\n * `error` — engine creation or initial load failed; `errorMessage`\n * holds the user-facing reason.\n */\nexport type EditorState = 'uninitialized' | 'loading' | 'ready' | 'error';\n\n/**\n * Shared editor state for the in-tree shell.\n *\n * Scoped to the `CoolmsImageEditorComponent` instance via that\n * component's `providers` array, so opening two editors at once would\n * give each one its own engine, history flags, and active-tool slot.\n *\n * Kept deliberately thin: signals + the methods that mutate them. Tool\n * implementations in beta.4 reach the engine through `engine()` rather\n * than threading domain logic through this service.\n */\n@Injectable()\nexport class ImageEditorStateService {\n private readonly engineInstance = signal<ImageEditorEngine | null>(null);\n\n readonly state = signal<EditorState>('uninitialized');\n readonly canvasSize = signal<Size | null>(null);\n readonly canUndo = signal<boolean>(false);\n readonly canRedo = signal<boolean>(false);\n /** Tool ID set by the right-sidebar picker. beta.3 leaves this null. */\n readonly activeTool = signal<string | null>(null);\n readonly errorMessage = signal<string | null>(null);\n /**\n * Viewport zoom level, where 1.0 = 100%. Mirrors the engine's\n * canvas zoom; mutated through `zoomIn` / `zoomOut` / `resetZoom` /\n * `setZoom`, never directly by consumers (the value here must\n * stay in lockstep with what the engine actually rendered).\n */\n readonly currentZoom = signal<number>(1);\n /**\n * Fit-to-viewport zoom — the scale at which the loaded image\n * fills the canvas-mount (with a small margin). Calculated by\n * the canvas-mount component once it has measured its viewport,\n * and re-calculated on container resize. Used as the target for\n * `resetZoom()` and the full `reset()` so \"back to 100%\" lands\n * the user at the same view they saw on first mount.\n */\n readonly fitZoom = signal<number>(1);\n /**\n * Hand-tool toggle. When true, mouse-down + drag on the canvas\n * pans the viewport instead of doing nothing. The cursor swaps\n * to grab / grabbing via canvas-mount's class bindings.\n */\n readonly handToolActive = signal<boolean>(false);\n\n // Image transform state. Kept in sync with the engine through\n // the `imageTransformed` event. Tool components read these to\n // bind their UI (rotate slider value, flip button highlight,\n // resize input fields) to the actual image, regardless of\n // whether the change came from a mouse drag on the canvas or\n // from another sidebar tool.\n readonly imageRotation = signal<number>(0);\n readonly imageScaleX = signal<number>(1);\n readonly imageScaleY = signal<number>(1);\n readonly imageFlipX = signal<boolean>(false);\n readonly imageFlipY = signal<boolean>(false);\n readonly imagePosition = signal<{ x: number; y: number }>({ x: 0, y: 0 });\n\n /**\n * The layer stack (top-most first), mirrored from the engine's\n * `layersChanged` event. The Layers panel binds to this. (C.1)\n */\n readonly layers = signal<LayerInfo[]>([]);\n /** Active layer id, mirrored from `activeObjectChanged`. (C.1) */\n readonly activeLayerId = signal<string | null>(null);\n /** Active layer kind, so style panels know which controls apply. (C.1) */\n readonly activeLayerKind = signal<LayerKind | null>(null);\n\n /**\n * The active non-image layer's transform, mirrored from the engine\n * (C.1c). The Rotate / Flip tools read these via the\n * `transformTarget*` computeds so a selected shape / text layer is\n * the transform target instead of the base image.\n */\n readonly activeLayerAngle = signal<number>(0);\n readonly activeLayerFlipX = signal<boolean>(false);\n readonly activeLayerFlipY = signal<boolean>(false);\n\n /** True when a non-image layer (not the Background) is the active object. */\n private readonly targetingLayer = computed(() => {\n const kind = this.activeLayerKind();\n return kind !== null && kind !== 'image';\n });\n\n /**\n * The rotation / flip the Rotate + Flip tools bind to: the selected\n * non-image layer's when one is active, else the base image's. (C.1c)\n */\n readonly transformTargetRotation = computed(() =>\n this.targetingLayer() ? this.activeLayerAngle() : this.imageRotation(),\n );\n readonly transformTargetFlipX = computed(() =>\n this.targetingLayer() ? this.activeLayerFlipX() : this.imageFlipX(),\n );\n readonly transformTargetFlipY = computed(() =>\n this.targetingLayer() ? this.activeLayerFlipY() : this.imageFlipY(),\n );\n\n /**\n * Image scale as a percentage rounded to a whole number. Uses the\n * absolute scale value so a horizontally-flipped image at scale\n * -1 reads as 100%, not -100%. Flip is reported separately.\n */\n readonly imageScalePercent = computed(() =>\n Math.round(Math.abs(this.imageScaleX()) * 100)\n );\n\n /** Read-only handle the toolbar and tools use to drive the engine. */\n readonly engine = computed(() => this.engineInstance());\n\n readonly isReady = computed(\n () => this.state() === 'ready' && this.engineInstance() !== null,\n );\n\n /**\n * Create the engine, load the image, and attach the listeners that\n * keep the history-state signals in sync. Throws (and flips state to\n * 'error') if either step fails — the shell surfaces the message\n * through the canvas-mount overlay.\n *\n * The 'uninitialized' guard is what makes the service safe to call\n * from `ngAfterViewInit`: a re-entrant call (e.g. after a hot\n * module replace cycle in dev) is a no-op rather than a duplicate\n * mount.\n */\n async initializeEngine(\n container: HTMLElement,\n sourceUrl: string,\n filename: string,\n ): Promise<void> {\n if (this.state() !== 'uninitialized') {\n throw new Error('Engine already initialised');\n }\n\n this.state.set('loading');\n\n try {\n const engine = await FabricEngineAdapter.create({ container });\n engine.setCanvasDimensions({\n width: Math.max(1, container.clientWidth),\n height: Math.max(1, container.clientHeight),\n });\n const size = await engine.loadImage(sourceUrl, filename);\n\n this.engineInstance.set(engine);\n this.canvasSize.set(size);\n this.state.set('ready');\n\n this.attachEngineListeners(engine);\n } catch (err) {\n this.state.set('error');\n this.errorMessage.set(\n err instanceof Error ? err.message : 'Failed to initialise editor',\n );\n throw err;\n }\n }\n\n /**\n * Tear down the engine and reset every signal to its starting\n * state. Idempotent so the host can call it from `ngOnDestroy`\n * without checking `state()` first.\n */\n destroyEngine(): void {\n const engine = this.engineInstance();\n if (engine !== null) {\n engine.destroy();\n this.engineInstance.set(null);\n }\n this.state.set('uninitialized');\n this.canvasSize.set(null);\n this.canUndo.set(false);\n this.canRedo.set(false);\n this.activeTool.set(null);\n this.errorMessage.set(null);\n this.currentZoom.set(1);\n this.fitZoom.set(1);\n this.handToolActive.set(false);\n this.imageRotation.set(0);\n this.imageScaleX.set(1);\n this.imageScaleY.set(1);\n this.imageFlipX.set(false);\n this.imageFlipY.set(false);\n this.imagePosition.set({ x: 0, y: 0 });\n this.layers.set([]);\n this.activeLayerId.set(null);\n this.activeLayerKind.set(null);\n this.activeLayerAngle.set(0);\n this.activeLayerFlipX.set(false);\n this.activeLayerFlipY.set(false);\n }\n\n setActiveTool(toolId: string | null): void {\n this.activeTool.set(toolId);\n }\n\n /**\n * Refresh the cached canvas dimensions after an in-place\n * operation that the engine doesn't proactively re-measure for\n * us (Resize tool's primary use). Engine load + initial mount\n * still write through `initializeEngine`.\n */\n updateCanvasSize(size: Size): void {\n this.canvasSize.set(size);\n }\n\n /**\n * Viewport zoom controls. Clamped 0.05..10 (5%..1000%) — wide\n * range to accommodate fit-zoom for very large images (a 8000px\n * image in a 600px viewport fits at ~7%) and the occasional\n * pixel-peeping zoom-in on small images. Step factor of 1.25\n * matches the convention used by Photoshop, Affinity, and most\n * desktop image editors.\n */\n private static readonly ZOOM_MIN = 0.05;\n private static readonly ZOOM_MAX = 10;\n private static readonly ZOOM_STEP = 1.25;\n\n setZoom(scale: number): void {\n const engine = this.engineInstance();\n if (engine === null) return;\n const clamped = Math.min(\n ImageEditorStateService.ZOOM_MAX,\n Math.max(ImageEditorStateService.ZOOM_MIN, scale),\n );\n engine.setZoom(clamped);\n this.currentZoom.set(clamped);\n }\n\n zoomIn(): void { this.setZoom(this.currentZoom() * ImageEditorStateService.ZOOM_STEP); }\n zoomOut(): void { this.setZoom(this.currentZoom() / ImageEditorStateService.ZOOM_STEP); }\n\n resetZoom(): void {\n const engine = this.engineInstance();\n if (engine === null) return;\n // The \"%\" button returns to fit (not raw 1.0). Pan is also\n // cleared so a zoomed-and-panned view snaps back to the\n // canonical centred fit view.\n engine.resetZoom();\n const fit = this.fitZoom();\n engine.setZoom(fit);\n this.currentZoom.set(fit);\n }\n\n /**\n * Compute and apply the fit-to-viewport zoom for the currently\n * loaded image. Called by canvas-mount after the engine emits\n * `imageLoaded` and on container resize. The fabric adapter\n * owns canvas dimensions, so the returned fit factor drives the\n * viewport zoom directly (small images upscale beyond 1.0 to\n * fill the viewport, large images shrink below 1.0 to fit).\n */\n applyFitZoom(viewportSize: Size): void {\n const engine = this.engineInstance();\n if (engine === null) return;\n const fit = engine.getFitZoom(viewportSize);\n this.fitZoom.set(fit);\n this.setZoom(fit);\n }\n\n /**\n * Update the cached fit zoom without touching the live view.\n * Used by the resize observer so a window resize while the\n * user has manually zoomed in doesn't yank them back to fit\n * mid-edit; the next Reset / \"%\" click picks up the fresh\n * value instead.\n */\n recalculateFitZoom(viewportSize: Size): void {\n const engine = this.engineInstance();\n if (engine === null) return;\n this.fitZoom.set(engine.getFitZoom(viewportSize));\n }\n\n toggleHandTool(): void {\n this.handToolActive.update(v => !v);\n }\n\n /**\n * Top-toolbar Reset button entry point. Restores the canvas to\n * the pristine loaded state in one call:\n * - any active tool is closed (its `ngOnDestroy` runs the\n * tool's deactivation, e.g. `exitCropMode` for the cropper);\n * - the Hand tool is deactivated;\n * - the engine reloads the original image and clears both\n * undo and redo stacks;\n * - the viewport pan offset is zeroed and the zoom is set to\n * the fit-to-viewport value (matches what the user saw on\n * first mount, not the raw 1.0× that would shrink large\n * images).\n *\n * The order matters: tool deactivation first so a mid-edit\n * cropper doesn't try to re-render against a stale canvas while\n * the engine is reloading the original image.\n */\n async reset(): Promise<void> {\n const engine = this.engineInstance();\n if (engine === null) return;\n\n this.activeTool.set(null);\n this.handToolActive.set(false);\n await engine.reset();\n // Full identity transform (zoom 1, pan 0). Was `resetPan()`,\n // which preserved the old zoom and left `setZoom(fit)` below\n // anchoring at `canvas-center * old_zoom` rather than the\n // viewport center, dropping the image into a corner after\n // Reset whenever the user had previously zoomed away from 1.\n engine.resetZoom();\n const fit = this.fitZoom();\n engine.setZoom(fit);\n this.currentZoom.set(fit);\n }\n\n private attachEngineListeners(engine: ImageEditorEngine): void {\n // Seed history flags from the engine's current state so the\n // toolbar's disabled state matches reality on the very first\n // render (before any action fires `historyStateChanged`).\n this.canUndo.set(engine.canUndo());\n this.canRedo.set(engine.canRedo());\n\n engine.on('historyStateChanged', ({ canUndo, canRedo }) => {\n this.canUndo.set(canUndo);\n this.canRedo.set(canRedo);\n });\n\n // Crop / resize replace the FabricImage with a new instance\n // and re-emit `imageLoaded`. Update canvasSize so canvas-mount\n // refits the view to the new dimensions, and reset\n // currentZoom because the adapter resets the viewport\n // transform during the replacement. The image transform\n // signals also reset here because the new image always lands\n // at angle 0 / scale 1 / no flips after the adapter's\n // `replaceImage` runs (the prior transforms are baked into\n // the replacement's pixel data).\n engine.on('imageLoaded', size => {\n this.canvasSize.set(size);\n this.currentZoom.set(1);\n this.imageRotation.set(0);\n this.imageScaleX.set(1);\n this.imageScaleY.set(1);\n this.imageFlipX.set(false);\n this.imageFlipY.set(false);\n this.imagePosition.set({ x: 0, y: 0 });\n });\n\n // Mouse drag on the canvas or any sidebar action that mutates\n // the image's transform routes through `imageTransformed`.\n // Mirroring it into signals here keeps the rotate slider,\n // flip-button highlight, and resize inputs reading the live\n // value without each tool wiring up its own listener.\n engine.on('imageTransformed', t => {\n this.imageRotation.set(t.angle);\n this.imageScaleX.set(t.scaleX);\n this.imageScaleY.set(t.scaleY);\n this.imageFlipX.set(t.flipX);\n this.imageFlipY.set(t.flipY);\n this.imagePosition.set({ x: t.left, y: t.top });\n });\n\n // C.1 layer stack + selection mirror. Seed from the freshly\n // loaded image (one Background layer, nothing selected) then\n // track the engine's layer / selection events.\n this.layers.set(engine.getLayers());\n this.activeLayerId.set(engine.getActiveLayerId());\n engine.on('layersChanged', () => this.layers.set(engine.getLayers()));\n engine.on('activeObjectChanged', ({ id, kind }) => {\n this.activeLayerId.set(id);\n this.activeLayerKind.set(kind);\n // Mirror the selected non-image layer's transform so the\n // Rotate / Flip tools target it (C.1c). `null` (image or\n // nothing selected) leaves the last values — the\n // `transformTarget*` computeds fall back to image state.\n const t = engine.getActiveLayerTransform();\n if (t !== null) {\n this.activeLayerAngle.set(t.angle);\n this.activeLayerFlipX.set(t.flipX);\n this.activeLayerFlipY.set(t.flipY);\n }\n });\n }\n}\n","import { ChangeDetectionStrategy, Component, inject } from '@angular/core';\nimport { ImageEditorStateService } from '../../services/image-editor-state.service';\n\n/**\n * Action commands for the editor: history (undo / redo), reset, and a\n * read-only image-size badge. beta.3 ships these because they are\n * engine-level concerns the shell already exposes via the state\n * service — tool-specific buttons (crop, rotate, etc.) come in beta.4.\n *\n * The toolbar talks to the engine through the state service rather\n * than holding its own engine reference; that keeps it interchangeable\n * with whatever beta.4 wires up.\n */\n@Component({\n selector: 'coolms-image-editor-top-toolbar',\n standalone: true,\n changeDetection: ChangeDetectionStrategy.OnPush,\n templateUrl: './top-toolbar.component.html',\n styleUrls: ['./top-toolbar.component.scss'],\n})\nexport class TopToolbarComponent {\n protected readonly state = inject(ImageEditorStateService);\n\n async undo(): Promise<void> {\n const engine = this.state.engine();\n if (engine !== null) await engine.undo();\n }\n\n async redo(): Promise<void> {\n const engine = this.state.engine();\n if (engine !== null) await engine.redo();\n }\n\n async reset(): Promise<void> {\n // Goes through the state service's reset() rather than\n // calling engine.reset() directly so the active tool gets\n // closed and the viewport zoom snaps back to 100% in the\n // same action.\n await this.state.reset();\n }\n}\n","<div class=\"top-toolbar\">\n <div class=\"top-toolbar__group\">\n <button type=\"button\"\n class=\"top-toolbar__btn\"\n [disabled]=\"!state.canUndo()\"\n (click)=\"undo()\"\n title=\"Undo\">\n <i class=\"bi bi-arrow-counterclockwise\"></i>\n </button>\n <button type=\"button\"\n class=\"top-toolbar__btn\"\n [disabled]=\"!state.canRedo()\"\n (click)=\"redo()\"\n title=\"Redo\">\n <i class=\"bi bi-arrow-clockwise\"></i>\n </button>\n </div>\n\n <div class=\"top-toolbar__separator\"></div>\n\n <div class=\"top-toolbar__group\">\n <button type=\"button\"\n class=\"top-toolbar__btn\"\n [disabled]=\"!state.canUndo()\"\n (click)=\"reset()\"\n title=\"Reset all changes\">\n <i class=\"bi bi-arrow-counterclockwise\"></i>\n <span>Reset</span>\n </button>\n </div>\n\n <div class=\"top-toolbar__separator\"></div>\n\n <div class=\"top-toolbar__group\">\n <button type=\"button\"\n class=\"top-toolbar__btn\"\n [class.top-toolbar__btn--active]=\"state.handToolActive()\"\n [disabled]=\"!state.isReady()\"\n (click)=\"state.toggleHandTool()\"\n title=\"Hand tool — drag to pan the image\">\n <i class=\"bi bi-hand-index\"></i>\n </button>\n </div>\n\n <div class=\"top-toolbar__separator\"></div>\n\n <div class=\"top-toolbar__group\">\n <button type=\"button\"\n class=\"top-toolbar__btn\"\n [disabled]=\"!state.isReady()\"\n (click)=\"state.zoomOut()\"\n title=\"Zoom out\">\n <i class=\"bi bi-zoom-out\"></i>\n </button>\n <button type=\"button\"\n class=\"top-toolbar__btn top-toolbar__btn--zoom-display\"\n [disabled]=\"!state.isReady()\"\n (click)=\"state.resetZoom()\"\n title=\"Reset zoom to 100%\">\n {{ (state.currentZoom() * 100).toFixed(0) }}%\n </button>\n <button type=\"button\"\n class=\"top-toolbar__btn\"\n [disabled]=\"!state.isReady()\"\n (click)=\"state.zoomIn()\"\n title=\"Zoom in\">\n <i class=\"bi bi-zoom-in\"></i>\n </button>\n </div>\n\n <div class=\"top-toolbar__spacer\"></div>\n\n @if (state.canvasSize(); as size) {\n <div class=\"top-toolbar__info\">\n {{ size.width }} &times; {{ size.height }}\n </div>\n }\n</div>\n","import {\n ChangeDetectionStrategy, Component, ElementRef, HostBinding, HostListener,\n NgZone, OnDestroy, OnInit, ViewChild, effect, inject,\n} from '@angular/core';\nimport { ImageEditorStateService } from '../../services/image-editor-state.service';\n\n/**\n * Canvas container. The shell mounts the engine into the inner\n * `<div #container>` element via `getContainerElement()`; that\n * element is then owned by Toast UI's fabric.Canvas instance for the\n * lifetime of the editor.\n *\n * Three responsibilities live here:\n *\n * 1. **Loading / error overlays** — surface the lifecycle states\n * the state service publishes through `state.state()`.\n *\n * 2. **Fit-to-viewport zoom** — once the engine emits `imageLoaded`\n * (visible through `state.isReady()`), measure the container and\n * apply the engine's calculated fit zoom. A `ResizeObserver`\n * keeps the cached fit value fresh on container resize without\n * yanking the user out of a manually-set zoom; the next Reset /\n * \"%\" click picks up the updated value.\n *\n * 3. **Hand-tool pan** — when `state.handToolActive()` is true,\n * mouse-down + drag on the host element pans the engine viewport\n * via `engine.pan(dx, dy)`. mousemove / mouseup are bound to\n * `document` so a drag that escapes the host's bounds still\n * completes cleanly.\n */\n@Component({\n selector: 'coolms-image-editor-canvas-mount',\n standalone: true,\n changeDetection: ChangeDetectionStrategy.OnPush,\n templateUrl: './canvas-mount.component.html',\n styleUrls: ['./canvas-mount.component.scss'],\n})\nexport class CanvasMountComponent implements OnInit, OnDestroy {\n protected readonly state = inject(ImageEditorStateService);\n private readonly ngZone = inject(NgZone);\n\n @ViewChild('container', { static: true })\n private readonly containerRef!: ElementRef<HTMLDivElement>;\n\n /** Class-binding hooks for the cursor-state SCSS. */\n @HostBinding('class.canvas-mount-host--hand')\n protected get handCursor(): boolean { return this.state.handToolActive(); }\n\n @HostBinding('class.canvas-mount-host--panning')\n protected get panningCursor(): boolean { return this.isPanning; }\n\n private isPanning = false;\n private panStartX = 0;\n private panStartY = 0;\n private resizeObs?: ResizeObserver;\n /**\n * True after the first fit pass has run. Used to gate the\n * ResizeObserver below so it doesn't try to recompute fit before\n * any image has loaded.\n */\n private fitApplied = false;\n\n constructor() {\n // Apply fit-to-viewport zoom whenever the loaded image's\n // dimensions change. Fires on:\n // - initial load (canvasSize transitions from null to size)\n // - crop / resize replacement (adapter re-emits imageLoaded\n // and the state service updates canvasSize accordingly)\n // ResizeObserver below does NOT change canvasSize, so a\n // container-only resize uses `recalculateFitZoom` (cache\n // only, doesn't yank the user's manual zoom).\n effect(() => {\n const size = this.state.canvasSize();\n if (this.state.isReady() && size !== null) {\n const el = this.containerRef.nativeElement;\n const viewport = {\n width: el.clientWidth,\n height: el.clientHeight,\n };\n this.state.engine()?.setCanvasDimensions(viewport);\n this.state.applyFitZoom(viewport);\n this.fitApplied = true;\n }\n });\n\n // Drive fabric's cursor and selection state from the Hand\n // tool toggle. fabric owns these properties internally —\n // CSS `cursor: grab` on the host element doesn't reach the\n // canvas, and without disabling `selection` a drag on empty\n // canvas draws fabric's group-select rectangle instead of\n // panning. Re-runs whenever handToolActive flips, and also\n // when the engine first becomes available (`engine()` is a\n // tracked dependency).\n effect(() => {\n const engine = this.state.engine();\n const handActive = this.state.handToolActive();\n if (engine === null) return;\n if (handActive) {\n engine.setCursor('grab');\n engine.setSelectionEnabled(false);\n } else {\n engine.setCursor('default');\n engine.setSelectionEnabled(true);\n }\n });\n }\n\n ngOnInit(): void {\n if (typeof ResizeObserver === 'undefined') return;\n // Run outside Angular's zone so a continuous drag-resize\n // doesn't fire a change-detection cycle on every frame; we\n // explicitly re-enter the zone when calling the state\n // service so the fitZoom signal updates downstream consumers.\n this.ngZone.runOutsideAngular(() => {\n this.resizeObs = new ResizeObserver(() => {\n if (!this.fitApplied) return;\n const el = this.containerRef.nativeElement;\n const viewport = {\n width: el.clientWidth,\n height: el.clientHeight,\n };\n // Fabric adapter owns canvas dimensions; resize the\n // backstore so viewport zoom stays the only scale knob.\n // Toast UI adapter's setCanvasDimensions is a no-op,\n // so this call is safe to make unconditionally.\n this.state.engine()?.setCanvasDimensions(viewport);\n this.ngZone.run(() => {\n this.state.recalculateFitZoom(viewport);\n });\n });\n this.resizeObs.observe(this.containerRef.nativeElement);\n });\n }\n\n ngOnDestroy(): void {\n this.resizeObs?.disconnect();\n }\n\n getContainerElement(): HTMLElement {\n return this.containerRef.nativeElement;\n }\n\n /**\n * Force a re-fit pass after an intentional container-size change\n * (e.g. dialog host's fullscreen toggle). Different from the\n * ResizeObserver path which preserves the user's manual zoom on\n * casual resizes — refit() unconditionally re-syncs canvas\n * dimensions and resets the viewport so the image stays centred\n * in the new viewport.\n *\n * Order matters: setCanvasDimensions resizes the backstore and\n * re-centers the image OBJECT to (canvas.w/2, canvas.h/2);\n * resetZoom collapses the viewport transform to identity (no\n * leftover pan from before the size change); then setZoom uses\n * `zoomToPoint(canvas_center, fit)` which keeps the (now\n * canvas-centred) image at the visible centre.\n */\n refit(): void {\n const el = this.containerRef.nativeElement;\n const viewport = { width: el.clientWidth, height: el.clientHeight };\n if (viewport.width === 0 || viewport.height === 0) return;\n const engine = this.state.engine();\n if (engine === null) return;\n engine.setCanvasDimensions(viewport);\n engine.resetZoom();\n this.state.applyFitZoom(viewport);\n }\n\n @HostListener('mousedown', ['$event'])\n onMouseDown(event: MouseEvent): void {\n if (!this.state.handToolActive()) return;\n const engine = this.state.engine();\n if (engine === null) return;\n // Swap to the closed-hand \"active drag\" cursor for the\n // duration of the gesture; reverts to grab on mouseup\n // (still in Hand mode) or default (Hand deactivated).\n engine.setCursor('grabbing');\n this.isPanning = true;\n this.panStartX = event.clientX;\n this.panStartY = event.clientY;\n // Suppress text-selection drag and the engine's own\n // mouse-down handlers; we own this gesture.\n event.preventDefault();\n }\n\n @HostListener('document:mousemove', ['$event'])\n onMouseMove(event: MouseEvent): void {\n if (!this.isPanning) return;\n const engine = this.state.engine();\n if (engine === null) return;\n\n const dx = event.clientX - this.panStartX;\n const dy = event.clientY - this.panStartY;\n // relativePan accumulates from the previous viewport\n // transform, so we feed it the per-frame delta and reset\n // the start position for the next frame.\n engine.pan(dx, dy);\n this.panStartX = event.clientX;\n this.panStartY = event.clientY;\n }\n\n @HostListener('document:mouseup')\n onMouseUp(): void {\n if (!this.isPanning) return;\n this.isPanning = false;\n const engine = this.state.engine();\n if (engine === null) return;\n // Back to grab cursor while Hand is still active. The\n // separate handToolActive effect covers the case where the\n // user toggles Hand off mid-gesture (rare but possible via\n // keyboard) — it'll reset to default on the next tick.\n if (this.state.handToolActive()) {\n engine.setCursor('grab');\n }\n }\n\n /**\n * Ctrl/Cmd + wheel zooms the viewport, matching the convention\n * used by Photoshop, Affinity, Figma, and every other desktop\n * image editor. Plain wheel without the modifier still scrolls\n * the page (the parent dialog isn't scrollable today, but the\n * editor may live inline elsewhere later, and stealing the wheel\n * unconditionally would surprise users in those embeddings).\n *\n * Mac trackpad pinch arrives as a wheel event with `ctrlKey:\n * true` set by the browser, so the same handler covers both\n * gestures with no extra code.\n *\n * Step factor of 1.1 per tick gives a smooth ~10% step that\n * matches what most editors use. The state service clamps to\n * [0.05, 10] so we don't need to clamp here. Anchor stays at\n * canvas centre (engine.setZoom centres on the backstore\n * midpoint); zoom-to-cursor is a known follow-up.\n */\n @HostListener('wheel', ['$event'])\n onWheel(event: WheelEvent): void {\n if (!event.ctrlKey && !event.metaKey) return;\n event.preventDefault();\n const factor = event.deltaY < 0 ? 1.1 : 1 / 1.1;\n const target = this.state.currentZoom() * factor;\n this.state.setZoom(target);\n }\n}\n","<div class=\"canvas-mount\">\n @if (state.state() === 'loading') {\n <div class=\"canvas-mount__overlay\">\n <span>Loading image&hellip;</span>\n </div>\n }\n @if (state.state() === 'error') {\n <div class=\"canvas-mount__overlay canvas-mount__overlay--error\">\n <i class=\"bi bi-exclamation-triangle\"></i>\n <span>{{ state.errorMessage() ?? 'Editor failed to load' }}</span>\n </div>\n }\n\n <div #container class=\"canvas-mount__container\"></div>\n</div>\n","import { Injectable, computed, signal } from '@angular/core';\nimport type { ToolMetadata, ToolCategory } from './tool.types';\n\n/**\n * Registry of image-editor tools.\n *\n * Tools register themselves via the shell's constructor (beta.4a) so the\n * service can stay agnostic of which tools ship in any given build —\n * the same registry plays host to beta.4a's transform tools, beta.4b's\n * filter sliders, and beta.4c's resize / zoom without further changes.\n *\n * Provided in `root` so the registry is shared across any future\n * shell instances (e.g., two editors open in different dialogs). The\n * `ImageEditorStateService` it complements is component-scoped — that\n * one tracks per-editor active tool, this one tracks the global\n * catalogue of available tools.\n *\n * Re-registering an id replaces the existing entry: this lets a host\n * swap a tool's component for testing without unwiring the rest.\n */\n@Injectable({ providedIn: 'root' })\nexport class ToolRegistryService {\n private readonly toolsMap = signal<ReadonlyMap<string, ToolMetadata>>(new Map());\n\n readonly tools = computed(() => Array.from(this.toolsMap().values()));\n\n register(tool: ToolMetadata): void {\n this.toolsMap.update(map => {\n const next = new Map(map);\n next.set(tool.id, tool);\n return next;\n });\n }\n\n get(id: string): ToolMetadata | undefined {\n return this.toolsMap().get(id);\n }\n\n byCategory(category: ToolCategory): ToolMetadata[] {\n return this.tools().filter(t => t.category === category);\n }\n}\n","import {\n ChangeDetectionStrategy, Component, computed, inject,\n} from '@angular/core';\nimport { NgComponentOutlet } from '@angular/common';\nimport { ImageEditorStateService } from '../../services/image-editor-state.service';\nimport { ToolRegistryService } from '../../tools/tool-registry.service';\nimport type { ToolMetadata } from '../../tools/tool.types';\n\n/**\n * Tool-picker pane.\n *\n * Renders the registered tools grouped by category (beta.4a ships only\n * the `transform` group). The active tool's properties component is\n * mounted into the lower slot via `NgComponentOutlet` — that\n * component's lifecycle (`ngOnInit` / `ngOnDestroy`) drives the\n * tool's activation hooks, so the sidebar stays a dumb shell.\n *\n * The tool catalogue is rendered ahead-of-mount; buttons are\n * disabled until `state.isReady()` to prevent users from clicking\n * Crop while the engine is still loading the image.\n */\n@Component({\n selector: 'coolms-image-editor-right-sidebar',\n standalone: true,\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [NgComponentOutlet],\n templateUrl: './right-sidebar.component.html',\n styleUrls: ['./right-sidebar.component.scss'],\n})\nexport class RightSidebarComponent {\n protected readonly state = inject(ImageEditorStateService);\n protected readonly registry = inject(ToolRegistryService);\n\n /** Tools to surface in the Transform section. */\n protected readonly transformTools = computed<ToolMetadata[]>(\n () => this.registry.byCategory('transform'),\n );\n\n /** Tools to surface in the Filters section (beta.4b). */\n protected readonly filterTools = computed<ToolMetadata[]>(\n () => this.registry.byCategory('filter'),\n );\n\n /** Insert tools — shapes / text (C.1). */\n protected readonly insertTools = computed<ToolMetadata[]>(\n () => this.registry.byCategory('insert'),\n );\n\n /** Layers panel entry (C.1). */\n protected readonly layersTools = computed<ToolMetadata[]>(\n () => this.registry.byCategory('layers'),\n );\n\n /** Metadata of the currently-active tool, or `null` if none. */\n protected readonly activeTool = computed<ToolMetadata | null>(() => {\n const id = this.state.activeTool();\n if (id === null) return null;\n return this.registry.get(id) ?? null;\n });\n\n selectTool(id: string): void {\n // Re-clicking an already-active tool deactivates it; matches the\n // common UX of \"click the icon again to close the panel\".\n if (this.state.activeTool() === id) {\n this.state.setActiveTool(null);\n return;\n }\n this.state.setActiveTool(id);\n }\n\n deactivateTool(): void {\n this.state.setActiveTool(null);\n }\n\n isActive(id: string): boolean {\n return this.state.activeTool() === id;\n }\n}\n","<aside class=\"right-sidebar\">\n <header class=\"right-sidebar__header\">\n <h3 class=\"right-sidebar__title\">Tools</h3>\n </header>\n\n <div class=\"right-sidebar__tools\">\n @if (transformTools().length > 0) {\n <section class=\"tool-category\">\n <h4 class=\"tool-category__label\">Transform</h4>\n <div class=\"tool-category__buttons\">\n @for (tool of transformTools(); track tool.id) {\n <button type=\"button\"\n class=\"tool-button\"\n [class.tool-button--active]=\"isActive(tool.id)\"\n [disabled]=\"!state.isReady()\"\n [title]=\"tool.label\"\n (click)=\"selectTool(tool.id)\">\n <i class=\"bi\" [class]=\"tool.icon\"></i>\n <span class=\"tool-button__label\">{{ tool.label }}</span>\n </button>\n }\n </div>\n </section>\n }\n\n @if (insertTools().length > 0) {\n <section class=\"tool-category\">\n <h4 class=\"tool-category__label\">Insert</h4>\n <div class=\"tool-category__buttons\">\n @for (tool of insertTools(); track tool.id) {\n <button type=\"button\"\n class=\"tool-button\"\n [class.tool-button--active]=\"isActive(tool.id)\"\n [disabled]=\"!state.isReady()\"\n [title]=\"tool.label\"\n (click)=\"selectTool(tool.id)\">\n <i class=\"bi\" [class]=\"tool.icon\"></i>\n <span class=\"tool-button__label\">{{ tool.label }}</span>\n </button>\n }\n </div>\n </section>\n }\n\n @if (filterTools().length > 0) {\n <section class=\"tool-category\">\n <h4 class=\"tool-category__label\">Filters</h4>\n <div class=\"tool-category__buttons\">\n @for (tool of filterTools(); track tool.id) {\n <button type=\"button\"\n class=\"tool-button\"\n [class.tool-button--active]=\"isActive(tool.id)\"\n [disabled]=\"!state.isReady()\"\n [title]=\"tool.label\"\n (click)=\"selectTool(tool.id)\">\n <i class=\"bi\" [class]=\"tool.icon\"></i>\n <span class=\"tool-button__label\">{{ tool.label }}</span>\n </button>\n }\n </div>\n </section>\n }\n\n @if (layersTools().length > 0) {\n <section class=\"tool-category\">\n <h4 class=\"tool-category__label\">Layers</h4>\n <div class=\"tool-category__buttons\">\n @for (tool of layersTools(); track tool.id) {\n <button type=\"button\"\n class=\"tool-button\"\n [class.tool-button--active]=\"isActive(tool.id)\"\n [disabled]=\"!state.isReady()\"\n [title]=\"tool.label\"\n (click)=\"selectTool(tool.id)\">\n <i class=\"bi\" [class]=\"tool.icon\"></i>\n <span class=\"tool-button__label\">{{ tool.label }}</span>\n </button>\n }\n </div>\n </section>\n }\n </div>\n\n @if (activeTool(); as active) {\n <div class=\"right-sidebar__properties\">\n <header class=\"properties-header\">\n <h4 class=\"properties-header__title\">{{ active.label }}</h4>\n <button type=\"button\"\n class=\"properties-header__close\"\n aria-label=\"Close tool\"\n (click)=\"deactivateTool()\">\n <i class=\"bi bi-x-lg\"></i>\n </button>\n </header>\n <div class=\"properties-body\">\n <ng-container *ngComponentOutlet=\"active.component; inputs: active.inputs\"></ng-container>\n </div>\n </div>\n }\n</aside>\n","import {\n ChangeDetectionStrategy, Component, OnDestroy, OnInit, inject, signal,\n} from '@angular/core';\n\nimport { ImageEditorStateService } from '../../services/image-editor-state.service';\nimport type { ImageEditorTool } from '../tool.types';\n\ninterface AspectPreset {\n readonly id: string;\n readonly label: string;\n /** width / height. `null` means free-form (user drags any rectangle). */\n readonly ratio: number | null;\n}\n\n/**\n * Properties panel for the Crop tool. Toast UI's interactive cropper\n * does the actual cropzone rendering and drag handling on the canvas;\n * this panel only:\n *\n * - Enters / exits crop mode through the engine adapter (lifecycle\n * hooks). NgComponentOutlet's create / destroy maps to those.\n * - Lets the user pick an aspect-ratio preset. Picking one calls\n * `setCropAspectRatio(ratio)` on the engine, which programmatically\n * replaces the current cropzone with a centred one at the chosen\n * ratio and locks subsequent user resizes to that ratio.\n * - Reads the user's final cropzone via `getCropRect()` on Apply\n * and feeds it into `engine.crop(rect)`.\n *\n * Live dimension display is intentionally absent: Toast UI does not\n * fire `objectModified` for the cropzone (the source skips it\n * explicitly), so there's no public event to drive a reactive label.\n * The user sees the cropzone size visually on the canvas while\n * dragging, which is the expected feedback channel.\n */\n@Component({\n selector: 'coolms-image-editor-crop-tool',\n standalone: true,\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [],\n templateUrl: './crop-tool.component.html',\n styleUrls: ['./crop-tool.component.scss'],\n})\nexport class CropToolComponent implements OnInit, OnDestroy, ImageEditorTool {\n private readonly state = inject(ImageEditorStateService);\n\n /** Aspect-ratio presets surfaced as buttons in the panel. */\n protected readonly presets: readonly AspectPreset[] = [\n { id: 'free', label: 'Free', ratio: null },\n { id: '1-1', label: '1 : 1', ratio: 1 },\n { id: '4-3', label: '4 : 3', ratio: 4 / 3 },\n { id: '16-9', label: '16 : 9', ratio: 16 / 9 },\n { id: '3-2', label: '3 : 2', ratio: 3 / 2 },\n ];\n\n readonly activePresetId = signal<string>('free');\n\n /** Live message shown above the action row for context cues. */\n readonly statusMessage = signal<string>('Drag inside the canvas to draw a crop area, or pick an aspect ratio.');\n\n ngOnInit(): void { void this.onActivate(); }\n ngOnDestroy(): void { void this.onDeactivate(); }\n\n async onActivate(): Promise<void> {\n const engine = this.state.engine();\n if (engine === null) return;\n await engine.enterCropMode();\n }\n\n async onDeactivate(): Promise<void> {\n const engine = this.state.engine();\n if (engine === null) return;\n await engine.exitCropMode();\n }\n\n selectPreset(preset: AspectPreset): void {\n const engine = this.state.engine();\n if (engine === null) return;\n engine.setCropAspectRatio(preset.ratio);\n this.activePresetId.set(preset.id);\n this.statusMessage.set(\n preset.ratio === null\n ? 'Cropzone reset. Drag the canvas to draw freely.'\n : `Locked to ${preset.label}. Drag the cropzone to reposition.`,\n );\n }\n\n async applyCrop(): Promise<void> {\n const engine = this.state.engine();\n if (engine === null) return;\n\n const rect = engine.getCropRect();\n if (rect === null || rect.width <= 0 || rect.height <= 0) {\n // The user opened crop and clicked Apply without ever\n // drawing a cropzone. Nudge them rather than no-op silently.\n this.statusMessage.set('Draw a cropzone on the canvas first.');\n return;\n }\n\n await engine.crop(rect);\n // Deactivating clears `activeTool` which destroys this\n // component; `ngOnDestroy` then calls `exitCropMode()`.\n this.state.setActiveTool(null);\n }\n\n cancelCrop(): void {\n this.state.setActiveTool(null);\n }\n}\n","<div class=\"crop-tool\">\n <p class=\"crop-tool__status\">{{ statusMessage() }}</p>\n\n <div class=\"crop-tool__section\">\n <h5 class=\"crop-tool__heading\">Aspect ratio</h5>\n <div class=\"crop-tool__presets\">\n @for (preset of presets; track preset.id) {\n <button type=\"button\"\n class=\"crop-tool__preset\"\n [class.crop-tool__preset--active]=\"activePresetId() === preset.id\"\n (click)=\"selectPreset(preset)\">\n {{ preset.label }}\n </button>\n }\n </div>\n </div>\n\n <div class=\"crop-tool__actions\">\n <button type=\"button\" class=\"cms-btn\" (click)=\"cancelCrop()\">Cancel</button>\n <button type=\"button\" class=\"cms-btn cms-btn-primary\" (click)=\"applyCrop()\">Apply</button>\n </div>\n</div>\n","import {\n ChangeDetectionStrategy, Component, OnDestroy,\n computed, effect, inject, signal,\n} from '@angular/core';\n\nimport { ImageEditorStateService } from '../../services/image-editor-state.service';\n\n/**\n * Properties panel for the Rotate tool.\n *\n * Two interaction modes side-by-side:\n *\n * - **Quick presets** (90° CCW, 90° CW, 180°). Each button calls\n * `engine.rotate(degrees)` immediately (relative rotation), which\n * pushes a single command. Pressing 90° CW four times returns to\n * the original orientation, with four entries in the undo stack.\n *\n * - **Free rotation slider** (-180..+180 in 1° steps). The slider's\n * value is bound to the live image angle (`state.imageRotation`)\n * so it stays in sync with mouse-driven rotations on the canvas.\n * During a drag we use the same preview / commit cycle the\n * filter sliders use: each input event undoes the previous\n * preview and applies a fresh rotation from the captured\n * baseline, so the undo stack ends up with one entry per drag\n * session rather than one per pixel of slider movement.\n * `clearRedoStack` on release drops the phantom redo entries\n * left behind by the undo cycles.\n */\n@Component({\n selector: 'coolms-image-editor-rotate-tool',\n standalone: true,\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [],\n templateUrl: './rotate-tool.component.html',\n styleUrls: ['./rotate-tool.component.scss'],\n})\nexport class RotateToolComponent implements OnDestroy {\n private readonly state = inject(ImageEditorStateService);\n\n /**\n * Angle the slider currently displays. Mirrors\n * `state.imageRotation()` while the user isn't actively dragging.\n * During a drag, the user's input value wins so a programmatic\n * mid-drag state change (from the preview cycle's undo step) doesn't\n * yank the slider thumb away from the user's finger.\n */\n readonly displayAngle = signal<number>(0);\n\n /** Whether the user is currently dragging the slider. */\n readonly dragging = signal<boolean>(false);\n\n /** True while a preview rotation is currently applied to the engine. */\n private readonly previewActive = signal<boolean>(false);\n\n /**\n * Image angle captured at the start of the current drag session.\n * Each preview applies `target - baseline` so successive previews\n * compose correctly even after the intermediate undo. Reset to\n * `null` between drag sessions.\n */\n private dragBaselineAngle: number | null = null;\n\n readonly currentDisplayAngle = computed(() => Math.round(this.displayAngle() * 10) / 10);\n\n constructor() {\n effect(() => {\n // Pull state into the slider when no drag is in progress.\n // During a drag the user's input is authoritative; once\n // they release, the next state emission re-syncs us. Reads\n // the transform target (selected layer, else the base\n // image) so the slider rotates whatever's selected (C.1c).\n if (!this.dragging()) {\n this.displayAngle.set(this.state.transformTargetRotation());\n }\n });\n }\n\n ngOnDestroy(): void {\n // Tool dismissed while still mid-drag (rare): commit cleanly so\n // the undo stack lands in a sane shape. The last preview stays\n // as the committed entry; phantom redo entries get cleared.\n if (this.dragging()) this.commitDrag();\n }\n\n async rotatePreset(degrees: number): Promise<void> {\n const engine = this.state.engine();\n if (engine === null) return;\n // A preset click while the user is mid-drag would stack a\n // standalone preset command on top of the in-flight preview\n // entry. Cancel any active drag session first so the engine\n // sees a clean state.\n if (this.dragging()) this.commitDrag();\n await engine.rotate(degrees);\n }\n\n async onSliderInput(value: number): Promise<void> {\n const engine = this.state.engine();\n if (engine === null) return;\n\n if (!this.dragging()) {\n this.dragging.set(true);\n this.dragBaselineAngle = this.state.transformTargetRotation();\n }\n this.displayAngle.set(value);\n\n if (this.previewActive()) {\n await engine.undo();\n this.previewActive.set(false);\n }\n\n const baseline = this.dragBaselineAngle ?? 0;\n const delta = value - baseline;\n if (Math.abs(delta) < 0.01) return;\n\n await engine.rotate(delta);\n this.previewActive.set(true);\n }\n\n onSliderChange(): void {\n if (this.dragging()) this.commitDrag();\n }\n\n closeTool(): void {\n if (this.dragging()) this.commitDrag();\n this.state.setActiveTool(null);\n }\n\n private commitDrag(): void {\n const engine = this.state.engine();\n engine?.clearRedoStack();\n this.dragging.set(false);\n this.previewActive.set(false);\n this.dragBaselineAngle = null;\n }\n}\n","<div class=\"rotate-tool\">\n <div class=\"rotate-tool__section\">\n <h5 class=\"rotate-tool__heading\">Quick rotate</h5>\n <div class=\"rotate-tool__presets\">\n <button type=\"button\"\n class=\"cms-btn\"\n title=\"Rotate 90° counter-clockwise\"\n (click)=\"rotatePreset(-90)\">\n <i class=\"bi bi-arrow-counterclockwise\"></i>\n <span>90&deg; CCW</span>\n </button>\n <button type=\"button\"\n class=\"cms-btn\"\n title=\"Rotate 90° clockwise\"\n (click)=\"rotatePreset(90)\">\n <i class=\"bi bi-arrow-clockwise\"></i>\n <span>90&deg; CW</span>\n </button>\n <button type=\"button\"\n class=\"cms-btn\"\n title=\"Rotate 180°\"\n (click)=\"rotatePreset(180)\">\n <i class=\"bi bi-arrow-repeat\"></i>\n <span>180&deg;</span>\n </button>\n </div>\n </div>\n\n <div class=\"rotate-tool__separator\"></div>\n\n <div class=\"rotate-tool__section\">\n <h5 class=\"rotate-tool__heading\">Free rotation</h5>\n <div class=\"rotate-tool__slider-row\">\n <input type=\"range\"\n class=\"rotate-tool__slider\"\n min=\"-180\" max=\"180\" step=\"1\"\n [value]=\"displayAngle()\"\n (input)=\"onSliderInput($any($event.target).valueAsNumber)\"\n (change)=\"onSliderChange()\">\n <code class=\"rotate-tool__angle\">{{ currentDisplayAngle() }}&deg;</code>\n </div>\n\n <div class=\"rotate-tool__actions\">\n <button type=\"button\"\n class=\"cms-btn\"\n (click)=\"closeTool()\">Close</button>\n </div>\n </div>\n</div>\n","import {\n ChangeDetectionStrategy, Component, inject, signal,\n} from '@angular/core';\n\nimport { ImageEditorStateService } from '../../services/image-editor-state.service';\n\n/**\n * Properties panel for the Flip tool. Stateless on commit — each\n * click flips the canvas immediately, no Apply / Cancel.\n *\n * The visual `--active` state on each button is local to the tool's\n * lifetime: when the user closes the tool and reopens it, both\n * indicators reset even if the canvas is currently flipped. Toast\n * UI doesn't expose a public getter for the canvas's flip state, so\n * tracking it across tool re-opens would require burrowing into\n * private fabric.js state — not worth the fragility for an\n * indicator. The actual canvas pixels are the source of truth; the\n * undo stack reverses any flip if the user wants to back out.\n */\n@Component({\n selector: 'coolms-image-editor-flip-tool',\n standalone: true,\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [],\n templateUrl: './flip-tool.component.html',\n styleUrls: ['./flip-tool.component.scss'],\n})\nexport class FlipToolComponent {\n private readonly state = inject(ImageEditorStateService);\n\n // Bound to the transform target's flip state (selected layer, else\n // the base image — C.1c) so the button highlight tracks any path\n // that mutates flipX/flipY: this tool's buttons, a mouse rotation\n // that crosses 180°, an undo/redo, or a flip via another tool.\n readonly flippedH = this.state.transformTargetFlipX;\n readonly flippedV = this.state.transformTargetFlipY;\n\n async toggleHorizontal(): Promise<void> {\n const engine = this.state.engine();\n if (engine === null) return;\n await engine.flip('horizontal');\n }\n\n async toggleVertical(): Promise<void> {\n const engine = this.state.engine();\n if (engine === null) return;\n await engine.flip('vertical');\n }\n\n closeTool(): void {\n this.state.setActiveTool(null);\n }\n}\n","<div class=\"flip-tool\">\n <p class=\"flip-tool__hint\">\n Click a direction to flip the image. Click again to flip back.\n </p>\n\n <div class=\"flip-tool__buttons\">\n <button type=\"button\"\n class=\"flip-tool__btn\"\n [class.flip-tool__btn--active]=\"flippedH()\"\n title=\"Flip horizontally\"\n (click)=\"toggleHorizontal()\">\n <i class=\"bi bi-symmetry-horizontal\"></i>\n <span>Horizontal</span>\n @if (flippedH()) {\n <i class=\"bi bi-check-lg flip-tool__check\"></i>\n }\n </button>\n\n <button type=\"button\"\n class=\"flip-tool__btn\"\n [class.flip-tool__btn--active]=\"flippedV()\"\n title=\"Flip vertically\"\n (click)=\"toggleVertical()\">\n <i class=\"bi bi-symmetry-vertical\"></i>\n <span>Vertical</span>\n @if (flippedV()) {\n <i class=\"bi bi-check-lg flip-tool__check\"></i>\n }\n </button>\n </div>\n\n <div class=\"flip-tool__actions\">\n <button type=\"button\" class=\"cms-btn\" (click)=\"closeTool()\">Close</button>\n </div>\n</div>\n","import {\n ChangeDetectionStrategy, Component, computed, effect, inject, signal,\n} from '@angular/core';\n\nimport { ImageEditorStateService } from '../../services/image-editor-state.service';\nimport type { ImageEditorTool } from '../tool.types';\nimport type { Size } from '../../types/geometry.types';\n\n/**\n * Properties panel for the Resize tool.\n *\n * Commit-style — no live preview. Live-resizing the canvas on every\n * keystroke would jank the editor, particularly for large images\n * where each resize is a full image-data rewrite. The user changes\n * the numeric fields, optionally toggles the aspect lock, then\n * commits with Apply.\n *\n * Aspect lock — captured against the original (pre-tool) dimensions\n * rather than the current input values so that toggling the lock\n * after free-form edits doesn't snap to a freshly-distorted ratio.\n * When width changes with the lock on, height auto-fills to\n * preserve the original ratio (and vice versa).\n *\n * The Apply path goes through `engine.resize(size)`, which the\n * fabric adapter implements as a bake-and-reload: the current image\n * (with rotation, flip, filters all applied) is rendered to a\n * temp canvas at the target dimensions and reloaded as a fresh\n * FabricImage. Single undo entry, exported bytes match the new\n * dimensions.\n */\n@Component({\n selector: 'coolms-image-editor-resize-tool',\n standalone: true,\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [],\n templateUrl: './resize-tool.component.html',\n styleUrls: ['./resize-tool.component.scss'],\n})\nexport class ResizeToolComponent implements ImageEditorTool {\n private readonly state = inject(ImageEditorStateService);\n\n readonly targetWidth = signal<number>(0);\n readonly targetHeight = signal<number>(0);\n readonly aspectLocked = signal<boolean>(true);\n\n /**\n * Set to `true` the moment the user types or steps a value in\n * either input. While dirty, the live-sync effect below stops\n * overwriting the user's typed numbers from state. Reset and\n * Apply clear it so the next mouse drag flows back into the\n * inputs.\n */\n private readonly userDirty = signal<boolean>(false);\n\n /** Live image dimensions in canvas-coords (natural × |scale|). */\n private readonly liveSize = computed<Size>(() => {\n const size = this.state.canvasSize();\n if (size === null) return { width: 0, height: 0 };\n const scaleX = Math.abs(this.state.imageScaleX());\n const scaleY = Math.abs(this.state.imageScaleY());\n return {\n width: Math.max(1, Math.round(size.width * scaleX)),\n height: Math.max(1, Math.round(size.height * scaleY)),\n };\n });\n\n /**\n * Aspect-ratio baseline for the lock. Pinned to the live image\n * dimensions while the user hasn't edited the inputs, captured\n * to a snapshot the moment they do, so a mid-edit width change\n * with the lock on doesn't snap to a freshly-distorted ratio.\n */\n private readonly aspectBaseline = signal<{ width: number; height: number }>({ width: 0, height: 0 });\n\n private readonly originalAspect = computed(() => {\n const a = this.aspectBaseline();\n return a.height > 0 ? a.width / a.height : 1;\n });\n\n readonly isDirty = computed(() => {\n const live = this.liveSize();\n return this.targetWidth() !== live.width || this.targetHeight() !== live.height;\n });\n\n readonly canApply = computed(() =>\n this.isDirty()\n && this.targetWidth() > 0\n && this.targetHeight() > 0\n && this.state.isReady(),\n );\n\n /**\n * Display value the template binds for \"Original: WxH\". Also\n * pinned to the live image dimensions when the user hasn't\n * touched the inputs; once they have, it freezes at the size\n * captured at first edit so the user has a stable reference\n * while typing.\n */\n readonly originalView = this.aspectBaseline.asReadonly();\n\n constructor() {\n // Live-sync the inputs to the visually-current image\n // dimensions. Picks up:\n // - the initial dimensions when the tool first opens\n // (ngOnInit equivalent now folded in here)\n // - mouse-driven scale changes from corner-handle drags\n // - undo / redo of any prior resize / scale operation\n // Stops overwriting once the user has typed a value, so the\n // sync doesn't fight the editor.\n effect(() => {\n const live = this.liveSize();\n if (live.width === 0 || live.height === 0) return;\n if (this.userDirty()) return;\n this.aspectBaseline.set(live);\n this.targetWidth.set(live.width);\n this.targetHeight.set(live.height);\n });\n }\n\n onActivate(): void { /* live-sync handled by the effect */ }\n onDeactivate(): void { /* nothing to clean up */ }\n\n onWidthChange(value: number): void {\n const valid = Math.max(1, Math.round(value));\n if (!this.userDirty()) this.aspectBaseline.set(this.liveSize());\n this.userDirty.set(true);\n this.targetWidth.set(valid);\n if (this.aspectLocked()) {\n this.targetHeight.set(Math.max(1, Math.round(valid / this.originalAspect())));\n }\n }\n\n onHeightChange(value: number): void {\n const valid = Math.max(1, Math.round(value));\n if (!this.userDirty()) this.aspectBaseline.set(this.liveSize());\n this.userDirty.set(true);\n this.targetHeight.set(valid);\n if (this.aspectLocked()) {\n this.targetWidth.set(Math.max(1, Math.round(valid * this.originalAspect())));\n }\n }\n\n toggleAspectLock(): void { this.aspectLocked.update(v => !v); }\n\n reset(): void {\n // Drop the dirty flag so the live-sync effect repopulates\n // the inputs from the current image state on the next tick.\n this.userDirty.set(false);\n const live = this.liveSize();\n this.aspectBaseline.set(live);\n this.targetWidth.set(live.width);\n this.targetHeight.set(live.height);\n }\n\n async applyResize(): Promise<void> {\n const engine = this.state.engine();\n if (engine === null || !this.canApply()) return;\n\n const newSize: Size = {\n width: this.targetWidth(),\n height: this.targetHeight(),\n };\n await engine.resize(newSize);\n // Refresh the cached canvas size so any subsequent tool\n // (or this tool re-opened) sees the new baseline.\n this.state.updateCanvasSize(newSize);\n // Clear the dirty flag so a re-open of the tool sees the\n // freshly resized image's dimensions through the live sync\n // rather than the stale values we just typed.\n this.userDirty.set(false);\n this.state.setActiveTool(null);\n }\n\n cancel(): void { this.state.setActiveTool(null); }\n}\n","<div class=\"resize-tool\">\n <div class=\"resize-tool__field\">\n <label class=\"resize-tool__label\" for=\"resize-width\">Width</label>\n <div class=\"resize-tool__input-row\">\n <input id=\"resize-width\"\n type=\"number\"\n class=\"resize-tool__input\"\n min=\"1\"\n [value]=\"targetWidth()\"\n (change)=\"onWidthChange($any($event.target).valueAsNumber)\">\n <span class=\"resize-tool__unit\">px</span>\n </div>\n </div>\n\n <button type=\"button\"\n class=\"resize-tool__lock\"\n [class.resize-tool__lock--active]=\"aspectLocked()\"\n [title]=\"aspectLocked() ? 'Aspect ratio locked' : 'Aspect ratio unlocked'\"\n (click)=\"toggleAspectLock()\">\n <i class=\"bi\" [class]=\"aspectLocked() ? 'bi-link-45deg' : 'bi-unlock'\"></i>\n <span class=\"resize-tool__lock-label\">{{ aspectLocked() ? 'Locked' : 'Free' }}</span>\n </button>\n\n <div class=\"resize-tool__field\">\n <label class=\"resize-tool__label\" for=\"resize-height\">Height</label>\n <div class=\"resize-tool__input-row\">\n <input id=\"resize-height\"\n type=\"number\"\n class=\"resize-tool__input\"\n min=\"1\"\n [value]=\"targetHeight()\"\n (change)=\"onHeightChange($any($event.target).valueAsNumber)\">\n <span class=\"resize-tool__unit\">px</span>\n </div>\n </div>\n\n <p class=\"resize-tool__info\">\n Original: {{ originalView().width }} &times; {{ originalView().height }} px\n </p>\n\n <div class=\"resize-tool__actions\">\n <button type=\"button\"\n class=\"cms-btn\"\n title=\"Reset to original size\"\n [disabled]=\"!isDirty()\"\n (click)=\"reset()\">\n <i class=\"bi bi-arrow-counterclockwise\"></i>\n <span>Reset</span>\n </button>\n <button type=\"button\"\n class=\"cms-btn\"\n (click)=\"cancel()\">Cancel</button>\n <button type=\"button\"\n class=\"cms-btn cms-btn-primary\"\n [disabled]=\"!canApply()\"\n (click)=\"applyResize()\">Apply</button>\n </div>\n</div>\n","/**\n * SVG -> clip-path geometry extraction for custom masks (C.1d).\n *\n * Accepts either a bare SVG path `d` string or a full SVG document\n * (pasted markup or the text of an uploaded `.svg` file) and returns a\n * single combined path `d` string the engine can hand to fabric's\n * `new Path(d)` as a clipPath — or a user-facing error message.\n *\n * Security model: the output is ALWAYS pure path geometry, consumed only\n * by `new Path(d)` and NEVER injected as HTML, so no `<script>`, event\n * handler, or external reference (`<image href>`, `<use href>`) can\n * survive into anything executable — they're simply never read. We also\n * parse with `DOMParser` into a detached `image/svg+xml` document, which\n * neither executes scripts nor fetches external resources. As an\n * explicit up-front signal we still reject markup that carries scripts,\n * `<foreignObject>`, or inline `on*` handlers.\n *\n * Every drawable element (path / rect / circle / ellipse / polygon /\n * polyline) is flattened to path commands and concatenated; everything\n * else is ignored (\"paths only\"). Per-element `transform` attributes and\n * non-geometry elements are NOT applied — flatten transforms in your\n * source SVG first if a mask looks off. Fabric-free and Angular-free so\n * it stays trivially unit-testable and keeps the engine firewall intact.\n *\n * This file imports nothing — it relies only on browser DOM APIs.\n */\n\n/** ~200 KB — generous for \"a small SVG file\", a guard against pathological input. */\nconst MAX_INPUT_LENGTH = 200_000;\n\n/**\n * Characters legal in SVG path `d` data: the command letters, digits,\n * sign / decimal / exponent, and separators. Anything outside this set\n * (notably `<`, `>`, `(`, `)`, quotes) is rejected — a defensive second\n * gate on top of \"we only ever feed this to `new Path`\".\n */\nconst PATH_D_CHARS = /^[\\sMmLlHhVvCcSsQqTtAaZz0-9eE.,+-]+$/;\n\n/** A usable path must contain at least one move command. */\nconst HAS_MOVE = /[Mm]/;\n\nexport type SvgMaskExtraction =\n | { readonly ok: true; readonly d: string }\n | { readonly ok: false; readonly error: string };\n\n/** Narrowing guard for the error arm of {@link extractSvgMaskPath}. */\nexport function isSvgMaskError(r: SvgMaskExtraction): r is { ok: false; error: string } {\n return !r.ok;\n}\n\n/**\n * Extract sanitised combined path `d` data from pasted path / SVG input.\n */\nexport function extractSvgMaskPath(input: string): SvgMaskExtraction {\n const raw = input.trim();\n if (raw === '') {\n return { ok: false, error:'Paste SVG path data or an SVG file, or choose a file.' };\n }\n if (raw.length > MAX_INPUT_LENGTH) {\n return { ok: false, error:'SVG is too large (max ~200 KB).' };\n }\n\n // Bare path data (no markup) — validate and use directly.\n if (!raw.includes('<')) {\n if (!HAS_MOVE.test(raw) || !PATH_D_CHARS.test(raw)) {\n return { ok: false, error:'Not valid path data (expected something like \"M0 0 L10 10 Z\").' };\n }\n return { ok: true, d:normalise(raw) };\n }\n\n // Full SVG markup — reject obviously unsafe content up front for a\n // clear signal (the geometry-only extraction below is already safe).\n if (/<\\s*script\\b/i.test(raw) || /<\\s*foreignObject\\b/i.test(raw) || /\\son[a-z]+\\s*=/i.test(raw)) {\n return { ok: false, error:'SVG contains scripts or event handlers, which are not allowed.' };\n }\n\n const doc = new DOMParser().parseFromString(raw, 'image/svg+xml');\n if (doc.querySelector('parsererror') !== null) {\n return { ok: false, error:'The SVG markup is malformed.' };\n }\n\n const segments: string[] = [];\n doc.querySelectorAll('path, rect, circle, ellipse, polygon, polyline').forEach((el) => {\n const d = elementToPathData(el);\n if (d !== null) segments.push(d);\n });\n\n if (segments.length === 0) {\n return { ok: false, error:'No drawable shapes found (paths, rects, circles, ellipses or polygons only).' };\n }\n\n const combined = normalise(segments.join(' '));\n if (!HAS_MOVE.test(combined) || !PATH_D_CHARS.test(combined)) {\n return { ok: false, error:'The SVG shapes could not be converted to path data.' };\n }\n return { ok: true, d:combined };\n}\n\n/** Collapse runs of whitespace so the stored `d` round-trips compactly. */\nfunction normalise(d: string): string {\n return d.replace(/\\s+/g, ' ').trim();\n}\n\n/**\n * Convert a single SVG geometry element to path `d` data. Returns `null`\n * for unsupported / zero-area elements (which are skipped). Only the\n * absolute-coordinate primitives are handled; the bounding box is\n * re-scaled to the clip box in the engine, so the source coordinate\n * space / viewBox is irrelevant.\n */\nfunction elementToPathData(el: Element): string | null {\n const num = (name: string): number => {\n const v = parseFloat(el.getAttribute(name) ?? '');\n return Number.isFinite(v) ? v : 0;\n };\n\n switch (el.tagName.toLowerCase()) {\n case 'path': {\n const d = (el.getAttribute('d') ?? '').trim();\n return d !== '' && PATH_D_CHARS.test(d) ? d : null;\n }\n case 'rect': {\n const x = num('x'), y = num('y'), w = num('width'), h = num('height');\n if (w <= 0 || h <= 0) return null;\n return `M ${x} ${y} H ${x + w} V ${y + h} H ${x} Z`;\n }\n case 'circle': {\n const cx = num('cx'), cy = num('cy'), r = num('r');\n if (r <= 0) return null;\n // Two semicircular arcs back to the start (a full circle).\n return `M ${cx - r} ${cy} A ${r} ${r} 0 1 0 ${cx + r} ${cy} A ${r} ${r} 0 1 0 ${cx - r} ${cy} Z`;\n }\n case 'ellipse': {\n const cx = num('cx'), cy = num('cy'), rx = num('rx'), ry = num('ry');\n if (rx <= 0 || ry <= 0) return null;\n return `M ${cx - rx} ${cy} A ${rx} ${ry} 0 1 0 ${cx + rx} ${cy} A ${rx} ${ry} 0 1 0 ${cx - rx} ${cy} Z`;\n }\n case 'polygon':\n case 'polyline': {\n const pts = parsePoints(el.getAttribute('points') ?? '');\n if (pts.length < 2) return null;\n // Close both (a polyline used as a mask is treated as filled).\n return `M ${pts[0]} ${pts.slice(1).map((p) => `L ${p}`).join(' ')} Z`;\n }\n default:\n return null;\n }\n}\n\n/** Parse an SVG `points` list into `\"x y\"` coordinate pairs. */\nfunction parsePoints(raw: string): string[] {\n const nums = raw.match(/-?\\d*\\.?\\d+(?:e-?\\d+)?/gi) ?? [];\n const pairs: string[] = [];\n for (let i = 0; i + 1 < nums.length; i += 2) {\n pairs.push(`${nums[i]} ${nums[i + 1]}`);\n }\n return pairs;\n}\n","import {\n ChangeDetectionStrategy, Component, computed, effect, inject, signal,\n} from '@angular/core';\nimport { ImageEditorStateService } from '../../services/image-editor-state.service';\nimport type { MaskShape, MaskSpec } from '../../types/layer.types';\nimport { DEFAULT_MASK_SPEC } from '../../types/layer.types';\nimport { extractSvgMaskPath } from './svg-mask.util';\n\n/**\n * Mask / clip tool (C.1c / C.1d). Cuts the mask target to a shape —\n * geometric primitives (rect / rounded / ellipse / triangle), the\n * SVG-path presets (star / heart / hexagon), or an arbitrary **custom**\n * SVG the user pastes or uploads (C.1d). The target is the selected\n * shape / text layer when one is active, otherwise the base image — so\n * selecting a layer masks it, selecting nothing masks the photo.\n *\n * The engine owns the fabric `clipPath`; this panel only round-trips a\n * {@link MaskSpec} through `getMask` / `setMask`, and the export flatten\n * bakes the clip in for free (it's part of the object's render path).\n * Custom SVG input is sanitised to pure path geometry by\n * {@link extractSvgMaskPath} before it reaches the engine.\n */\n@Component({\n selector: 'coolms-image-editor-mask-tool',\n standalone: true,\n changeDetection: ChangeDetectionStrategy.OnPush,\n template: `\n <div class=\"mask-tool\">\n <span class=\"prop-hint\">Masking: {{ targetName() }}</span>\n\n <div class=\"shape-grid\">\n @for (s of shapes; track s.value) {\n <button type=\"button\" class=\"shape-btn\"\n [class.shape-btn--on]=\"shape() === s.value\"\n [title]=\"s.label\" [disabled]=\"!state.isReady()\"\n (click)=\"onShape(s.value)\">\n <i class=\"bi\" [class]=\"s.icon\"></i>\n <span>{{ s.label }}</span>\n </button>\n }\n </div>\n\n @if (shape() === 'custom') {\n <div class=\"svg-panel\">\n <textarea class=\"svg-input\" rows=\"4\" spellcheck=\"false\"\n placeholder=\"Paste an SVG path (M0 0 …) or a small SVG file\"\n [value]=\"svgInput()\"\n (input)=\"svgInput.set($any($event.target).value)\"></textarea>\n <div class=\"svg-actions\">\n <label class=\"svg-file-btn\" title=\"Upload an SVG file\">\n <i class=\"bi bi-upload\"></i> Upload SVG\n <input type=\"file\" accept=\".svg,image/svg+xml\" hidden\n (change)=\"onFile($event)\">\n </label>\n <button type=\"button\" class=\"svg-apply-btn\"\n [disabled]=\"!state.isReady()\" (click)=\"applySvg()\">\n Use as mask\n </button>\n </div>\n @if (svgError(); as err) {\n <p class=\"svg-msg svg-msg--err\"><i class=\"bi bi-exclamation-triangle\"></i> {{ err }}</p>\n } @else if (customPath() !== '') {\n <p class=\"svg-msg svg-msg--ok\"><i class=\"bi bi-check-circle\"></i> Custom SVG mask applied.</p>\n }\n </div>\n }\n\n @if (shape() !== 'none') {\n <label class=\"prop-row prop-row--range\">\n <span>Inset</span>\n <input type=\"range\" min=\"0\" max=\"40\" step=\"1\" [value]=\"inset()\"\n (input)=\"onInset(+$any($event.target).value)\">\n <output>{{ inset() }}%</output>\n </label>\n }\n @if (shape() === 'rounded') {\n <label class=\"prop-row prop-row--range\">\n <span>Radius</span>\n <input type=\"range\" min=\"0\" max=\"50\" step=\"1\" [value]=\"radius()\"\n (input)=\"onRadius(+$any($event.target).value)\">\n <output>{{ radius() }}%</output>\n </label>\n }\n\n @if (shape() !== 'none') {\n <button type=\"button\" class=\"clear-btn\" (click)=\"onShape('none')\">\n <i class=\"bi bi-x-circle\"></i> Remove mask\n </button>\n }\n </div>\n `,\n styles: [`\n .mask-tool { display: flex; flex-direction: column; gap: 14px; }\n .prop-hint {\n font-size: .6875rem; font-weight: 700; letter-spacing: .04em;\n text-transform: uppercase; color: var(--cms-text-muted);\n }\n .shape-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 6px; }\n .shape-btn {\n display: flex; flex-direction: column; align-items: center; gap: 4px;\n padding: 10px 4px; background: var(--cms-surface);\n border: 1px solid var(--cms-border); border-radius: var(--cms-radius);\n color: var(--cms-text-secondary); cursor: pointer;\n }\n .shape-btn > .bi { font-size: 1.125rem; }\n .shape-btn > span { font-size: .625rem; }\n .shape-btn:hover:not(:disabled) {\n background: var(--cms-btn-hover-bg); border-color: var(--cms-btn-hover-border);\n color: var(--cms-text);\n }\n .shape-btn--on { background: var(--cms-accent-light); border-color: var(--cms-accent); color: var(--cms-accent-text); }\n .shape-btn:disabled { opacity: .4; cursor: not-allowed; }\n .prop-row {\n display: grid; grid-template-columns: 64px 1fr auto; align-items: center; gap: 10px;\n font-size: .8125rem; color: var(--cms-text-secondary);\n }\n .prop-row input[type=range] { width: 100%; }\n .prop-row output { font-variant-numeric: tabular-nums; color: var(--cms-text-muted); min-width: 36px; text-align: right; }\n .clear-btn {\n display: flex; align-items: center; justify-content: center; gap: 6px;\n padding: 8px 12px; background: var(--cms-surface);\n border: 1px solid var(--cms-border); border-radius: var(--cms-radius);\n color: var(--cms-text-secondary); font-size: .8125rem; cursor: pointer;\n }\n .clear-btn:hover { background: var(--cms-btn-hover-bg); color: var(--cms-text); }\n .svg-panel { display: flex; flex-direction: column; gap: 8px; }\n .svg-input {\n width: 100%; resize: vertical; min-height: 64px;\n padding: 8px 10px; background: var(--cms-surface);\n border: 1px solid var(--cms-border); border-radius: var(--cms-radius);\n color: var(--cms-text); font-family: var(--cms-font-mono, monospace);\n font-size: .75rem; line-height: 1.4;\n }\n .svg-input:focus { outline: none; border-color: var(--cms-accent); }\n .svg-actions { display: flex; gap: 6px; }\n .svg-file-btn, .svg-apply-btn {\n display: inline-flex; align-items: center; justify-content: center; gap: 6px;\n padding: 7px 12px; border-radius: var(--cms-radius);\n font-size: .8125rem; cursor: pointer; border: 1px solid var(--cms-border);\n }\n .svg-file-btn { background: var(--cms-surface); color: var(--cms-text-secondary); }\n .svg-file-btn:hover { background: var(--cms-btn-hover-bg); color: var(--cms-text); }\n .svg-apply-btn {\n flex: 1; background: var(--cms-accent-light);\n border-color: var(--cms-accent); color: var(--cms-accent-text); font-weight: 600;\n }\n .svg-apply-btn:hover:not(:disabled) { filter: brightness(1.05); }\n .svg-apply-btn:disabled { opacity: .4; cursor: not-allowed; }\n .svg-msg {\n display: flex; align-items: flex-start; gap: 6px;\n margin: 0; font-size: .75rem; line-height: 1.4;\n }\n .svg-msg--err { color: var(--cms-danger, #dc2626); }\n .svg-msg--ok { color: var(--cms-success, #16a34a); }\n `],\n})\nexport class MaskToolComponent {\n protected readonly state = inject(ImageEditorStateService);\n\n protected readonly shapes: { value: MaskShape; icon: string; label: string }[] = [\n { value: 'none', icon: 'bi-slash-circle', label: 'None' },\n { value: 'rect', icon: 'bi-square', label: 'Rect' },\n { value: 'rounded', icon: 'bi-app', label: 'Rounded' },\n { value: 'ellipse', icon: 'bi-circle', label: 'Ellipse' },\n { value: 'triangle', icon: 'bi-triangle', label: 'Triangle' },\n { value: 'star', icon: 'bi-star', label: 'Star' },\n { value: 'heart', icon: 'bi-heart', label: 'Heart' },\n { value: 'hexagon', icon: 'bi-hexagon', label: 'Hexagon' },\n { value: 'custom', icon: 'bi-filetype-svg', label: 'SVG' },\n ];\n\n protected readonly shape = signal<MaskShape>(DEFAULT_MASK_SPEC.shape);\n protected readonly inset = signal(DEFAULT_MASK_SPEC.inset);\n protected readonly radius = signal(DEFAULT_MASK_SPEC.radius);\n\n /** Raw textarea / uploaded-file content for the custom SVG mask (C.1d). */\n protected readonly svgInput = signal('');\n /** The sanitised combined path `d` currently applied (empty = none). */\n protected readonly customPath = signal('');\n /** Last validation error for the SVG input, or `null` when clean. */\n protected readonly svgError = signal<string | null>(null);\n\n /** Name of what's being masked — the selected layer, else \"Background\". */\n protected readonly targetName = computed<string>(() => {\n const kind = this.state.activeLayerKind();\n if (kind !== null && kind !== 'image') {\n const id = this.state.activeLayerId();\n return this.state.layers().find(l => l.id === id)?.name ?? 'Layer';\n }\n return 'Background';\n });\n\n constructor() {\n // Seed the controls from the target's current mask whenever the\n // selection changes (depends on the active-layer signals only,\n // so a live mask edit doesn't feed back into the inputs).\n effect(() => {\n this.state.activeLayerKind();\n this.state.activeLayerId();\n const spec = this.state.engine()?.getMask();\n if (spec == null) return;\n this.shape.set(spec.shape);\n this.inset.set(spec.inset);\n this.radius.set(spec.radius);\n // Restore the custom path + textarea so re-selecting a layer\n // shows the SVG that's actually clipping it (C.1d round-trip).\n if (spec.shape === 'custom' && typeof spec.svgPath === 'string') {\n this.customPath.set(spec.svgPath);\n this.svgInput.set(spec.svgPath);\n } else if (spec.shape !== 'custom') {\n this.customPath.set('');\n }\n this.svgError.set(null);\n });\n }\n\n protected onShape(value: MaskShape): void { this.shape.set(value); this.apply(); }\n protected onInset(value: number): void { this.inset.set(value); this.apply(); }\n protected onRadius(value: number): void { this.radius.set(value); this.apply(); }\n\n /** Validate + apply the textarea contents as a custom SVG mask (C.1d). */\n protected applySvg(): void {\n const result = extractSvgMaskPath(this.svgInput());\n if (!result.ok) {\n this.svgError.set(result.error);\n return;\n }\n this.svgError.set(null);\n this.customPath.set(result.d);\n this.shape.set('custom');\n this.apply();\n }\n\n /** Read an uploaded SVG file into the textarea and apply it. */\n protected async onFile(event: Event): Promise<void> {\n const input = event.target as HTMLInputElement;\n const file = input.files?.[0] ?? null;\n // Reset so re-picking the same file fires `change` again.\n input.value = '';\n if (file === null) return;\n try {\n this.svgInput.set(await file.text());\n this.applySvg();\n } catch {\n this.svgError.set('Could not read the file.');\n }\n }\n\n private apply(): void {\n const shape = this.shape();\n // A custom mask with no geometry yet is a no-op — wait for the\n // user to paste / upload and hit \"Use as mask\" rather than\n // stamping (and clearing) an empty clip.\n if (shape === 'custom' && this.customPath().trim() === '') return;\n\n const spec: MaskSpec = {\n shape,\n inset: this.inset(),\n radius: this.radius(),\n svgPath: shape === 'custom' ? this.customPath() : undefined,\n };\n this.state.engine()?.setMask(spec);\n }\n}\n","import {\n ChangeDetectionStrategy, Component, OnDestroy, OnInit,\n computed, inject, input, signal,\n} from '@angular/core';\n\nimport { ImageEditorStateService } from '../../services/image-editor-state.service';\nimport type { ImageEditorTool } from '../tool.types';\nimport type { SliderFilterConfig } from './filter.types';\nimport type { FilterParams } from '../../types/filter.types';\n\n/**\n * Generic slider-driven filter tool (Brightness, Contrast,\n * Saturation, Blur).\n *\n * Live preview model — each slider drag applies the filter to the\n * canvas immediately so the user sees the change in real time. The\n * undo stack stays clean by undoing the previous preview before\n * applying the new one: at any moment during a preview session the\n * stack holds at most a single preview entry.\n *\n * drag -> [undo prev preview] -> apply new preview -> repeat\n * apply -> commit (no engine call; current preview already on canvas)\n * -> clearRedoStack() so the redo button doesn't surface\n * stale intermediate values\n * cancel -> undo() the in-flight preview\n * -> clearRedoStack()\n *\n * Coalescing — slider `input` events fire much faster than each\n * undo+apply cycle can finish (especially for Blur on large images).\n * The `inFlight` guard drops intermediate values; only the most\n * recent slider position is rendered. The stale ones are silently\n * abandoned, so the UI never falls behind the pointer.\n *\n * Identity-value short-circuit — when the slider sits at `default`\n * (typically 0), the tool removes the filter entirely instead of\n * applying an identity pass. This means the pre-tool canvas state\n * is byte-equal to the \"slider returned to zero\" state.\n */\n@Component({\n selector: 'coolms-image-editor-slider-filter',\n standalone: true,\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [],\n templateUrl: './slider-filter.component.html',\n styleUrls: ['./slider-filter.component.scss'],\n})\nexport class SliderFilterComponent implements OnInit, OnDestroy, ImageEditorTool {\n private readonly state = inject(ImageEditorStateService);\n\n readonly config = input.required<SliderFilterConfig>();\n\n readonly currentValue = signal<number>(0);\n /**\n * Tracks whether we have an un-committed preview filter on the\n * canvas. `null` means no preview is currently applied (either\n * because we're at the default value or the preview was reverted).\n */\n private readonly previewActive = signal<boolean>(false);\n\n readonly isDirty = computed(() => this.currentValue() !== this.config().default);\n\n /** Coalescing state for the slider input handler. */\n private inFlight = false;\n private pendingValue: number | null = null;\n\n ngOnInit(): void {\n this.currentValue.set(this.config().default);\n }\n\n async ngOnDestroy(): Promise<void> {\n // If the user closed the tool without Apply or Cancel\n // (e.g., switched to another tool) revert any preview so the\n // canvas stays in the same state it was in before activation.\n await this.onDeactivate();\n }\n\n onActivate(): void { /* nothing extra; preview only fires on slider input */ }\n\n async onDeactivate(): Promise<void> {\n if (this.previewActive()) {\n await this.revertPreview();\n }\n }\n\n onSliderInput(value: number): void {\n this.currentValue.set(value);\n this.pendingValue = value;\n // Fire-and-forget the coalescer; awaiting would block the UI\n // event handler, which is the opposite of what we want.\n void this.processPendingValue();\n }\n\n async applyAndCommit(): Promise<void> {\n // Drain any in-flight preview so the canvas matches `currentValue()`.\n // Without this, a fast-clicked Apply right after a slider drag could\n // commit the previous-but-one preview value.\n await this.flushPending();\n\n const engine = this.state.engine();\n if (engine === null) return;\n\n // The current preview entry stays in the undo stack as the\n // committed change; we just stop tracking it as \"in-flight\"\n // and clear the redo stack of stale preview cycles.\n this.previewActive.set(false);\n engine.clearRedoStack();\n this.state.setActiveTool(null);\n }\n\n async cancel(): Promise<void> {\n await this.flushPending();\n await this.revertPreview();\n const engine = this.state.engine();\n engine?.clearRedoStack();\n this.state.setActiveTool(null);\n }\n\n async reset(): Promise<void> {\n this.currentValue.set(this.config().default);\n this.pendingValue = this.config().default;\n await this.processPendingValue();\n }\n\n private async processPendingValue(): Promise<void> {\n if (this.inFlight) return;\n this.inFlight = true;\n try {\n while (this.pendingValue !== null) {\n const value = this.pendingValue;\n this.pendingValue = null;\n await this.applyPreview(value);\n }\n } finally {\n this.inFlight = false;\n }\n }\n\n private async flushPending(): Promise<void> {\n // If a preview is mid-flight, wait until the queue drains.\n // Re-enters the processor in case the queue picked up a new\n // value between calls.\n while (this.inFlight || this.pendingValue !== null) {\n await Promise.resolve();\n if (this.pendingValue !== null && !this.inFlight) {\n await this.processPendingValue();\n }\n }\n }\n\n private async applyPreview(value: number): Promise<void> {\n const engine = this.state.engine();\n if (engine === null) return;\n\n if (this.previewActive()) {\n await engine.undo();\n this.previewActive.set(false);\n }\n\n if (value === this.config().default) {\n // No filter to apply at the identity value; the canvas is\n // already in the pre-filter state after the undo above.\n return;\n }\n\n const params = { [this.config().paramKey]: value } as FilterParams;\n await engine.applyFilter(this.config().filterName, params);\n this.previewActive.set(true);\n }\n\n private async revertPreview(): Promise<void> {\n if (!this.previewActive()) return;\n const engine = this.state.engine();\n if (engine === null) return;\n await engine.undo();\n this.previewActive.set(false);\n }\n}\n","<div class=\"slider-filter\">\n <h5 class=\"slider-filter__heading\">{{ config().label }}</h5>\n\n <div class=\"slider-filter__slider-row\">\n <input type=\"range\"\n class=\"slider-filter__slider\"\n [min]=\"config().min\"\n [max]=\"config().max\"\n [step]=\"config().step\"\n [value]=\"currentValue()\"\n (input)=\"onSliderInput($any($event.target).valueAsNumber)\">\n <code class=\"slider-filter__value\">{{ currentValue().toFixed(2) }}</code>\n </div>\n\n <div class=\"slider-filter__actions\">\n <button type=\"button\"\n class=\"cms-btn\"\n title=\"Reset to default\"\n [disabled]=\"!isDirty()\"\n (click)=\"reset()\">\n <i class=\"bi bi-arrow-counterclockwise\"></i>\n <span>Reset</span>\n </button>\n <button type=\"button\"\n class=\"cms-btn\"\n (click)=\"cancel()\">Cancel</button>\n <button type=\"button\"\n class=\"cms-btn cms-btn-primary\"\n [disabled]=\"!isDirty()\"\n (click)=\"applyAndCommit()\">Apply</button>\n </div>\n</div>\n","import {\n ChangeDetectionStrategy, Component, OnInit, computed, inject, input, signal,\n} from '@angular/core';\n\nimport { ImageEditorStateService } from '../../services/image-editor-state.service';\nimport type { ToggleFilterConfig } from './filter.types';\n\n/**\n * Generic toggle-style filter tool (Sepia, Grayscale, Sharpen).\n *\n * The \"applied\" state is read from the engine on activation via\n * `hasFilter(name)` so opening the tool against an already-applied\n * filter shows the correct indicator. Each toggle commits to the\n * undo stack (apply or remove); the user can revert through the\n * top toolbar's Undo button just like any other operation.\n */\n@Component({\n selector: 'coolms-image-editor-toggle-filter',\n standalone: true,\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [],\n templateUrl: './toggle-filter.component.html',\n styleUrls: ['./toggle-filter.component.scss'],\n})\nexport class ToggleFilterComponent implements OnInit {\n protected readonly state = inject(ImageEditorStateService);\n\n readonly config = input.required<ToggleFilterConfig>();\n\n readonly isApplied = signal<boolean>(false);\n readonly buttonLabel = computed(() => this.isApplied() ? 'Remove' : 'Apply');\n\n ngOnInit(): void {\n const engine = this.state.engine();\n if (engine === null) return;\n this.isApplied.set(engine.hasFilter(this.config().filterName));\n }\n\n async toggle(): Promise<void> {\n const engine = this.state.engine();\n if (engine === null) return;\n\n if (this.isApplied()) {\n await engine.removeFilter(this.config().filterName);\n this.isApplied.set(false);\n } else {\n await engine.applyFilter(this.config().filterName);\n this.isApplied.set(true);\n }\n }\n\n closeTool(): void {\n this.state.setActiveTool(null);\n }\n}\n","<div class=\"toggle-filter\">\n <h5 class=\"toggle-filter__heading\">{{ config().label }}</h5>\n\n <button type=\"button\"\n class=\"toggle-filter__btn\"\n [class.toggle-filter__btn--active]=\"isApplied()\"\n [disabled]=\"!state.isReady()\"\n (click)=\"toggle()\">\n <i class=\"bi\" [class]=\"config().icon\"></i>\n <span class=\"toggle-filter__btn-label\">{{ buttonLabel() }}</span>\n @if (isApplied()) {\n <i class=\"bi bi-check-lg toggle-filter__check\"></i>\n }\n </button>\n\n <div class=\"toggle-filter__actions\">\n <button type=\"button\" class=\"cms-btn\" (click)=\"closeTool()\">Close</button>\n </div>\n</div>\n","import {\n ChangeDetectionStrategy, Component, computed, effect, inject, signal,\n} from '@angular/core';\nimport { ImageEditorStateService } from '../../services/image-editor-state.service';\nimport type { ShapeKind, FillType, FillSpec } from '../../types/layer.types';\nimport { DEFAULT_SHAPE_OPTIONS, DEFAULT_FILL_SPEC } from '../../types/layer.types';\n\n/**\n * Insert + style shapes (C.1). The kind buttons add a centred shape\n * using the current fill / stroke / width as defaults; when a shape\n * layer is selected, the same controls edit it live through the\n * engine's `updateActiveObject`. The controls double as next-insert\n * defaults, so styling one shape pre-styles the next.\n */\n@Component({\n selector: 'coolms-image-editor-shape-tool',\n standalone: true,\n changeDetection: ChangeDetectionStrategy.OnPush,\n template: `\n <div class=\"shape-tool\">\n <div class=\"shape-grid\">\n @for (s of shapes; track s.kind) {\n <button type=\"button\" class=\"shape-btn\" [title]=\"s.label\"\n [disabled]=\"!state.isReady()\" (click)=\"add(s.kind)\">\n <i class=\"bi\" [class]=\"s.icon\"></i>\n <span>{{ s.label }}</span>\n </button>\n }\n </div>\n\n <div class=\"prop-group\">\n <span class=\"prop-hint\">\n {{ editingShape() ? 'Editing selected shape' : 'Style for new shapes' }}\n </span>\n\n <div class=\"prop-row\">\n <span>Fill</span>\n <div class=\"btn-row\">\n @for (m of fillModes; track m.value) {\n <button type=\"button\" class=\"seg\" [class.seg--on]=\"fillType() === m.value\"\n [title]=\"m.label\" (click)=\"onFillType(m.value)\">{{ m.label }}</button>\n }\n </div>\n </div>\n <label class=\"prop-row\">\n <span>{{ fillType() === 'solid' ? 'Colour' : 'Colour 1' }}</span>\n <input type=\"color\" [value]=\"fill()\" (input)=\"onFill($any($event.target).value)\">\n </label>\n @if (fillType() !== 'solid') {\n <label class=\"prop-row\">\n <span>Colour 2</span>\n <input type=\"color\" [value]=\"fill2()\" (input)=\"onFill2($any($event.target).value)\">\n </label>\n }\n @if (fillType() === 'linear') {\n <label class=\"prop-row\">\n <span>Angle</span>\n <input type=\"range\" min=\"0\" max=\"360\" step=\"5\" [value]=\"angle()\"\n (input)=\"onAngle(+$any($event.target).value)\">\n <output>{{ angle() }}°</output>\n </label>\n }\n\n <label class=\"prop-row\">\n <span>Stroke</span>\n <input type=\"color\" [value]=\"stroke()\" (input)=\"onStroke($any($event.target).value)\">\n </label>\n <label class=\"prop-row\">\n <span>Width</span>\n <input type=\"range\" min=\"0\" max=\"40\" step=\"1\" [value]=\"strokeWidth()\"\n (input)=\"onStrokeWidth(+$any($event.target).value)\">\n <output>{{ strokeWidth() }}</output>\n </label>\n <label class=\"prop-row\">\n <span>Opacity</span>\n <input type=\"range\" min=\"0\" max=\"1\" step=\"0.05\" [value]=\"opacity()\"\n (input)=\"onOpacity(+$any($event.target).value)\">\n <output>{{ (opacity() * 100).toFixed(0) }}%</output>\n </label>\n </div>\n </div>\n `,\n styles: [`\n .shape-tool { display: flex; flex-direction: column; gap: 16px; }\n .shape-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 6px; }\n .shape-btn {\n display: flex; flex-direction: column; align-items: center; gap: 4px;\n padding: 10px 4px; background: var(--cms-surface);\n border: 1px solid var(--cms-border); border-radius: var(--cms-radius);\n color: var(--cms-text-secondary); cursor: pointer;\n }\n .shape-btn > .bi { font-size: 1.125rem; }\n .shape-btn > span { font-size: .6875rem; }\n .shape-btn:hover:not(:disabled) {\n background: var(--cms-btn-hover-bg); border-color: var(--cms-btn-hover-border);\n color: var(--cms-text);\n }\n .shape-btn:disabled { opacity: .4; cursor: not-allowed; }\n .prop-group { display: flex; flex-direction: column; gap: 10px; }\n .prop-hint {\n font-size: .6875rem; font-weight: 700; letter-spacing: .04em;\n text-transform: uppercase; color: var(--cms-text-muted);\n }\n .prop-row {\n display: grid; grid-template-columns: 64px 1fr auto; align-items: center; gap: 10px;\n font-size: .8125rem; color: var(--cms-text-secondary);\n }\n .prop-row input[type=color] { width: 100%; height: 28px; padding: 0; border: 1px solid var(--cms-border); border-radius: var(--cms-radius-sm); background: none; cursor: pointer; }\n .prop-row input[type=range] { width: 100%; }\n .prop-row output { font-variant-numeric: tabular-nums; color: var(--cms-text-muted); min-width: 36px; text-align: right; }\n .btn-row { display: flex; gap: 6px; }\n .seg {\n flex: 1; padding: 6px 4px; background: var(--cms-surface);\n border: 1px solid var(--cms-border); border-radius: var(--cms-radius-sm);\n color: var(--cms-text-secondary); font-size: .75rem; cursor: pointer;\n }\n .seg--on { background: var(--cms-accent-light); border-color: var(--cms-accent); color: var(--cms-accent-text); }\n `],\n})\nexport class ShapeToolComponent {\n protected readonly state = inject(ImageEditorStateService);\n\n protected readonly shapes: { kind: ShapeKind; icon: string; label: string }[] = [\n { kind: 'rect', icon: 'bi-square', label: 'Rect' },\n { kind: 'ellipse', icon: 'bi-circle', label: 'Ellipse' },\n { kind: 'triangle', icon: 'bi-triangle', label: 'Triangle' },\n { kind: 'line', icon: 'bi-slash-lg', label: 'Line' },\n { kind: 'arrow', icon: 'bi-arrow-right', label: 'Arrow' },\n ];\n\n protected readonly fillModes: { value: FillType; label: string }[] = [\n { value: 'solid', label: 'Solid' },\n { value: 'linear', label: 'Linear' },\n { value: 'radial', label: 'Radial' },\n ];\n\n protected readonly fillType = signal<FillType>(DEFAULT_FILL_SPEC.type);\n protected readonly fill = signal(DEFAULT_SHAPE_OPTIONS.fill);\n protected readonly fill2 = signal(DEFAULT_FILL_SPEC.color2);\n protected readonly angle = signal(DEFAULT_FILL_SPEC.angle);\n protected readonly stroke = signal(DEFAULT_SHAPE_OPTIONS.stroke);\n protected readonly strokeWidth = signal(DEFAULT_SHAPE_OPTIONS.strokeWidth);\n protected readonly opacity = signal(1);\n\n /** True while a shape layer is the active object. */\n protected readonly editingShape = computed(() => this.state.activeLayerKind() === 'shape');\n\n constructor() {\n // When the selected shape changes, pull its current style into\n // the controls so they edit (not reset) it. Depends on the\n // active-layer signals only, never the layer list, so a live\n // style edit doesn't feed back into the inputs.\n effect(() => {\n const kind = this.state.activeLayerKind();\n const id = this.state.activeLayerId();\n if (kind !== 'shape' || id === null) return;\n const engine = this.state.engine();\n const props = engine?.getActiveObjectProps();\n if (props == null) return;\n if (props['stroke'] !== undefined && props['stroke'] !== '') this.stroke.set(String(props['stroke']));\n if (props['strokeWidth'] !== undefined) this.strokeWidth.set(Number(props['strokeWidth']));\n if (props['opacity'] !== undefined) this.opacity.set(Number(props['opacity']));\n // Fill comes back as a structured spec so a gradient\n // round-trips (mode + both stops + angle), not just a colour.\n const f = engine?.getActiveObjectFill();\n if (f != null) {\n this.fillType.set(f.type);\n this.fill.set(f.color);\n this.fill2.set(f.color2);\n this.angle.set(f.angle);\n }\n });\n }\n\n protected add(kind: ShapeKind): void {\n this.state.engine()?.addShape(kind, {\n fill: this.fill(), stroke: this.stroke(), strokeWidth: this.strokeWidth(),\n fillSpec: this.currentFill(),\n });\n }\n\n protected onFillType(v: FillType): void { this.fillType.set(v); this.applyFill(); }\n protected onFill(v: string): void { this.fill.set(v); this.applyFill(); }\n protected onFill2(v: string): void { this.fill2.set(v); this.applyFill(); }\n protected onAngle(v: number): void { this.angle.set(v); this.applyFill(); }\n protected onStroke(v: string): void { this.stroke.set(v); this.applyIfEditing({ stroke: v }); }\n protected onStrokeWidth(v: number): void { this.strokeWidth.set(v); this.applyIfEditing({ strokeWidth: v }); }\n protected onOpacity(v: number): void { this.opacity.set(v); this.applyIfEditing({ opacity: v }); }\n\n private currentFill(): FillSpec {\n return { type: this.fillType(), color: this.fill(), color2: this.fill2(), angle: this.angle() };\n }\n\n private applyFill(): void {\n if (this.editingShape()) this.state.engine()?.setActiveObjectFill(this.currentFill());\n }\n\n private applyIfEditing(props: Record<string, string | number>): void {\n if (this.editingShape()) this.state.engine()?.updateActiveObject(props);\n }\n}\n","import {\n ChangeDetectionStrategy, Component, computed, effect, inject, signal,\n} from '@angular/core';\nimport { ImageEditorStateService } from '../../services/image-editor-state.service';\nimport type { FillType, FillSpec } from '../../types/layer.types';\nimport { DEFAULT_TEXT_OPTIONS, DEFAULT_FILL_SPEC, TEXT_FONT_FAMILIES } from '../../types/layer.types';\n\n/**\n * Insert + style text (C.1). \"Add text\" drops a centred editable\n * text box; when a text layer is selected, the controls edit it live\n * (content, font, size, colour, weight / style, alignment) through the\n * engine's `updateActiveObject`.\n */\n@Component({\n selector: 'coolms-image-editor-text-tool',\n standalone: true,\n changeDetection: ChangeDetectionStrategy.OnPush,\n template: `\n <div class=\"text-tool\">\n <button type=\"button\" class=\"add-btn\" [disabled]=\"!state.isReady()\" (click)=\"add()\">\n <i class=\"bi bi-fonts\"></i> Add text\n </button>\n\n @if (editingText()) {\n <label class=\"prop-row prop-row--stack\">\n <span>Text</span>\n <textarea rows=\"2\" [value]=\"text()\"\n (input)=\"onText($any($event.target).value)\"></textarea>\n </label>\n }\n\n <div class=\"prop-group\">\n <span class=\"prop-hint\">\n {{ editingText() ? 'Editing selected text' : 'Style for new text' }}\n </span>\n\n <label class=\"prop-row\">\n <span>Font</span>\n <select [value]=\"fontFamily()\" (change)=\"onFontFamily($any($event.target).value)\">\n @for (f of fonts; track f) { <option [value]=\"f\">{{ f }}</option> }\n </select>\n </label>\n <label class=\"prop-row\">\n <span>Size</span>\n <input type=\"number\" min=\"6\" max=\"400\" step=\"1\" [value]=\"fontSize()\"\n (input)=\"onFontSize(+$any($event.target).value)\">\n </label>\n <div class=\"prop-row\">\n <span>Fill</span>\n <div class=\"btn-row\">\n @for (m of fillModes; track m.value) {\n <button type=\"button\" class=\"seg\" [class.seg--on]=\"fillType() === m.value\"\n [title]=\"m.label\" (click)=\"onFillType(m.value)\">{{ m.label }}</button>\n }\n </div>\n </div>\n <label class=\"prop-row\">\n <span>{{ fillType() === 'solid' ? 'Colour' : 'Colour 1' }}</span>\n <input type=\"color\" [value]=\"fill()\" (input)=\"onFill($any($event.target).value)\">\n </label>\n @if (fillType() !== 'solid') {\n <label class=\"prop-row\">\n <span>Colour 2</span>\n <input type=\"color\" [value]=\"fill2()\" (input)=\"onFill2($any($event.target).value)\">\n </label>\n }\n @if (fillType() === 'linear') {\n <label class=\"prop-row prop-row--range\">\n <span>Angle</span>\n <input type=\"range\" min=\"0\" max=\"360\" step=\"5\" [value]=\"angle()\"\n (input)=\"onAngle(+$any($event.target).value)\">\n <output>{{ angle() }}°</output>\n </label>\n }\n\n <div class=\"prop-row\">\n <span>Style</span>\n <div class=\"btn-row\">\n <button type=\"button\" class=\"seg\" [class.seg--on]=\"bold()\" title=\"Bold\" (click)=\"toggleBold()\"><i class=\"bi bi-type-bold\"></i></button>\n <button type=\"button\" class=\"seg\" [class.seg--on]=\"italic()\" title=\"Italic\" (click)=\"toggleItalic()\"><i class=\"bi bi-type-italic\"></i></button>\n </div>\n </div>\n <div class=\"prop-row\">\n <span>Align</span>\n <div class=\"btn-row\">\n @for (a of aligns; track a.value) {\n <button type=\"button\" class=\"seg\" [class.seg--on]=\"textAlign() === a.value\"\n [title]=\"a.value\" (click)=\"onAlign(a.value)\"><i class=\"bi\" [class]=\"a.icon\"></i></button>\n }\n </div>\n </div>\n </div>\n </div>\n `,\n styles: [`\n .text-tool { display: flex; flex-direction: column; gap: 14px; }\n .add-btn {\n display: flex; align-items: center; justify-content: center; gap: 6px;\n padding: 9px 12px; background: var(--cms-accent); color: var(--cms-accent-fg, #1a1a1a);\n border: 1px solid var(--cms-accent); border-radius: var(--cms-radius);\n font-size: .8125rem; font-weight: 600; cursor: pointer;\n }\n .add-btn:disabled { opacity: .4; cursor: not-allowed; }\n .prop-group { display: flex; flex-direction: column; gap: 10px; }\n .prop-hint {\n font-size: .6875rem; font-weight: 700; letter-spacing: .04em;\n text-transform: uppercase; color: var(--cms-text-muted);\n }\n .prop-row {\n display: grid; grid-template-columns: 64px 1fr; align-items: center; gap: 10px;\n font-size: .8125rem; color: var(--cms-text-secondary);\n }\n .prop-row--stack { grid-template-columns: 1fr; }\n .prop-row--range { grid-template-columns: 64px 1fr auto; }\n .prop-row input[type=range] { width: 100%; }\n .prop-row output { font-variant-numeric: tabular-nums; color: var(--cms-text-muted); min-width: 36px; text-align: right; }\n .prop-row textarea, .prop-row select, .prop-row input[type=number] {\n width: 100%; padding: 6px 8px; background: var(--cms-surface);\n border: 1px solid var(--cms-border); border-radius: var(--cms-radius-sm);\n color: var(--cms-text); font: inherit;\n }\n .prop-row input[type=color] { width: 100%; height: 28px; padding: 0; border: 1px solid var(--cms-border); border-radius: var(--cms-radius-sm); background: none; cursor: pointer; }\n .btn-row { display: flex; gap: 6px; }\n .seg {\n flex: 1; padding: 6px; background: var(--cms-surface);\n border: 1px solid var(--cms-border); border-radius: var(--cms-radius-sm);\n color: var(--cms-text-secondary); cursor: pointer;\n }\n .seg--on { background: var(--cms-accent-light); border-color: var(--cms-accent); color: var(--cms-accent-text); }\n `],\n})\nexport class TextToolComponent {\n protected readonly state = inject(ImageEditorStateService);\n\n protected readonly fonts = TEXT_FONT_FAMILIES;\n protected readonly aligns = [\n { value: 'left' as const, icon: 'bi-text-left' },\n { value: 'center' as const, icon: 'bi-text-center' },\n { value: 'right' as const, icon: 'bi-text-right' },\n ];\n\n protected readonly fillModes: { value: FillType; label: string }[] = [\n { value: 'solid', label: 'Solid' },\n { value: 'linear', label: 'Linear' },\n { value: 'radial', label: 'Radial' },\n ];\n\n protected readonly text = signal(DEFAULT_TEXT_OPTIONS.text);\n protected readonly fontFamily = signal<string>(DEFAULT_TEXT_OPTIONS.fontFamily);\n protected readonly fontSize = signal(DEFAULT_TEXT_OPTIONS.fontSize);\n protected readonly fillType = signal<FillType>(DEFAULT_FILL_SPEC.type);\n protected readonly fill = signal(DEFAULT_TEXT_OPTIONS.fill);\n protected readonly fill2 = signal(DEFAULT_FILL_SPEC.color2);\n protected readonly angle = signal(DEFAULT_FILL_SPEC.angle);\n protected readonly bold = signal(false);\n protected readonly italic = signal(false);\n protected readonly textAlign = signal<'left' | 'center' | 'right'>('left');\n\n protected readonly editingText = computed(() => this.state.activeLayerKind() === 'text');\n\n constructor() {\n effect(() => {\n const kind = this.state.activeLayerKind();\n const id = this.state.activeLayerId();\n if (kind !== 'text' || id === null) return;\n const engine = this.state.engine();\n const props = engine?.getActiveObjectProps();\n if (props == null) return;\n this.text.set(String(props['text'] ?? ''));\n this.fontFamily.set(String(props['fontFamily'] ?? this.fontFamily()));\n this.fontSize.set(Number(props['fontSize'] ?? this.fontSize()));\n this.bold.set(String(props['fontWeight'] ?? 'normal') === 'bold');\n this.italic.set(String(props['fontStyle'] ?? 'normal') === 'italic');\n this.textAlign.set((String(props['textAlign'] ?? 'left') as 'left' | 'center' | 'right'));\n // Fill round-trips as a structured spec so a gradient\n // restores its mode + both stops + angle, not just a colour.\n const f = engine?.getActiveObjectFill();\n if (f != null) {\n this.fillType.set(f.type);\n this.fill.set(f.color);\n this.fill2.set(f.color2);\n this.angle.set(f.angle);\n }\n });\n }\n\n protected add(): void {\n this.state.engine()?.addText({\n text: this.text() || 'Text',\n fontFamily: this.fontFamily(),\n fontSize: this.fontSize(),\n fill: this.fill(),\n fillSpec: this.currentFill(),\n fontWeight: this.bold() ? 'bold' : 'normal',\n fontStyle: this.italic() ? 'italic' : 'normal',\n textAlign: this.textAlign(),\n });\n }\n\n protected onText(v: string): void { this.text.set(v); this.apply({ text: v }); }\n protected onFontFamily(v: string): void { this.fontFamily.set(v); this.apply({ fontFamily: v }); }\n protected onFontSize(v: number): void { this.fontSize.set(v); this.apply({ fontSize: v }); }\n protected onFillType(v: FillType): void { this.fillType.set(v); this.applyFill(); }\n protected onFill(v: string): void { this.fill.set(v); this.applyFill(); }\n protected onFill2(v: string): void { this.fill2.set(v); this.applyFill(); }\n protected onAngle(v: number): void { this.angle.set(v); this.applyFill(); }\n protected onAlign(v: 'left' | 'center' | 'right'): void { this.textAlign.set(v); this.apply({ textAlign: v }); }\n\n protected toggleBold(): void {\n this.bold.update(b => !b);\n this.apply({ fontWeight: this.bold() ? 'bold' : 'normal' });\n }\n protected toggleItalic(): void {\n this.italic.update(i => !i);\n this.apply({ fontStyle: this.italic() ? 'italic' : 'normal' });\n }\n\n private currentFill(): FillSpec {\n return { type: this.fillType(), color: this.fill(), color2: this.fill2(), angle: this.angle() };\n }\n\n private applyFill(): void {\n if (this.editingText()) this.state.engine()?.setActiveObjectFill(this.currentFill());\n }\n\n private apply(props: Record<string, string | number>): void {\n if (this.editingText()) this.state.engine()?.updateActiveObject(props);\n }\n}\n","import {\n ChangeDetectionStrategy, Component, computed, inject,\n} from '@angular/core';\nimport { ImageEditorStateService } from '../../services/image-editor-state.service';\nimport type { LayerInfo } from '../../types/layer.types';\n\n/**\n * Layers panel (C.1). Lists the stack top-most first: select, show /\n * hide, reorder, delete, and adjust the selected layer's opacity. The\n * base image is the locked floor — it can't be deleted or restacked.\n */\n@Component({\n selector: 'coolms-image-editor-layers-panel',\n standalone: true,\n changeDetection: ChangeDetectionStrategy.OnPush,\n template: `\n <div class=\"layers\">\n @if (selected(); as sel) {\n @if (!sel.locked) {\n <label class=\"opacity-row\">\n <span>Opacity</span>\n <input type=\"range\" min=\"0\" max=\"1\" step=\"0.05\" [value]=\"sel.opacity\"\n (input)=\"setOpacity(sel.id, +$any($event.target).value)\">\n <output>{{ (sel.opacity * 100).toFixed(0) }}%</output>\n </label>\n }\n }\n\n <ul class=\"layer-list\">\n @for (layer of layers(); track layer.id; let i = $index, last = $last) {\n <li class=\"layer-item\"\n [class.layer-item--active]=\"layer.id === activeId()\"\n [class.layer-item--hidden]=\"!layer.visible\">\n <button type=\"button\" class=\"icon-btn\" [title]=\"layer.visible ? 'Hide' : 'Show'\"\n (click)=\"toggleVisible(layer)\">\n <i class=\"bi\" [class]=\"layer.visible ? 'bi-eye' : 'bi-eye-slash'\"></i>\n </button>\n <button type=\"button\" class=\"layer-name\" (click)=\"select(layer.id)\">\n <i class=\"bi\" [class]=\"kindIcon(layer.kind)\"></i>\n <span>{{ layer.name }}</span>\n @if (layer.locked) { <i class=\"bi bi-lock-fill lock\"></i> }\n </button>\n @if (!layer.locked) {\n <div class=\"layer-actions\">\n <button type=\"button\" class=\"icon-btn\" title=\"Move up\"\n [disabled]=\"i === 0\" (click)=\"reorder(layer.id, 'up')\">\n <i class=\"bi bi-chevron-up\"></i>\n </button>\n <button type=\"button\" class=\"icon-btn\" title=\"Move down\"\n [disabled]=\"i >= layers().length - 2\" (click)=\"reorder(layer.id, 'down')\">\n <i class=\"bi bi-chevron-down\"></i>\n </button>\n <button type=\"button\" class=\"icon-btn icon-btn--danger\" title=\"Delete\"\n (click)=\"remove(layer.id)\">\n <i class=\"bi bi-trash\"></i>\n </button>\n </div>\n }\n </li>\n }\n </ul>\n </div>\n `,\n styles: [`\n .layers { display: flex; flex-direction: column; gap: 12px; }\n .opacity-row {\n display: grid; grid-template-columns: 56px 1fr auto; align-items: center; gap: 10px;\n font-size: .8125rem; color: var(--cms-text-secondary);\n padding-bottom: 10px; border-bottom: 1px solid var(--cms-border-light);\n }\n .opacity-row output { font-variant-numeric: tabular-nums; color: var(--cms-text-muted); min-width: 36px; text-align: right; }\n .layer-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 4px; }\n .layer-item {\n display: flex; align-items: center; gap: 4px; padding: 4px 6px;\n border: 1px solid transparent; border-radius: var(--cms-radius-sm);\n }\n .layer-item--active { background: var(--cms-accent-light); border-color: var(--cms-accent); }\n .layer-item--hidden .layer-name { opacity: .5; }\n .layer-name {\n flex: 1; display: flex; align-items: center; gap: 8px; min-width: 0;\n background: none; border: none; color: var(--cms-text); cursor: pointer;\n font-size: .8125rem; text-align: left; padding: 4px 2px;\n }\n .layer-name > span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\n .layer-name .lock { font-size: .6875rem; color: var(--cms-text-muted); margin-left: auto; }\n .layer-actions { display: flex; gap: 2px; }\n .icon-btn {\n border: none; background: transparent; color: var(--cms-text-muted);\n cursor: pointer; padding: 4px 5px; border-radius: var(--cms-radius-sm); line-height: 1;\n }\n .icon-btn:hover:not(:disabled) { background: var(--cms-border-light); color: var(--cms-text); }\n .icon-btn:disabled { opacity: .3; cursor: not-allowed; }\n .icon-btn--danger:hover:not(:disabled) { color: var(--cms-danger, #dc2626); }\n `],\n})\nexport class LayersPanelComponent {\n protected readonly state = inject(ImageEditorStateService);\n\n protected readonly layers = this.state.layers;\n protected readonly activeId = this.state.activeLayerId;\n\n protected readonly selected = computed<LayerInfo | null>(() => {\n const id = this.activeId();\n return id === null ? null : (this.layers().find(l => l.id === id) ?? null);\n });\n\n protected kindIcon(kind: LayerInfo['kind']): string {\n return kind === 'image' ? 'bi-image' : kind === 'text' ? 'bi-fonts' : 'bi-pentagon';\n }\n\n protected select(id: string): void { this.state.engine()?.selectLayer(id); }\n protected remove(id: string): void { this.state.engine()?.removeLayer(id); }\n protected reorder(id: string, dir: 'up' | 'down'): void { this.state.engine()?.reorderLayer(id, dir); }\n protected setOpacity(id: string, value: number): void { this.state.engine()?.setLayerOpacity(id, value); }\n protected toggleVisible(layer: LayerInfo): void { this.state.engine()?.setLayerVisibility(layer.id, !layer.visible); }\n}\n","import {\n AfterViewInit, ChangeDetectionStrategy, Component, OnDestroy, ViewChild,\n inject, input, output,\n} from '@angular/core';\nimport { TopToolbarComponent } from './top-toolbar/top-toolbar.component';\nimport { CanvasMountComponent } from './canvas-mount/canvas-mount.component';\nimport { RightSidebarComponent } from './right-sidebar/right-sidebar.component';\nimport { ImageEditorStateService } from '../services/image-editor-state.service';\nimport { ToolRegistryService } from '../tools/tool-registry.service';\nimport { CropToolComponent } from '../tools/crop/crop-tool.component';\nimport { RotateToolComponent } from '../tools/rotate/rotate-tool.component';\nimport { FlipToolComponent } from '../tools/flip/flip-tool.component';\nimport { ResizeToolComponent } from '../tools/resize/resize-tool.component';\nimport { MaskToolComponent } from '../tools/mask/mask-tool.component';\nimport { SliderFilterComponent } from '../tools/filter/slider-filter.component';\nimport { ToggleFilterComponent } from '../tools/filter/toggle-filter.component';\nimport { ShapeToolComponent } from '../tools/shape/shape-tool.component';\nimport { TextToolComponent } from '../tools/text/text-tool.component';\nimport { LayersPanelComponent } from '../tools/layers/layers-panel.component';\nimport type {\n SliderFilterConfig, ToggleFilterConfig,\n} from '../tools/filter/filter.types';\nimport type { ImageEditorEngine } from '../engine/image-editor-engine.interface';\n\n/**\n * Three-pane shell for the CoolMS image editor.\n *\n * Composition: top toolbar (action commands + size badge), canvas\n * mount (centre / left, fills remaining space), right sidebar (tool\n * picker placeholder, 320 px). The footer (Save / Save as / Cancel)\n * lives in the host component so the shell can later be embedded in\n * non-dialog contexts (inline editing, side panels) where the save\n * flow looks different.\n *\n * The shell owns engine lifecycle through `ImageEditorStateService`,\n * which is provided locally so each shell instance has its own state.\n * `engineReady` fires once the image is loaded so the host can wire up\n * its save action against a known-good engine handle.\n *\n * Ordering note on `ngAfterViewInit`: the canvas-mount child uses\n * `static: true` for its container ViewChild, so by the time this\n * component's `ngAfterViewInit` runs the inner `<div #container>`\n * exists. The engine adapter is created against that element and the\n * image is loaded before `engineReady` emits — consumers never see\n * an unloaded engine.\n */\n@Component({\n selector: 'coolms-image-editor',\n standalone: true,\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [TopToolbarComponent, CanvasMountComponent, RightSidebarComponent],\n providers: [ImageEditorStateService],\n templateUrl: './coolms-image-editor.component.html',\n styleUrls: ['./coolms-image-editor.component.scss'],\n})\nexport class CoolmsImageEditorComponent implements AfterViewInit, OnDestroy {\n sourceUrl = input.required<string>();\n sourceFilename = input.required<string>();\n\n /** Fires after the engine is created and the initial image has loaded. */\n readonly engineReady = output<ImageEditorEngine>();\n /**\n * Fires if engine creation or initial load throws.\n *\n * `failed`, not `error`: an output named after a native DOM event is\n * ambiguous in a template -- `(error)` could bind either, and which one\n * wins is not visible to whoever reads the template.\n */\n readonly failed = output<Error>();\n\n protected readonly state = inject(ImageEditorStateService);\n\n @ViewChild(CanvasMountComponent, { static: true })\n private readonly canvasMount!: CanvasMountComponent;\n\n /**\n * Tracks teardown so an engine that finishes loading after the host\n * dialog has already been dismissed gets cleaned up promptly. Without\n * this guard a slow `loadImage` could leave an orphan canvas in the\n * DOM after `ngOnDestroy`.\n */\n private destroyed = false;\n\n constructor() {\n // Register the beta.4a transform tools. The registry is\n // `providedIn: 'root'`, so registering here is idempotent across\n // multiple shell instances — re-registering an id replaces the\n // existing entry, and metadata is identical between instances.\n const registry = inject(ToolRegistryService);\n registry.register({\n id: 'crop',\n label: 'Crop',\n icon: 'bi-crop',\n category: 'transform',\n component: CropToolComponent,\n });\n registry.register({\n id: 'rotate',\n label: 'Rotate',\n icon: 'bi-arrow-clockwise',\n category: 'transform',\n component: RotateToolComponent,\n });\n registry.register({\n id: 'flip',\n label: 'Flip',\n icon: 'bi-symmetry-horizontal',\n category: 'transform',\n component: FlipToolComponent,\n });\n // beta.4c: Resize joins the Transform group. Sits last because\n // it changes the canvas baseline, which crop/rotate/flip\n // operations are usually run against rather than after.\n registry.register({\n id: 'resize',\n label: 'Resize',\n icon: 'bi-aspect-ratio',\n category: 'transform',\n component: ResizeToolComponent,\n });\n // C.1c: Mask clips the selected layer (or the base image) to a\n // shape. Sits last in Transform — it's applied over whatever\n // crop / rotate / resize produced.\n registry.register({\n id: 'mask',\n label: 'Mask',\n icon: 'bi-mask',\n category: 'transform',\n component: MaskToolComponent,\n });\n\n // C.1: Insert group (shapes + text as annotation layers) and a\n // Layers panel for the object stack.\n registry.register({\n id: 'shape',\n label: 'Shapes',\n // `bi-shapes` does not exist. Bootstrap Icons has no generic\n // shapes glyph, and a class naming no icon renders nothing at\n // all -- the button kept its label and lost its picture, with no\n // error anywhere. `bi-pentagon` is a shape that is NOT one of the\n // five this tool inserts (rect, ellipse, triangle, line, arrow),\n // so it reads as the group rather than as one of its members.\n icon: 'bi-pentagon',\n category: 'insert',\n component: ShapeToolComponent,\n });\n registry.register({\n id: 'text',\n label: 'Text',\n icon: 'bi-fonts',\n category: 'insert',\n component: TextToolComponent,\n });\n registry.register({\n id: 'layers',\n label: 'Layers',\n icon: 'bi-stack',\n category: 'layers',\n component: LayersPanelComponent,\n });\n\n // beta.4b: Filter tools. The shared SliderFilterComponent and\n // ToggleFilterComponent classes back every filter — only the\n // `config` input differs. ToolMetadata's `inputs` map carries\n // the per-filter config, which the right-sidebar pipes\n // through `NgComponentOutlet`'s `inputs` binding.\n const sliderFilters: SliderFilterConfig[] = [\n { type: 'slider', filterName: 'brightness', label: 'Brightness',\n icon: 'bi-sun', min: -1, max: 1, step: 0.05,\n default: 0, paramKey: 'brightness' },\n { type: 'slider', filterName: 'contrast', label: 'Contrast',\n icon: 'bi-circle-half', min: -1, max: 1, step: 0.05,\n default: 0, paramKey: 'contrast' },\n { type: 'slider', filterName: 'saturation', label: 'Saturation',\n icon: 'bi-droplet-half', min: -1, max: 1, step: 0.05,\n default: 0, paramKey: 'saturation' },\n { type: 'slider', filterName: 'blur', label: 'Blur',\n icon: 'bi-cloud', min: 0, max: 1, step: 0.02,\n default: 0, paramKey: 'blur' },\n ];\n for (const config of sliderFilters) {\n registry.register({\n id: `filter-${config.filterName}`,\n label: config.label,\n icon: config.icon,\n category: 'filter',\n component: SliderFilterComponent,\n inputs: { config },\n });\n }\n\n const toggleFilters: ToggleFilterConfig[] = [\n { type: 'toggle', filterName: 'sepia', label: 'Sepia', icon: 'bi-palette' },\n { type: 'toggle', filterName: 'grayscale', label: 'Grayscale', icon: 'bi-palette-fill' },\n { type: 'toggle', filterName: 'sharpen', label: 'Sharpen', icon: 'bi-stars' },\n ];\n for (const config of toggleFilters) {\n registry.register({\n id: `filter-${config.filterName}`,\n label: config.label,\n icon: config.icon,\n category: 'filter',\n component: ToggleFilterComponent,\n inputs: { config },\n });\n }\n }\n\n /**\n * Public escape hatch the host calls before `engine.export()` to\n * make sure no tool is mid-edit (e.g., user forgot to Apply a\n * crop). Setting `activeTool` to `null` destroys the properties\n * component, whose `ngOnDestroy` runs the tool's deactivation\n * (e.g., `exitCropMode()`) — so the export captures clean canvas\n * pixels with no overlay.\n *\n * The adapter's `exportDataUrl()` also defensively calls\n * `stopDrawingMode()`, but doing it here too makes the\n * higher-level intent obvious in the host's save flow.\n */\n deactivateActiveTool(): void {\n this.state.setActiveTool(null);\n }\n\n /**\n * Public hook the host calls after an intentional dialog size\n * change (fullscreen toggle). Delegates to the canvas mount which\n * re-syncs the fabric canvas dimensions, recalculates fit zoom,\n * and re-applies it so the image stays centred. The\n * ResizeObserver inside canvas-mount stays conservative for\n * casual window resizes (preserves manual zoom).\n */\n refit(): void {\n this.canvasMount.refit();\n }\n\n async ngAfterViewInit(): Promise<void> {\n const container = this.canvasMount.getContainerElement();\n\n try {\n await this.state.initializeEngine(\n container,\n this.sourceUrl(),\n this.sourceFilename(),\n );\n\n if (this.destroyed) {\n this.state.destroyEngine();\n return;\n }\n\n const engine = this.state.engine();\n if (engine !== null) {\n this.engineReady.emit(engine);\n }\n } catch (err) {\n this.failed.emit(err instanceof Error ? err : new Error(String(err)));\n }\n }\n\n ngOnDestroy(): void {\n this.destroyed = true;\n this.state.destroyEngine();\n }\n}\n","<div class=\"coolms-image-editor\">\n <coolms-image-editor-top-toolbar />\n\n <div class=\"coolms-image-editor__body\">\n <coolms-image-editor-canvas-mount />\n <coolms-image-editor-right-sidebar />\n </div>\n</div>\n","import { ChangeDetectionStrategy, Component, inject } from '@angular/core';\nimport { DIALOG_DATA, DialogRef } from '@angular/cdk/dialog';\n\ninterface OverwriteConfirmData {\n readonly filename: string;\n /**\n * Optional note shown above the actions — e.g. a transparency ->\n * PNG format-change warning on overwrite (C.1d).\n */\n readonly formatNote?: string;\n}\n\n/**\n * Confirmation dialog before an overwrite save commits.\n *\n * Closes with `true` on Replace, `false` on Cancel. Lives inside the\n * package so the host has no dependency on the legacy\n * `features/image-editor/` directory; the wording is a near-copy of\n * the legacy version because the user-facing message hasn't changed.\n */\n@Component({\n selector: 'coolms-image-editor-overwrite-confirm-dialog',\n standalone: true,\n changeDetection: ChangeDetectionStrategy.OnPush,\n template: `\n <div class=\"confirm-dialog\">\n <header class=\"confirm-dialog__header\">\n <h3 class=\"confirm-dialog__title\">Replace original?</h3>\n </header>\n <p class=\"confirm-dialog__message\">\n This will replace\n <strong>{{ data.filename }}</strong>\n with the edited image. Existing references on pages will\n show the new bytes after thumbnail regeneration completes.\n </p>\n @if (data.formatNote) {\n <p class=\"confirm-dialog__note\">{{ data.formatNote }}</p>\n }\n <footer class=\"confirm-dialog__footer\">\n <button type=\"button\" class=\"cms-btn\" (click)=\"onCancel()\">Cancel</button>\n <button type=\"button\" class=\"cms-btn cms-btn-danger\" (click)=\"onConfirm()\">Replace</button>\n </footer>\n </div>\n `,\n styles: [`\n :host {\n display: block;\n width: min(90vw, 420px);\n background: var(--cms-surface);\n border-radius: var(--cms-radius-lg);\n }\n .confirm-dialog__header {\n padding: 12px 16px;\n border-bottom: 1px solid var(--cms-border);\n }\n .confirm-dialog__title { margin: 0; font-size: 1rem; }\n .confirm-dialog__message {\n padding: 16px;\n margin: 0;\n color: var(--cms-text);\n line-height: 1.5;\n }\n .confirm-dialog__note {\n margin: 0;\n padding: 0 16px 16px;\n color: var(--cms-text-secondary);\n font-size: .8125rem;\n line-height: 1.5;\n }\n .confirm-dialog__footer {\n display: flex;\n justify-content: flex-end;\n gap: 8px;\n padding: 12px 16px;\n border-top: 1px solid var(--cms-border);\n }\n `],\n})\nexport class OverwriteConfirmDialogComponent {\n private readonly dialogRef = inject<DialogRef<boolean>>(DialogRef);\n protected readonly data = inject<OverwriteConfirmData>(DIALOG_DATA);\n\n onConfirm(): void { this.dialogRef.close(true); }\n onCancel(): void { this.dialogRef.close(false); }\n}\n","import {\n ChangeDetectionStrategy, Component, OnInit, computed, inject, signal,\n} from '@angular/core';\n\nimport { FormsModule } from '@angular/forms';\nimport { DIALOG_DATA, DialogRef } from '@angular/cdk/dialog';\n\ninterface SaveAsData {\n readonly sourceFilename: string;\n /**\n * When true, the edit has transparency that only PNG can store\n * (C.1d): the default name is given a `.png` extension and a hint\n * explains the format choice.\n */\n readonly forcePng?: boolean;\n}\n\nexport interface CoolmsSaveAsDialogResult {\n readonly filename: string;\n}\n\n/**\n * \"Save as new\" filename prompt.\n *\n * The collection picker stays out of scope: the backend defaults to the\n * source asset's parent directory when no target collection is supplied,\n * which is the intended UX. Closes with `{ filename }` on Save and\n * `undefined` on Cancel.\n */\n@Component({\n selector: 'coolms-image-editor-save-as-dialog',\n standalone: true,\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [FormsModule],\n template: `\n <div class=\"save-as-dialog\">\n <header class=\"save-as-dialog__header\">\n <h3 class=\"save-as-dialog__title\">Save as new image</h3>\n </header>\n <div class=\"save-as-dialog__body\">\n <label class=\"save-as-dialog__field\">\n <span>Filename</span>\n <input type=\"text\"\n class=\"form-control\"\n autofocus\n [ngModel]=\"filename()\"\n (ngModelChange)=\"filename.set($event)\"\n (keydown.enter)=\"onConfirm()\"\n placeholder=\"filename.jpg\">\n </label>\n @if (data.forcePng) {\n <p class=\"save-as-dialog__hint save-as-dialog__hint--png\">\n This edit has transparent areas, so it'll be saved as\n <strong>PNG</strong> to keep them — the name was given a\n <code>.png</code> extension.\n </p>\n }\n <p class=\"save-as-dialog__hint\">\n Saved to the same collection as the source. You can\n move the new asset later from the media library.\n </p>\n </div>\n <footer class=\"save-as-dialog__footer\">\n <button type=\"button\" class=\"cms-btn\" (click)=\"onCancel()\">Cancel</button>\n <button type=\"button\"\n class=\"cms-btn cms-btn-primary\"\n [disabled]=\"!canSubmit()\"\n (click)=\"onConfirm()\">Save</button>\n </footer>\n </div>\n `,\n styles: [`\n :host {\n display: block;\n width: min(90vw, 460px);\n background: var(--cms-surface);\n border-radius: var(--cms-radius-lg);\n }\n .save-as-dialog__header {\n padding: 12px 16px;\n border-bottom: 1px solid var(--cms-border);\n }\n .save-as-dialog__title { margin: 0; font-size: 1rem; }\n .save-as-dialog__body { padding: 16px; }\n .save-as-dialog__field {\n display: flex;\n flex-direction: column;\n gap: 4px;\n font-size: .6875rem;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: .04em;\n color: var(--cms-text-muted);\n }\n .save-as-dialog__field input {\n font-size: .875rem; font-weight: 400;\n text-transform: none; letter-spacing: 0;\n }\n .save-as-dialog__hint {\n margin: 12px 0 0;\n color: var(--cms-text-muted);\n font-size: .75rem;\n line-height: 1.5;\n }\n .save-as-dialog__hint--png {\n color: var(--cms-text-secondary);\n }\n .save-as-dialog__hint code {\n font-family: var(--cms-font-mono, monospace);\n }\n .save-as-dialog__footer {\n display: flex;\n justify-content: flex-end;\n gap: 8px;\n padding: 12px 16px;\n border-top: 1px solid var(--cms-border);\n }\n `],\n})\nexport class SaveAsDialogComponent implements OnInit {\n private readonly dialogRef = inject<DialogRef<CoolmsSaveAsDialogResult | undefined>>(DialogRef);\n protected readonly data = inject<SaveAsData>(DIALOG_DATA);\n\n readonly filename = signal<string>('');\n readonly canSubmit = computed(() => this.filename().trim() !== '');\n\n ngOnInit(): void {\n const base = this.deriveDefault(this.data.sourceFilename);\n this.filename.set(this.data.forcePng ? this.withPngExtension(base) : base);\n }\n\n onConfirm(): void {\n if (!this.canSubmit()) return;\n this.dialogRef.close({ filename: this.filename().trim() });\n }\n\n onCancel(): void {\n this.dialogRef.close(undefined);\n }\n\n private deriveDefault(sourceFilename: string): string {\n const dotIdx = sourceFilename.lastIndexOf('.');\n if (dotIdx <= 0) {\n return sourceFilename + '-edited';\n }\n const stem = sourceFilename.slice(0, dotIdx);\n const ext = sourceFilename.slice(dotIdx);\n return stem + '-edited' + ext;\n }\n\n /** Swap (or append) a `.png` extension for a transparency-preserving save. */\n private withPngExtension(name: string): string {\n const dotIdx = name.lastIndexOf('.');\n const stem = dotIdx > 0 ? name.slice(0, dotIdx) : name;\n return stem + '.png';\n }\n}\n","import { inject, Injectable } from '@angular/core';\nimport { HttpClient } from '@angular/common/http';\nimport { firstValueFrom } from 'rxjs';\n\n/**\n * HTTP client for the image-editor save flows.\n *\n * Three endpoints, one per save scenario. The host component picks\n * which one to call based on its own discriminated context (media\n * vs vfs); the service stays a thin wrapper around `HttpClient`.\n *\n * `replaceMediaAsset` -> `POST /api/v1/media/{id}/replace`\n * (Media-owned, multipart, replaces\n * asset bytes in place, triggers thumbnail\n * regeneration).\n *\n * `writeVfsFile` -> `POST /api/v1/vfs/files/binary`\n * (VFS-owned, multipart, write or\n * replace at an absolute path; explicit\n * `overwrite=true` is required to clobber\n * an existing file). Also backs media \"Save as\"\n * — a new file under `/media/{collection}/` is\n * auto-promoted to a managed asset (the old\n * `/api/v1/media/upload` route was removed).\n *\n * The legacy `/api/v1/image-editor/edit` endpoint is no longer\n * called from the frontend. It remains registered server-side and is\n * scheduled for deprecation.\n */\n@Injectable({ providedIn: 'root' })\nexport class ImageEditorHttpService {\n private readonly http = inject(HttpClient);\n\n /**\n * Overwrite an existing media asset's bytes. Same VFS path,\n * same MediaAsset id, fresh content. Backend dispatches\n * thumbnail regeneration after the write lands.\n */\n async replaceMediaAsset(params: {\n readonly blob: Blob;\n readonly assetUuid: string;\n readonly filename: string;\n }): Promise<MediaSaveResponse> {\n const form = new FormData();\n form.append('file', params.blob, params.filename);\n\n return firstValueFrom(\n this.http.post<MediaSaveResponse>(\n `/api/v1/media/${params.assetUuid}/replace`,\n form,\n ),\n );\n }\n\n /**\n * Write or replace a binary VFS file. `overwrite=true` is\n * required to clobber an existing file (the backend returns\n * 409 Conflict otherwise — an explicit safety opt-in).\n */\n async writeVfsFile(params: {\n readonly blob: Blob;\n readonly path: string;\n readonly overwrite: boolean;\n readonly filename: string;\n }): Promise<VfsSaveResponse> {\n const form = new FormData();\n form.append('file', params.blob, params.filename);\n form.append('path', params.path);\n form.append('overwrite', params.overwrite ? '1' : '0');\n\n return firstValueFrom(\n this.http.post<VfsSaveResponse>('/api/v1/vfs/files/binary', form),\n );\n }\n}\n\n/** Subset of `MediaAssetResource` the host needs after a save. */\nexport interface MediaSaveResponse {\n readonly id?: string;\n readonly mimeType?: string;\n readonly originalFilename?: string;\n /** Anything else API Platform returns; the host only reads `id`. */\n readonly [key: string]: unknown;\n}\n\n/** Subset of `NodeResource` the host needs after a VFS save. */\nexport interface VfsSaveResponse {\n readonly id?: string;\n readonly path?: string;\n readonly [key: string]: unknown;\n}\n","import {\n ChangeDetectionStrategy, Component, DestroyRef, HostBinding, HostListener,\n OnDestroy, OnInit, ViewChild,\n computed, effect, inject, signal,\n} from '@angular/core';\n\nimport { HttpClient } from '@angular/common/http';\nimport { Dialog, DIALOG_DATA, DialogRef } from '@angular/cdk/dialog';\nimport { firstValueFrom } from 'rxjs';\n\nimport { CoolmsImageEditorComponent } from '../components/coolms-image-editor.component';\nimport { OverwriteConfirmDialogComponent } from './overwrite-confirm-dialog.component';\nimport {\n SaveAsDialogComponent, type CoolmsSaveAsDialogResult,\n} from './save-as-dialog.component';\nimport {\n CoolmsImageEditorHostData, CoolmsImageEditorHostResult,\n} from './coolms-image-editor-host.types';\nimport type { ImageEditorEngine } from '../engine/image-editor-engine.interface';\n\nimport { ConfirmDialogService, EscCoordinatorService, ToastService, UnsavedChangesService } from '@coolms/ui-angular';\nimport { ImageEditorHttpService } from '../services/image-editor-http.service';\n\ntype HostState = 'preparing' | 'editing' | 'saving' | 'error';\n\n/**\n * CDK Dialog host wrapping `CoolmsImageEditorComponent`.\n *\n * Save flow (discriminated context):\n *\n * Media context:\n * Save -> OverwriteConfirm -> POST /api/v1/media/{id}/replace\n * SaveAs -> SaveAs prompt -> POST /api/v1/vfs/files/binary (new file under\n * the source collection; auto-promoted to an asset)\n *\n * VFS context:\n * Save -> OverwriteConfirm -> POST /api/v1/vfs/files/binary (overwrite=true)\n * SaveAs -> SaveAs prompt -> POST /api/v1/vfs/files/binary (overwrite=false)\n *\n * Cancel -> close with `{ kind: 'cancelled' }` in either context.\n *\n * Save button gating: in the VFS context, `canWrite=false` disables\n * Save (overwriting a read-only file would 403 anyway) but Save as\n * stays enabled — the user can always save a copy if they have\n * write permission on the parent directory.\n *\n * Failures stay non-fatal: the dialog stays open with state set back\n * to `editing` so the author can retry, and a toast carries a\n * descriptive message (status code -> friendly label, or `.message`\n * fallback). The engine remains live throughout.\n */\n@Component({\n selector: 'coolms-image-editor-host',\n standalone: true,\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [CoolmsImageEditorComponent],\n templateUrl: './coolms-image-editor-host.component.html',\n styleUrls: ['./coolms-image-editor-host.component.scss'],\n})\nexport class CoolmsImageEditorHostComponent implements OnInit, OnDestroy {\n private readonly cdkDialog = inject(Dialog);\n private readonly dialogRef = inject<DialogRef<CoolmsImageEditorHostResult>>(DialogRef);\n private readonly editService = inject(ImageEditorHttpService);\n private readonly toast = inject(ToastService);\n private readonly http = inject(HttpClient);\n private readonly esc = inject(EscCoordinatorService);\n private readonly confirm = inject(ConfirmDialogService);\n private readonly unsaved = inject(UnsavedChangesService);\n private readonly destroyRef = inject(DestroyRef);\n\n protected readonly data = inject<CoolmsImageEditorHostData>(DIALOG_DATA);\n\n readonly state = signal<HostState>('preparing');\n readonly errorMessage = signal<string | null>(null);\n\n /**\n * Object URL fed into the embedded shell. Resolved asynchronously in\n * `ngOnInit`: VFS sources go through HttpClient (so the auth interceptor\n * attaches the Bearer token) and become a `blob:` URL the engine can\n * load via a regular `<img>` element. Media sources are public, so the\n * original URL passes through unchanged.\n */\n readonly resolvedSourceUrl = signal<string | null>(null);\n\n /** Tracks the blob: URL we own so `ngOnDestroy` can revoke it. */\n private ownedObjectUrl: string | null = null;\n\n /**\n * Captured the moment the shell finishes loading the image. Save\n * actions check this through the `engineReadyOk` signal so the\n * Save buttons only enable once an engine handle is available.\n */\n private engine: ImageEditorEngine | null = null;\n\n @ViewChild(CoolmsImageEditorComponent)\n private readonly shell?: CoolmsImageEditorComponent;\n\n readonly engineReadyOk = signal<boolean>(false);\n readonly isSaving = computed(() => this.state() === 'saving');\n /** Save (overwrite) is gated on engine readiness AND, for VFS context, write permission. */\n readonly canSave = computed(() => {\n if (!this.engineReadyOk() || this.state() !== 'editing') return false;\n const data = this.data;\n if (data.context === 'vfs' && !data.node.canWrite) return false;\n return true;\n });\n /** Save as is gated only on engine readiness — even read-only sources can be saved as new. */\n readonly canSaveAs = computed(\n () => this.engineReadyOk() && this.state() === 'editing',\n );\n readonly canClose = computed(() => this.state() !== 'saving');\n\n /** Filename header label and default save-as name. */\n readonly filename = computed(\n () => this.data.context === 'media' ? this.data.asset.filename : this.data.node.filename,\n );\n /** Source MIME, drives export format. */\n readonly mimeType = computed(\n () => this.data.context === 'media' ? this.data.asset.mimeType : this.data.node.mimeType,\n );\n\n readonly dimensionsLabel = computed(() => {\n const dim = this.data.context === 'media'\n ? this.data.asset.dimensions\n : this.data.node.dimensions ?? null;\n // Defensive: backend may serialise `dimensions` as an object\n // with `null` width/height before processing completes (the\n // shape is non-null but the values are). Treat that as \"not\n // available\" rather than rendering literal \"null × null\".\n if (dim == null || dim.width == null || dim.height == null) return '';\n return `${dim.width} × ${dim.height}`;\n });\n\n /**\n * CSS-only fullscreen mode, mirroring viewer-modal's pattern.\n * Toggle from the header button or by dblclicking a non-interactive\n * area of the host. ESC exits fullscreen via the EscCoordinator\n * stack so it composes cleanly with any future dialog-level ESC\n * handlers; the host opens with CDK `disableClose: true`, so the\n * dialog itself never closes on ESC — only the X / Cancel buttons\n * exit the editor.\n */\n readonly isFullscreen = signal(false);\n\n @HostBinding('class.image-editor-host--fullscreen')\n get fullscreenClass(): boolean {\n return this.isFullscreen();\n }\n\n toggleFullscreen(): void {\n this.isFullscreen.update((v) => !v);\n }\n\n /**\n * Double-click anywhere on the dialog toggles fullscreen, EXCEPT\n * on interactive controls and the editor canvas. The canvas is\n * the primary work surface and fabric.js may bind its own\n * dblclick semantics (object enter, text edit, etc.); excluding\n * it keeps that path clear.\n */\n @HostListener('dblclick', ['$event'])\n protected onDblClick(event: MouseEvent): void {\n const target = event.target as HTMLElement | null;\n if (target?.closest('button, a, input, select, textarea, canvas')) return;\n this.toggleFullscreen();\n }\n\n constructor() {\n // beforeunload half: a tab close cannot be intercepted by\n // the Cancel button. Disposed with the component so a closed editor\n // stops voting.\n this.destroyRef.onDestroy(this.unsaved.watch(this, () => this.hasEdits()));\n\n // ESC while fullscreen exits fullscreen. No-op outside\n // fullscreen — the dialog stays open until Close X / Cancel\n // (per Decision 1: editor had no ESC handler before, and\n // adding a dialog-close shortcut could trigger unsaved-work\n // surprises without a confirm flow in place).\n effect((onCleanup) => {\n if (!this.isFullscreen()) return;\n const unregister = this.esc.register(() => {\n this.isFullscreen.set(false);\n return true;\n });\n onCleanup(unregister);\n });\n\n // Refit the fabric canvas after every fullscreen toggle. The\n // canvas-mount ResizeObserver also fires on the size change\n // but stays conservative (preserves manual zoom); fullscreen\n // is an intentional viewport switch where re-centering and\n // re-fitting beat any prior manual zoom.\n let firstRun = true;\n effect(() => {\n this.isFullscreen();\n if (firstRun) {\n firstRun = false;\n return;\n }\n // Wait one frame for the CSS class swap (and the\n // ResizeObserver) to land before measuring + refitting.\n setTimeout(() => this.shell?.refit(), 50);\n });\n }\n\n async ngOnInit(): Promise<void> {\n try {\n // VFS preview is gated by the stateless API firewall, which only\n // accepts a Bearer token on the Authorization header. Plain\n // <img src> requests don't carry one, so Toast UI's\n // loadImageFromURL -> 401 -> \"Invalid image loaded.\". Fetching\n // through HttpClient runs the auth interceptor, then we hand\n // the engine a same-origin blob: URL it can render normally.\n // Media URLs are public, so we pass them through unchanged.\n if (this.data.context === 'vfs') {\n const blob = await firstValueFrom(\n this.http.get(this.data.node.sourceUrl, { responseType: 'blob' }),\n );\n this.ownedObjectUrl = URL.createObjectURL(blob);\n this.resolvedSourceUrl.set(this.ownedObjectUrl);\n } else {\n this.resolvedSourceUrl.set(this.data.asset.originalUrl);\n }\n this.state.set('editing');\n } catch (err) {\n this.state.set('error');\n this.errorMessage.set('Failed to load image: ' + this.describeError(err));\n }\n }\n\n ngOnDestroy(): void {\n if (this.ownedObjectUrl !== null) {\n URL.revokeObjectURL(this.ownedObjectUrl);\n this.ownedObjectUrl = null;\n }\n }\n\n onEngineReady(engine: ImageEditorEngine): void {\n this.engine = engine;\n this.engineReadyOk.set(true);\n }\n\n onShellError(err: Error): void {\n this.state.set('error');\n this.errorMessage.set(err.message);\n }\n\n async onSave(): Promise<void> {\n if (!this.canSave()) return;\n\n // Warn when transparency forces a JPEG -> PNG format change on\n // an in-place overwrite (C.1d) so it isn't a silent surprise.\n const willConvertToPng =\n this.contentWantsPng() && this.deriveFormat(this.mimeType(), false) !== 'png';\n\n const confirmRef = this.cdkDialog.open<boolean>(OverwriteConfirmDialogComponent, {\n data: {\n filename: this.filename(),\n formatNote: willConvertToPng\n ? 'This edit has transparent areas, so it will be saved as PNG — the original format can’t store transparency.'\n : undefined,\n },\n backdropClass: 'cdk-overlay-dark-backdrop',\n });\n const confirmed = await firstValueFrom(confirmRef.closed);\n if (confirmed !== true) return;\n\n await this.executeSave('overwrite');\n }\n\n async onSaveAs(): Promise<void> {\n if (!this.canSaveAs()) return;\n\n // Pre-fill the save-as name with a .png extension (and explain why)\n // when transparency forces PNG over a non-PNG source (C.1d).\n const forcePng =\n this.contentWantsPng() && this.deriveFormat(this.mimeType(), false) !== 'png';\n\n const dialogRef = this.cdkDialog.open<CoolmsSaveAsDialogResult | undefined>(\n SaveAsDialogComponent,\n {\n data: { sourceFilename: this.filename(), forcePng },\n backdropClass: 'cdk-overlay-dark-backdrop',\n },\n );\n const result = await firstValueFrom(dialogRef.closed);\n if (result === undefined) return;\n\n await this.executeSave('save_as_new', result.filename);\n }\n\n /**\n * `canClose()` only ever meant \"not mid-save\" -- there was no dirty\n * concept here at all, so a crop, a rotate and three filters were\n * thrown away by Cancel without a word.\n *\n * `engine.canUndo()` is the dirty flag we would otherwise have had to\n * invent: it is true exactly when the user has done something undoable,\n * and it goes back to false if they undo their way to the start.\n */\n onCancel(): void {\n if (!this.canClose()) return;\n\n if (!this.hasEdits()) {\n this.dialogRef.close({ kind: 'cancelled' });\n\n return;\n }\n\n this.confirm.confirmDiscard(this.filename()).subscribe((discard) => {\n if (discard) this.dialogRef.close({ kind: 'cancelled' });\n });\n }\n\n /** The engine's undo depth IS \"has anything been edited\". */\n private hasEdits(): boolean {\n return this.engine?.canUndo() ?? false;\n }\n\n private async executeSave(\n mode: 'overwrite' | 'save_as_new',\n filename?: string,\n ): Promise<void> {\n const engine = this.engine;\n if (engine === null) return;\n\n this.state.set('saving');\n\n try {\n // Drain any in-flight tool so a mid-edit cropper overlay\n // doesn't get baked into the exported pixels (same safety\n // net as beta.4a).\n this.shell?.deactivateActiveTool();\n\n const format = this.deriveFormat(this.mimeType(), engine.hasAlpha());\n const blob = await engine.export(format, 0.92);\n\n const result = this.data.context === 'media'\n ? await this.saveMedia(this.data, mode, blob, filename, format)\n : await this.saveVfs(this.data, mode, blob, filename, format);\n\n this.toast.success(mode === 'overwrite' ? 'Image saved' : 'New image created');\n this.dialogRef.close(result);\n } catch (error) {\n this.state.set('editing');\n this.toast.error('Save failed: ' + this.describeError(error));\n console.error('CoolmsImageEditorHost save failed:', error);\n }\n }\n\n private async saveMedia(\n data: Extract<CoolmsImageEditorHostData, { context: 'media' }>,\n mode: 'overwrite' | 'save_as_new',\n blob: Blob,\n newFilename: string | undefined,\n format: 'png' | 'jpeg',\n ): Promise<CoolmsImageEditorHostResult> {\n if (mode === 'overwrite') {\n // A transparency-forced PNG of a JPEG source changes the\n // bytes' format; the replace endpoint allows same-major-type\n // (image/jpeg -> image/png) and re-derives the MIME from the\n // content, so a matching .png name keeps the asset coherent.\n const response = await this.editService.replaceMediaAsset({\n blob,\n assetUuid: data.asset.uuid,\n filename: this.ensureExtension(data.asset.filename, format),\n });\n return {\n kind: 'saved',\n mode: 'overwrite',\n assetUuid: typeof response.id === 'string' && response.id !== '' ? response.id : data.asset.uuid,\n };\n }\n\n // \"Save as\" writes a fresh file via the live VFS binary endpoint.\n // The old `POST /api/v1/media/upload` route was removed (#87), so a\n // new image is created the current way: write it under the source\n // collection's `/media/{collection}/` directory and let the VFS-change\n // listeners auto-promote it to a managed media asset with thumbnails\n //. It then appears in the grid via the realtime refresh.\n const finalName = this.ensureExtension(newFilename ?? this.deriveSaveAsName(data.asset.filename), format);\n const targetDir = this.parentDir(data.asset.path ?? null) ?? '/media/uploads';\n const newPath = this.joinPath(targetDir, finalName);\n const response = await this.editService.writeVfsFile({\n blob,\n path: newPath,\n overwrite: false,\n filename: finalName,\n });\n return {\n kind: 'saved',\n mode: 'save_as_new',\n assetUuid: typeof response.id === 'string' && response.id !== '' ? response.id : undefined,\n };\n }\n\n private async saveVfs(\n data: Extract<CoolmsImageEditorHostData, { context: 'vfs' }>,\n mode: 'overwrite' | 'save_as_new',\n blob: Blob,\n newFilename: string | undefined,\n format: 'png' | 'jpeg',\n ): Promise<CoolmsImageEditorHostResult> {\n if (mode === 'overwrite') {\n // Overwrite is pinned to the existing path, so the extension\n // can't change here; the bytes carry the (possibly PNG)\n // format and the VFS write re-derives the MIME from content.\n await this.editService.writeVfsFile({\n blob,\n path: data.node.path,\n overwrite: true,\n filename: data.node.filename,\n });\n return { kind: 'saved', mode: 'overwrite', vfsPath: data.node.path };\n }\n\n const finalName = this.ensureExtension(newFilename ?? this.deriveSaveAsName(data.node.filename), format);\n const newPath = this.joinPath(data.node.parentPath, finalName);\n await this.editService.writeVfsFile({\n blob,\n path: newPath,\n overwrite: false,\n filename: finalName,\n });\n return { kind: 'saved', mode: 'save_as_new', vfsPath: newPath };\n }\n\n /**\n * Pull a user-readable message out of whatever the HTTP layer\n * threw at us. Angular's `HttpErrorResponse` implements the\n * `Error` interface but doesn't extend the class, so a plain\n * `instanceof Error` check misses it and we'd fall through to\n * \"unknown error\".\n */\n private describeError(error: unknown): string {\n if (error !== null && typeof error === 'object') {\n const status = (error as { status?: unknown }).status;\n if (typeof status === 'number') {\n if (status === 403) return 'permission denied (403)';\n if (status === 404) return 'asset not found (404)';\n if (status === 409) return 'a file already exists at that name (409)';\n if (status === 0) return 'network error';\n return `HTTP ${status}`;\n }\n const message = (error as { message?: unknown }).message;\n if (typeof message === 'string' && message !== '') return message;\n }\n if (error instanceof Error && error.message !== '') return error.message;\n return 'unknown error';\n }\n\n /**\n * Export format. Content wins over source: when the flattened image\n * has any transparency (a mask / clipPath cut-out, or a transparent\n * source) we force PNG, because flattening it onto an opaque JPEG\n * loses the cut-away region to opaque black (the C.1d fix — masked\n * Save-as previously baked black corners). Otherwise it follows the\n * source MIME (PNG stays PNG, everything else -> JPEG, the two formats\n * the underlying canvas reliably encodes).\n */\n private deriveFormat(mimeType: string, hasAlpha: boolean): 'png' | 'jpeg' {\n if (hasAlpha) return 'png';\n return mimeType === 'image/png' ? 'png' : 'jpeg';\n }\n\n /** Whether the current edit has transparency the export must preserve. */\n private contentWantsPng(): boolean {\n return this.engine?.hasAlpha() ?? false;\n }\n\n /**\n * Normalise a filename's extension to match the export format, so a\n * forced-PNG save (transparency preserved) doesn't keep a `.jpg`\n * name. `jpg`/`jpeg` both satisfy the JPEG format.\n */\n private ensureExtension(name: string, format: 'png' | 'jpeg'): string {\n const dot = name.lastIndexOf('.');\n const cur = dot > 0 ? name.slice(dot).toLowerCase() : '';\n if (format === 'png' && cur === '.png') return name;\n if (format === 'jpeg' && (cur === '.jpg' || cur === '.jpeg')) return name;\n const stem = dot > 0 ? name.slice(0, dot) : name;\n return stem + (format === 'png' ? '.png' : '.jpg');\n }\n\n private deriveSaveAsName(source: string): string {\n const dotIdx = source.lastIndexOf('.');\n if (dotIdx <= 0) return source + '-edited';\n return source.slice(0, dotIdx) + '-edited' + source.slice(dotIdx);\n }\n\n private parentDir(path: string | null): string | null {\n if (path === null || path === '') return null;\n const trimmed = path.replace(/\\/+$/, '');\n const idx = trimmed.lastIndexOf('/');\n if (idx <= 0) return '/';\n return trimmed.slice(0, idx);\n }\n\n private joinPath(parent: string, name: string): string {\n const left = parent.replace(/\\/+$/, '');\n const right = name.replace(/^\\/+/, '');\n return `${left}/${right}`;\n }\n}\n","<div class=\"image-editor-host\">\n <header class=\"image-editor-host__header\">\n <div class=\"image-editor-host__title\">\n <i class=\"bi bi-image\"></i>\n <span class=\"image-editor-host__filename\">{{ filename() }}</span>\n @if (dimensionsLabel() !== '') {\n <span class=\"image-editor-host__dimensions\">{{ dimensionsLabel() }}</span>\n }\n </div>\n <div class=\"image-editor-host__header-actions\">\n <button type=\"button\"\n class=\"image-editor-host__icon-btn\"\n [attr.aria-pressed]=\"isFullscreen()\"\n [attr.aria-label]=\"isFullscreen() ? 'Exit fullscreen' : 'Enter fullscreen'\"\n [attr.title]=\"isFullscreen() ? 'Exit fullscreen' : 'Fullscreen'\"\n (click)=\"toggleFullscreen()\">\n <i class=\"bi\"\n [class.bi-fullscreen]=\"!isFullscreen()\"\n [class.bi-fullscreen-exit]=\"isFullscreen()\"></i>\n </button>\n <button type=\"button\"\n class=\"image-editor-host__icon-btn image-editor-host__close\"\n aria-label=\"Close\"\n [disabled]=\"!canClose()\"\n (click)=\"onCancel()\">\n <i class=\"bi bi-x-lg\"></i>\n </button>\n </div>\n </header>\n\n <div class=\"image-editor-host__body\">\n @if (resolvedSourceUrl(); as src) {\n <coolms-image-editor\n [sourceUrl]=\"src\"\n [sourceFilename]=\"filename()\"\n (engineReady)=\"onEngineReady($event)\"\n (failed)=\"onShellError($event)\" />\n }\n\n @if (state() === 'preparing') {\n <div class=\"image-editor-host__overlay\">\n <span>Loading&hellip;</span>\n </div>\n }\n @if (state() === 'saving') {\n <div class=\"image-editor-host__overlay\">\n <span>Saving&hellip;</span>\n </div>\n }\n @if (state() === 'error' && errorMessage() !== null) {\n <div class=\"image-editor-host__overlay image-editor-host__overlay--error\">\n <i class=\"bi bi-exclamation-triangle\"></i>\n <span>{{ errorMessage() }}</span>\n </div>\n }\n </div>\n\n <footer class=\"image-editor-host__footer\">\n <button type=\"button\"\n class=\"cms-btn\"\n [disabled]=\"!canClose()\"\n (click)=\"onCancel()\">\n Cancel\n </button>\n <div class=\"image-editor-host__actions\">\n <button type=\"button\"\n class=\"cms-btn\"\n [disabled]=\"!canSaveAs()\"\n (click)=\"onSaveAs()\">\n Save as&hellip;\n </button>\n <button type=\"button\"\n class=\"cms-btn cms-btn-primary\"\n [disabled]=\"!canSave()\"\n (click)=\"onSave()\">\n {{ isSaving() ? 'Saving…' : 'Save' }}\n </button>\n </div>\n </footer>\n</div>\n","/**\n * @coolms/image-editor — public surface.\n *\n * Consumers (UI shells, smoke tests, future tools) import from\n * `@coolms/image-editor` only. The barrel keeps the internal file\n * layout reorganisable without breaking downstream imports.\n *\n * surface: engine + types + shell components + CDK Dialog\n * host. Tools land iteratively in beta.4.\n */\n\n// Engine contract + reference adapter\nexport type { ImageEditorEngine } from './engine/image-editor-engine.interface';\nexport { FabricEngineAdapter } from './engine/fabric-engine.adapter';\n\n// Event surface\nexport type {\n EngineEvents,\n EngineEventType,\n EngineEventHandler,\n} from './engine/engine-events';\n\n// Geometry primitives\nexport type { Point, Size, Rect, Bounds } from './types/geometry.types';\n\n// Annotation-authoring seams (geometry over the image, e.g. ImageMap regions)\nexport type { ShapeGeometry, AnnotationShapeOptions } from './types/layer.types';\n\n// Filter contract\nexport type { FilterName, FilterParams } from './types/filter.types';\n\n// Engine construction options\nexport type { EngineOptions } from './types/engine-options.types';\n\n// Shell components (beta.3)\nexport { CoolmsImageEditorComponent } from './components/coolms-image-editor.component';\nexport { ImageEditorStateService, type EditorState } from './services/image-editor-state.service';\n\n// CDK Dialog host (beta.3)\nexport { CoolmsImageEditorHostComponent } from './host/coolms-image-editor-host.component';\nexport type {\n CoolmsImageEditorHostData,\n CoolmsImageEditorHostResult,\n} from './host/coolms-image-editor-host.types';\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":["FabricRect","fabricConfig"],"mappings":";;;;;;;;;;;AAAA;;;;;;;;;;;;;;;;AAgBG;AAmHI,MAAM,qBAAqB,GAAiB;AAC/C,IAAA,IAAI,EAAS,SAAS;AACtB,IAAA,MAAM,EAAO,SAAS;AACtB,IAAA,WAAW,EAAE,CAAC;CACjB;AAED;AACO,MAAM,iBAAiB,GAAa;AACvC,IAAA,IAAI,EAAI,OAAO;IACf,KAAK,EAAG,qBAAqB,CAAC,IAAI;;;AAGlC,IAAA,MAAM,EAAE,SAAS;AACjB,IAAA,KAAK,EAAG,CAAC;CACZ;AAEM,MAAM,oBAAoB,GAAgB;AAC7C,IAAA,IAAI,EAAQ,MAAM;AAClB,IAAA,UAAU,EAAE,OAAO;AACnB,IAAA,QAAQ,EAAI,EAAE;AACd,IAAA,IAAI,EAAQ,SAAS;AACrB,IAAA,UAAU,EAAE,QAAQ;AACpB,IAAA,SAAS,EAAG,QAAQ;AACpB,IAAA,SAAS,EAAG,MAAM;CACrB;AAED;AACO,MAAM,kBAAkB,GAAG;IAC9B,OAAO;IACP,WAAW;IACX,iBAAiB;IACjB,SAAS;IACT,aAAa;IACb,SAAS;IACT,cAAc;IACd,QAAQ;CACF;AAyCV;AACO,MAAM,iBAAiB,GAAa;AACvC,IAAA,KAAK,EAAG,MAAM;AACd,IAAA,KAAK,EAAG,CAAC;AACT,IAAA,MAAM,EAAE,EAAE;CACb;AAED;;;AAGG;AACI,MAAM,UAAU,GAA2D;AAC9E,IAAA,IAAI,EAAK,uEAAuE;AAChF,IAAA,KAAK,EAAI,mHAAmH;AAC5H,IAAA,OAAO,EAAE,0CAA0C;CAC7C;;AC7NV;;;;;AAKG;MACU,YAAY,CAAA;IACb,SAAS,GAAoB,EAAE;IAC/B,SAAS,GAAoB,EAAE;AAEvC,IAAA,IAAI,CAAC,GAAkB,EAAA;AACnB,QAAA,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,GAAG,CAAC;AACxB,QAAA,IAAI,CAAC,SAAS,GAAG,EAAE;IACvB;AAEA,IAAA,MAAM,IAAI,GAAA;QACN,MAAM,GAAG,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,EAAE;QAChC,IAAI,GAAG,KAAK,SAAS;YAAE;AACvB,QAAA,MAAM,GAAG,CAAC,IAAI,EAAE;AAChB,QAAA,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,GAAG,CAAC;IAC5B;AAEA,IAAA,MAAM,IAAI,GAAA;QACN,MAAM,GAAG,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,EAAE;QAChC,IAAI,GAAG,KAAK,SAAS;YAAE;AACvB,QAAA,MAAM,GAAG,CAAC,EAAE,EAAE;AACd,QAAA,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,GAAG,CAAC;IAC5B;IAEA,OAAO,GAAA,EAAc,OAAO,IAAI,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IACvD,OAAO,GAAA,EAAc,OAAO,IAAI,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IAEvD,SAAS,GAAA,EAAW,IAAI,CAAC,SAAS,GAAG,EAAE,CAAC,CAAC;IAEzC,KAAK,GAAA;AACD,QAAA,IAAI,CAAC,SAAS,GAAG,EAAE;AACnB,QAAA,IAAI,CAAC,SAAS,GAAG,EAAE;IACvB;AACH;;ACsBD,MAAM,cAAc,GAAsB,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC;AAEzE;;;;;AAKG;AACH,MAAM,oBAAoB,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,EAAW;AAEzE;;;;;;;;;;;;;;;;;;;;;;;AAuBG;MACU,mBAAmB,CAAA;IACpB,OAAgB,cAAc,GAAkD;QACpF,KAAK,EAAM,OAAO,CAAC,KAAK;QACxB,SAAS,EAAE,OAAO,CAAC,SAAS;QAC5B,MAAM,EAAK,OAAO,CAAC,MAAM;KAC5B;IAEO,OAAgB,cAAc,GAAkD;QACpF,UAAU,EAAE,OAAO,CAAC,UAAU;QAC9B,QAAQ,EAAI,OAAO,CAAC,QAAQ;QAC5B,UAAU,EAAE,OAAO,CAAC,UAAU;QAC9B,IAAI,EAAQ,OAAO,CAAC,IAAI;QACxB,KAAK,EAAO,OAAO,CAAC,KAAK;QACzB,QAAQ,EAAI,OAAO,CAAC,QAAQ;KAC/B;AAEgB,IAAA,MAAM;AACN,IAAA,QAAQ;AACR,IAAA,SAAS;;AAElB,IAAA,OAAgB,kBAAkB,GAAG,yBAAyB;AAErD,IAAA,SAAS,GAAG,IAAI,GAAG,EAA6C;AAChE,IAAA,YAAY,GAAG,IAAI,YAAY,EAAE;IAE1C,KAAK,GAAuB,IAAI;IAChC,UAAU,GAA2B,IAAI;IACzC,cAAc,GAAwE,IAAI;IAC1F,WAAW,GAAsB,IAAI;IACrC,YAAY,GAAsB,IAAI;IACtC,sBAAsB,GAA+B,IAAI;;;IAIzD,WAAW,GAAG,CAAC;AACvB;;;;AAIG;IACK,oBAAoB,GAAgE,IAAI;AAEhG,IAAA,WAAA,CAAoB,MAAc,EAAE,QAA2B,EAAE,SAAsB,EAAA;AACnF,QAAA,IAAI,CAAC,MAAM,GAAG,MAAM;AACpB,QAAA,IAAI,CAAC,QAAQ,GAAG,QAAQ;AACxB,QAAA,IAAI,CAAC,SAAS,GAAG,SAAS;QAC1B,IAAI,CAAC,qBAAqB,EAAE;IAChC;AAEA;;;;AAIG;AACH,IAAA,aAAa,MAAM,CAAC,OAAkC,EAAA;AAClD,QAAA,MAAM,SAAS,GAAG,OAAO,CAAC,SAAS;QACnC,MAAM,QAAQ,GAAG,QAAQ,CAAC,aAAa,CAAC,QAAQ,CAAC;AACjD,QAAA,QAAQ,CAAC,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,SAAS,CAAC,WAAW,CAAC;AACnD,QAAA,QAAQ,CAAC,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,SAAS,CAAC,YAAY,CAAC;AACrD,QAAA,SAAS,CAAC,WAAW,CAAC,QAAQ,CAAC;AAE/B,QAAA,MAAM,MAAM,GAAG,IAAI,MAAM,CAAC,QAAQ,EAAE;AAChC,YAAA,sBAAsB,EAAE,IAAI;AAC5B,YAAA,SAAS,EAAe,IAAI;AAC5B,YAAA,eAAe,EAAS,aAAa;AACrC,YAAA,iBAAiB,EAAO,IAAI;AAC/B,SAAA,CAAC;QAEF,OAAO,IAAI,mBAAmB,CAAC,MAAM,EAAE,QAAQ,EAAE,SAAS,CAAC;IAC/D;AAEA,IAAA,MAAM,SAAS,CAAC,MAAqB,EAAE,IAAI,GAAG,OAAO,EAAA;AACjD,QAAA,MAAM,GAAG,GAAG,OAAO,MAAM,KAAK;AAC1B,cAAE;AACF,cAAE,GAAG,CAAC,eAAe,CAAC,MAAM,CAAC;AACjC,QAAA,MAAM,OAAO,GAAG,OAAO,MAAM,KAAK,QAAQ;AAE1C,QAAA,IAAI;AACA,YAAA,MAAM,KAAK,GAAG,MAAM,WAAW,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,WAAW,EAAE,WAAW,EAAE,EAAE,oBAAoB,CAAC;AAChG,YAAA,IAAI,IAAI,CAAC,KAAK,KAAK,IAAI,EAAE;gBACrB,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC;YAClC;;;YAGA,IAAI,CAAC,kBAAkB,EAAE;YACzB,IAAI,CAAC,kBAAkB,EAAE;AACzB,YAAA,IAAI,CAAC,KAAK,GAAG,KAAK;YAClB,IAAI,CAAC,UAAU,CAAC,KAAK,EAAE,OAAO,EAAE,YAAY,CAAC;AAC7C,YAAA,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC;AACtB,YAAA,IAAI,CAAC,MAAM,CAAC,YAAY,CAAC,KAAK,CAAC;;;;;;;AAO/B,YAAA,IAAI,CAAC,MAAM,CAAC,oBAAoB,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;YACpD,IAAI,CAAC,eAAe,EAAE;AACtB,YAAA,IAAI,CAAC,MAAM,CAAC,gBAAgB,EAAE;AAC9B,YAAA,IAAI,CAAC,YAAY,CAAC,KAAK,EAAE;AAEzB,YAAA,IAAI,CAAC,cAAc,GAAG,OAAO,MAAM,KAAK;AACpC,kBAAE,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI;kBACnB,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE;AAE5B,YAAA,MAAM,IAAI,GAAS,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE;AAC/D,YAAA,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,IAAI,CAAC;AAC9B,YAAA,IAAI,CAAC,IAAI,CAAC,cAAc,EAAE,SAAS,CAAC;AACpC,YAAA,IAAI,CAAC,IAAI,CAAC,qBAAqB,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;AACpE,YAAA,IAAI,CAAC,IAAI,CAAC,eAAe,EAAE,SAAS,CAAC;AACrC,YAAA,IAAI,CAAC,IAAI,CAAC,qBAAqB,EAAE,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;AAC1D,YAAA,OAAO,IAAI;QACf;gBAAU;AACN,YAAA,IAAI,OAAO;AAAE,gBAAA,GAAG,CAAC,eAAe,CAAC,GAAG,CAAC;QACzC;IACJ;AAEA,IAAA,MAAM,KAAK,GAAA;AACP,QAAA,IAAI,IAAI,CAAC,cAAc,KAAK,IAAI;YAAE;AAClC,QAAA,MAAM,GAAG,GAAG,IAAI,CAAC,cAAc;AAC/B,QAAA,MAAM,MAAM,GAAG,KAAK,IAAI,GAAG,GAAG,GAAG,CAAC,GAAG,GAAG,GAAG,CAAC,IAAI;QAChD,MAAM,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,GAAG,CAAC,IAAI,CAAC;IAC1C;IAEA,MAAM,IAAI,CAAC,eAAqB,EAAA;AAC5B,QAAA,MAAM,KAAK,GAAG,IAAI,CAAC,YAAY,EAAE;AACjC,QAAA,MAAM,WAAW,GAAG,KAAK,CAAC,eAAe,EAAE;;;;;;;;;AAU3C,QAAA,MAAM,KAAK,GAAG,KAAK,CAAC,eAAe,CAAC,EAAE,UAAU,EAAE,CAAC,EAAE,CAAC;AAEtD,QAAA,MAAM,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,eAAe,CAAC,CAAC,GAAG,WAAW,CAAC,IAAI,CAAC;AAC5D,QAAA,MAAM,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,eAAe,CAAC,CAAC,GAAG,WAAW,CAAC,GAAG,CAAC;QAC3D,MAAM,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,eAAe,CAAC,KAAK,EAAG,WAAW,CAAC,KAAK,GAAI,EAAE,CAAC,CAAC;QACjF,MAAM,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,eAAe,CAAC,MAAM,EAAE,WAAW,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC;QAEjF,MAAM,MAAM,GAAG,QAAQ,CAAC,aAAa,CAAC,QAAQ,CAAC;QAC/C,MAAM,CAAC,KAAK,GAAI,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;QAC9B,MAAM,CAAC,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;QAC9B,MAAM,GAAG,GAAG,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC;AACnC,QAAA,IAAI,GAAG,KAAK,IAAI,EAAE;AACd,YAAA,MAAM,IAAI,KAAK,CAAC,sDAAsD,CAAC;QAC3E;QACA,GAAG,CAAC,SAAS,CAAC,KAAK,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,CAAC;QACvE,MAAM,UAAU,GAAG,MAAM,CAAC,SAAS,CAAC,WAAW,CAAC;;;;;;;;;;QAWhD,MAAM,mBAAmB,GAAG,KAAK,CAAC,SAAS,CAAC,WAAW,CAAC;;;;;;;;;;AAWxD,QAAA,MAAM,OAAO,GAAG,IAAI,CAAC,YAAY;AAC5B,aAAA,MAAM,CAAC,CAAC,IAAI,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,KAAK,OAAO;AACzC,aAAA,GAAG,CAAC,CAAC,KAAK;AACP,YAAA,GAAG,EAAG,CAAC;YACP,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,IAAI,WAAW,CAAC,IAAI;YACtC,GAAG,EAAG,CAAC,CAAC,CAAC,GAAG,IAAK,CAAC,IAAI,WAAW,CAAC,GAAG;AACxC,SAAA,CAAC,CAAC;QACP,MAAM,WAAW,GAAG,CAAC,UAAkB,EAAE,SAAiB,EAAE,KAAa,EAAE,KAAa,KAAU;YAC9F,KAAK,MAAM,EAAE,GAAG,EAAE,IAAI,EAAE,GAAG,EAAE,IAAI,OAAO,EAAE;gBACtC,GAAG,CAAC,GAAG,CAAC,EAAE,IAAI,EAAE,UAAU,GAAG,IAAI,GAAG,KAAK,EAAE,GAAG,EAAE,SAAS,GAAG,GAAG,GAAG,KAAK,EAAE,CAAC;gBAC1E,GAAG,CAAC,SAAS,EAAE;YACnB;AACJ,QAAA,CAAC;AAED,QAAA,MAAM,QAAQ,GAAG,MAAM,WAAW,CAAC,OAAO,CAAC,UAAU,EAAE,SAAS,EAAE,oBAAoB,CAAC;AACvF,QAAA,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC;AACzB,QAAA,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC;AAC3B,QAAA,WAAW,CAAC,QAAQ,CAAC,IAAI,IAAI,CAAC,EAAE,QAAQ,CAAC,GAAG,IAAI,CAAC,EAAE,EAAE,EAAE,EAAE,CAAC;AAC1D,QAAA,IAAI,CAAC,MAAM,CAAC,gBAAgB,EAAE;QAE9B,IAAI,CAAC,WAAW,CAAC;AACb,YAAA,IAAI,EAAE,MAAM;YACZ,EAAE,EAAE,YAAW;AACX,gBAAA,IAAI,IAAI,CAAC,KAAK,KAAK,QAAQ;oBAAE;gBAC7B,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,YAAY,EAAE,CAAC;AACvC,gBAAA,MAAM,MAAM,GAAG,MAAM,WAAW,CAAC,OAAO,CAAC,UAAU,EAAE,SAAS,EAAE,oBAAoB,CAAC;AACrF,gBAAA,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC;AACzB,gBAAA,WAAW,CAAC,MAAM,CAAC,IAAI,IAAI,CAAC,EAAE,MAAM,CAAC,GAAG,IAAI,CAAC,EAAE,EAAE,EAAE,EAAE,CAAC;AACtD,gBAAA,IAAI,CAAC,MAAM,CAAC,gBAAgB,EAAE;YAClC,CAAC;YACD,IAAI,EAAE,YAAW;gBACb,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,YAAY,EAAE,CAAC;AACvC,gBAAA,MAAM,QAAQ,GAAG,MAAM,WAAW,CAAC,OAAO,CAAC,mBAAmB,EAAE,SAAS,EAAE,oBAAoB,CAAC;AAChG,gBAAA,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC;AAC3B,gBAAA,WAAW,CAAC,QAAQ,CAAC,IAAI,IAAI,CAAC,EAAE,QAAQ,CAAC,GAAG,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;AACxD,gBAAA,IAAI,CAAC,MAAM,CAAC,gBAAgB,EAAE;YAClC,CAAC;AACJ,SAAA,CAAC;IACN;AAEA,IAAA,MAAM,aAAa,GAAA;AACf,QAAA,MAAM,KAAK,GAAG,IAAI,CAAC,YAAY,EAAE;AACjC,QAAA,IAAI,IAAI,CAAC,WAAW,KAAK,IAAI;YAAE;;;;;;;AAQ/B,QAAA,KAAK,CAAC,UAAU,GAAG,KAAK;AACxB,QAAA,KAAK,CAAC,OAAO,GAAM,KAAK;AACxB,QAAA,IAAI,CAAC,oBAAoB,CAAC,KAAK,CAAC;;;AAIhC,QAAA,IAAI,IAAI,CAAC,YAAY,KAAK,IAAI,EAAE;AAC5B,YAAA,IAAI,CAAC,YAAY,CAAC,OAAO,GAAG,KAAK;QACrC;AAEA,QAAA,MAAM,MAAM,GAAG,KAAK,CAAC,eAAe,EAAE;AACtC,QAAA,MAAM,OAAO,GAAG,IAAIA,IAAU,CAAC;;;;;AAK3B,YAAA,OAAO,EAAc,MAAM;AAC3B,YAAA,OAAO,EAAc,KAAK;YAC1B,IAAI,EAAiB,MAAM,CAAC,IAAI;YAChC,GAAG,EAAkB,MAAM,CAAC,GAAG;YAC/B,KAAK,EAAgB,MAAM,CAAC,KAAK;YACjC,MAAM,EAAe,MAAM,CAAC,MAAM;AAClC,YAAA,IAAI,EAAiB,eAAe;AACpC,YAAA,MAAM,EAAe,SAAS;AAC9B,YAAA,eAAe,EAAM,CAAC,CAAC,EAAE,CAAC,CAAC;AAC3B,YAAA,aAAa,EAAQ,IAAI;AACzB,YAAA,WAAW,EAAU,QAAQ;;;;;;AAM7B,YAAA,WAAW,EAAU,SAAS;AAC9B,YAAA,iBAAiB,EAAI,SAAS;AAC9B,YAAA,kBAAkB,EAAG,KAAK;AAC1B,YAAA,YAAY,EAAS,IAAI;AACzB,YAAA,gBAAgB,EAAK,KAAK;AAC1B,YAAA,eAAe,EAAM,KAAK;AAC1B,YAAA,aAAa,EAAQ,KAAK;AACtB,SAAA,CAAC;AACT,QAAA,IAAI,CAAC,WAAW,GAAG,OAAO;AAC1B,QAAA,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC;AACxB,QAAA,IAAI,CAAC,MAAM,CAAC,eAAe,CAAC,OAAO,CAAC;AACpC,QAAA,IAAI,CAAC,MAAM,CAAC,gBAAgB,EAAE;IAClC;AAEA,IAAA,MAAM,YAAY,GAAA;AACd,QAAA,IAAI,IAAI,CAAC,WAAW,KAAK,IAAI,EAAE;YAC3B,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC;AACpC,YAAA,IAAI,CAAC,WAAW,GAAG,IAAI;QAC3B;AACA,QAAA,IAAI,IAAI,CAAC,KAAK,KAAK,IAAI,EAAE;AACrB,YAAA,IAAI,CAAC,KAAK,CAAC,UAAU,GAAG,IAAI;AAC5B,YAAA,IAAI,CAAC,KAAK,CAAC,OAAO,GAAM,IAAI;QAChC;AACA,QAAA,IAAI,CAAC,oBAAoB,CAAC,IAAI,CAAC;AAC/B,QAAA,IAAI,IAAI,CAAC,YAAY,KAAK,IAAI,EAAE;AAC5B,YAAA,IAAI,CAAC,YAAY,CAAC,OAAO,GAAG,IAAI;YAChC,IAAI,CAAC,gBAAgB,EAAE;QAC3B;AACA,QAAA,IAAI,CAAC,MAAM,CAAC,mBAAmB,EAAE;AACjC,QAAA,IAAI,CAAC,MAAM,CAAC,gBAAgB,EAAE;IAClC;;AAGQ,IAAA,oBAAoB,CAAC,OAAgB,EAAA;QACzC,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,YAAY,EAAE,EAAE;AACjC,YAAA,IAAI,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,KAAK,OAAO;gBAAE;AACnC,YAAA,CAAC,CAAC,UAAU,GAAG,OAAO;AACtB,YAAA,CAAC,CAAC,OAAO,GAAM,OAAO;QAC1B;IACJ;AAEA,IAAA,kBAAkB,CAAC,KAAoB,EAAA;AACnC,QAAA,MAAM,OAAO,GAAG,IAAI,CAAC,WAAW;AAChC,QAAA,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK;AACxB,QAAA,IAAI,OAAO,KAAK,IAAI,IAAI,KAAK,KAAK,IAAI;YAAE;AAExC,QAAA,IAAI,KAAK,KAAK,IAAI,EAAE;AACf,YAAA,OAAe,CAAC,cAAc,GAAG,KAAK;AACvC,YAAA,IAAI,CAAC,MAAM,CAAC,gBAAgB,EAAE;YAC9B;QACJ;AAEA,QAAA,MAAM,MAAM,GAAG,KAAK,CAAC,eAAe,EAAE;AACtC,QAAA,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,GAAG,KAAK,CAAC;AAC1D,QAAA,MAAM,IAAI,GAAG,IAAI,GAAG,KAAK;QACzB,OAAO,CAAC,GAAG,CAAC;AACR,YAAA,IAAI,EAAI,MAAM,CAAC,IAAI,GAAG,CAAC,MAAM,CAAC,KAAK,GAAG,IAAI,IAAI,CAAC;AAC/C,YAAA,GAAG,EAAK,MAAM,CAAC,GAAG,GAAG,CAAC,MAAM,CAAC,MAAM,GAAG,IAAI,IAAI,CAAC;AAC/C,YAAA,KAAK,EAAG,IAAI;AACZ,YAAA,MAAM,EAAE,IAAI;AACZ,YAAA,MAAM,EAAE,CAAC;AACT,YAAA,MAAM,EAAE,CAAC;AACZ,SAAA,CAAC;AACD,QAAA,OAAe,CAAC,cAAc,GAAG,IAAI;QACtC,OAAO,CAAC,SAAS,EAAE;AACnB,QAAA,IAAI,CAAC,MAAM,CAAC,gBAAgB,EAAE;IAClC;IAEA,WAAW,GAAA;AACP,QAAA,MAAM,OAAO,GAAG,IAAI,CAAC,WAAW;QAChC,IAAI,OAAO,KAAK,IAAI;AAAE,YAAA,OAAO,IAAI;;;;;;AAMjC,QAAA,MAAM,MAAM,GAAG,OAAO,CAAC,eAAe,EAAE;QACxC,IAAI,MAAM,CAAC,KAAK,IAAI,CAAC,IAAI,MAAM,CAAC,MAAM,IAAI,CAAC;AAAE,YAAA,OAAO,IAAI;QACxD,OAAO;YACH,CAAC,EAAO,MAAM,CAAC,IAAI;YACnB,CAAC,EAAO,MAAM,CAAC,GAAG;YAClB,KAAK,EAAG,MAAM,CAAC,KAAK;YACpB,MAAM,EAAE,MAAM,CAAC,MAAM;SACxB;IACL;IAEA,MAAM,MAAM,CAAC,OAAe,EAAA;;;AAGxB,QAAA,MAAM,KAAK,GAAG,IAAI,CAAC,mBAAmB,EAAE;AACxC,QAAA,IAAI,KAAK,KAAK,IAAI,EAAE;AAChB,YAAA,IAAI,CAAC,WAAW,CAAC,KAAK,EAAE,OAAO,CAAC;YAChC;QACJ;AACA,QAAA,MAAM,KAAK,GAAG,IAAI,CAAC,YAAY,EAAE;AACjC,QAAA,MAAM,aAAa,GAAG,KAAK,CAAC,KAAK,IAAI,CAAC;AACtC,QAAA,MAAM,WAAW,GAAG,aAAa,GAAG,OAAO;QAC3C,MAAM,YAAY,GAAG,MAAW;AAC5B,YAAA,KAAK,CAAC,MAAM,CAAC,WAAW,CAAC;YACzB,KAAK,CAAC,SAAS,EAAE;AACjB,YAAA,IAAI,CAAC,MAAM,CAAC,gBAAgB,EAAE;AAC9B,YAAA,IAAI,CAAC,oBAAoB,CAAC,KAAK,EAAE,SAAS,CAAC;AAC/C,QAAA,CAAC;AACD,QAAA,YAAY,EAAE;QACd,IAAI,CAAC,WAAW,CAAC;AACb,YAAA,IAAI,EAAE,QAAQ;YACd,EAAE,EAAI,MAAK,EAAG,YAAY,EAAE,CAAC,CAAC,CAAC;YAC/B,IAAI,EAAE,MAAK;AACP,gBAAA,KAAK,CAAC,MAAM,CAAC,aAAa,CAAC;gBAC3B,KAAK,CAAC,SAAS,EAAE;AACjB,gBAAA,IAAI,CAAC,MAAM,CAAC,gBAAgB,EAAE;AAC9B,gBAAA,IAAI,CAAC,oBAAoB,CAAC,KAAK,EAAE,SAAS,CAAC;YAC/C,CAAC;AACJ,SAAA,CAAC;IACN;IAEA,MAAM,IAAI,CAAC,IAA+B,EAAA;;;AAGtC,QAAA,MAAM,KAAK,GAAG,IAAI,CAAC,mBAAmB,EAAE;AACxC,QAAA,IAAI,KAAK,KAAK,IAAI,EAAE;AAChB,YAAA,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,CAAC;YAC3B;QACJ;AACA,QAAA,MAAM,KAAK,GAAG,IAAI,CAAC,YAAY,EAAE;AACjC,QAAA,MAAM,IAAI,GAAsB,IAAI,KAAK,YAAY,GAAG,OAAO,GAAG,OAAO;QACzE,MAAM,QAAQ,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,KAAK;QACrC,MAAM,YAAY,GAAG,MAAW;AAC5B,YAAA,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,QAAQ;YACvB,KAAK,CAAC,SAAS,EAAE;AACjB,YAAA,IAAI,CAAC,MAAM,CAAC,gBAAgB,EAAE;AAC9B,YAAA,IAAI,CAAC,oBAAoB,CAAC,KAAK,EAAE,SAAS,CAAC;AAC/C,QAAA,CAAC;AACD,QAAA,YAAY,EAAE;QACd,IAAI,CAAC,WAAW,CAAC;YACb,IAAI,EAAE,CAAA,KAAA,EAAQ,IAAI,CAAA,CAAE;YACpB,EAAE,EAAI,MAAK,EAAG,YAAY,EAAE,CAAC,CAAC,CAAC;YAC/B,IAAI,EAAE,MAAK;AACP,gBAAA,KAAK,CAAC,IAAI,CAAC,GAAG,QAAQ;gBACtB,KAAK,CAAC,SAAS,EAAE;AACjB,gBAAA,IAAI,CAAC,MAAM,CAAC,gBAAgB,EAAE;AAC9B,gBAAA,IAAI,CAAC,oBAAoB,CAAC,KAAK,EAAE,SAAS,CAAC;YAC/C,CAAC;AACJ,SAAA,CAAC;IACN;IAEA,MAAM,MAAM,CAAC,IAAU,EAAA;AACnB,QAAA,MAAM,KAAK,GAAG,IAAI,CAAC,YAAY,EAAE;AACjC,QAAA,MAAM,WAAW,GAAG,KAAK,CAAC,eAAe,EAAE;AAC3C,QAAA,MAAM,KAAK,GAAG,KAAK,CAAC,eAAe,CAAC,EAAE,UAAU,EAAE,CAAC,EAAE,CAAC;QAEtD,MAAM,MAAM,GAAG,QAAQ,CAAC,aAAa,CAAC,QAAQ,CAAC;AAC/C,QAAA,MAAM,CAAC,KAAK,GAAI,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;AACnD,QAAA,MAAM,CAAC,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACpD,MAAM,GAAG,GAAG,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC;AACnC,QAAA,IAAI,GAAG,KAAK,IAAI,EAAE;AACd,YAAA,MAAM,IAAI,KAAK,CAAC,wDAAwD,CAAC;QAC7E;AACA,QAAA,GAAG,CAAC,SAAS,CAAC,KAAK,EAAE,CAAC,EAAE,CAAC,EAAE,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,CAAC;QACvD,MAAM,UAAU,GAAG,MAAM,CAAC,SAAS,CAAC,WAAW,CAAC;;;;QAKhD,MAAM,mBAAmB,GAAG,KAAK,CAAC,SAAS,CAAC,WAAW,CAAC;;;;;;;;;;;;;;AAexD,QAAA,MAAM,EAAE,GAAG,MAAM,CAAC,KAAK,GAAI,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,WAAW,CAAC,KAAK,CAAC;AACzD,QAAA,MAAM,EAAE,GAAG,MAAM,CAAC,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,WAAW,CAAC,MAAM,CAAC;AAC1D,QAAA,MAAM,OAAO,GAAG,IAAI,CAAC,YAAY;AAC5B,aAAA,MAAM,CAAC,CAAC,IAAI,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,KAAK,OAAO;AACzC,aAAA,GAAG,CAAC,CAAC,KAAK;AACP,YAAA,GAAG,EAAK,CAAC;YACT,IAAI,EAAI,CAAC,CAAC,CAAC,IAAI,IAAM,CAAC,IAAI,WAAW,CAAC,IAAI;YAC1C,GAAG,EAAK,CAAC,CAAC,CAAC,GAAG,IAAO,CAAC,IAAI,WAAW,CAAC,GAAG;AACzC,YAAA,MAAM,EAAE,CAAC,CAAC,MAAM,IAAI,CAAC;AACrB,YAAA,MAAM,EAAE,CAAC,CAAC,MAAM,IAAI,CAAC;AACxB,SAAA,CAAC,CAAC;QACP,MAAM,WAAW,GAAG,CAAC,UAAkB,EAAE,SAAiB,EAAE,OAAe,EAAE,OAAe,KAAU;AAClG,YAAA,KAAK,MAAM,EAAE,GAAG,EAAE,IAAI,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,OAAO,EAAE;gBACtD,GAAG,CAAC,GAAG,CAAC;AACJ,oBAAA,IAAI,EAAI,UAAU,GAAG,IAAI,GAAG,OAAO;AACnC,oBAAA,GAAG,EAAK,SAAS,GAAI,GAAG,GAAI,OAAO;oBACnC,MAAM,EAAE,MAAM,GAAG,OAAO;oBACxB,MAAM,EAAE,MAAM,GAAG,OAAO;AAC3B,iBAAA,CAAC;gBACF,GAAG,CAAC,SAAS,EAAE;YACnB;AACJ,QAAA,CAAC;AAED,QAAA,MAAM,QAAQ,GAAG,MAAM,WAAW,CAAC,OAAO,CAAC,UAAU,EAAE,SAAS,EAAE,oBAAoB,CAAC;AACvF,QAAA,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC;AACzB,QAAA,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC;AAC3B,QAAA,WAAW,CAAC,QAAQ,CAAC,IAAI,IAAI,CAAC,EAAE,QAAQ,CAAC,GAAG,IAAI,CAAC,EAAE,EAAE,EAAE,EAAE,CAAC;AAC1D,QAAA,IAAI,CAAC,MAAM,CAAC,gBAAgB,EAAE;QAE9B,IAAI,CAAC,WAAW,CAAC;AACb,YAAA,IAAI,EAAE,QAAQ;YACd,EAAE,EAAE,YAAW;AACX,gBAAA,IAAI,IAAI,CAAC,KAAK,KAAK,QAAQ;oBAAE;gBAC7B,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,YAAY,EAAE,CAAC;AACvC,gBAAA,MAAM,MAAM,GAAG,MAAM,WAAW,CAAC,OAAO,CAAC,UAAU,EAAE,SAAS,EAAE,oBAAoB,CAAC;AACrF,gBAAA,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC;AACzB,gBAAA,WAAW,CAAC,MAAM,CAAC,IAAI,IAAI,CAAC,EAAE,MAAM,CAAC,GAAG,IAAI,CAAC,EAAE,EAAE,EAAE,EAAE,CAAC;AACtD,gBAAA,IAAI,CAAC,MAAM,CAAC,gBAAgB,EAAE;YAClC,CAAC;YACD,IAAI,EAAE,YAAW;gBACb,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,YAAY,EAAE,CAAC;AACvC,gBAAA,MAAM,QAAQ,GAAG,MAAM,WAAW,CAAC,OAAO,CAAC,mBAAmB,EAAE,SAAS,EAAE,oBAAoB,CAAC;AAChG,gBAAA,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC;AAC3B,gBAAA,WAAW,CAAC,QAAQ,CAAC,IAAI,IAAI,CAAC,EAAE,QAAQ,CAAC,GAAG,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;AACxD,gBAAA,IAAI,CAAC,MAAM,CAAC,gBAAgB,EAAE;YAClC,CAAC;AACJ,SAAA,CAAC;IACN;AAEA,IAAA,MAAM,WAAW,CAAC,IAAgB,EAAE,SAAuB,EAAE,EAAA;AACzD,QAAA,MAAM,KAAK,GAAG,IAAI,CAAC,YAAY,EAAE;AACjC,QAAA,IAAI,CAAC,4BAA4B,CAAC,KAAK,CAAC;QACxC,MAAM,OAAO,GAAG,IAAI,CAAC,iBAAiB,CAAC,IAAI,CAAC;QAC5C,MAAM,SAAS,GAAG,IAAI,CAAC,iBAAiB,CAAC,IAAI,EAAE,MAAM,CAAC;AAEtD,QAAA,MAAM,aAAa,GAAG,KAAK,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,IAAK,CAAS,YAAY,OAAO,CAAC;AACjF,QAAA,MAAM,cAAc,GAAG,aAAa,IAAI,CAAC,GAAG,KAAK,CAAC,OAAO,CAAC,aAAa,CAAC,GAAG,IAAI;QAE/E,MAAM,YAAY,GAAG,MAAW;AAC5B,YAAA,IAAI,aAAa,IAAI,CAAC,EAAE;AACpB,gBAAA,KAAK,CAAC,OAAO,CAAC,aAAa,CAAC,GAAG,SAAS;YAC5C;iBAAO;AACH,gBAAA,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC;YACjC;YACA,KAAK,CAAC,YAAY,EAAE;AACpB,YAAA,IAAI,CAAC,MAAM,CAAC,gBAAgB,EAAE;AAClC,QAAA,CAAC;AACD,QAAA,YAAY,EAAE;QAEd,IAAI,CAAC,WAAW,CAAC;YACb,IAAI,EAAE,CAAA,OAAA,EAAU,IAAI,CAAA,CAAE;YACtB,EAAE,EAAI,MAAK,EAAG,YAAY,EAAE,CAAC,CAAC,CAAC;YAC/B,IAAI,EAAE,MAAK;AACP,gBAAA,IAAI,cAAc,KAAK,IAAI,EAAE;oBACzB,MAAM,GAAG,GAAG,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,SAAS,CAAC;oBAC5C,IAAI,GAAG,IAAI,CAAC;AAAE,wBAAA,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,cAAc;gBACrD;qBAAO;oBACH,MAAM,GAAG,GAAG,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,SAAS,CAAC;oBAC5C,IAAI,GAAG,IAAI,CAAC;wBAAE,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC,CAAC;gBAC9C;gBACA,KAAK,CAAC,YAAY,EAAE;AACpB,gBAAA,IAAI,CAAC,MAAM,CAAC,gBAAgB,EAAE;YAClC,CAAC;AACJ,SAAA,CAAC;IACN;IAEA,MAAM,YAAY,CAAC,IAAgB,EAAA;AAC/B,QAAA,MAAM,KAAK,GAAG,IAAI,CAAC,YAAY,EAAE;AACjC,QAAA,IAAI,CAAC,4BAA4B,CAAC,KAAK,CAAC;QACxC,MAAM,OAAO,GAAG,IAAI,CAAC,iBAAiB,CAAC,IAAI,CAAC;AAC5C,QAAA,MAAM,GAAG,GAAG,KAAK,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,IAAK,CAAS,YAAY,OAAO,CAAC;QACvE,IAAI,GAAG,GAAG,CAAC;YAAE;QAEb,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC;QAClC,MAAM,YAAY,GAAG,MAAW;YAC5B,MAAM,EAAE,GAAG,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC;YACzC,IAAI,EAAE,IAAI,CAAC;gBAAE,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,EAAE,CAAC,CAAC;YACxC,KAAK,CAAC,YAAY,EAAE;AACpB,YAAA,IAAI,CAAC,MAAM,CAAC,gBAAgB,EAAE;AAClC,QAAA,CAAC;AACD,QAAA,YAAY,EAAE;QAEd,IAAI,CAAC,WAAW,CAAC;YACb,IAAI,EAAE,CAAA,cAAA,EAAiB,IAAI,CAAA,CAAE;YAC7B,EAAE,EAAI,MAAK,EAAG,YAAY,EAAE,CAAC,CAAC,CAAC;YAC/B,IAAI,EAAE,MAAK;gBACP,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE;oBAClC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC,EAAE,OAAO,CAAC;gBACzC;gBACA,KAAK,CAAC,YAAY,EAAE;AACpB,gBAAA,IAAI,CAAC,MAAM,CAAC,gBAAgB,EAAE;YAClC,CAAC;AACJ,SAAA,CAAC;IACN;AAEA,IAAA,SAAS,CAAC,IAAgB,EAAA;AACtB,QAAA,IAAI,IAAI,CAAC,KAAK,KAAK,IAAI;AAAE,YAAA,OAAO,KAAK;QACrC,MAAM,OAAO,GAAG,IAAI,CAAC,iBAAiB,CAAC,IAAI,CAAC;AAC5C,QAAA,OAAO,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,IAAK,CAAS,YAAY,OAAO,CAAC;IACtE;;AAIA,IAAA,QAAQ,CAAC,IAAe,EAAE,IAAA,GAA8B,EAAE,EAAA;QACtD,MAAM,CAAC,GAAiB,EAAE,GAAG,qBAAqB,EAAE,GAAG,IAAI,EAAE;QAC7D,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,WAAW,CAAC,IAAI,EAAE,CAAC,CAAC,EAAE,OAAO,EAAE,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;IAC/E;IAEA,OAAO,CAAC,OAA6B,EAAE,EAAA;QACnC,MAAM,CAAC,GAAgB,EAAE,GAAG,oBAAoB,EAAE,GAAG,IAAI,EAAE;QAC3D,MAAM,IAAI,GAAG,IAAI,OAAO,CAAC,CAAC,CAAC,IAAI,EAAE;AAC7B,YAAA,KAAK,EAAO,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,KAAK,EAAE,KAAK,IAAI,GAAG,IAAI,GAAG,CAAC;YAC3D,UAAU,EAAE,CAAC,CAAC,UAAU;YACxB,QAAQ,EAAI,CAAC,CAAC,QAAQ;AACtB,YAAA,IAAI,EAAQ,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC,IAAI,CAAC;YAChD,UAAU,EAAE,CAAC,CAAC,UAAU;YACxB,SAAS,EAAG,CAAC,CAAC,SAAS;YACvB,SAAS,EAAG,CAAC,CAAC,SAAS;AAC1B,SAAA,CAAC;QACF,IAAI,CAAC,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC;IAC1C;;IAIA,cAAc,GAAA;AACV,QAAA,IAAI,IAAI,CAAC,KAAK,KAAK,IAAI;AAAE,YAAA,OAAO,IAAI;QACpC,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,eAAe,EAAE;QACtC,OAAO,EAAE,CAAC,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,EAAE,CAAC,CAAC,GAAG,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE;IACpE;AAEA,IAAA,UAAU,CAAC,QAAuB,EAAE,IAAA,GAA+B,EAAE,EAAA;AACjE,QAAA,MAAM,KAAK,GAAG;AACV,YAAA,IAAI,EAAW,IAAI,CAAC,IAAI,IAAW,mBAAmB,CAAC,kBAAkB;AACzE,YAAA,MAAM,EAAS,IAAI,CAAC,MAAM,IAAS,SAAS;AAC5C,YAAA,WAAW,EAAI,IAAI,CAAC,WAAW,IAAI,CAAC;;;AAGpC,YAAA,aAAa,EAAE,IAAI;SACtB;AACD,QAAA,IAAI,GAAiB;AACrB,QAAA,QAAQ,QAAQ,CAAC,IAAI;AACjB,YAAA,KAAK,MAAM;gBACP,GAAG,GAAG,IAAIA,IAAU,CAAC;AACjB,oBAAA,GAAG,KAAK;AACR,oBAAA,IAAI,EAAK,QAAQ,CAAC,IAAI,CAAC,CAAC;AACxB,oBAAA,GAAG,EAAM,QAAQ,CAAC,IAAI,CAAC,CAAC;AACxB,oBAAA,KAAK,EAAI,QAAQ,CAAC,IAAI,CAAC,KAAK;AAC5B,oBAAA,MAAM,EAAG,QAAQ,CAAC,IAAI,CAAC,MAAM;AAC7B,oBAAA,OAAO,EAAE,MAAM;AACf,oBAAA,OAAO,EAAE,KAAK;AACjB,iBAAA,CAAC;gBACF;AACJ,YAAA,KAAK,SAAS;gBACV,GAAG,GAAG,IAAI,OAAO,CAAC;AACd,oBAAA,GAAG,KAAK;AACR,oBAAA,IAAI,EAAK,QAAQ,CAAC,MAAM,CAAC,CAAC;AAC1B,oBAAA,GAAG,EAAM,QAAQ,CAAC,MAAM,CAAC,CAAC;oBAC1B,EAAE,EAAO,QAAQ,CAAC,EAAE;oBACpB,EAAE,EAAO,QAAQ,CAAC,EAAE;AACpB,oBAAA,OAAO,EAAE,QAAQ;AACjB,oBAAA,OAAO,EAAE,QAAQ;AACpB,iBAAA,CAAC;gBACF;AACJ,YAAA,KAAK,SAAS;AACV,gBAAA,GAAG,GAAG,IAAI,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,GAAG,KAAK,EAAE,CAAC;gBAC/E;;AAER,QAAA,IAAI,IAAI,CAAC,YAAY,KAAK,IAAI,EAAE;YAC5B,GAAG,CAAC,qBAAqB,CAAC,EAAE,GAAG,EAAE,KAAK,EAAE,CAAC;QAC7C;AACA,QAAA,IAAI,IAAI,CAAC,qBAAqB,KAAK,IAAI,EAAE;YACrC,GAAG,CAAC,qBAAqB,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,KAAK,EAAE,CAAC;QAC7E;QACA,GAAG,CAAC,SAAS,EAAE;QAEf,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,IAAI,QAAQ,CAAC,IAAI;QACvC,IAAI,CAAC,UAAU,CAAC,GAAG,EAAE,OAAO,EAAE,IAAI,CAAC;AACnC,QAAA,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC;QACpB,IAAI,CAAC,eAAe,EAAE;AACtB,QAAA,IAAI,CAAC,MAAM,CAAC,eAAe,CAAC,GAAG,CAAC;AAChC,QAAA,IAAI,CAAC,MAAM,CAAC,gBAAgB,EAAE;QAE9B,IAAI,CAAC,WAAW,CAAC;YACb,IAAI,EAAE,CAAA,IAAA,EAAO,IAAI,CAAA,CAAE;YACnB,EAAE,EAAE,MAAK;AACL,gBAAA,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC;gBACpB,IAAI,CAAC,eAAe,EAAE;AACtB,gBAAA,IAAI,CAAC,MAAM,CAAC,eAAe,CAAC,GAAG,CAAC;AAChC,gBAAA,IAAI,CAAC,MAAM,CAAC,gBAAgB,EAAE;gBAC9B,IAAI,CAAC,kBAAkB,EAAE;YAC7B,CAAC;YACD,IAAI,EAAE,MAAK;AACP,gBAAA,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC;AACvB,gBAAA,IAAI,CAAC,MAAM,CAAC,mBAAmB,EAAE;AACjC,gBAAA,IAAI,CAAC,MAAM,CAAC,gBAAgB,EAAE;gBAC9B,IAAI,CAAC,kBAAkB,EAAE;YAC7B,CAAC;AACJ,SAAA,CAAC;QACF,IAAI,CAAC,kBAAkB,EAAE;AACzB,QAAA,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC;IAC5B;AAEA,IAAA,gBAAgB,CAAC,EAAU,EAAA;QACvB,MAAM,GAAG,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC;QAC9B,IAAI,GAAG,KAAK,IAAI,IAAI,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,KAAK,OAAO;AAAE,YAAA,OAAO,IAAI;AAEhE,QAAA,IAAI,GAAG,YAAY,OAAO,EAAE;AACxB,YAAA,MAAM,CAAC,GAAG,GAAG,CAAC,cAAc,EAAE;YAC9B,OAAO;AACH,gBAAA,IAAI,EAAI,SAAS;AACjB,gBAAA,MAAM,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE;AAC1B,gBAAA,EAAE,EAAM,CAAC,GAAG,CAAC,EAAE,IAAI,CAAC,KAAK,GAAG,CAAC,MAAM,IAAI,CAAC,CAAC;AACzC,gBAAA,EAAE,EAAM,CAAC,GAAG,CAAC,EAAE,IAAI,CAAC,KAAK,GAAG,CAAC,MAAM,IAAI,CAAC,CAAC;aAC5C;QACL;AACA,QAAA,IAAI,GAAG,YAAY,OAAO,EAAE;AACxB,YAAA,MAAM,CAAC,GAAG,GAAG,CAAC,mBAAmB,EAAE;YACnC,MAAM,MAAM,GAAG,CAAC,GAAG,CAAC,MAAM,IAAI,EAAE;AAC3B,iBAAA,GAAG,CAAC,CAAC,IAAI,IAAI,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,UAAU,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC;iBAC/E,GAAG,CAAC,CAAC,KAAK,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;AACnC,YAAA,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE;QACtC;AACA,QAAA,IAAI,GAAG,YAAYA,IAAU,EAAE;;;AAG3B,YAAA,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,IAAK,CAAC,KAAK,GAAG,CAAC,MAAM,IAAI,CAAC,CAAC;AAC/C,YAAA,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,IAAI,CAAC,KAAK,GAAG,CAAC,MAAM,IAAI,CAAC,CAAC;AAC/C,YAAA,MAAM,CAAC,GAAG,GAAG,CAAC,cAAc,EAAE;AAC9B,YAAA,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,EAAE;QAC1F;AACA,QAAA,OAAO,IAAI;IACf;IAEA,gBAAgB,CAAC,EAAU,EAAE,OAAgB,EAAA;QACzC,MAAM,GAAG,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC;AAC9B,QAAA,IAAI,GAAG,KAAK,IAAI,IAAI,EAAE,GAAG,YAAY,OAAO,CAAC,IAAI,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,KAAK,OAAO;AAAE,YAAA,OAAO,KAAK;QAC9F,IAAI,OAAO,EAAE;AACT,YAAA,IAAI,IAAI,CAAC,UAAU,EAAE,GAAG,KAAK,GAAG;AAAE,gBAAA,OAAO,IAAI;AAC7C,YAAA,IAAI,IAAI,CAAC,UAAU,KAAK,IAAI;gBAAE,IAAI,CAAC,cAAc,EAAE;AACnD,YAAA,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC;QAC7B;aAAO,IAAI,IAAI,CAAC,UAAU,EAAE,GAAG,KAAK,GAAG,EAAE;YACrC,IAAI,CAAC,cAAc,EAAE;QACzB;AACA,QAAA,IAAI,CAAC,MAAM,CAAC,gBAAgB,EAAE;AAC9B,QAAA,OAAO,IAAI;IACf;AAEA;;;;;;;;AAQG;AACK,IAAA,eAAe,CAAC,OAAgB,EAAA;AACpC,QAAA,MAAM,aAAa,GAAG,OAAO,CAAC,QAAQ;AACtC,QAAA,MAAM,UAAU,GAAG;YACf,UAAU,EAAU,OAAO,CAAC,UAAU;YACtC,aAAa,EAAO,OAAO,CAAC,aAAa;YACzC,aAAa,EAAO,OAAO,CAAC,aAAa;YACzC,WAAW,EAAS,OAAO,CAAC,WAAW;YACvC,WAAW,EAAS,OAAO,CAAC,WAAW;YACvC,iBAAiB,EAAG,OAAO,CAAC,iBAAiB;YAC7C,kBAAkB,EAAE,OAAO,CAAC,kBAAkB;SACjD;AAED,QAAA,IAAI,CAAC,qBAAqB,CAAC,OAAO,CAAC;AACnC,QAAA,OAAO,CAAC,UAAU,GAAG,KAAK;;;AAG1B,QAAA,OAAO,CAAC,aAAa,GAAG,IAAI;AAC5B,QAAA,OAAO,CAAC,aAAa,GAAG,IAAI;;;;AAI5B,QAAA,OAAO,CAAC,WAAW,GAAG,QAAQ;AAC9B,QAAA,OAAO,CAAC,kBAAkB,GAAG,KAAK;AAClC,QAAA,OAAO,CAAC,WAAW,GAAG,SAAS;AAC/B,QAAA,OAAO,CAAC,iBAAiB,GAAG,SAAS;QACrC,OAAO,CAAC,SAAS,EAAE;AACnB,QAAA,IAAI,CAAC,MAAM,CAAC,eAAe,CAAC,OAAO,CAAC;AACpC,QAAA,IAAI,CAAC,UAAU,GAAG,EAAE,GAAG,EAAE,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,YAAY,EAAE,IAAI,EAAE;IACrF;IAEQ,cAAc,GAAA;AAClB,QAAA,MAAM,IAAI,GAAG,IAAI,CAAC,UAAU;QAC5B,IAAI,IAAI,KAAK,IAAI;YAAE;AACnB,QAAA,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG;AACpB,QAAA,GAAG,CAAC,QAAQ,GAAG,IAAI,CAAC,aAAa;QACjC,GAAG,CAAC,UAAU,GAAG,IAAI,CAAC,UAAU,CAAC,UAAU;QAC3C,GAAG,CAAC,aAAa,GAAG,IAAI,CAAC,UAAU,CAAC,aAAa;QACjD,GAAG,CAAC,aAAa,GAAG,IAAI,CAAC,UAAU,CAAC,aAAa;QACjD,GAAG,CAAC,WAAW,GAAG,IAAI,CAAC,UAAU,CAAC,WAAW;QAC7C,GAAG,CAAC,WAAW,GAAG,IAAI,CAAC,UAAU,CAAC,WAAW;QAC7C,GAAG,CAAC,iBAAiB,GAAG,IAAI,CAAC,UAAU,CAAC,iBAAiB;QACzD,GAAG,CAAC,kBAAkB,GAAG,IAAI,CAAC,UAAU,CAAC,kBAAkB;QAC3D,GAAG,CAAC,SAAS,EAAE;AACf,QAAA,IAAI,CAAC,UAAU,GAAG,IAAI;IAC1B;IAEQ,qBAAqB,CAAC,OAAgB,EAAE,KAAa,EAAA;QACzD,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,MAAM,IAAI,EAAE,EAAE,KAAK,CAAC,IAAI,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE;QACzD,OAAO,IAAI,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,SAAS,CAC9E,IAAI,CAAC,yBAAyB,CAC1B,OAAO,CAAC,MAAM,EAAE,iBAAiB,IAAI,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,EACvD,OAAO,CAAC,mBAAmB,EAAE,CAChC,CACJ;IACL;AAEQ,IAAA,UAAU,CAAC,SAAoB,EAAE,KAAa,EAAE,CAAS,EAAE,CAAS,EAAA;AACxE,QAAA,MAAM,OAAO,GAAG,SAAS,CAAC,MAAM;AAChC,QAAA,IAAI,EAAE,OAAO,YAAY,OAAO,CAAC;AAAE,YAAA,OAAO,KAAK;AAC/C,QAAA,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,IAAI,EAAE;QACnC,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,IAAI,KAAK,IAAI,MAAM,CAAC,MAAM;AAAE,YAAA,OAAO,KAAK;;;AAI7D,QAAA,MAAM,WAAW,GAAG,KAAK,GAAG,CAAC,GAAG,KAAK,GAAG,CAAC,GAAG,MAAM,CAAC,MAAM,GAAG,CAAC;AAC7D,QAAA,MAAM,SAAS,GAAG,IAAI,KAAK,CACvB,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC,EAC5C,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC,CAC/C,CAAC,SAAS,CAAC,OAAO,CAAC,mBAAmB,EAAE,CAAC;;;QAI1C,MAAM,KAAK,GAAG,IAAI,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,IAAI,CAAC,eAAe,CAAC,OAAO,CAAC,mBAAmB,EAAE,CAAC,CAAC;QAC5F,MAAM,IAAI,GAAG,IAAI,CAAC,qBAAqB,CAAC,OAAO,CAAC;QAChD,MAAM,CAAC,KAAK,CAAC,GAAG;YACZ,CAAC,EAAE,KAAK,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,IAAI,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;YACnE,CAAC,EAAE,KAAK,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,IAAI,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;SACvE;QACD,OAAO,CAAC,aAAa,EAAE;QAEvB,MAAM,SAAS,GAAG,IAAI,CAAC,qBAAqB,CAAC,OAAO,CAAC;QACrD,MAAM,IAAI,GAAG,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC,IAAI,SAAS,CAAC,CAAC;QACzE,MAAM,IAAI,GAAG,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC,IAAI,SAAS,CAAC,CAAC;AACzE,QAAA,OAAO,CAAC,mBAAmB,CAAC,SAAS,EAAE,IAAI,GAAG,GAAG,EAAE,IAAI,GAAG,GAAG,CAAC;QAC9D,OAAO,CAAC,SAAS,EAAE;AACnB,QAAA,OAAO,IAAI;IACf;AAEA;;;;AAIG;AACK,IAAA,qBAAqB,CAAC,OAAgB,EAAA;QAC1C,MAAM,QAAQ,GAA4B,EAAE;AAC5C,QAAA,CAAC,OAAO,CAAC,MAAM,IAAI,EAAE,EAAE,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,KAAI;YACpC,QAAQ,CAAC,QAAQ,GAAG,CAAC,CAAC,GAAG,IAAI,OAAO,CAAC;AACjC,gBAAA,UAAU,EAAE,qBAAqB;AACjC,gBAAA,eAAe,EAAE,CAAC,GAAG,EAAE,WAAW,EAAE,YAAY,KAC5C,IAAI,CAAC,qBAAqB,CAAC,YAAuB,EAAE,CAAC,CAAC;gBAC1D,aAAa,EAAE,CAAC,SAAS,EAAE,SAAS,EAAE,CAAC,EAAE,CAAC,KAAK,IAAI,CAAC,UAAU,CAAC,SAAS,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;AAClF,gBAAA,gBAAgB,EAAE,MAAK,EAAG,IAAI,CAAC,eAAe,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,IAAI,CAAC,CAAC,CAAC;AACvE,gBAAA,cAAc,EAAI,MAAK,EAAG,IAAI,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,IAAI,CAAC,CAAC,CAAC;AACxE,aAAA,CAAC;AACN,QAAA,CAAC,CAAC;AACF,QAAA,OAAO,CAAC,QAAQ,GAAG,QAAQ;IAC/B;AAEA,IAAA,WAAW,CAAC,EAAU,EAAE,MAAc,EAAE,MAAc,EAAA;QAClD,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC;AAClC,QAAA,IAAI,IAAI,CAAC,UAAU,KAAK,IAAI,IAAI,EAAE,OAAO,YAAY,OAAO,CAAC,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,KAAK,OAAO;AAAE,YAAA,OAAO,KAAK;AAC9G,QAAA,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,IAAI,EAAE;AACnC,QAAA,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC;AAAE,YAAA,OAAO,KAAK;;QAGnC,MAAM,KAAK,GAAG,IAAI,KAAK,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,SAAS,CAAC,IAAI,CAAC,eAAe,CAAC,OAAO,CAAC,mBAAmB,EAAE,CAAC,CAAC;QACtG,MAAM,IAAI,GAAG,IAAI,CAAC,qBAAqB,CAAC,OAAO,CAAC;AAChD,QAAA,MAAM,MAAM,GAAG;YACX,CAAC,EAAE,KAAK,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,IAAI,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;YACnE,CAAC,EAAE,KAAK,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,IAAI,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;SACvE;;;;QAKD,IAAI,SAAS,GAAG,CAAC;QACjB,IAAI,UAAU,GAAG,QAAQ;QACzB,IAAI,SAAS,GAAc,EAAE,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE;AAC7D,QAAA,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE;YACpC,MAAM,IAAI,GAAG,IAAI,CAAC,gBAAgB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,MAAM,CAAC,MAAM,CAAC,CAAC;YACtF,MAAM,EAAE,GAAG,IAAI,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC;YAC5B,MAAM,EAAE,GAAG,IAAI,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC;YAC5B,MAAM,MAAM,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE;AAChC,YAAA,IAAI,MAAM,GAAG,UAAU,EAAE;gBAAE,UAAU,GAAG,MAAM;gBAAE,SAAS,GAAG,CAAC;gBAAE,SAAS,GAAG,IAAI;YAAE;QACrF;QAEA,MAAM,MAAM,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;AACpD,QAAA,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,EAAE;QAC5B,KAAK,CAAC,MAAM,CAAC,SAAS,GAAG,CAAC,EAAE,CAAC,EAAE,SAAS,CAAC;AAEzC,QAAA,IAAI,CAAC,mBAAmB,CAAC,OAAO,EAAE,KAAK,CAAC;QACxC,IAAI,CAAC,WAAW,CAAC;AACb,YAAA,IAAI,EAAE,YAAY;YAClB,EAAE,EAAI,MAAM,IAAI,CAAC,mBAAmB,CAAC,OAAO,EAAE,KAAK,CAAC;YACpD,IAAI,EAAE,MAAM,IAAI,CAAC,mBAAmB,CAAC,OAAO,EAAE,MAAM,CAAC;AACxD,SAAA,CAAC;AACF,QAAA,IAAI,CAAC,MAAM,CAAC,gBAAgB,EAAE;AAC9B,QAAA,OAAO,IAAI;IACf;AAEA,IAAA,cAAc,CAAC,EAAU,EAAE,MAAc,EAAE,MAAc,EAAA;QACrD,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC;AAClC,QAAA,IAAI,IAAI,CAAC,UAAU,KAAK,IAAI,IAAI,EAAE,OAAO,YAAY,OAAO,CAAC,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,KAAK,OAAO;AAAE,YAAA,OAAO,KAAK;AAC9G,QAAA,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,IAAI,EAAE;;AAEnC,QAAA,IAAI,MAAM,CAAC,MAAM,IAAI,CAAC;AAAE,YAAA,OAAO,KAAK;;QAGpC,MAAM,KAAK,GAAG,IAAI,KAAK,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,SAAS,CAAC,IAAI,CAAC,eAAe,CAAC,OAAO,CAAC,mBAAmB,EAAE,CAAC,CAAC;QACtG,MAAM,IAAI,GAAG,IAAI,CAAC,qBAAqB,CAAC,OAAO,CAAC;AAChD,QAAA,MAAM,MAAM,GAAG;YACX,CAAC,EAAE,KAAK,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,IAAI,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;YACnE,CAAC,EAAE,KAAK,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,IAAI,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;SACvE;;QAGD,IAAI,SAAS,GAAG,CAAC;QACjB,IAAI,UAAU,GAAG,QAAQ;AACzB,QAAA,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE;AACpC,YAAA,MAAM,EAAE,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC;AACjC,YAAA,MAAM,EAAE,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC;YACjC,MAAM,MAAM,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE;AAChC,YAAA,IAAI,MAAM,GAAG,UAAU,EAAE;gBAAE,UAAU,GAAG,MAAM;gBAAE,SAAS,GAAG,CAAC;YAAE;QACnE;;;;;AAMA,QAAA,MAAM,CAAC,GAAG,OAAO,CAAC,KAAK,IAAI,CAAC;AAC5B,QAAA,MAAM,CAAC,GAAG,OAAO,CAAC,MAAM,IAAI,CAAC;AAC7B,QAAA,MAAM,SAAS,GAAG,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC;AACzC,QAAA,IAAI,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,SAAS;AAAE,YAAA,OAAO,KAAK;QAEnD,MAAM,MAAM,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;AACpD,QAAA,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,EAAE;AAC5B,QAAA,KAAK,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,CAAC;;;AAG1B,QAAA,MAAM,OAAO,GAAG,SAAS,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC;QAEvC,IAAI,CAAC,mBAAmB,CAAC,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC,CAAC;QACpD,IAAI,CAAC,WAAW,CAAC;AACb,YAAA,IAAI,EAAE,eAAe;AACrB,YAAA,EAAE,EAAI,MAAM,IAAI,CAAC,mBAAmB,CAAC,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC,CAAC;AAChE,YAAA,IAAI,EAAE,MAAM,IAAI,CAAC,mBAAmB,CAAC,OAAO,EAAE,MAAM,EAAE,CAAC,EAAE,OAAO,CAAC;AACpE,SAAA,CAAC;AACF,QAAA,IAAI,CAAC,MAAM,CAAC,gBAAgB,EAAE;AAC9B,QAAA,OAAO,IAAI;IACf;;AAGQ,IAAA,gBAAgB,CAAC,CAAY,EAAE,CAAY,EAAE,CAAY,EAAA;QAC7D,MAAM,GAAG,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;QACrB,MAAM,GAAG,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;QACrB,MAAM,KAAK,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG;AACnC,QAAA,IAAI,CAAC,GAAG,KAAK,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,GAAG,IAAI,KAAK;AACzE,QAAA,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;QAC/B,OAAO,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,GAAG,EAAE;IACjD;AAEA;;;;;;;;;;;AAWG;IACK,mBAAmB,CAAC,OAAgB,EAAE,GAAgB,EAAE,SAAS,GAAG,CAAC,EAAE,OAAO,GAAG,CAAC,EAAA;AACtF,QAAA,MAAM,OAAO,GAAG,OAAO,CAAC,MAAM,IAAI,EAAE;QACpC,MAAM,SAAS,GAAG,IAAI,KAAK,CACvB,CAAC,OAAO,CAAC,SAAS,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,OAAO,CAAC,UAAU,CAAC,CAAC,EACnD,CAAC,OAAO,CAAC,SAAS,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,OAAO,CAAC,UAAU,CAAC,CAAC,CACtD,CAAC,SAAS,CAAC,OAAO,CAAC,mBAAmB,EAAE,CAAC;QAE1C,OAAO,CAAC,MAAM,GAAG,GAAG,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QACnD,OAAO,CAAC,aAAa,EAAE;QAEvB,MAAM,SAAS,GAAG,IAAI,CAAC,qBAAqB,CAAC,OAAO,CAAC;QACrD,MAAM,IAAI,GAAG,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,OAAO,CAAC,UAAU,CAAC,CAAC,IAAI,SAAS,CAAC,CAAC;QACrF,MAAM,IAAI,GAAG,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,OAAO,CAAC,UAAU,CAAC,CAAC,IAAI,SAAS,CAAC,CAAC;AACrF,QAAA,OAAO,CAAC,mBAAmB,CAAC,SAAS,EAAE,IAAI,GAAG,GAAG,EAAE,IAAI,GAAG,GAAG,CAAC;AAE9D,QAAA,IAAI,CAAC,qBAAqB,CAAC,OAAO,CAAC;QACnC,OAAO,CAAC,SAAS,EAAE;IACvB;AAEQ,IAAA,qBAAqB,CAAC,OAAgB,EAAA;AAC1C,QAAA,MAAM,WAAW,GAAG,OAAO,CAAC,WAAW,IAAI,CAAC;QAC5C,MAAM,EAAE,GAAG,OAAO,CAAC,aAAa,KAAK,IAAI,GAAG,WAAW,IAAI,OAAO,CAAC,MAAM,IAAI,CAAC,CAAC,GAAG,WAAW;QAC7F,MAAM,EAAE,GAAG,OAAO,CAAC,aAAa,KAAK,IAAI,GAAG,WAAW,IAAI,OAAO,CAAC,MAAM,IAAI,CAAC,CAAC,GAAG,WAAW;QAC7F,OAAO,IAAI,KAAK,CAAC,CAAC,OAAO,CAAC,KAAK,IAAI,CAAC,IAAI,EAAE,EAAE,CAAC,OAAO,CAAC,MAAM,IAAI,CAAC,IAAI,EAAE,CAAC;IAC3E;AAEQ,IAAA,eAAe,CAAC,OAAgB,EAAA;AACpC,QAAA,IAAI,IAAI,CAAC,UAAU,EAAE,GAAG,KAAK,OAAO;YAAE;AACtC,QAAA,IAAI,CAAC,UAAU,CAAC,YAAY,GAAG;AAC3B,YAAA,MAAM,EAAE,CAAC,OAAO,CAAC,MAAM,IAAI,EAAE,EAAE,GAAG,CAAC,CAAC,KAAK,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;AAC7D,YAAA,IAAI,EAAI,OAAO,CAAC,IAAI,IAAI,CAAC;AACzB,YAAA,GAAG,EAAK,OAAO,CAAC,GAAG,IAAI,CAAC;SAC3B;IACL;AAEQ,IAAA,aAAa,CAAC,OAAgB,EAAA;AAClC,QAAA,MAAM,IAAI,GAAG,IAAI,CAAC,UAAU;QAC5B,IAAI,IAAI,EAAE,GAAG,KAAK,OAAO,IAAI,IAAI,CAAC,YAAY,KAAK,IAAI;YAAE;AACzD,QAAA,MAAM,MAAM,GAAG,IAAI,CAAC,YAAY;AAChC,QAAA,IAAI,CAAC,YAAY,GAAG,IAAI;AAExB,QAAA,MAAM,KAAK,GAAG;AACV,YAAA,MAAM,EAAE,CAAC,OAAO,CAAC,MAAM,IAAI,EAAE,EAAE,GAAG,CAAC,CAAC,KAAK,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;AAC7D,YAAA,IAAI,EAAI,OAAO,CAAC,IAAI,IAAI,CAAC;AACzB,YAAA,GAAG,EAAK,OAAO,CAAC,GAAG,IAAI,CAAC;SAC3B;AACD,QAAA,MAAM,SAAS,GAAG,MAAM,CAAC,MAAM,CAAC,MAAM,KAAK,KAAK,CAAC,MAAM,CAAC;AACjD,eAAA,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAC5F,QAAA,IAAI,SAAS;YAAE;;;AAIf,QAAA,MAAM,KAAK,GAAG,CAAC,KAAyB,KAAI;AACxC,YAAA,OAAO,CAAC,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;YAC5D,OAAO,CAAC,aAAa,EAAE;AACvB,YAAA,OAAO,CAAC,GAAG,CAAC,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,GAAG,EAAE,KAAK,CAAC,GAAG,EAAE,CAAC;YACjD,OAAO,CAAC,SAAS,EAAE;AACnB,YAAA,IAAI,CAAC,MAAM,CAAC,gBAAgB,EAAE;AAClC,QAAA,CAAC;QACD,IAAI,CAAC,WAAW,CAAC;AACb,YAAA,IAAI,EAAE,aAAa;AACnB,YAAA,EAAE,EAAI,MAAM,KAAK,CAAC,KAAK,CAAC;AACxB,YAAA,IAAI,EAAE,MAAM,KAAK,CAAC,MAAM,CAAC;AAC5B,SAAA,CAAC;IACN;IAEA,SAAS,GAAA;;QAEL,OAAO,IAAI,CAAC,YAAY;AACnB,aAAA,KAAK;AACL,aAAA,OAAO;AACP,aAAA,GAAG,CAAC,CAAC,KAAK;AACP,YAAA,EAAE,EAAO,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC;AACxB,YAAA,IAAI,EAAK,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC;AAC1B,YAAA,IAAI,EAAK,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC;AAC1B,YAAA,OAAO,EAAE,CAAC,CAAC,OAAO,KAAK,KAAK;AAC5B,YAAA,OAAO,EAAE,CAAC,CAAC,OAAO,IAAI,CAAC;YACvB,MAAM,EAAG,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,KAAK,OAAO;AACzC,SAAA,CAAC,CAAC;IACX;IAEA,gBAAgB,GAAA;QACZ,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,eAAe,EAAE;AAC5C,QAAA,OAAO,MAAM,IAAI,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,IAAI,IAAI,IAAI;IACzD;AAEA,IAAA,WAAW,CAAC,EAAiB,EAAA;AACzB,QAAA,IAAI,EAAE,KAAK,IAAI,EAAE;AACb,YAAA,IAAI,CAAC,MAAM,CAAC,mBAAmB,EAAE;AACjC,YAAA,IAAI,CAAC,MAAM,CAAC,gBAAgB,EAAE;YAC9B,IAAI,CAAC,oBAAoB,EAAE;YAC3B;QACJ;QACA,MAAM,GAAG,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC;QAC9B,IAAI,GAAG,KAAK,IAAI;YAAE;AAClB,QAAA,IAAI,CAAC,MAAM,CAAC,eAAe,CAAC,GAAG,CAAC;AAChC,QAAA,IAAI,CAAC,MAAM,CAAC,gBAAgB,EAAE;QAC9B,IAAI,CAAC,oBAAoB,EAAE;IAC/B;IAEA,YAAY,CAAC,EAAU,EAAE,IAAmB,EAAA;QACxC,MAAM,GAAG,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC;QAC9B,IAAI,GAAG,KAAK,IAAI,IAAI,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,KAAK,OAAO;YAAE;;;;;QAKrD,GAAG,CAAC,GAAG,CAAC,MAAM,EAAE,IAAI,IAAI,mBAAmB,CAAC,kBAAkB,CAAC;AAC/D,QAAA,IAAI,CAAC,MAAM,CAAC,gBAAgB,EAAE;IAClC;AAEA,IAAA,WAAW,CAAC,EAAU,EAAA;QAClB,MAAM,GAAG,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC;QAC9B,IAAI,GAAG,KAAK,IAAI,IAAI,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,KAAK,OAAO;YAAE;QAErD,MAAM,SAAS,GAAG,IAAI,CAAC,MAAM,CAAC,eAAe,EAAE,KAAK,GAAG;AACvD,QAAA,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC;AACvB,QAAA,IAAI,SAAS;AAAE,YAAA,IAAI,CAAC,MAAM,CAAC,mBAAmB,EAAE;AAChD,QAAA,IAAI,CAAC,MAAM,CAAC,gBAAgB,EAAE;QAE9B,IAAI,CAAC,WAAW,CAAC;AACb,YAAA,IAAI,EAAE,cAAc;YACpB,EAAE,EAAE,MAAK;AACL,gBAAA,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC;AACvB,gBAAA,IAAI,CAAC,MAAM,CAAC,mBAAmB,EAAE;gBACjC,IAAI,CAAC,kBAAkB,EAAE;YAC7B,CAAC;YACD,IAAI,EAAE,MAAK;AACP,gBAAA,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC;gBACpB,IAAI,CAAC,eAAe,EAAE;gBACtB,IAAI,CAAC,kBAAkB,EAAE;YAC7B,CAAC;AACJ,SAAA,CAAC;QACF,IAAI,CAAC,kBAAkB,EAAE;IAC7B;IAEA,kBAAkB,CAAC,EAAU,EAAE,OAAgB,EAAA;QAC3C,MAAM,GAAG,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC;QAC9B,IAAI,GAAG,KAAK,IAAI;YAAE;AAClB,QAAA,MAAM,MAAM,GAAG,GAAG,CAAC,OAAO,KAAK,KAAK;QACpC,IAAI,MAAM,KAAK,OAAO;YAAE;AACxB,QAAA,GAAG,CAAC,OAAO,GAAG,OAAO;AACrB,QAAA,IAAI,CAAC,MAAM,CAAC,gBAAgB,EAAE;QAC9B,IAAI,CAAC,WAAW,CAAC;AACb,YAAA,IAAI,EAAE,mBAAmB;AACzB,YAAA,EAAE,EAAI,MAAK,EAAG,GAAG,CAAC,OAAO,GAAG,OAAO,CAAC,CAAC,IAAI,CAAC,kBAAkB,EAAE,CAAC,CAAC,CAAC;AACjE,YAAA,IAAI,EAAE,MAAK,EAAG,GAAG,CAAC,OAAO,GAAG,MAAM,CAAC,CAAE,IAAI,CAAC,kBAAkB,EAAE,CAAC,CAAC,CAAC;AACpE,SAAA,CAAC;QACF,IAAI,CAAC,kBAAkB,EAAE;IAC7B;IAEA,eAAe,CAAC,EAAU,EAAE,OAAe,EAAA;QACvC,MAAM,GAAG,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC;QAC9B,IAAI,GAAG,KAAK,IAAI;YAAE;AAClB,QAAA,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;AAC9C,QAAA,MAAM,MAAM,GAAG,GAAG,CAAC,OAAO,IAAI,CAAC;QAC/B,IAAI,MAAM,KAAK,IAAI;YAAE;QACrB,GAAG,CAAC,GAAG,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;AAC1B,QAAA,IAAI,CAAC,MAAM,CAAC,gBAAgB,EAAE;QAC9B,IAAI,CAAC,WAAW,CAAC;AACb,YAAA,IAAI,EAAE,SAAS;YACf,EAAE,EAAI,MAAK,EAAG,GAAG,CAAC,GAAG,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,CAAG,IAAI,CAAC,kBAAkB,EAAE,CAAC,CAAC,CAAC;YACxE,IAAI,EAAE,MAAK,EAAG,GAAG,CAAC,GAAG,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,kBAAkB,EAAE,CAAC,CAAC,CAAC;AAC3E,SAAA,CAAC;QACF,IAAI,CAAC,kBAAkB,EAAE;IAC7B;IAEA,YAAY,CAAC,EAAU,EAAE,SAA2C,EAAA;QAChE,MAAM,GAAG,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC;QAC9B,IAAI,GAAG,KAAK,IAAI,IAAI,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,KAAK,OAAO;YAAE;AAErD,QAAA,MAAM,WAAW,GAAG,IAAI,CAAC,MAAM,CAAC,UAAU,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC;QACzD,QAAQ,SAAS;AACb,YAAA,KAAK,IAAI;AAAK,gBAAA,IAAI,CAAC,MAAM,CAAC,kBAAkB,CAAC,GAAG,CAAC;gBAAG;AACpD,YAAA,KAAK,MAAM;AAAG,gBAAA,IAAI,CAAC,MAAM,CAAC,mBAAmB,CAAC,GAAG,CAAC;gBAAE;AACpD,YAAA,KAAK,OAAO;AAAE,gBAAA,IAAI,CAAC,MAAM,CAAC,kBAAkB,CAAC,GAAG,CAAC;gBAAG;AACpD,YAAA,KAAK,MAAM;AAAG,gBAAA,IAAI,CAAC,MAAM,CAAC,gBAAgB,CAAC,GAAG,CAAC;gBAAK;;;;QAIxD,IAAI,CAAC,eAAe,EAAE;AACtB,QAAA,MAAM,UAAU,GAAG,IAAI,CAAC,MAAM,CAAC,UAAU,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC;AACxD,QAAA,IAAI,CAAC,MAAM,CAAC,gBAAgB,EAAE;AAC9B,QAAA,IAAI,UAAU,KAAK,WAAW,EAAE;YAAE,IAAI,CAAC,kBAAkB,EAAE;YAAE;QAAQ;QAErE,IAAI,CAAC,WAAW,CAAC;AACb,YAAA,IAAI,EAAE,eAAe;AACrB,YAAA,EAAE,EAAI,MAAK,EAAG,IAAI,CAAC,MAAM,CAAC,YAAY,CAAC,GAAG,EAAE,UAAU,CAAC,CAAC,CAAE,IAAI,CAAC,eAAe,EAAE,CAAC,CAAC,IAAI,CAAC,kBAAkB,EAAE,CAAC,CAAC,CAAC;AAC9G,YAAA,IAAI,EAAE,MAAK,EAAG,IAAI,CAAC,MAAM,CAAC,YAAY,CAAC,GAAG,EAAE,WAAW,CAAC,CAAC,CAAC,IAAI,CAAC,eAAe,EAAE,CAAC,CAAC,IAAI,CAAC,kBAAkB,EAAE,CAAC,CAAC,CAAC;AACjH,SAAA,CAAC;QACF,IAAI,CAAC,kBAAkB,EAAE;IAC7B;IAEA,oBAAoB,GAAA;QAChB,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,eAAe,EAAE;AAC5C,QAAA,IAAI,MAAM,KAAK,SAAS,IAAI,MAAM,KAAK,IAAI;AAAE,YAAA,OAAO,IAAI;QACxD,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC;QACnC,IAAI,IAAI,KAAK,OAAO,IAAI,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,EAAE;AAAE,YAAA,OAAO,IAAI;AAEhE,QAAA,IAAI,IAAI,KAAK,MAAM,EAAE;YACjB,MAAM,CAAC,GAAG,MAAiB;YAC3B,OAAO;AACH,gBAAA,IAAI,EAAQ,CAAC,CAAC,IAAI,IAAI,EAAE;AACxB,gBAAA,UAAU,EAAE,CAAC,CAAC,UAAU,IAAI,OAAO;AACnC,gBAAA,QAAQ,EAAI,CAAC,CAAC,QAAQ,IAAI,EAAE;gBAC5B,IAAI,EAAQ,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC;AAClC,gBAAA,UAAU,EAAE,CAAC,CAAC,UAAU,IAAI,QAAQ;AACpC,gBAAA,SAAS,EAAG,CAAC,CAAC,SAAS,IAAI,QAAQ;AACnC,gBAAA,SAAS,EAAG,CAAC,CAAC,SAAS,IAAI,MAAM;AACjC,gBAAA,OAAO,EAAK,MAAM,CAAC,OAAO,IAAI,CAAC;aAClC;QACL;QACA,OAAO;YACH,IAAI,EAAS,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,IAAI,CAAC;AACxC,YAAA,MAAM,EAAQ,MAAM,CAAC,MAAiB,IAAI,EAAE;AAC5C,YAAA,WAAW,EAAE,MAAM,CAAC,WAAW,IAAI,CAAC;AACpC,YAAA,OAAO,EAAM,MAAM,CAAC,OAAO,IAAI,CAAC;SACnC;IACL;IAEA,mBAAmB,GAAA;QACf,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,eAAe,EAAE;AAC5C,QAAA,IAAI,MAAM,KAAK,SAAS,IAAI,MAAM,KAAK,IAAI;AAAE,YAAA,OAAO,IAAI;AACxD,QAAA,IAAI,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,KAAK,OAAO,IAAI,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,EAAE;AAAE,YAAA,OAAO,IAAI;QAClF,OAAO,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC;IACrC;AAEA,IAAA,mBAAmB,CAAC,IAAc,EAAA;QAC9B,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,eAAe,EAAE;AAC5C,QAAA,IAAI,MAAM,KAAK,SAAS,IAAI,MAAM,KAAK,IAAI;YAAE;AAC7C,QAAA,IAAI,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,KAAK,OAAO,IAAI,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,EAAE;YAAE;QAEvE,MAAM,MAAM,GAAG,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC;QACjC,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;AACjC,QAAA,MAAM,KAAK,GAAG,CAAC,GAAY,KAAU;AACjC,YAAA,MAAM,CAAC,GAAG,CAAC,MAAM,EAAE,GAAU,CAAC;YAC9B,MAAM,CAAC,SAAS,EAAE;AAClB,YAAA,IAAI,CAAC,MAAM,CAAC,gBAAgB,EAAE;AAClC,QAAA,CAAC;QACD,KAAK,CAAC,IAAI,CAAC;QAEX,IAAI,CAAC,WAAW,CAAC;AACb,YAAA,IAAI,EAAE,YAAY;AAClB,YAAA,EAAE,EAAI,MAAK,EAAG,KAAK,CAAC,IAAI,CAAC,CAAC,CAAG,IAAI,CAAC,kBAAkB,EAAE,CAAC,CAAC,CAAC;AACzD,YAAA,IAAI,EAAE,MAAK,EAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,kBAAkB,EAAE,CAAC,CAAC,CAAC;AAC5D,SAAA,CAAC;QACF,IAAI,CAAC,kBAAkB,EAAE;IAC7B;;IAIA,uBAAuB,GAAA;AACnB,QAAA,MAAM,KAAK,GAAG,IAAI,CAAC,mBAAmB,EAAE;QACxC,IAAI,KAAK,KAAK,IAAI;AAAE,YAAA,OAAO,IAAI;QAC/B,OAAO;AACH,YAAA,KAAK,EAAE,KAAK,CAAC,KAAK,IAAI,CAAC;AACvB,YAAA,KAAK,EAAE,KAAK,CAAC,KAAK,IAAI,KAAK;AAC3B,YAAA,KAAK,EAAE,KAAK,CAAC,KAAK,IAAI,KAAK;SAC9B;IACL;AAEA,IAAA,OAAO,CAAC,IAAc,EAAA;AAClB,QAAA,MAAM,MAAM,GAAG,IAAI,CAAC,UAAU,EAAE;QAChC,IAAI,MAAM,KAAK,IAAI;YAAE;;;;QAKrB,MAAM,MAAM,IAAQ,MAAM,CAAC,QAAQ,IAAI,IAAI,CAAwB;QACnE,MAAM,WAAW,GAAI,MAA6C,CAAC,YAAY,CAAC,IAAI,IAAI;AACxF,QAAA,MAAM,KAAK,GAAG,CAAC,IAAyB,EAAE,KAAc,KAAU;;;AAG7D,YAAA,MAA6C,CAAC,UAAU,CAAC,GAAI,IAAI,IAAI,SAAS;AAC9E,YAAA,MAA6C,CAAC,YAAY,CAAC,GAAG,KAAK,IAAI,SAAS;YACjF,MAAM,CAAC,GAAG,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;YAC3B,MAAM,CAAC,SAAS,EAAE;AAClB,YAAA,IAAI,CAAC,MAAM,CAAC,gBAAgB,EAAE;AAClC,QAAA,CAAC;AAED,QAAA,MAAM,SAAS,GAAG,IAAI,CAAC,KAAK,KAAK,MAAM,GAAG,IAAI,GAAG,EAAE,GAAG,IAAI,EAAE;AAC5D,QAAA,KAAK,CAAC,IAAI,CAAC,aAAa,CAAC,MAAM,EAAE,IAAI,CAAC,EAAE,SAAS,CAAC;QAElD,IAAI,CAAC,WAAW,CAAC;AACb,YAAA,IAAI,EAAE,MAAM;YACZ,EAAE,EAAI,MAAK,EAAG,KAAK,CAAC,IAAI,CAAC,aAAa,CAAC,MAAM,EAAE,IAAI,CAAC,EAAE,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,kBAAkB,EAAE,CAAC,CAAC,CAAC;AAC9F,YAAA,IAAI,EAAE,QAAQ,KAAK,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC,IAAI,CAAC,kBAAkB,EAAE,CAAC,CAAC,CAAC;AACzE,SAAA,CAAC;QACF,IAAI,CAAC,kBAAkB,EAAE;IAC7B;IAEA,OAAO,GAAA;AACH,QAAA,MAAM,MAAM,GAAG,IAAI,CAAC,UAAU,EAAE;QAChC,IAAI,MAAM,KAAK,IAAI;AAAE,YAAA,OAAO,IAAI;AAChC,QAAA,MAAM,KAAK,GAAI,MAA6C,CAAC,YAAY,CAAC;QAC1E,IAAI,KAAK,KAAK,IAAI,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE;AAC7C,YAAA,OAAO,EAAE,GAAG,iBAAiB,EAAE,GAAI,KAA2B,EAAE;QACpE;AACA,QAAA,OAAO,EAAE,GAAG,iBAAiB,EAAE;IACnC;AAEA,IAAA,kBAAkB,CAAC,KAAkB,EAAA;QACjC,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,eAAe,EAAE;AAC5C,QAAA,IAAI,MAAM,KAAK,SAAS,IAAI,MAAM,KAAK,IAAI;YAAE;AAC7C,QAAA,IAAI,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,KAAK,OAAO,IAAI,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,EAAE;YAAE;QAEvE,MAAM,MAAM,GAAgB,EAAE;QAC9B,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE;AAClC,YAAA,MAAM,CAAC,GAAG,CAAC,GAAI,MAAM,CAAC,GAAG,CAAC,GAAG,CAAqB,IAAI,EAAE;QAC5D;AACA,QAAA,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC;QACjB,MAAM,CAAC,SAAS,EAAE;AAClB,QAAA,IAAI,CAAC,MAAM,CAAC,gBAAgB,EAAE;QAE9B,IAAI,CAAC,WAAW,CAAC;AACb,YAAA,IAAI,EAAE,aAAa;AACnB,YAAA,EAAE,EAAI,MAAK,EAAG,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAE,MAAM,CAAC,SAAS,EAAE,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,gBAAgB,EAAE,CAAC,CAAC,IAAI,CAAC,kBAAkB,EAAE,CAAC,CAAC,CAAC;AAClH,YAAA,IAAI,EAAE,MAAK,EAAG,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,gBAAgB,EAAE,CAAC,CAAC,IAAI,CAAC,kBAAkB,EAAE,CAAC,CAAC,CAAC;AACrH,SAAA,CAAC;QACF,IAAI,CAAC,kBAAkB,EAAE;IAC7B;AAEA,IAAA,MAAM,IAAI,GAAA;AACN,QAAA,MAAM,IAAI,CAAC,YAAY,CAAC,IAAI,EAAE;AAC9B,QAAA,IAAI,CAAC,IAAI,CAAC,cAAc,EAAE,SAAS,CAAC;AACpC,QAAA,IAAI,CAAC,IAAI,CAAC,qBAAqB,EAAE;AAC7B,YAAA,OAAO,EAAE,IAAI,CAAC,YAAY,CAAC,OAAO,EAAE;AACpC,YAAA,OAAO,EAAE,IAAI,CAAC,YAAY,CAAC,OAAO,EAAE;AACvC,SAAA,CAAC;IACN;AAEA,IAAA,MAAM,IAAI,GAAA;AACN,QAAA,MAAM,IAAI,CAAC,YAAY,CAAC,IAAI,EAAE;AAC9B,QAAA,IAAI,CAAC,IAAI,CAAC,cAAc,EAAE,SAAS,CAAC;AACpC,QAAA,IAAI,CAAC,IAAI,CAAC,qBAAqB,EAAE;AAC7B,YAAA,OAAO,EAAE,IAAI,CAAC,YAAY,CAAC,OAAO,EAAE;AACpC,YAAA,OAAO,EAAE,IAAI,CAAC,YAAY,CAAC,OAAO,EAAE;AACvC,SAAA,CAAC;IACN;IAEA,OAAO,GAAA,EAAc,OAAO,IAAI,CAAC,YAAY,CAAC,OAAO,EAAE,CAAC,CAAC;IACzD,OAAO,GAAA,EAAc,OAAO,IAAI,CAAC,YAAY,CAAC,OAAO,EAAE,CAAC,CAAC;IAEzD,cAAc,GAAA;AACV,QAAA,IAAI,CAAC,YAAY,CAAC,SAAS,EAAE;AAC7B,QAAA,IAAI,CAAC,IAAI,CAAC,qBAAqB,EAAE;AAC7B,YAAA,OAAO,EAAE,IAAI,CAAC,YAAY,CAAC,OAAO,EAAE;AACpC,YAAA,OAAO,EAAE,IAAI,CAAC,YAAY,CAAC,OAAO,EAAE;AACvC,SAAA,CAAC;IACN;IAEA,MAAM,MAAM,CAAC,MAAA,GAAkC,KAAK,EAAE,OAAO,GAAG,IAAI,EAAA;AAChE,QAAA,MAAM,IAAI,GAAG,IAAI,CAAC,eAAe,EAAE;AACnC,QAAA,MAAM,IAAI,GAAG,MAAM,IAAI,OAAO,CAAc,OAAO,IAC/C,IAAI,CAAC,MAAM,CAAC,CAAC,IAAI,OAAO,CAAC,CAAC,CAAC,EAAE,CAAA,MAAA,EAAS,MAAM,CAAA,CAAE,EAAE,OAAO,CAAC,CAC3D;AACD,QAAA,IAAI,IAAI,KAAK,IAAI,EAAE;AACf,YAAA,MAAM,IAAI,KAAK,CAAC,gDAAgD,CAAC;QACrE;AACA,QAAA,OAAO,IAAI;IACf;AAEA,IAAA,aAAa,CAAC,MAAA,GAAkC,KAAK,EAAE,OAAO,GAAG,IAAI,EAAA;AACjE,QAAA,OAAO,IAAI,CAAC,eAAe,EAAE,CAAC,SAAS,CAAC,CAAA,MAAA,EAAS,MAAM,CAAA,CAAE,EAAE,OAAO,CAAC;IACvE;IAEA,QAAQ,GAAA;AACJ,QAAA,IAAI,IAAI,CAAC,KAAK,KAAK,IAAI;AAAE,YAAA,OAAO,KAAK;;;;;AAMrC,QAAA,IAAI,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC;AAAE,YAAA,OAAO,IAAI;QAC/C,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,YAAY,EAAE,EAAE;YACjC,IAAI,CAAC,CAAC,OAAO,KAAK,KAAK,IAAI,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC;AAAE,gBAAA,OAAO,IAAI;QACjE;;;;;;AAOA,QAAA,IAAI;AACA,YAAA,MAAM,IAAI,GAAG,IAAI,CAAC,eAAe,EAAE;AACnC,YAAA,MAAM,GAAG,GAAG,IAAI,CAAC,UAAU,CAAC,IAAI,EAAE,EAAE,kBAAkB,EAAE,IAAI,EAAE,CAAC;YAC/D,IAAI,GAAG,KAAK,IAAI;AAAE,gBAAA,OAAO,KAAK;YAC9B,MAAM,EAAE,IAAI,EAAE,GAAG,GAAG,CAAC,YAAY,CAAC,CAAC,EAAE,CAAC,EAAE,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,MAAM,CAAC;AAChE,YAAA,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,IAAI,CAAC,EAAE;AACrC,gBAAA,IAAI,IAAI,CAAC,CAAC,CAAC,GAAG,GAAG;AAAE,oBAAA,OAAO,IAAI;YAClC;QACJ;AAAE,QAAA,MAAM;;;;AAIJ,YAAA,OAAO,KAAK;QAChB;AACA,QAAA,OAAO,KAAK;IAChB;;AAGQ,IAAA,aAAa,CAAC,GAAwB,EAAA;QAC1C,OAAO,GAAG,KAAK;AACP,eAAA,GAA0C,CAAC,UAAU,CAAC,IAAI,IAAI;IAC1E;AAEA;;;;;;;;;;;;AAYG;IACK,eAAe,GAAA;AACnB,QAAA,MAAM,KAAK,GAAG,IAAI,CAAC,YAAY,EAAE;AACjC,QAAA,MAAM,MAAM,GAAG,IAAI,CAAC,YAAY,EAAE,CAAC,MAAM,CACrC,CAAC,IAAI,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,KAAK,OAAO,IAAI,CAAC,CAAC,OAAO,KAAK,KAAK,CAC5D;AAED,QAAA,MAAM,MAAM,GAAG,KAAK,CAAC,eAAe,CAAC,EAAE,UAAU,EAAE,CAAC,EAAE,CAAC;AACvD,QAAA,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE;AACrB,YAAA,OAAO,MAAM;QACjB;AAEA,QAAA,MAAM,IAAI,GAAG,KAAK,CAAC,eAAe,EAAE;QACpC,MAAM,GAAG,GAAG,QAAQ,CAAC,aAAa,CAAC,QAAQ,CAAC;AAC5C,QAAA,GAAG,CAAC,KAAK,GAAI,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;AAChD,QAAA,GAAG,CAAC,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACjD,MAAM,GAAG,GAAG,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC;AAChC,QAAA,IAAI,GAAG,KAAK,IAAI,EAAE;AACd,YAAA,MAAM,IAAI,KAAK,CAAC,wDAAwD,CAAC;QAC7E;QACA,GAAG,CAAC,SAAS,CAAC,MAAM,EAAE,CAAC,EAAE,CAAC,CAAC;AAC3B,QAAA,KAAK,MAAM,GAAG,IAAI,MAAM,EAAE;AACtB,YAAA,MAAM,MAAM,GAAG,GAAG,CAAC,eAAe,EAAE;AACpC,YAAA,MAAM,EAAE,GAAG,GAAG,CAAC,eAAe,CAAC,EAAE,UAAU,EAAE,CAAC,EAAE,CAAC;AACjD,YAAA,GAAG,CAAC,SAAS,CAAC,EAAE,EAAE,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC;QAC7F;AACA,QAAA,OAAO,GAAG;IACd;IAEA,aAAa,GAAA;AACT,QAAA,IAAI,IAAI,CAAC,KAAK,KAAK,IAAI;YAAE,OAAO,EAAE,KAAK,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE;AACvD,QAAA,OAAO,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE;IACjE;AAEA,IAAA,OAAO,CAAC,KAAa,EAAA;QACjB,MAAM,MAAM,GAAG,IAAI,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,GAAG,CAAC,EAAE,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC;QACjF,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC,MAAM,EAAE,KAAK,CAAC;QACtC,IAAI,CAAC,gBAAgB,EAAE;AACvB,QAAA,IAAI,CAAC,MAAM,CAAC,gBAAgB,EAAE;IAClC;IAEA,OAAO,GAAA;AACH,QAAA,OAAO,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE;IAChC;IAEA,SAAS,GAAA;AACL,QAAA,IAAI,CAAC,MAAM,CAAC,oBAAoB,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;QACpD,IAAI,CAAC,gBAAgB,EAAE;AACvB,QAAA,IAAI,CAAC,MAAM,CAAC,gBAAgB,EAAE;IAClC;IAEA,GAAG,CAAC,EAAU,EAAE,EAAU,EAAA;AACtB,QAAA,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC,IAAI,KAAK,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;AAC1C,QAAA,IAAI,CAAC,MAAM,CAAC,gBAAgB,EAAE;IAClC;IAEA,YAAY,GAAA;QACR,MAAM,EAAE,GAAG,IAAI,CAAC,MAAM,CAAC,iBAAiB,IAAI,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;AAC9D,QAAA,OAAO,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE;IAC3C;AAEA,IAAA,YAAY,CAAC,MAAiB,EAAA;QAC1B,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE;QAClC,IAAI,CAAC,MAAM,CAAC,oBAAoB,CAAC,CAAC,IAAI,EAAE,CAAC,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC;AACxE,QAAA,IAAI,CAAC,MAAM,CAAC,gBAAgB,EAAE;IAClC;IAEA,QAAQ,GAAA;QACJ,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE;AAClC,QAAA,IAAI,CAAC,MAAM,CAAC,oBAAoB,CAAC,CAAC,IAAI,EAAE,CAAC,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;AAC1D,QAAA,IAAI,CAAC,MAAM,CAAC,gBAAgB,EAAE;IAClC;AAEA,IAAA,UAAU,CAAC,YAAkB,EAAA;AACzB,QAAA,IAAI,IAAI,CAAC,KAAK,KAAK,IAAI;AAAE,YAAA,OAAO,CAAC;QACjC,MAAM,MAAM,GAAG,IAAI;AACnB,QAAA,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK;AAC1B,QAAA,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM;AAC3B,QAAA,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC;AAAE,YAAA,OAAO,CAAC;QAC9B,MAAM,UAAU,GAAI,CAAC,YAAY,CAAC,KAAK,GAAI,MAAM,IAAI,CAAC;QACtD,MAAM,WAAW,GAAG,CAAC,YAAY,CAAC,MAAM,GAAG,MAAM,IAAI,CAAC;QACtD,OAAO,IAAI,CAAC,GAAG,CAAC,UAAU,EAAE,WAAW,CAAC;IAC5C;AAEA,IAAA,SAAS,CAAC,MAAqD,EAAA;AAC3D,QAAA,IAAI,CAAC,MAAM,CAAC,aAAa,GAAG,MAAM;AAClC,QAAA,IAAI,CAAC,MAAM,CAAC,WAAW,GAAK,MAAM;AAClC,QAAA,IAAI,CAAC,MAAM,CAAC,UAAU,GAAM,MAAM;IACtC;AAEA,IAAA,mBAAmB,CAAC,OAAgB,EAAA;AAChC,QAAA,IAAI,CAAC,MAAM,CAAC,SAAS,GAAQ,OAAO;AACpC,QAAA,IAAI,CAAC,MAAM,CAAC,cAAc,GAAG,CAAC,OAAO;QACrC,IAAI,CAAC,OAAO,EAAE;AACV,YAAA,IAAI,CAAC,MAAM,CAAC,mBAAmB,EAAE;AACjC,YAAA,IAAI,CAAC,MAAM,CAAC,gBAAgB,EAAE;QAClC;IACJ;AAEA,IAAA,mBAAmB,CAAC,QAAc,EAAA;AAC9B,QAAA,MAAM,KAAK,GAAI,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;AACtD,QAAA,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;QACvD,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC;AAC5C,QAAA,IAAI,IAAI,CAAC,KAAK,KAAK,IAAI,EAAE;YACrB,IAAI,CAAC,MAAM,CAAC,YAAY,CAAC,IAAI,CAAC,KAAK,CAAC;;;;;;;;;;;;;;;;YAgBpC,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE;YAClC,MAAM,CAAC,GAAM,IAAI,CAAC,MAAM,CAAC,cAAc,EAAE;AACzC,YAAA,IAAI,CAAC,MAAM,CAAC,oBAAoB,CAAC,CAAC,IAAI,EAAE,CAAC,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC;QAC5F;QACA,IAAI,CAAC,gBAAgB,EAAE;AACvB,QAAA,IAAI,CAAC,MAAM,CAAC,gBAAgB,EAAE;IAClC;IAEA,EAAE,CAA4B,KAAQ,EAAE,OAA8B,EAAA;QAClE,IAAI,GAAG,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,KAAK,CAAC;AACnC,QAAA,IAAI,GAAG,KAAK,SAAS,EAAE;AACnB,YAAA,GAAG,GAAG,IAAI,GAAG,EAAE;YACf,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,KAAK,EAAE,GAAG,CAAC;QAClC;AACA,QAAA,GAAG,CAAC,GAAG,CAAC,OAA8B,CAAC;IAC3C;IAEA,GAAG,CAA4B,KAAQ,EAAE,OAA+B,EAAA;QACpE,MAAM,GAAG,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,KAAK,CAAC;QACrC,IAAI,GAAG,KAAK,SAAS;YAAE;AACvB,QAAA,IAAI,OAAO,KAAK,SAAS,EAAE;YACvB,GAAG,CAAC,KAAK,EAAE;QACf;aAAO;AACH,YAAA,GAAG,CAAC,MAAM,CAAC,OAA8B,CAAC;QAC9C;IACJ;IAEA,OAAO,GAAA;AACH,QAAA,IAAI,IAAI,CAAC,WAAW,KAAK,IAAI,EAAE;YAC3B,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC;AACpC,YAAA,IAAI,CAAC,WAAW,GAAG,IAAI;QAC3B;QACA,IAAI,CAAC,kBAAkB,EAAE;AACzB,QAAA,IAAI,CAAC,YAAY,CAAC,KAAK,EAAE;AACzB,QAAA,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE;AACtB,QAAA,IAAI,CAAC,KAAK,GAAG,IAAI;;;;AAIjB,QAAA,KAAK,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE;QAC1B,IAAI,IAAI,CAAC,QAAQ,CAAC,aAAa,KAAK,IAAI,CAAC,SAAS,EAAE;YAChD,IAAI,CAAC,SAAS,CAAC,WAAW,CAAC,IAAI,CAAC,QAAQ,CAAC;QAC7C;IACJ;AAEA,IAAA,IAAI,aAAa,GAAA;QACb,OAAO,IAAI,CAAC,QAAQ;IACxB;IAEQ,YAAY,GAAA;AAChB,QAAA,IAAI,IAAI,CAAC,KAAK,KAAK,IAAI,EAAE;AACrB,YAAA,MAAM,IAAI,KAAK,CAAC,sCAAsC,CAAC;QAC3D;QACA,OAAO,IAAI,CAAC,KAAK;IACrB;AAEA;;;;;;;;;;AAUG;IACK,eAAe,GAAA;AACnB,QAAA,IAAI,IAAI,CAAC,KAAK,KAAK,IAAI;YAAE;AACzB,QAAA,IAAI,IAAI,CAAC,YAAY,KAAK,IAAI,EAAE;YAC5B,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,YAAY,CAAC;AACrC,YAAA,IAAI,CAAC,YAAY,GAAG,IAAI;QAC5B;AACA,QAAA,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK;QACxB,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,IAAI,CAAC;AACvC,QAAA,MAAM,KAAK,GAAG,IAAIA,IAAU,CAAC;AACzB,YAAA,IAAI,EAAK,KAAK,CAAC,IAAI,IAAM,CAAC;AAC1B,YAAA,GAAG,EAAM,KAAK,CAAC,GAAG,IAAO,CAAC;YAC1B,KAAK,EAAI,KAAK,CAAC,KAAK;YACpB,MAAM,EAAG,KAAK,CAAC,MAAM;AACrB,YAAA,KAAK,EAAI,KAAK,CAAC,KAAK,IAAK,CAAC;AAC1B,YAAA,MAAM,EAAG,KAAK,CAAC,MAAM,IAAI,CAAC;AAC1B,YAAA,MAAM,EAAG,KAAK,CAAC,MAAM,IAAI,CAAC;AAC1B,YAAA,KAAK,EAAI,KAAK,CAAC,KAAK,IAAK,KAAK;AAC9B,YAAA,KAAK,EAAI,KAAK,CAAC,KAAK,IAAK,KAAK;YAC9B,OAAO,EAAE,KAAK,CAAC,OAAO;YACtB,OAAO,EAAE,KAAK,CAAC,OAAO;AACtB,YAAA,IAAI,EAAe,aAAa;AAChC,YAAA,MAAM,EAAa,yBAAyB;YAC5C,WAAW,EAAQ,CAAC,GAAG,IAAI;AAC3B,YAAA,aAAa,EAAM,KAAK;AACxB,YAAA,UAAU,EAAS,KAAK;AACxB,YAAA,OAAO,EAAY,KAAK;AACxB,YAAA,iBAAiB,EAAE,IAAI;AACvB,YAAA,aAAa,EAAM,KAAK;AACxB,YAAA,WAAW,EAAQ,SAAS;AACxB,SAAA,CAAC;AACT,QAAA,IAAI,CAAC,YAAY,GAAG,KAAK;AACzB,QAAA,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC;AACtB,QAAA,IAAI,CAAC,MAAM,CAAC,gBAAgB,CAAC,KAAK,CAAC;AACnC,QAAA,IAAI,CAAC,MAAM,CAAC,gBAAgB,EAAE;IAClC;AAEA;;;;;;;AAOG;IACK,gBAAgB,GAAA;AACpB,QAAA,MAAM,KAAK,GAAG,IAAI,CAAC,YAAY;AAC/B,QAAA,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK;AACxB,QAAA,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,IAAI;YAAE;QACtC,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,IAAI,CAAC;QACvC,KAAK,CAAC,GAAG,CAAC;AACN,YAAA,IAAI,EAAS,KAAK,CAAC,IAAI,IAAM,CAAC;AAC9B,YAAA,GAAG,EAAU,KAAK,CAAC,GAAG,IAAO,CAAC;YAC9B,KAAK,EAAQ,KAAK,CAAC,KAAK;YACxB,MAAM,EAAO,KAAK,CAAC,MAAM;AACzB,YAAA,KAAK,EAAQ,KAAK,CAAC,KAAK,IAAK,CAAC;AAC9B,YAAA,MAAM,EAAO,KAAK,CAAC,MAAM,IAAI,CAAC;AAC9B,YAAA,MAAM,EAAO,KAAK,CAAC,MAAM,IAAI,CAAC;AAC9B,YAAA,KAAK,EAAQ,KAAK,CAAC,KAAK,IAAK,KAAK;AAClC,YAAA,KAAK,EAAQ,KAAK,CAAC,KAAK,IAAK,KAAK;YAClC,WAAW,EAAE,CAAC,GAAG,IAAI;AACxB,SAAA,CAAC;QACF,KAAK,CAAC,SAAS,EAAE;AACjB,QAAA,IAAI,CAAC,MAAM,CAAC,gBAAgB,EAAE;IAClC;IAEQ,kBAAkB,GAAA;AACtB,QAAA,IAAI,IAAI,CAAC,YAAY,KAAK,IAAI,EAAE;YAC5B,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,YAAY,CAAC;AACrC,YAAA,IAAI,CAAC,YAAY,GAAG,IAAI;QAC5B;IACJ;AAEA;;;;;;;;AAQG;AACK,IAAA,YAAY,CAAC,QAAqB,EAAA;QACtC,IAAI,CAAC,kBAAkB,EAAE;AACzB,QAAA,IAAI,CAAC,KAAK,GAAG,QAAQ;AACrB,QAAA,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;;;;QAIzB,IAAI,CAAC,eAAe,EAAE;AACtB,QAAA,IAAI,CAAC,MAAM,CAAC,YAAY,CAAC,QAAQ,CAAC;AAClC,QAAA,IAAI,CAAC,MAAM,CAAC,oBAAoB,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;QACpD,IAAI,CAAC,eAAe,EAAE;AACtB,QAAA,IAAI,CAAC,MAAM,CAAC,gBAAgB,EAAE;AAC9B,QAAA,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,EAAE,KAAK,EAAE,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,CAAC,MAAM,EAAE,CAAC;IAChF;AAEA;;;;;;;;;;;;;;;;AAgBG;AACK,IAAA,4BAA4B,CAAC,KAAkB,EAAA;AACnD,QAAA,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,EAAE,KAAK,CAAC,MAAM,CAAC;AACpD,QAAA,IAAI,QAAQ,IAAIC,MAAY,CAAC,WAAW;YAAE;AAC1C,QAAA,MAAM,QAAQ,GAAG,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QACpDA,MAAY,CAAC,WAAW,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,QAAQ,CAAC;AACpD,QAAA,gBAAgB,CAAC,iBAAiB,EAAE,CAAC;IACzC;AAEQ,IAAA,WAAW,CAAC,GAAkB,EAAA;AAClC,QAAA,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,GAAG,CAAC;AAC3B,QAAA,IAAI,CAAC,IAAI,CAAC,cAAc,EAAE,SAAS,CAAC;AACpC,QAAA,IAAI,CAAC,IAAI,CAAC,qBAAqB,EAAE;AAC7B,YAAA,OAAO,EAAE,IAAI,CAAC,YAAY,CAAC,OAAO,EAAE;AACpC,YAAA,OAAO,EAAE,IAAI,CAAC,YAAY,CAAC,OAAO,EAAE;AACvC,SAAA,CAAC;IACN;AAEQ,IAAA,iBAAiB,CAAC,IAAgB,EAAA;QACtC,IAAI,IAAI,KAAK,SAAS;YAAE,OAAO,OAAO,CAAC,SAAS;QAChD,MAAM,MAAM,GAAG,mBAAmB,CAAC,cAAc,CAAC,IAAI,CAAC;QACvD,IAAI,MAAM,KAAK,SAAS;AAAE,YAAA,OAAO,MAAM;QACvC,MAAM,MAAM,GAAG,mBAAmB,CAAC,cAAc,CAAC,IAAI,CAAC;QACvD,IAAI,MAAM,KAAK,SAAS;AAAE,YAAA,OAAO,MAAM;AACvC,QAAA,MAAM,IAAI,KAAK,CAAC,wCAAwC,IAAI,CAAA,CAAA,CAAG,CAAC;IACpE;IAEQ,iBAAiB,CAAC,IAAgB,EAAE,MAAoB,EAAA;AAC5D,QAAA,IAAI,IAAI,KAAK,SAAS,EAAE;AACpB,YAAA,MAAM,IAAI,GAAG,OAAO,CAAC,SAAgC;AACrD,YAAA,OAAO,IAAI,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC,GAAG,cAAc,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC;QACnE;AACA,QAAA,IAAI,IAAI,KAAK,UAAU,EAAE;AACrB,YAAA,MAAM,IAAI,GAAG,OAAO,CAAC,QAA4B;AACjD,YAAA,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,QAAQ,IAAI,CAAC,CAAC,CAAC;AAC/D,YAAA,OAAO,IAAI,IAAI,CAAC,EAAE,SAAS,EAAE,CAAC;QAClC;QACA,MAAM,MAAM,GAAG,mBAAmB,CAAC,cAAc,CAAC,IAAI,CAAC;AACvD,QAAA,IAAI,MAAM,KAAK,SAAS,EAAE;YACtB,MAAM,KAAK,GAAI,MAA6C,CAAC,IAAI,CAAC,IAAI,CAAC;YACvE,OAAO,IAAI,MAAM,CAAC,EAAE,CAAC,IAAI,GAAG,KAAK,EAAE,CAAC;QACxC;QACA,MAAM,MAAM,GAAG,mBAAmB,CAAC,cAAc,CAAC,IAAI,CAAC;AACvD,QAAA,IAAI,MAAM,KAAK,SAAS,EAAE;YACtB,OAAO,IAAI,MAAM,EAAE;QACvB;AACA,QAAA,MAAM,IAAI,KAAK,CAAC,wCAAwC,IAAI,CAAA,CAAA,CAAG,CAAC;IACpE;IAEQ,qBAAqB,GAAA;;;;;AAKzB,QAAA,IAAI,CAAC,EAAE,CAAC,kBAAkB,EAAE,MAAM,IAAI,CAAC,gBAAgB,EAAE,CAAC;QAE1D,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,mBAAmB,EAAE,CAAC,CAAM,KAAI;YAC3C,MAAM,MAAM,GAAG,CAAC,CAAC,QAAQ,GAAG,CAAC,CAAC,IAAI,IAAI;AACtC,YAAA,IAAI,CAAC,IAAI,CAAC,iBAAiB,EAAE,EAAE,UAAU,EAAE,MAAM,EAAE,IAAI,IAAI,EAAE,EAAE,CAAC;YAChE,IAAI,CAAC,oBAAoB,EAAE;AAC/B,QAAA,CAAC,CAAC;QACF,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,mBAAmB,EAAE,CAAC,CAAM,KAAI;YAC3C,MAAM,MAAM,GAAG,CAAC,CAAC,QAAQ,GAAG,CAAC,CAAC,IAAI,IAAI;AACtC,YAAA,IAAI,CAAC,IAAI,CAAC,iBAAiB,EAAE,EAAE,UAAU,EAAE,MAAM,EAAE,IAAI,IAAI,EAAE,EAAE,CAAC;YAChE,IAAI,CAAC,oBAAoB,EAAE;AAC/B,QAAA,CAAC,CAAC;QACF,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,mBAAmB,EAAE,MAAK;AACrC,YAAA,IAAI,CAAC,IAAI,CAAC,mBAAmB,EAAE,SAAS,CAAC;AACzC,YAAA,IAAI,CAAC,IAAI,CAAC,qBAAqB,EAAE,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;AAC9D,QAAA,CAAC,CAAC;;;;;;;;QASF,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,YAAY,EAAE,CAAC,CAAM,KAAI;AACpC,YAAA,MAAM,MAAM,GAAG,CAAC,CAAC,MAAkC;AACnD,YAAA,IAAI,IAAI,CAAC,KAAK,KAAK,IAAI,IAAI,MAAM,KAAK,IAAI,CAAC,KAAK,EAAE;gBAC9C,IAAI,CAAC,sBAAsB,GAAG,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,KAAK,CAAC;YACnE;iBAAO,IAAI,MAAM,IAAI,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,EAAE,IAAI,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,KAAK,OAAO,EAAE;AACpF,gBAAA,IAAI,CAAC,oBAAoB,GAAG,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,CAAC,kBAAkB,CAAC,MAAM,CAAC,EAAE;YACvF;AACJ,QAAA,CAAC,CAAC;QAEF,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,iBAAiB,EAAE,CAAC,CAAM,KAAI;;;AAGzC,YAAA,MAAM,GAAG,GAAG,CAAC,CAAC,MAAkC;YAChD,IAAI,GAAG,IAAI,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,EAAE,IAAI,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,KAAK,OAAO,EAAE;AACpE,gBAAA,MAAM,IAAI,GAAG,IAAI,CAAC,oBAAoB;AACtC,gBAAA,IAAI,CAAC,oBAAoB,GAAG,IAAI;gBAChC,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI,CAAC,GAAG,KAAK,GAAG,EAAE;AACnC,oBAAA,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK;oBACzB,MAAM,KAAK,GAAG,IAAI,CAAC,kBAAkB,CAAC,GAAG,CAAC;AAC1C,oBAAA,IAAI,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,KAAK,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE;AAClD,wBAAA,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC;AACnB,4BAAA,IAAI,EAAE,YAAY;AAClB,4BAAA,EAAE,EAAI,MAAK,EAAG,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAE,GAAG,CAAC,SAAS,EAAE,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,gBAAgB,EAAE,CAAC,CAAC,IAAI,CAAC,kBAAkB,EAAE,CAAC,CAAC,CAAC;AAC5G,4BAAA,IAAI,EAAE,MAAK,EAAG,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,SAAS,EAAE,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,gBAAgB,EAAE,CAAC,CAAC,IAAI,CAAC,kBAAkB,EAAE,CAAC,CAAC,CAAC;AAC/G,yBAAA,CAAC;AACF,wBAAA,IAAI,CAAC,IAAI,CAAC,cAAc,EAAE,SAAS,CAAC;AACpC,wBAAA,IAAI,CAAC,IAAI,CAAC,qBAAqB,EAAE;AAC7B,4BAAA,OAAO,EAAE,IAAI,CAAC,YAAY,CAAC,OAAO,EAAE;AACpC,4BAAA,OAAO,EAAE,IAAI,CAAC,YAAY,CAAC,OAAO,EAAE;AACvC,yBAAA,CAAC;oBACN;gBACJ;;;;gBAIA,IAAI,CAAC,oBAAoB,EAAE;gBAC3B;YACJ;AAEA,YAAA,IAAI,IAAI,CAAC,KAAK,KAAK,IAAI,IAAI,CAAC,CAAC,MAAM,KAAK,IAAI,CAAC,KAAK;gBAAE;AACpD,YAAA,MAAM,MAAM,GAAG,IAAI,CAAC,sBAAsB;AAC1C,YAAA,IAAI,CAAC,sBAAsB,GAAG,IAAI;YAClC,IAAI,MAAM,KAAK,IAAI;gBAAE;YACrB,MAAM,KAAK,GAAG,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,KAAK,CAAC;AAC/C,YAAA,IAAI,IAAI,CAAC,eAAe,CAAC,MAAM,EAAE,KAAK,CAAC;gBAAE;AAEzC,YAAA,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK;AACxB,YAAA,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC;AACnB,gBAAA,IAAI,EAAE,WAAW;gBACjB,EAAE,EAAI,MAAK;AACP,oBAAA,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC;oBAChB,KAAK,CAAC,SAAS,EAAE;AACjB,oBAAA,IAAI,CAAC,MAAM,CAAC,gBAAgB,EAAE;AAC9B,oBAAA,IAAI,CAAC,oBAAoB,CAAC,KAAK,EAAE,SAAS,CAAC;gBAC/C,CAAC;gBACD,IAAI,EAAE,MAAK;AACP,oBAAA,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC;oBACjB,KAAK,CAAC,SAAS,EAAE;AACjB,oBAAA,IAAI,CAAC,MAAM,CAAC,gBAAgB,EAAE;AAC9B,oBAAA,IAAI,CAAC,oBAAoB,CAAC,KAAK,EAAE,SAAS,CAAC;gBAC/C,CAAC;AACJ,aAAA,CAAC;AACF,YAAA,IAAI,CAAC,IAAI,CAAC,cAAc,EAAE,SAAS,CAAC;AACpC,YAAA,IAAI,CAAC,IAAI,CAAC,qBAAqB,EAAE;AAC7B,gBAAA,OAAO,EAAE,IAAI,CAAC,YAAY,CAAC,OAAO,EAAE;AACpC,gBAAA,OAAO,EAAE,IAAI,CAAC,YAAY,CAAC,OAAO,EAAE;AACvC,aAAA,CAAC;AACF,YAAA,IAAI,CAAC,oBAAoB,CAAC,KAAK,EAAE,OAAO,CAAC;AAC7C,QAAA,CAAC,CAAC;;;;QAKF,MAAM,gBAAgB,GAAG,CAAC,KAA0C,KAAK,CAAC,CAAM,KAAI;AAChF,YAAA,MAAM,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC;AACxC,YAAA,MAAM,MAAM,GAAG,CAAC,CAAC,MAAkC;AACnD,YAAA,IAAI,CAAC,IAAI,CAAC,cAAc,EAAE;gBACtB,KAAK;gBACL,CAAC,EAAE,CAAC,CAAC,CAAC;gBACN,CAAC,EAAE,CAAC,CAAC,CAAC;AACN,gBAAA,aAAa,EAAE,MAAM,IAAI,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,IAAI,IAAI,IAAI;AAChE,aAAA,CAAC;AACN,QAAA,CAAC;AACD,QAAA,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,YAAY,EAAE,gBAAgB,CAAC,MAAM,CAAC,CAAC;AACtD,QAAA,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,YAAY,EAAE,gBAAgB,CAAC,MAAM,CAAC,CAAC;AACtD,QAAA,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,UAAU,EAAE,gBAAgB,CAAC,IAAI,CAAC,CAAC;AAClD,QAAA,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,gBAAgB,EAAE,gBAAgB,CAAC,UAAU,CAAC,CAAC;IAClE;AAEQ,IAAA,gBAAgB,CAAC,KAAkB,EAAA;QACvC,OAAO;AACH,YAAA,KAAK,EAAG,KAAK,CAAC,KAAK,IAAK,CAAC;AACzB,YAAA,MAAM,EAAE,KAAK,CAAC,MAAM,IAAI,CAAC;AACzB,YAAA,MAAM,EAAE,KAAK,CAAC,MAAM,IAAI,CAAC;AACzB,YAAA,KAAK,EAAG,KAAK,CAAC,KAAK,IAAK,KAAK;AAC7B,YAAA,KAAK,EAAG,KAAK,CAAC,KAAK,IAAK,KAAK;AAC7B,YAAA,IAAI,EAAI,KAAK,CAAC,IAAI,IAAM,CAAC;AACzB,YAAA,GAAG,EAAK,KAAK,CAAC,GAAG,IAAO,CAAC;SAC5B;IACL;IAEQ,eAAe,CAAC,CAAsB,EAAE,CAAsB,EAAA;AAClE,QAAA,OAAO,CAAC,CAAC,KAAK,KAAM,CAAC,CAAC;AACf,eAAA,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC;AACf,eAAA,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC;AACf,eAAA,CAAC,CAAC,KAAK,KAAM,CAAC,CAAC;AACf,eAAA,CAAC,CAAC,KAAK,KAAM,CAAC,CAAC;AACf,eAAA,CAAC,CAAC,IAAI,KAAO,CAAC,CAAC;AACf,eAAA,CAAC,CAAC,GAAG,KAAQ,CAAC,CAAC,GAAG;IAC7B;IAEQ,oBAAoB,CAAC,KAAkB,EAAE,MAA2B,EAAA;QACxE,MAAM,CAAC,GAAG,IAAI,CAAC,gBAAgB,CAAC,KAAK,CAAC;AACtC,QAAA,IAAI,CAAC,IAAI,CAAC,kBAAkB,EAAE,EAAE,GAAG,CAAC,EAAE,MAAM,EAAE,CAAC;IACnD;;;IAKQ,OAAgB,YAAY,GAAwC;QACxE,EAAE,CAAC,EAAE,CAAC,EAAI,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC,EAAE;AACtD,QAAA,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,EAAE;KAC3E;IAEO,WAAW,CAAC,IAAe,EAAE,CAAe,EAAA;AAChD,QAAA,MAAM,IAAI,GAAG,EAAE,IAAI,EAAE,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,WAAW,EAAE,CAAC,CAAC,WAAW,EAAE;QACzG,QAAQ,IAAI;YACR,KAAK,MAAM,EAAM,OAAO,IAAID,IAAU,CAAC,EAAE,GAAG,IAAI,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC;YAC5E,KAAK,SAAS,EAAG,OAAO,IAAI,OAAO,CAAC,EAAE,GAAG,IAAI,EAAE,EAAE,EAAE,GAAG,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC;YACjE,KAAK,UAAU,EAAE,OAAO,IAAI,QAAQ,CAAC,EAAE,GAAG,IAAI,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC;AAC1E,YAAA,KAAK,MAAM,EAAM,OAAO,IAAI,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,WAAW,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,WAAW,CAAC,EAAE,CAAC;AAC/G,YAAA,KAAK,OAAO,EAAK,OAAO,IAAI,OAAO,CAAC,CAAC,GAAG,mBAAmB,CAAC,YAAY,CAAC,EAAE,EAAE,GAAG,IAAI,EAAE,CAAC;;IAE/F;;;IAKQ,WAAW,CAAC,IAA0B,EAAE,QAAgB,EAAA;AAC5D,QAAA,OAAO,IAAI,KAAK,SAAS,GAAG,QAAQ,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;IAC/D;AAEA;;;;;;;AAOG;AACK,IAAA,SAAS,CAAC,IAAc,EAAA;AAC5B,QAAA,IAAI,IAAI,CAAC,IAAI,KAAK,OAAO;YAAE,OAAO,IAAI,CAAC,KAAK;AAE5C,QAAA,MAAM,UAAU,GAAG;YACf,EAAE,MAAM,EAAE,CAAC,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE;YAChC,EAAE,MAAM,EAAE,CAAC,EAAE,KAAK,EAAE,IAAI,CAAC,MAAM,EAAE;SACpC;AAED,QAAA,IAAI,IAAI,CAAC,IAAI,KAAK,QAAQ,EAAE;;YAExB,OAAO,IAAI,QAAQ,CAAW;AAC1B,gBAAA,IAAI,EAAW,QAAQ;AACvB,gBAAA,aAAa,EAAE,YAAY;gBAC3B,MAAM,EAAS,EAAE,EAAE,EAAE,GAAG,EAAE,EAAE,EAAE,GAAG,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,GAAG,EAAE,EAAE,EAAE,GAAG,EAAE,EAAE,EAAE,GAAG,EAAE;gBACrE,UAAU;AACb,aAAA,CAAC;QACN;;AAGA,QAAA,MAAM,GAAG,GAAG,CAAC,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,EAAE,IAAI,GAAG;QACxC,MAAM,EAAE,GAAI,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC;QAC7B,MAAM,EAAE,GAAI,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC;QAC7B,OAAO,IAAI,QAAQ,CAAW;AAC1B,YAAA,IAAI,EAAW,QAAQ;AACvB,YAAA,aAAa,EAAE,YAAY;YAC3B,MAAM,EAAS,EAAE,EAAE,EAAE,GAAG,GAAG,EAAE,EAAE,EAAE,EAAE,GAAG,GAAG,EAAE,EAAE,EAAE,EAAE,GAAG,GAAG,EAAE,EAAE,EAAE,EAAE,GAAG,GAAG,EAAE,EAAE;YACzE,UAAU;AACb,SAAA,CAAC;IACN;;AAGQ,IAAA,QAAQ,CAAC,IAAa,EAAA;AAC1B,QAAA,IAAI,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE;AACvB,YAAA,MAAM,KAAK,GAAI,IAAI,CAAC,UAAU,IAAI,EAAE;AACpC,YAAA,MAAM,KAAK,GAAI,IAAI,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,SAAS,CAAC;AAC5D,YAAA,MAAM,MAAM,GAAG,IAAI,CAAC,YAAY,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,EAAE,KAAK,EAAE,SAAS,CAAC;AAC3E,YAAA,IAAI,IAAI,CAAC,IAAI,KAAK,QAAQ,EAAE;AACxB,gBAAA,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,EAAE;YACtD;AACA,YAAA,MAAM,CAAC,GAAK,IAAI,CAAC,MAAM;YACvB,MAAM,GAAG,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC,GAAG,GAAG,IAAI,IAAI,CAAC,EAAE;YAC9F,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,GAAG,GAAG,GAAG,IAAI,GAAG,CAAC,EAAE;QAClF;AACA,QAAA,MAAM,KAAK,GAAG,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,KAAK,EAAE,GAAG,IAAI,GAAG,SAAS;AACxE,QAAA,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC,EAAE;IAChE;;AAGQ,IAAA,SAAS,CAAC,IAAa,EAAA;QAC3B,IAAI,OAAO,IAAI,KAAK,QAAQ;AAAE,YAAA,OAAO,IAAI;QACzC,OAAO,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,KAAK;IACpC;AAEQ,IAAA,UAAU,CAAC,CAAU,EAAA;AAKzB,QAAA,OAAO,CAAC,KAAK,IAAI,IAAI,OAAO,CAAC,KAAK;AAC3B,eAAA,KAAK,CAAC,OAAO,CAAE,CAA8B,CAAC,UAAU,CAAC;IACpE;;IAGQ,YAAY,CAAC,KAAyB,EAAE,QAAgB,EAAA;AAC5D,QAAA,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,mBAAmB,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,KAAK,GAAG,QAAQ;IAC1F;AAEQ,IAAA,UAAU,CAAC,IAAe,EAAA;AAC9B,QAAA,MAAM,MAAM,GAA8B;AACtC,YAAA,IAAI,EAAE,WAAW,EAAE,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO;SAC5F;AACD,QAAA,OAAO,MAAM,CAAC,IAAI,CAAC;IACvB;AAEA;;;AAGG;AACK,IAAA,WAAW,CAAC,GAAiB,EAAE,IAAe,EAAE,IAAY,EAAA;AAChE,QAAA,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,KAAK;AAC1B,cAAE,IAAI,CAAC,KAAK,CAAC,cAAc;cACzB,IAAI,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,GAAG,CAAC,EAAE,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC;QACxE,GAAG,CAAC,GAAG,CAAC,EAAE,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,CAAC,CAAC,EAAE,CAAC;QAChF,GAAG,CAAC,SAAS,EAAE;QACf,IAAI,CAAC,UAAU,CAAC,GAAG,EAAE,IAAI,EAAE,IAAI,CAAC;AAChC,QAAA,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC;QACpB,IAAI,CAAC,eAAe,EAAE;AACtB,QAAA,IAAI,CAAC,MAAM,CAAC,eAAe,CAAC,GAAG,CAAC;AAChC,QAAA,IAAI,CAAC,MAAM,CAAC,gBAAgB,EAAE;QAE9B,IAAI,CAAC,WAAW,CAAC;YACb,IAAI,EAAE,CAAA,IAAA,EAAO,IAAI,CAAA,CAAE;YACnB,EAAE,EAAE,MAAK;AACL,gBAAA,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC;gBACpB,IAAI,CAAC,eAAe,EAAE;AACtB,gBAAA,IAAI,CAAC,MAAM,CAAC,eAAe,CAAC,GAAG,CAAC;AAChC,gBAAA,IAAI,CAAC,MAAM,CAAC,gBAAgB,EAAE;gBAC9B,IAAI,CAAC,kBAAkB,EAAE;YAC7B,CAAC;YACD,IAAI,EAAE,MAAK;AACP,gBAAA,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC;AACvB,gBAAA,IAAI,CAAC,MAAM,CAAC,mBAAmB,EAAE;AACjC,gBAAA,IAAI,CAAC,MAAM,CAAC,gBAAgB,EAAE;gBAC9B,IAAI,CAAC,kBAAkB,EAAE;YAC7B,CAAC;AACJ,SAAA,CAAC;QACF,IAAI,CAAC,kBAAkB,EAAE;IAC7B;AAEQ,IAAA,UAAU,CAAC,GAAiB,EAAE,IAAe,EAAE,IAAY,EAAA;QAC/D,MAAM,CAAC,GAAG,GAAyC;QACnD,CAAC,CAAC,UAAU,CAAC,GAAK,IAAI,KAAK,OAAO,GAAG,UAAU,GAAG,CAAA,MAAA,EAAS,IAAI,CAAC,WAAW,EAAE,EAAE;AAC/E,QAAA,CAAC,CAAC,YAAY,CAAC,GAAG,IAAI;AACtB,QAAA,CAAC,CAAC,YAAY,CAAC,GAAG,IAAI;IAC1B;;IAGQ,YAAY,GAAA;QAChB,OAAO,IAAI,CAAC,MAAM,CAAC,UAAU,EAAE,CAAC,MAAM,CAAC,CAAC,IAAK,CAAwC,CAAC,UAAU,CAAC,KAAK,SAAS,CAAC;IACpH;;IAGQ,kBAAkB,GAAA;QACtB,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,YAAY,EAAE,EAAE;AACjC,YAAA,IAAI,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,KAAK,OAAO;AAAE,gBAAA,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC;QAC5D;AACA,QAAA,IAAI,CAAC,WAAW,GAAG,CAAC;IACxB;AAEQ,IAAA,SAAS,CAAC,EAAU,EAAA;QACxB,OAAO,IAAI,CAAC,YAAY,EAAE,CAAC,IAAI,CAAC,CAAC,IAAI,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,EAAE,CAAC,IAAI,IAAI;IACxE;AAEQ,IAAA,OAAO,CAAC,CAAe,EAAA;AAC3B,QAAA,OAAQ,CAAwC,CAAC,UAAU,CAAW,IAAI,EAAE;IAChF;AAEQ,IAAA,SAAS,CAAC,CAAe,EAAA;AAC7B,QAAA,OAAQ,CAAwC,CAAC,YAAY,CAAc,IAAI,OAAO;IAC1F;AAEQ,IAAA,SAAS,CAAC,CAAe,EAAA;AAC7B,QAAA,OAAQ,CAAwC,CAAC,YAAY,CAAW,IAAI,OAAO;IACvF;;IAGQ,eAAe,GAAA;AACnB,QAAA,IAAI,IAAI,CAAC,KAAK,KAAK,IAAI,IAAI,IAAI,CAAC,MAAM,CAAC,UAAU,EAAE,CAAC,MAAM,GAAG,CAAC,EAAE;YAC5D,IAAI,CAAC,MAAM,CAAC,gBAAgB,CAAC,IAAI,CAAC,KAAK,CAAC;QAC5C;IACJ;;IAGQ,kBAAkB,GAAA;AACtB,QAAA,IAAI,CAAC,IAAI,CAAC,eAAe,EAAE,SAAS,CAAC;QACrC,IAAI,CAAC,oBAAoB,EAAE;IAC/B;IAEQ,oBAAoB,GAAA;QACxB,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,eAAe,EAAE;QAC5C,IAAI,MAAM,KAAK,SAAS,IAAI,MAAM,KAAK,IAAI,EAAE;AACzC,YAAA,IAAI,CAAC,IAAI,CAAC,qBAAqB,EAAE,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;YAC1D;QACJ;QACA,MAAM,EAAE,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC;AAC/B,QAAA,IAAI,CAAC,IAAI,CAAC,qBAAqB,EAAE;YAC7B,EAAE,EAAI,EAAE,KAAK,EAAE,GAAG,IAAI,GAAG,EAAE;AAC3B,YAAA,IAAI,EAAE,EAAE,KAAK,EAAE,GAAG,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC;AAClD,SAAA,CAAC;IACN;AAEQ,IAAA,kBAAkB,CAAC,CAAe,EAAA;QACtC,OAAO;AACH,YAAA,IAAI,EAAI,CAAC,CAAC,IAAI,IAAM,CAAC;AACrB,YAAA,GAAG,EAAK,CAAC,CAAC,GAAG,IAAO,CAAC;AACrB,YAAA,MAAM,EAAE,CAAC,CAAC,MAAM,IAAI,CAAC;AACrB,YAAA,MAAM,EAAE,CAAC,CAAC,MAAM,IAAI,CAAC;AACrB,YAAA,KAAK,EAAG,CAAC,CAAC,KAAK,IAAK,CAAC;AACrB,YAAA,KAAK,EAAG,CAAC,CAAC,KAAK,IAAK,CAAC;AACrB,YAAA,KAAK,EAAG,CAAC,CAAC,KAAK,IAAK,CAAC;AACrB,YAAA,KAAK,EAAG,CAAC,CAAC,KAAK,IAAK,CAAC;AACrB,YAAA,MAAM,EAAE,CAAC,CAAC,MAAM,IAAI,CAAC;SACxB;IACL;;AAIA;;;;AAIG;IACK,mBAAmB,GAAA;QACvB,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,eAAe,EAAE;AAC5C,QAAA,IAAI,MAAM,KAAK,SAAS,IAAI,MAAM,KAAK,IAAI;AAAE,YAAA,OAAO,IAAI;AACxD,QAAA,IAAI,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,EAAE,IAAI,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,KAAK,OAAO;AAAE,YAAA,OAAO,IAAI;AAClF,QAAA,OAAO,MAAM;IACjB;AAEA;;;AAGG;IACK,UAAU,GAAA;QACd,OAAO,IAAI,CAAC,mBAAmB,EAAE,IAAI,IAAI,CAAC,KAAK;IACnD;IAEQ,WAAW,CAAC,GAAiB,EAAE,OAAe,EAAA;AAClD,QAAA,MAAM,IAAI,GAAG,GAAG,CAAC,KAAK,IAAI,CAAC;AAC3B,QAAA,MAAM,IAAI,GAAG,IAAI,GAAG,OAAO;AAC3B,QAAA,MAAM,KAAK,GAAG,CAAC,KAAa,KAAU;AAClC,YAAA,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC;YACjB,GAAG,CAAC,SAAS,EAAE;AACf,YAAA,IAAI,CAAC,MAAM,CAAC,gBAAgB,EAAE;YAC9B,IAAI,CAAC,kBAAkB,EAAE;AAC7B,QAAA,CAAC;QACD,KAAK,CAAC,IAAI,CAAC;QACX,IAAI,CAAC,WAAW,CAAC;AACb,YAAA,IAAI,EAAE,cAAc;YACpB,EAAE,EAAI,MAAK,EAAG,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YAC5B,IAAI,EAAE,MAAK,EAAG,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAC/B,SAAA,CAAC;IACN;IAEQ,SAAS,CAAC,GAAiB,EAAE,IAA+B,EAAA;AAChE,QAAA,MAAM,IAAI,GAAsB,IAAI,KAAK,YAAY,GAAG,OAAO,GAAG,OAAO;QACzE,MAAM,IAAI,GAAG,GAAG,CAAC,IAAI,CAAC,IAAI,KAAK;AAC/B,QAAA,MAAM,KAAK,GAAG,CAAC,KAAc,KAAU;AACnC,YAAA,GAAG,CAAC,GAAG,CAAC,IAAI,EAAE,KAAK,CAAC;YACpB,GAAG,CAAC,SAAS,EAAE;AACf,YAAA,IAAI,CAAC,MAAM,CAAC,gBAAgB,EAAE;YAC9B,IAAI,CAAC,kBAAkB,EAAE;AAC7B,QAAA,CAAC;AACD,QAAA,KAAK,CAAC,CAAC,IAAI,CAAC;QACZ,IAAI,CAAC,WAAW,CAAC;YACb,IAAI,EAAE,CAAA,WAAA,EAAc,IAAI,CAAA,CAAE;YAC1B,EAAE,EAAI,MAAK,EAAG,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YAC7B,IAAI,EAAE,MAAK,EAAG,KAAK,CAAC,IAAI,CAAC,CAAC,CAAE,CAAC;AAChC,SAAA,CAAC;IACN;AAEA;;;;;;;AAOG;IACK,aAAa,CAAC,MAAoB,EAAE,IAAc,EAAA;AACtD,QAAA,IAAI,IAAI,CAAC,KAAK,KAAK,MAAM;AAAE,YAAA,OAAO,IAAI;AAEtC,QAAA,MAAM,CAAC,GAAG,MAAM,CAAC,KAAK,IAAK,CAAC;AAC5B,QAAA,MAAM,CAAC,GAAG,MAAM,CAAC,MAAM,IAAI,CAAC;QAC5B,MAAM,EAAE,GAAG,CAAC,IAAI,IAAI,CAAC,KAAK,GAAG,GAAG,CAAC;QACjC,MAAM,EAAE,GAAG,CAAC,IAAI,IAAI,CAAC,KAAK,GAAG,GAAG,CAAC;AACjC,QAAA,MAAM,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC;AAClC,QAAA,MAAM,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC;AAClC,QAAA,MAAM,MAAM,GAAG,EAAE,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,EAAW;AAEjF,QAAA,QAAQ,IAAI,CAAC,KAAK;AACd,YAAA,KAAK,MAAM;AACP,gBAAA,OAAO,IAAIA,IAAU,CAAC,EAAE,GAAG,MAAM,EAAE,KAAK,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC;YAC/D,KAAK,SAAS,EAAE;gBACZ,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,CAAC,GAAG,CAAC,KAAK,IAAI,CAAC,MAAM,GAAG,GAAG,CAAC;gBACtD,OAAO,IAAIA,IAAU,CAAC,EAAE,GAAG,MAAM,EAAE,KAAK,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC;YAC7E;AACA,YAAA,KAAK,SAAS;gBACV,OAAO,IAAI,OAAO,CAAC,EAAE,GAAG,MAAM,EAAE,EAAE,EAAE,EAAE,GAAG,CAAC,EAAE,EAAE,EAAE,EAAE,GAAG,CAAC,EAAE,CAAC;AAC7D,YAAA,KAAK,UAAU;AACX,gBAAA,OAAO,IAAI,QAAQ,CAAC,EAAE,GAAG,MAAM,EAAE,KAAK,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC;AAC7D,YAAA,KAAK,QAAQ;;;;AAIT,gBAAA,OAAO,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,OAAO,IAAI,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,MAAM,CAAC;AACjE,YAAA;;;AAGI,gBAAA,OAAO,IAAI,CAAC,aAAa,CAAC,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,MAAM,CAAC;;IAE7E;AAEA;;;;;;;;AAQG;AACK,IAAA,aAAa,CACjB,CAAS,EACT,EAAU,EACV,EAAU,EACV,MAA2E,EAAA;AAE3E,QAAA,IAAI,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE;AAAE,YAAA,OAAO,IAAI;AAChC,QAAA,IAAI,IAAU;AACd,QAAA,IAAI;YACA,IAAI,GAAG,IAAI,IAAI,CAAC,CAAC,EAAE,EAAE,GAAG,MAAM,EAAE,CAAC;QACrC;AAAE,QAAA,MAAM;;;AAGJ,YAAA,OAAO,IAAI;QACf;AACA,QAAA,MAAM,EAAE,GAAG,IAAI,CAAC,KAAK,IAAK,GAAG;AAC7B,QAAA,MAAM,EAAE,GAAG,IAAI,CAAC,MAAM,IAAI,GAAG;AAC7B,QAAA,IAAI,CAAC,GAAG,CAAC,EAAE,MAAM,EAAE,EAAE,GAAG,EAAE,EAAE,MAAM,EAAE,EAAE,GAAG,EAAE,EAAE,CAAC;QAC9C,IAAI,CAAC,SAAS,EAAE;AAChB,QAAA,OAAO,IAAI;IACf;IAEQ,IAAI,CAA4B,KAAQ,EAAE,IAAqB,EAAA;QACnE,MAAM,GAAG,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,KAAK,CAAC;QACrC,IAAI,GAAG,KAAK,SAAS;YAAE;AACvB,QAAA,KAAK,MAAM,OAAO,IAAI,GAAG,EAAE;YACvB,OAAO,CAAC,IAAI,CAAC;QACjB;IACJ;;;ACruEJ;;;;;;;;;;AAUG;MAEU,uBAAuB,CAAA;IACf,cAAc,GAAG,MAAM,CAA2B,IAAI;uFAAC;IAE/D,KAAK,GAAW,MAAM,CAAc,eAAe;8EAAC;IACpD,UAAU,GAAM,MAAM,CAAc,IAAI;mFAAC;IACzC,OAAO,GAAS,MAAM,CAAU,KAAK;gFAAC;IACtC,OAAO,GAAS,MAAM,CAAU,KAAK;gFAAC;;IAEtC,UAAU,GAAM,MAAM,CAAgB,IAAI;mFAAC;IAC3C,YAAY,GAAI,MAAM,CAAgB,IAAI;qFAAC;AACpD;;;;;AAKG;IACM,WAAW,GAAK,MAAM,CAAS,CAAC;oFAAC;AAC1C;;;;;;;AAOG;IACM,OAAO,GAAS,MAAM,CAAS,CAAC;gFAAC;AAC1C;;;;AAIG;IACM,cAAc,GAAG,MAAM,CAAU,KAAK;uFAAC;;;;;;;IAQvC,aAAa,GAAG,MAAM,CAAS,CAAC;sFAAC;IACjC,WAAW,GAAK,MAAM,CAAS,CAAC;oFAAC;IACjC,WAAW,GAAK,MAAM,CAAS,CAAC;oFAAC;IACjC,UAAU,GAAM,MAAM,CAAU,KAAK;mFAAC;IACtC,UAAU,GAAM,MAAM,CAAU,KAAK;mFAAC;IACtC,aAAa,GAAG,MAAM,CAA2B,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE;sFAAC;AAEzE;;;AAGG;IACM,MAAM,GAAG,MAAM,CAAc,EAAE;+EAAC;;IAEhC,aAAa,GAAG,MAAM,CAAgB,IAAI;sFAAC;;IAE3C,eAAe,GAAG,MAAM,CAAmB,IAAI;wFAAC;AAEzD;;;;;AAKG;IACM,gBAAgB,GAAG,MAAM,CAAS,CAAC;yFAAC;IACpC,gBAAgB,GAAG,MAAM,CAAU,KAAK;yFAAC;IACzC,gBAAgB,GAAG,MAAM,CAAU,KAAK;yFAAC;;AAGjC,IAAA,cAAc,GAAG,QAAQ,CAAC,MAAK;AAC5C,QAAA,MAAM,IAAI,GAAG,IAAI,CAAC,eAAe,EAAE;AACnC,QAAA,OAAO,IAAI,KAAK,IAAI,IAAI,IAAI,KAAK,OAAO;IAC5C,CAAC;uFAAC;AAEF;;;AAGG;IACM,uBAAuB,GAAG,QAAQ,CAAC,MACxC,IAAI,CAAC,cAAc,EAAE,GAAG,IAAI,CAAC,gBAAgB,EAAE,GAAG,IAAI,CAAC,aAAa,EAAE;gGACzE;IACQ,oBAAoB,GAAG,QAAQ,CAAC,MACrC,IAAI,CAAC,cAAc,EAAE,GAAG,IAAI,CAAC,gBAAgB,EAAE,GAAG,IAAI,CAAC,UAAU,EAAE;6FACtE;IACQ,oBAAoB,GAAG,QAAQ,CAAC,MACrC,IAAI,CAAC,cAAc,EAAE,GAAG,IAAI,CAAC,gBAAgB,EAAE,GAAG,IAAI,CAAC,UAAU,EAAE;6FACtE;AAED;;;;AAIG;IACM,iBAAiB,GAAG,QAAQ,CAAC,MAClC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,GAAG,GAAG,CAAC;0FACjD;;IAGQ,MAAM,GAAU,QAAQ,CAAC,MAAM,IAAI,CAAC,cAAc,EAAE;+EAAC;AAErD,IAAA,OAAO,GAAS,QAAQ,CAC7B,MAAM,IAAI,CAAC,KAAK,EAAE,KAAK,OAAO,IAAI,IAAI,CAAC,cAAc,EAAE,KAAK,IAAI;gFACnE;AAED;;;;;;;;;;AAUG;AACH,IAAA,MAAM,gBAAgB,CAClB,SAAsB,EACtB,SAAiB,EACjB,QAAgB,EAAA;AAEhB,QAAA,IAAI,IAAI,CAAC,KAAK,EAAE,KAAK,eAAe,EAAE;AAClC,YAAA,MAAM,IAAI,KAAK,CAAC,4BAA4B,CAAC;QACjD;AAEA,QAAA,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,SAAS,CAAC;AAEzB,QAAA,IAAI;YACA,MAAM,MAAM,GAAG,MAAM,mBAAmB,CAAC,MAAM,CAAC,EAAE,SAAS,EAAE,CAAC;YAC9D,MAAM,CAAC,mBAAmB,CAAC;gBACvB,KAAK,EAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,SAAS,CAAC,WAAW,CAAC;gBAC1C,MAAM,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,SAAS,CAAC,YAAY,CAAC;AAC9C,aAAA,CAAC;YACF,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,SAAS,CAAC,SAAS,EAAE,QAAQ,CAAC;AAExD,YAAA,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,MAAM,CAAC;AAC/B,YAAA,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC;AACzB,YAAA,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC;AAEvB,YAAA,IAAI,CAAC,qBAAqB,CAAC,MAAM,CAAC;QACtC;QAAE,OAAO,GAAG,EAAE;AACV,YAAA,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC;AACvB,YAAA,IAAI,CAAC,YAAY,CAAC,GAAG,CACjB,GAAG,YAAY,KAAK,GAAG,GAAG,CAAC,OAAO,GAAG,6BAA6B,CACrE;AACD,YAAA,MAAM,GAAG;QACb;IACJ;AAEA;;;;AAIG;IACH,aAAa,GAAA;AACT,QAAA,MAAM,MAAM,GAAG,IAAI,CAAC,cAAc,EAAE;AACpC,QAAA,IAAI,MAAM,KAAK,IAAI,EAAE;YACjB,MAAM,CAAC,OAAO,EAAE;AAChB,YAAA,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,IAAI,CAAC;QACjC;AACA,QAAA,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,eAAe,CAAC;AAC/B,QAAA,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC;AACzB,QAAA,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC;AACvB,QAAA,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC;AACvB,QAAA,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC;AACzB,QAAA,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,IAAI,CAAC;AAC3B,QAAA,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC;AACvB,QAAA,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC;AACnB,QAAA,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,KAAK,CAAC;AAC9B,QAAA,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC,CAAC;AACzB,QAAA,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC;AACvB,QAAA,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC;AACvB,QAAA,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,KAAK,CAAC;AAC1B,QAAA,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,KAAK,CAAC;AAC1B,QAAA,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC;AACtC,QAAA,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC;AACnB,QAAA,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,IAAI,CAAC;AAC5B,QAAA,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,IAAI,CAAC;AAC9B,QAAA,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,CAAC,CAAC;AAC5B,QAAA,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,KAAK,CAAC;AAChC,QAAA,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,KAAK,CAAC;IACpC;AAEA,IAAA,aAAa,CAAC,MAAqB,EAAA;AAC/B,QAAA,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,MAAM,CAAC;IAC/B;AAEA;;;;;AAKG;AACH,IAAA,gBAAgB,CAAC,IAAU,EAAA;AACvB,QAAA,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC;IAC7B;AAEA;;;;;;;AAOG;AACK,IAAA,OAAgB,QAAQ,GAAI,IAAI;AAChC,IAAA,OAAgB,QAAQ,GAAI,EAAE;AAC9B,IAAA,OAAgB,SAAS,GAAG,IAAI;AAExC,IAAA,OAAO,CAAC,KAAa,EAAA;AACjB,QAAA,MAAM,MAAM,GAAG,IAAI,CAAC,cAAc,EAAE;QACpC,IAAI,MAAM,KAAK,IAAI;YAAE;QACrB,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,CACpB,uBAAuB,CAAC,QAAQ,EAChC,IAAI,CAAC,GAAG,CAAC,uBAAuB,CAAC,QAAQ,EAAE,KAAK,CAAC,CACpD;AACD,QAAA,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC;AACvB,QAAA,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,OAAO,CAAC;IACjC;AAEA,IAAA,MAAM,KAAY,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,WAAW,EAAE,GAAG,uBAAuB,CAAC,SAAS,CAAC,CAAC,CAAC;AACxF,IAAA,OAAO,KAAW,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,WAAW,EAAE,GAAG,uBAAuB,CAAC,SAAS,CAAC,CAAC,CAAC;IAExF,SAAS,GAAA;AACL,QAAA,MAAM,MAAM,GAAG,IAAI,CAAC,cAAc,EAAE;QACpC,IAAI,MAAM,KAAK,IAAI;YAAE;;;;QAIrB,MAAM,CAAC,SAAS,EAAE;AAClB,QAAA,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,EAAE;AAC1B,QAAA,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC;AACnB,QAAA,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,GAAG,CAAC;IAC7B;AAEA;;;;;;;AAOG;AACH,IAAA,YAAY,CAAC,YAAkB,EAAA;AAC3B,QAAA,MAAM,MAAM,GAAG,IAAI,CAAC,cAAc,EAAE;QACpC,IAAI,MAAM,KAAK,IAAI;YAAE;QACrB,MAAM,GAAG,GAAG,MAAM,CAAC,UAAU,CAAC,YAAY,CAAC;AAC3C,QAAA,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC;AACrB,QAAA,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC;IACrB;AAEA;;;;;;AAMG;AACH,IAAA,kBAAkB,CAAC,YAAkB,EAAA;AACjC,QAAA,MAAM,MAAM,GAAG,IAAI,CAAC,cAAc,EAAE;QACpC,IAAI,MAAM,KAAK,IAAI;YAAE;AACrB,QAAA,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,UAAU,CAAC,YAAY,CAAC,CAAC;IACrD;IAEA,cAAc,GAAA;AACV,QAAA,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;IACvC;AAEA;;;;;;;;;;;;;;;;AAgBG;AACH,IAAA,MAAM,KAAK,GAAA;AACP,QAAA,MAAM,MAAM,GAAG,IAAI,CAAC,cAAc,EAAE;QACpC,IAAI,MAAM,KAAK,IAAI;YAAE;AAErB,QAAA,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC;AACzB,QAAA,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,KAAK,CAAC;AAC9B,QAAA,MAAM,MAAM,CAAC,KAAK,EAAE;;;;;;QAMpB,MAAM,CAAC,SAAS,EAAE;AAClB,QAAA,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,EAAE;AAC1B,QAAA,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC;AACnB,QAAA,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,GAAG,CAAC;IAC7B;AAEQ,IAAA,qBAAqB,CAAC,MAAyB,EAAA;;;;QAInD,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;QAClC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;AAElC,QAAA,MAAM,CAAC,EAAE,CAAC,qBAAqB,EAAE,CAAC,EAAE,OAAO,EAAE,OAAO,EAAE,KAAI;AACtD,YAAA,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC;AACzB,YAAA,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC;AAC7B,QAAA,CAAC,CAAC;;;;;;;;;;AAWF,QAAA,MAAM,CAAC,EAAE,CAAC,aAAa,EAAE,IAAI,IAAG;AAC5B,YAAA,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC;AACzB,YAAA,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC;AACvB,YAAA,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC,CAAC;AACzB,YAAA,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC;AACvB,YAAA,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC;AACvB,YAAA,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,KAAK,CAAC;AAC1B,YAAA,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,KAAK,CAAC;AAC1B,YAAA,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC;AAC1C,QAAA,CAAC,CAAC;;;;;;AAOF,QAAA,MAAM,CAAC,EAAE,CAAC,kBAAkB,EAAE,CAAC,IAAG;YAC9B,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC;YAC/B,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC;YAC9B,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC;YAC9B,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC;YAC5B,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC;AAC5B,YAAA,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,EAAE,CAAC,CAAC,GAAG,EAAE,CAAC;AACnD,QAAA,CAAC,CAAC;;;;QAKF,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC;QACnC,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,MAAM,CAAC,gBAAgB,EAAE,CAAC;QACjD,MAAM,CAAC,EAAE,CAAC,eAAe,EAAE,MAAM,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,CAAC;AACrE,QAAA,MAAM,CAAC,EAAE,CAAC,qBAAqB,EAAE,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,KAAI;AAC9C,YAAA,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,EAAE,CAAC;AAC1B,YAAA,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,IAAI,CAAC;;;;;AAK9B,YAAA,MAAM,CAAC,GAAG,MAAM,CAAC,uBAAuB,EAAE;AAC1C,YAAA,IAAI,CAAC,KAAK,IAAI,EAAE;gBACZ,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC;gBAClC,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC;gBAClC,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC;YACtC;AACJ,QAAA,CAAC,CAAC;IACN;uGA9WS,uBAAuB,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,UAAA,EAAA,CAAA;2GAAvB,uBAAuB,EAAA,CAAA;;2FAAvB,uBAAuB,EAAA,UAAA,EAAA,CAAA;kBADnC;;;ACzBD;;;;;;;;;AASG;MAQU,mBAAmB,CAAA;AACT,IAAA,KAAK,GAAG,MAAM,CAAC,uBAAuB,CAAC;AAE1D,IAAA,MAAM,IAAI,GAAA;QACN,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE;QAClC,IAAI,MAAM,KAAK,IAAI;AAAE,YAAA,MAAM,MAAM,CAAC,IAAI,EAAE;IAC5C;AAEA,IAAA,MAAM,IAAI,GAAA;QACN,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE;QAClC,IAAI,MAAM,KAAK,IAAI;AAAE,YAAA,MAAM,MAAM,CAAC,IAAI,EAAE;IAC5C;AAEA,IAAA,MAAM,KAAK,GAAA;;;;;AAKP,QAAA,MAAM,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE;IAC5B;uGAnBS,mBAAmB,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAAnB,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,QAAA,EAAA,IAAA,EAAA,mBAAmB,2FCpBhC,yrFA8EA,EAAA,MAAA,EAAA,CAAA,k9CAAA,CAAA,EAAA,eAAA,EAAA,EAAA,CAAA,uBAAA,CAAA,MAAA,EAAA,CAAA;;2FD1Da,mBAAmB,EAAA,UAAA,EAAA,CAAA;kBAP/B,SAAS;AACI,YAAA,IAAA,EAAA,CAAA,EAAA,QAAA,EAAA,iCAAiC,EAAA,UAAA,EAC/B,IAAI,EAAA,eAAA,EACC,uBAAuB,CAAC,MAAM,EAAA,QAAA,EAAA,yrFAAA,EAAA,MAAA,EAAA,CAAA,k9CAAA,CAAA,EAAA;;;AEVnD;;;;;;;;;;;;;;;;;;;;;;;AAuBG;MAQU,oBAAoB,CAAA;AACV,IAAA,KAAK,GAAG,MAAM,CAAC,uBAAuB,CAAC;AACzC,IAAA,MAAM,GAAI,MAAM,CAAC,MAAM,CAAC;AAGxB,IAAA,YAAY;;IAG7B,IACc,UAAU,GAAA,EAAc,OAAO,IAAI,CAAC,KAAK,CAAC,cAAc,EAAE,CAAC,CAAC;IAE1E,IACc,aAAa,KAAc,OAAO,IAAI,CAAC,SAAS,CAAC,CAAC;IAExD,SAAS,GAAI,KAAK;IAClB,SAAS,GAAI,CAAC;IACd,SAAS,GAAI,CAAC;AACd,IAAA,SAAS;AACjB;;;;AAIG;IACK,UAAU,GAAG,KAAK;AAE1B,IAAA,WAAA,GAAA;;;;;;;;;QASI,MAAM,CAAC,MAAK;YACR,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,UAAU,EAAE;YACpC,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,EAAE,IAAI,IAAI,KAAK,IAAI,EAAE;AACvC,gBAAA,MAAM,EAAE,GAAG,IAAI,CAAC,YAAY,CAAC,aAAa;AAC1C,gBAAA,MAAM,QAAQ,GAAG;oBACb,KAAK,EAAG,EAAE,CAAC,WAAW;oBACtB,MAAM,EAAE,EAAE,CAAC,YAAY;iBAC1B;gBACD,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,EAAE,mBAAmB,CAAC,QAAQ,CAAC;AAClD,gBAAA,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,QAAQ,CAAC;AACjC,gBAAA,IAAI,CAAC,UAAU,GAAG,IAAI;YAC1B;AACJ,QAAA,CAAC,CAAC;;;;;;;;;QAUF,MAAM,CAAC,MAAK;YACR,MAAM,MAAM,GAAO,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE;YACtC,MAAM,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,cAAc,EAAE;YAC9C,IAAI,MAAM,KAAK,IAAI;gBAAE;YACrB,IAAI,UAAU,EAAE;AACZ,gBAAA,MAAM,CAAC,SAAS,CAAC,MAAM,CAAC;AACxB,gBAAA,MAAM,CAAC,mBAAmB,CAAC,KAAK,CAAC;YACrC;iBAAO;AACH,gBAAA,MAAM,CAAC,SAAS,CAAC,SAAS,CAAC;AAC3B,gBAAA,MAAM,CAAC,mBAAmB,CAAC,IAAI,CAAC;YACpC;AACJ,QAAA,CAAC,CAAC;IACN;IAEA,QAAQ,GAAA;QACJ,IAAI,OAAO,cAAc,KAAK,WAAW;YAAE;;;;;AAK3C,QAAA,IAAI,CAAC,MAAM,CAAC,iBAAiB,CAAC,MAAK;AAC/B,YAAA,IAAI,CAAC,SAAS,GAAG,IAAI,cAAc,CAAC,MAAK;gBACrC,IAAI,CAAC,IAAI,CAAC,UAAU;oBAAE;AACtB,gBAAA,MAAM,EAAE,GAAG,IAAI,CAAC,YAAY,CAAC,aAAa;AAC1C,gBAAA,MAAM,QAAQ,GAAG;oBACb,KAAK,EAAG,EAAE,CAAC,WAAW;oBACtB,MAAM,EAAE,EAAE,CAAC,YAAY;iBAC1B;;;;;gBAKD,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,EAAE,mBAAmB,CAAC,QAAQ,CAAC;AAClD,gBAAA,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,MAAK;AACjB,oBAAA,IAAI,CAAC,KAAK,CAAC,kBAAkB,CAAC,QAAQ,CAAC;AAC3C,gBAAA,CAAC,CAAC;AACN,YAAA,CAAC,CAAC;YACF,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,YAAY,CAAC,aAAa,CAAC;AAC3D,QAAA,CAAC,CAAC;IACN;IAEA,WAAW,GAAA;AACP,QAAA,IAAI,CAAC,SAAS,EAAE,UAAU,EAAE;IAChC;IAEA,mBAAmB,GAAA;AACf,QAAA,OAAO,IAAI,CAAC,YAAY,CAAC,aAAa;IAC1C;AAEA;;;;;;;;;;;;;;AAcG;IACH,KAAK,GAAA;AACD,QAAA,MAAM,EAAE,GAAG,IAAI,CAAC,YAAY,CAAC,aAAa;AAC1C,QAAA,MAAM,QAAQ,GAAG,EAAE,KAAK,EAAE,EAAE,CAAC,WAAW,EAAE,MAAM,EAAE,EAAE,CAAC,YAAY,EAAE;QACnE,IAAI,QAAQ,CAAC,KAAK,KAAK,CAAC,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC;YAAE;QACnD,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE;QAClC,IAAI,MAAM,KAAK,IAAI;YAAE;AACrB,QAAA,MAAM,CAAC,mBAAmB,CAAC,QAAQ,CAAC;QACpC,MAAM,CAAC,SAAS,EAAE;AAClB,QAAA,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,QAAQ,CAAC;IACrC;AAGA,IAAA,WAAW,CAAC,KAAiB,EAAA;AACzB,QAAA,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,cAAc,EAAE;YAAE;QAClC,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE;QAClC,IAAI,MAAM,KAAK,IAAI;YAAE;;;;AAIrB,QAAA,MAAM,CAAC,SAAS,CAAC,UAAU,CAAC;AAC5B,QAAA,IAAI,CAAC,SAAS,GAAG,IAAI;AACrB,QAAA,IAAI,CAAC,SAAS,GAAG,KAAK,CAAC,OAAO;AAC9B,QAAA,IAAI,CAAC,SAAS,GAAG,KAAK,CAAC,OAAO;;;QAG9B,KAAK,CAAC,cAAc,EAAE;IAC1B;AAGA,IAAA,WAAW,CAAC,KAAiB,EAAA;QACzB,IAAI,CAAC,IAAI,CAAC,SAAS;YAAE;QACrB,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE;QAClC,IAAI,MAAM,KAAK,IAAI;YAAE;QAErB,MAAM,EAAE,GAAG,KAAK,CAAC,OAAO,GAAG,IAAI,CAAC,SAAS;QACzC,MAAM,EAAE,GAAG,KAAK,CAAC,OAAO,GAAG,IAAI,CAAC,SAAS;;;;AAIzC,QAAA,MAAM,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,CAAC;AAClB,QAAA,IAAI,CAAC,SAAS,GAAG,KAAK,CAAC,OAAO;AAC9B,QAAA,IAAI,CAAC,SAAS,GAAG,KAAK,CAAC,OAAO;IAClC;IAGA,SAAS,GAAA;QACL,IAAI,CAAC,IAAI,CAAC,SAAS;YAAE;AACrB,QAAA,IAAI,CAAC,SAAS,GAAG,KAAK;QACtB,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE;QAClC,IAAI,MAAM,KAAK,IAAI;YAAE;;;;;AAKrB,QAAA,IAAI,IAAI,CAAC,KAAK,CAAC,cAAc,EAAE,EAAE;AAC7B,YAAA,MAAM,CAAC,SAAS,CAAC,MAAM,CAAC;QAC5B;IACJ;AAEA;;;;;;;;;;;;;;;;;AAiBG;AAEH,IAAA,OAAO,CAAC,KAAiB,EAAA;QACrB,IAAI,CAAC,KAAK,CAAC,OAAO,IAAI,CAAC,KAAK,CAAC,OAAO;YAAE;QACtC,KAAK,CAAC,cAAc,EAAE;AACtB,QAAA,MAAM,MAAM,GAAI,KAAK,CAAC,MAAM,GAAG,CAAC,GAAG,GAAG,GAAG,CAAC,GAAG,GAAG;QAChD,MAAM,MAAM,GAAI,IAAI,CAAC,KAAK,CAAC,WAAW,EAAE,GAAG,MAAM;AACjD,QAAA,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC;IAC9B;uGA5MS,oBAAoB,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAApB,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,QAAA,EAAA,IAAA,EAAA,oBAAoB,4fCrCjC,2hBAeA,EAAA,MAAA,EAAA,CAAA,mnCAAA,CAAA,EAAA,eAAA,EAAA,EAAA,CAAA,uBAAA,CAAA,MAAA,EAAA,CAAA;;2FDsBa,oBAAoB,EAAA,UAAA,EAAA,CAAA;kBAPhC,SAAS;AACI,YAAA,IAAA,EAAA,CAAA,EAAA,QAAA,EAAA,kCAAkC,EAAA,UAAA,EAChC,IAAI,EAAA,eAAA,EACC,uBAAuB,CAAC,MAAM,EAAA,QAAA,EAAA,2hBAAA,EAAA,MAAA,EAAA,CAAA,mnCAAA,CAAA,EAAA;;sBAQ9C,SAAS;AAAC,gBAAA,IAAA,EAAA,CAAA,WAAW,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE;;sBAIvC,WAAW;uBAAC,+BAA+B;;sBAG3C,WAAW;uBAAC,kCAAkC;;sBAwH9C,YAAY;uBAAC,WAAW,EAAE,CAAC,QAAQ,CAAC;;sBAiBpC,YAAY;uBAAC,oBAAoB,EAAE,CAAC,QAAQ,CAAC;;sBAgB7C,YAAY;uBAAC,kBAAkB;;sBAiC/B,YAAY;uBAAC,OAAO,EAAE,CAAC,QAAQ,CAAC;;;AEvOrC;;;;;;;;;;;;;;;;AAgBG;MAEU,mBAAmB,CAAA;AACX,IAAA,QAAQ,GAAG,MAAM,CAAoC,IAAI,GAAG,EAAE;iFAAC;AAEvE,IAAA,KAAK,GAAG,QAAQ,CAAC,MAAM,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC,MAAM,EAAE,CAAC;8EAAC;AAErE,IAAA,QAAQ,CAAC,IAAkB,EAAA;AACvB,QAAA,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,GAAG,IAAG;AACvB,YAAA,MAAM,IAAI,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC;YACzB,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,EAAE,IAAI,CAAC;AACvB,YAAA,OAAO,IAAI;AACf,QAAA,CAAC,CAAC;IACN;AAEA,IAAA,GAAG,CAAC,EAAU,EAAA;QACV,OAAO,IAAI,CAAC,QAAQ,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC;IAClC;AAEA,IAAA,UAAU,CAAC,QAAsB,EAAA;AAC7B,QAAA,OAAO,IAAI,CAAC,KAAK,EAAE,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,QAAQ,KAAK,QAAQ,CAAC;IAC5D;uGAnBS,mBAAmB,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,UAAA,EAAA,CAAA;AAAnB,IAAA,OAAA,KAAA,GAAA,EAAA,CAAA,qBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,QAAA,EAAA,QAAA,EAAA,EAAA,EAAA,IAAA,EAAA,mBAAmB,cADN,MAAM,EAAA,CAAA;;2FACnB,mBAAmB,EAAA,UAAA,EAAA,CAAA;kBAD/B,UAAU;mBAAC,EAAE,UAAU,EAAE,MAAM,EAAE;;;ACZlC;;;;;;;;;;;;AAYG;MASU,qBAAqB,CAAA;AACX,IAAA,KAAK,GAAM,MAAM,CAAC,uBAAuB,CAAC;AAC1C,IAAA,QAAQ,GAAG,MAAM,CAAC,mBAAmB,CAAC;;AAGtC,IAAA,cAAc,GAAG,QAAQ,CACxC,MAAM,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,WAAW,CAAC;uFAC9C;;AAGkB,IAAA,WAAW,GAAG,QAAQ,CACrC,MAAM,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,QAAQ,CAAC;oFAC3C;;AAGkB,IAAA,WAAW,GAAG,QAAQ,CACrC,MAAM,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,QAAQ,CAAC;oFAC3C;;AAGkB,IAAA,WAAW,GAAG,QAAQ,CACrC,MAAM,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,QAAQ,CAAC;oFAC3C;;AAGkB,IAAA,UAAU,GAAG,QAAQ,CAAsB,MAAK;QAC/D,MAAM,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,UAAU,EAAE;QAClC,IAAI,EAAE,KAAK,IAAI;AAAE,YAAA,OAAO,IAAI;QAC5B,OAAO,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,IAAI;IACxC,CAAC;mFAAC;AAEF,IAAA,UAAU,CAAC,EAAU,EAAA;;;QAGjB,IAAI,IAAI,CAAC,KAAK,CAAC,UAAU,EAAE,KAAK,EAAE,EAAE;AAChC,YAAA,IAAI,CAAC,KAAK,CAAC,aAAa,CAAC,IAAI,CAAC;YAC9B;QACJ;AACA,QAAA,IAAI,CAAC,KAAK,CAAC,aAAa,CAAC,EAAE,CAAC;IAChC;IAEA,cAAc,GAAA;AACV,QAAA,IAAI,CAAC,KAAK,CAAC,aAAa,CAAC,IAAI,CAAC;IAClC;AAEA,IAAA,QAAQ,CAAC,EAAU,EAAA;QACf,OAAO,IAAI,CAAC,KAAK,CAAC,UAAU,EAAE,KAAK,EAAE;IACzC;uGA/CS,qBAAqB,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;2FAArB,qBAAqB,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,mCAAA,EAAA,QAAA,EAAA,EAAA,EAAA,QAAA,EC7BlC,0jJAoGA,EAAA,MAAA,EAAA,CAAA,wwEAAA,CAAA,EAAA,YAAA,EAAA,CAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,ED3Ec,iBAAiB,EAAA,QAAA,EAAA,qBAAA,EAAA,MAAA,EAAA,CAAA,mBAAA,EAAA,yBAAA,EAAA,2BAAA,EAAA,sCAAA,EAAA,0BAAA,EAAA,2BAAA,CAAA,EAAA,QAAA,EAAA,CAAA,mBAAA,CAAA,EAAA,CAAA,EAAA,eAAA,EAAA,EAAA,CAAA,uBAAA,CAAA,MAAA,EAAA,CAAA;;2FAIlB,qBAAqB,EAAA,UAAA,EAAA,CAAA;kBARjC,SAAS;+BACI,mCAAmC,EAAA,UAAA,EACjC,IAAI,EAAA,eAAA,EACC,uBAAuB,CAAC,MAAM,EAAA,OAAA,EACtC,CAAC,iBAAiB,CAAC,EAAA,QAAA,EAAA,0jJAAA,EAAA,MAAA,EAAA,CAAA,wwEAAA,CAAA,EAAA;;;AEXhC;;;;;;;;;;;;;;;;;;;AAmBG;MASU,iBAAiB,CAAA;AACT,IAAA,KAAK,GAAG,MAAM,CAAC,uBAAuB,CAAC;;AAGrC,IAAA,OAAO,GAA4B;QAClD,EAAE,EAAE,EAAE,MAAM,EAAG,KAAK,EAAE,MAAM,EAAG,KAAK,EAAE,IAAI,EAAK;QAC/C,EAAE,EAAE,EAAE,KAAK,EAAI,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,EAAQ;AAC/C,QAAA,EAAE,EAAE,EAAE,KAAK,EAAI,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,GAAG,CAAC,EAAI;AAC/C,QAAA,EAAE,EAAE,EAAE,MAAM,EAAG,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,EAAE,GAAG,CAAC,EAAE;AAC/C,QAAA,EAAE,EAAE,EAAE,KAAK,EAAI,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,GAAG,CAAC,EAAI;KAClD;IAEQ,cAAc,GAAG,MAAM,CAAS,MAAM;uFAAC;;IAGvC,aAAa,GAAI,MAAM,CAAS,sEAAsE;sFAAC;IAEhH,QAAQ,GAAA,EAAc,KAAK,IAAI,CAAC,UAAU,EAAE,CAAC,CAAC;IAC9C,WAAW,GAAA,EAAW,KAAK,IAAI,CAAC,YAAY,EAAE,CAAC,CAAC;AAEhD,IAAA,MAAM,UAAU,GAAA;QACZ,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE;QAClC,IAAI,MAAM,KAAK,IAAI;YAAE;AACrB,QAAA,MAAM,MAAM,CAAC,aAAa,EAAE;IAChC;AAEA,IAAA,MAAM,YAAY,GAAA;QACd,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE;QAClC,IAAI,MAAM,KAAK,IAAI;YAAE;AACrB,QAAA,MAAM,MAAM,CAAC,YAAY,EAAE;IAC/B;AAEA,IAAA,YAAY,CAAC,MAAoB,EAAA;QAC7B,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE;QAClC,IAAI,MAAM,KAAK,IAAI;YAAE;AACrB,QAAA,MAAM,CAAC,kBAAkB,CAAC,MAAM,CAAC,KAAK,CAAC;QACvC,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC;QAClC,IAAI,CAAC,aAAa,CAAC,GAAG,CAClB,MAAM,CAAC,KAAK,KAAK;AACb,cAAE;AACF,cAAE,CAAA,UAAA,EAAa,MAAM,CAAC,KAAK,CAAA,kCAAA,CAAoC,CACtE;IACL;AAEA,IAAA,MAAM,SAAS,GAAA;QACX,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE;QAClC,IAAI,MAAM,KAAK,IAAI;YAAE;AAErB,QAAA,MAAM,IAAI,GAAG,MAAM,CAAC,WAAW,EAAE;AACjC,QAAA,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI,CAAC,KAAK,IAAI,CAAC,IAAI,IAAI,CAAC,MAAM,IAAI,CAAC,EAAE;;;AAGtD,YAAA,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,sCAAsC,CAAC;YAC9D;QACJ;AAEA,QAAA,MAAM,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC;;;AAGvB,QAAA,IAAI,CAAC,KAAK,CAAC,aAAa,CAAC,IAAI,CAAC;IAClC;IAEA,UAAU,GAAA;AACN,QAAA,IAAI,CAAC,KAAK,CAAC,aAAa,CAAC,IAAI,CAAC;IAClC;uGAhES,iBAAiB,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAAjB,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,QAAA,EAAA,IAAA,EAAA,iBAAiB,yFC1C9B,+4BAsBA,EAAA,MAAA,EAAA,CAAA,6oCAAA,CAAA,EAAA,eAAA,EAAA,EAAA,CAAA,uBAAA,CAAA,MAAA,EAAA,CAAA;;2FDoBa,iBAAiB,EAAA,UAAA,EAAA,CAAA;kBAR7B,SAAS;AACI,YAAA,IAAA,EAAA,CAAA,EAAA,QAAA,EAAA,+BAA+B,cAC7B,IAAI,EAAA,eAAA,EACC,uBAAuB,CAAC,MAAM,WACtC,EAAE,EAAA,QAAA,EAAA,+4BAAA,EAAA,MAAA,EAAA,CAAA,6oCAAA,CAAA,EAAA;;;AE/Bf;;;;;;;;;;;;;;;;;;;;AAoBG;MASU,mBAAmB,CAAA;AACX,IAAA,KAAK,GAAG,MAAM,CAAC,uBAAuB,CAAC;AAExD;;;;;;AAMG;IACM,YAAY,GAAG,MAAM,CAAS,CAAC;qFAAC;;IAGhC,QAAQ,GAAG,MAAM,CAAU,KAAK;iFAAC;;IAGzB,aAAa,GAAG,MAAM,CAAU,KAAK;sFAAC;AAEvD;;;;;AAKG;IACK,iBAAiB,GAAkB,IAAI;AAEtC,IAAA,mBAAmB,GAAG,QAAQ,CAAC,MAAM,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,YAAY,EAAE,GAAG,EAAE,CAAC,GAAG,EAAE;4FAAC;AAExF,IAAA,WAAA,GAAA;QACI,MAAM,CAAC,MAAK;;;;;;AAMR,YAAA,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,EAAE;AAClB,gBAAA,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,uBAAuB,EAAE,CAAC;YAC/D;AACJ,QAAA,CAAC,CAAC;IACN;IAEA,WAAW,GAAA;;;;QAIP,IAAI,IAAI,CAAC,QAAQ,EAAE;YAAE,IAAI,CAAC,UAAU,EAAE;IAC1C;IAEA,MAAM,YAAY,CAAC,OAAe,EAAA;QAC9B,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE;QAClC,IAAI,MAAM,KAAK,IAAI;YAAE;;;;;QAKrB,IAAI,IAAI,CAAC,QAAQ,EAAE;YAAE,IAAI,CAAC,UAAU,EAAE;AACtC,QAAA,MAAM,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC;IAChC;IAEA,MAAM,aAAa,CAAC,KAAa,EAAA;QAC7B,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE;QAClC,IAAI,MAAM,KAAK,IAAI;YAAE;AAErB,QAAA,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,EAAE;AAClB,YAAA,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC;YACvB,IAAI,CAAC,iBAAiB,GAAG,IAAI,CAAC,KAAK,CAAC,uBAAuB,EAAE;QACjE;AACA,QAAA,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,KAAK,CAAC;AAE5B,QAAA,IAAI,IAAI,CAAC,aAAa,EAAE,EAAE;AACtB,YAAA,MAAM,MAAM,CAAC,IAAI,EAAE;AACnB,YAAA,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,KAAK,CAAC;QACjC;AAEA,QAAA,MAAM,QAAQ,GAAG,IAAI,CAAC,iBAAiB,IAAI,CAAC;AAC5C,QAAA,MAAM,KAAK,GAAG,KAAK,GAAG,QAAQ;AAC9B,QAAA,IAAI,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,IAAI;YAAE;AAE5B,QAAA,MAAM,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC;AAC1B,QAAA,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,IAAI,CAAC;IAChC;IAEA,cAAc,GAAA;QACV,IAAI,IAAI,CAAC,QAAQ,EAAE;YAAE,IAAI,CAAC,UAAU,EAAE;IAC1C;IAEA,SAAS,GAAA;QACL,IAAI,IAAI,CAAC,QAAQ,EAAE;YAAE,IAAI,CAAC,UAAU,EAAE;AACtC,QAAA,IAAI,CAAC,KAAK,CAAC,aAAa,CAAC,IAAI,CAAC;IAClC;IAEQ,UAAU,GAAA;QACd,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE;QAClC,MAAM,EAAE,cAAc,EAAE;AACxB,QAAA,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC;AACxB,QAAA,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,KAAK,CAAC;AAC7B,QAAA,IAAI,CAAC,iBAAiB,GAAG,IAAI;IACjC;uGAjGS,mBAAmB,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAAnB,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,QAAA,EAAA,IAAA,EAAA,mBAAmB,2FCpChC,47DAiDA,EAAA,MAAA,EAAA,CAAA,s4BAAA,CAAA,EAAA,eAAA,EAAA,EAAA,CAAA,uBAAA,CAAA,MAAA,EAAA,CAAA;;2FDba,mBAAmB,EAAA,UAAA,EAAA,CAAA;kBAR/B,SAAS;AACI,YAAA,IAAA,EAAA,CAAA,EAAA,QAAA,EAAA,iCAAiC,cAC/B,IAAI,EAAA,eAAA,EACC,uBAAuB,CAAC,MAAM,WACtC,EAAE,EAAA,QAAA,EAAA,47DAAA,EAAA,MAAA,EAAA,CAAA,s4BAAA,CAAA,EAAA;;;AE1Bf;;;;;;;;;;;;AAYG;MASU,iBAAiB,CAAA;AACT,IAAA,KAAK,GAAG,MAAM,CAAC,uBAAuB,CAAC;;;;;AAM/C,IAAA,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,oBAAoB;AAC1C,IAAA,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,oBAAoB;AAEnD,IAAA,MAAM,gBAAgB,GAAA;QAClB,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE;QAClC,IAAI,MAAM,KAAK,IAAI;YAAE;AACrB,QAAA,MAAM,MAAM,CAAC,IAAI,CAAC,YAAY,CAAC;IACnC;AAEA,IAAA,MAAM,cAAc,GAAA;QAChB,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE;QAClC,IAAI,MAAM,KAAK,IAAI;YAAE;AACrB,QAAA,MAAM,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC;IACjC;IAEA,SAAS,GAAA;AACL,QAAA,IAAI,CAAC,KAAK,CAAC,aAAa,CAAC,IAAI,CAAC;IAClC;uGAxBS,iBAAiB,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAAjB,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,QAAA,EAAA,IAAA,EAAA,iBAAiB,yFC3B9B,gvCAmCA,EAAA,MAAA,EAAA,CAAA,mnCAAA,CAAA,EAAA,eAAA,EAAA,EAAA,CAAA,uBAAA,CAAA,MAAA,EAAA,CAAA;;2FDRa,iBAAiB,EAAA,UAAA,EAAA,CAAA;kBAR7B,SAAS;AACI,YAAA,IAAA,EAAA,CAAA,EAAA,QAAA,EAAA,+BAA+B,cAC7B,IAAI,EAAA,eAAA,EACC,uBAAuB,CAAC,MAAM,WACtC,EAAE,EAAA,QAAA,EAAA,gvCAAA,EAAA,MAAA,EAAA,CAAA,mnCAAA,CAAA,EAAA;;;AEff;;;;;;;;;;;;;;;;;;;;;AAqBG;MASU,mBAAmB,CAAA;AACX,IAAA,KAAK,GAAG,MAAM,CAAC,uBAAuB,CAAC;IAE/C,WAAW,GAAI,MAAM,CAAS,CAAC;oFAAC;IAChC,YAAY,GAAG,MAAM,CAAS,CAAC;qFAAC;IAChC,YAAY,GAAG,MAAM,CAAU,IAAI;qFAAC;AAE7C;;;;;;AAMG;IACc,SAAS,GAAG,MAAM,CAAU,KAAK;kFAAC;;AAGlC,IAAA,QAAQ,GAAG,QAAQ,CAAO,MAAK;QAC5C,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,UAAU,EAAE;QACpC,IAAI,IAAI,KAAK,IAAI;YAAE,OAAO,EAAE,KAAK,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE;AACjD,QAAA,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC;AACjD,QAAA,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC;QACjD,OAAO;AACH,YAAA,KAAK,EAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,GAAI,MAAM,CAAC,CAAC;AACrD,YAAA,MAAM,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC,CAAC;SACxD;IACL,CAAC;iFAAC;AAEF;;;;;AAKG;IACc,cAAc,GAAG,MAAM,CAAoC,EAAE,KAAK,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE;uFAAC;AAEnF,IAAA,cAAc,GAAG,QAAQ,CAAC,MAAK;AAC5C,QAAA,MAAM,CAAC,GAAG,IAAI,CAAC,cAAc,EAAE;AAC/B,QAAA,OAAO,CAAC,CAAC,MAAM,GAAG,CAAC,GAAG,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,MAAM,GAAG,CAAC;IAChD,CAAC;uFAAC;AAEO,IAAA,OAAO,GAAG,QAAQ,CAAC,MAAK;AAC7B,QAAA,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,EAAE;AAC5B,QAAA,OAAO,IAAI,CAAC,WAAW,EAAE,KAAK,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,YAAY,EAAE,KAAK,IAAI,CAAC,MAAM;IACnF,CAAC;gFAAC;IAEO,QAAQ,GAAG,QAAQ,CAAC,MACzB,IAAI,CAAC,OAAO;AACT,WAAA,IAAI,CAAC,WAAW,EAAE,GAAI;AACtB,WAAA,IAAI,CAAC,YAAY,EAAE,GAAG;AACtB,WAAA,IAAI,CAAC,KAAK,CAAC,OAAO,EAAE;iFAC1B;AAED;;;;;;AAMG;AACM,IAAA,YAAY,GAAG,IAAI,CAAC,cAAc,CAAC,UAAU,EAAE;AAExD,IAAA,WAAA,GAAA;;;;;;;;;QASI,MAAM,CAAC,MAAK;AACR,YAAA,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,EAAE;YAC5B,IAAI,IAAI,CAAC,KAAK,KAAK,CAAC,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC;gBAAE;YAC3C,IAAI,IAAI,CAAC,SAAS,EAAE;gBAAE;AACtB,YAAA,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,IAAI,CAAC;YAC7B,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC;YAChC,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC;AACtC,QAAA,CAAC,CAAC;IACN;AAEA,IAAA,UAAU,KAAmD;AAC7D,IAAA,YAAY,KAAqC;AAEjD,IAAA,aAAa,CAAC,KAAa,EAAA;AACvB,QAAA,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;AAC5C,QAAA,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE;YAAE,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC;AAC/D,QAAA,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC;AACxB,QAAA,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,KAAK,CAAC;AAC3B,QAAA,IAAI,IAAI,CAAC,YAAY,EAAE,EAAE;YACrB,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,KAAK,GAAG,IAAI,CAAC,cAAc,EAAE,CAAC,CAAC,CAAC;QACjF;IACJ;AAEA,IAAA,cAAc,CAAC,KAAa,EAAA;AACxB,QAAA,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;AAC5C,QAAA,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE;YAAE,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC;AAC/D,QAAA,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC;AACxB,QAAA,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,KAAK,CAAC;AAC5B,QAAA,IAAI,IAAI,CAAC,YAAY,EAAE,EAAE;YACrB,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,KAAK,GAAG,IAAI,CAAC,cAAc,EAAE,CAAC,CAAC,CAAC;QAChF;IACJ;AAEA,IAAA,gBAAgB,KAAW,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;IAE9D,KAAK,GAAA;;;AAGD,QAAA,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,KAAK,CAAC;AACzB,QAAA,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,EAAE;AAC5B,QAAA,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,IAAI,CAAC;QAC7B,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC;QAChC,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC;IACtC;AAEA,IAAA,MAAM,WAAW,GAAA;QACb,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE;QAClC,IAAI,MAAM,KAAK,IAAI,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE;YAAE;AAEzC,QAAA,MAAM,OAAO,GAAS;AAClB,YAAA,KAAK,EAAG,IAAI,CAAC,WAAW,EAAE;AAC1B,YAAA,MAAM,EAAE,IAAI,CAAC,YAAY,EAAE;SAC9B;AACD,QAAA,MAAM,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC;;;AAG5B,QAAA,IAAI,CAAC,KAAK,CAAC,gBAAgB,CAAC,OAAO,CAAC;;;;AAIpC,QAAA,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,KAAK,CAAC;AACzB,QAAA,IAAI,CAAC,KAAK,CAAC,aAAa,CAAC,IAAI,CAAC;IAClC;IAEA,MAAM,GAAA,EAAW,IAAI,CAAC,KAAK,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC,CAAC;uGAvIxC,mBAAmB,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAAnB,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,QAAA,EAAA,IAAA,EAAA,mBAAmB,2FCtChC,k2EA0DA,EAAA,MAAA,EAAA,CAAA,kmEAAA,CAAA,EAAA,eAAA,EAAA,EAAA,CAAA,uBAAA,CAAA,MAAA,EAAA,CAAA;;2FDpBa,mBAAmB,EAAA,UAAA,EAAA,CAAA;kBAR/B,SAAS;AACI,YAAA,IAAA,EAAA,CAAA,EAAA,QAAA,EAAA,iCAAiC,cAC/B,IAAI,EAAA,eAAA,EACC,uBAAuB,CAAC,MAAM,WACtC,EAAE,EAAA,QAAA,EAAA,k2EAAA,EAAA,MAAA,EAAA,CAAA,kmEAAA,CAAA,EAAA;;;AElCf;;;;;;;;;;;;;;;;;;;;;;;;;AAyBG;AAEH;AACA,MAAM,gBAAgB,GAAG,OAAO;AAEhC;;;;;AAKG;AACH,MAAM,YAAY,GAAG,sCAAsC;AAE3D;AACA,MAAM,QAAQ,GAAG,MAAM;AAMvB;AACM,SAAU,cAAc,CAAC,CAAoB,EAAA;AAC/C,IAAA,OAAO,CAAC,CAAC,CAAC,EAAE;AAChB;AAEA;;AAEG;AACG,SAAU,kBAAkB,CAAC,KAAa,EAAA;AAC5C,IAAA,MAAM,GAAG,GAAG,KAAK,CAAC,IAAI,EAAE;AACxB,IAAA,IAAI,GAAG,KAAK,EAAE,EAAE;QACZ,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAC,uDAAuD,EAAE;IACvF;AACA,IAAA,IAAI,GAAG,CAAC,MAAM,GAAG,gBAAgB,EAAE;QAC/B,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAC,iCAAiC,EAAE;IACjE;;IAGA,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE;AACpB,QAAA,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE;YAChD,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAC,gEAAgE,EAAE;QAChG;AACA,QAAA,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC,EAAC,SAAS,CAAC,GAAG,CAAC,EAAE;IACzC;;;IAIA,IAAI,eAAe,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,sBAAsB,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,iBAAiB,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE;QAC9F,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAC,gEAAgE,EAAE;IAChG;AAEA,IAAA,MAAM,GAAG,GAAG,IAAI,SAAS,EAAE,CAAC,eAAe,CAAC,GAAG,EAAE,eAAe,CAAC;IACjE,IAAI,GAAG,CAAC,aAAa,CAAC,aAAa,CAAC,KAAK,IAAI,EAAE;QAC3C,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAC,8BAA8B,EAAE;IAC9D;IAEA,MAAM,QAAQ,GAAa,EAAE;IAC7B,GAAG,CAAC,gBAAgB,CAAC,gDAAgD,CAAC,CAAC,OAAO,CAAC,CAAC,EAAE,KAAI;AAClF,QAAA,MAAM,CAAC,GAAG,iBAAiB,CAAC,EAAE,CAAC;QAC/B,IAAI,CAAC,KAAK,IAAI;AAAE,YAAA,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC;AACpC,IAAA,CAAC,CAAC;AAEF,IAAA,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE;QACvB,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAC,8EAA8E,EAAE;IAC9G;IAEA,MAAM,QAAQ,GAAG,SAAS,CAAC,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAC9C,IAAA,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE;QAC1D,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAC,qDAAqD,EAAE;IACrF;IACA,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC,EAAC,QAAQ,EAAE;AACnC;AAEA;AACA,SAAS,SAAS,CAAC,CAAS,EAAA;IACxB,OAAO,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,IAAI,EAAE;AACxC;AAEA;;;;;;AAMG;AACH,SAAS,iBAAiB,CAAC,EAAW,EAAA;AAClC,IAAA,MAAM,GAAG,GAAG,CAAC,IAAY,KAAY;AACjC,QAAA,MAAM,CAAC,GAAG,UAAU,CAAC,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;AACjD,QAAA,OAAO,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC;AACrC,IAAA,CAAC;AAED,IAAA,QAAQ,EAAE,CAAC,OAAO,CAAC,WAAW,EAAE;QAC5B,KAAK,MAAM,EAAE;AACT,YAAA,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,YAAY,CAAC,GAAG,CAAC,IAAI,EAAE,EAAE,IAAI,EAAE;AAC7C,YAAA,OAAO,CAAC,KAAK,EAAE,IAAI,YAAY,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,IAAI;QACtD;QACA,KAAK,MAAM,EAAE;YACT,MAAM,CAAC,GAAG,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC,GAAG,GAAG,CAAC,QAAQ,CAAC;AACrE,YAAA,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC;AAAE,gBAAA,OAAO,IAAI;AACjC,YAAA,OAAO,CAAA,EAAA,EAAK,CAAC,CAAA,CAAA,EAAI,CAAC,MAAM,CAAC,GAAG,CAAC,CAAA,GAAA,EAAM,CAAC,GAAG,CAAC,CAAA,GAAA,EAAM,CAAC,IAAI;QACvD;QACA,KAAK,QAAQ,EAAE;YACX,MAAM,EAAE,GAAG,GAAG,CAAC,IAAI,CAAC,EAAE,EAAE,GAAG,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,GAAG,GAAG,CAAC,GAAG,CAAC;YAClD,IAAI,CAAC,IAAI,CAAC;AAAE,gBAAA,OAAO,IAAI;;YAEvB,OAAO,CAAA,EAAA,EAAK,EAAE,GAAG,CAAC,CAAA,CAAA,EAAI,EAAE,CAAA,GAAA,EAAM,CAAC,CAAA,CAAA,EAAI,CAAC,CAAA,OAAA,EAAU,EAAE,GAAG,CAAC,CAAA,CAAA,EAAI,EAAE,CAAA,GAAA,EAAM,CAAC,CAAA,CAAA,EAAI,CAAC,CAAA,OAAA,EAAU,EAAE,GAAG,CAAC,CAAA,CAAA,EAAI,EAAE,CAAA,EAAA,CAAI;QACpG;QACA,KAAK,SAAS,EAAE;YACZ,MAAM,EAAE,GAAG,GAAG,CAAC,IAAI,CAAC,EAAE,EAAE,GAAG,GAAG,CAAC,IAAI,CAAC,EAAE,EAAE,GAAG,GAAG,CAAC,IAAI,CAAC,EAAE,EAAE,GAAG,GAAG,CAAC,IAAI,CAAC;AACpE,YAAA,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC;AAAE,gBAAA,OAAO,IAAI;YACnC,OAAO,CAAA,EAAA,EAAK,EAAE,GAAG,EAAE,CAAA,CAAA,EAAI,EAAE,CAAA,GAAA,EAAM,EAAE,CAAA,CAAA,EAAI,EAAE,CAAA,OAAA,EAAU,EAAE,GAAG,EAAE,CAAA,CAAA,EAAI,EAAE,CAAA,GAAA,EAAM,EAAE,CAAA,CAAA,EAAI,EAAE,CAAA,OAAA,EAAU,EAAE,GAAG,EAAE,CAAA,CAAA,EAAI,EAAE,CAAA,EAAA,CAAI;QAC3G;AACA,QAAA,KAAK,SAAS;QACd,KAAK,UAAU,EAAE;AACb,YAAA,MAAM,GAAG,GAAG,WAAW,CAAC,EAAE,CAAC,YAAY,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC;AACxD,YAAA,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC;AAAE,gBAAA,OAAO,IAAI;;AAE/B,YAAA,OAAO,CAAA,EAAA,EAAK,GAAG,CAAC,CAAC,CAAC,CAAA,CAAA,EAAI,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,CAAA,EAAA,EAAK,CAAC,CAAA,CAAE,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI;QACzE;AACA,QAAA;AACI,YAAA,OAAO,IAAI;;AAEvB;AAEA;AACA,SAAS,WAAW,CAAC,GAAW,EAAA;IAC5B,MAAM,IAAI,GAAG,GAAG,CAAC,KAAK,CAAC,0BAA0B,CAAC,IAAI,EAAE;IACxD,MAAM,KAAK,GAAa,EAAE;AAC1B,IAAA,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,IAAI,CAAC,EAAE;AACzC,QAAA,KAAK,CAAC,IAAI,CAAC,CAAA,EAAG,IAAI,CAAC,CAAC,CAAC,CAAA,CAAA,EAAI,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAA,CAAE,CAAC;IAC3C;AACA,IAAA,OAAO,KAAK;AAChB;;ACrJA;;;;;;;;;;;;;AAaG;MAuIU,iBAAiB,CAAA;AACP,IAAA,KAAK,GAAG,MAAM,CAAC,uBAAuB,CAAC;AAEvC,IAAA,MAAM,GAAwD;QAC7E,EAAE,KAAK,EAAE,MAAM,EAAM,IAAI,EAAE,iBAAiB,EAAE,KAAK,EAAE,MAAM,EAAE;QAC7D,EAAE,KAAK,EAAE,MAAM,EAAM,IAAI,EAAE,WAAW,EAAQ,KAAK,EAAE,MAAM,EAAE;QAC7D,EAAE,KAAK,EAAE,SAAS,EAAG,IAAI,EAAE,QAAQ,EAAW,KAAK,EAAE,SAAS,EAAE;QAChE,EAAE,KAAK,EAAE,SAAS,EAAG,IAAI,EAAE,WAAW,EAAQ,KAAK,EAAE,SAAS,EAAE;QAChE,EAAE,KAAK,EAAE,UAAU,EAAE,IAAI,EAAE,aAAa,EAAM,KAAK,EAAE,UAAU,EAAE;QACjE,EAAE,KAAK,EAAE,MAAM,EAAM,IAAI,EAAE,SAAS,EAAU,KAAK,EAAE,MAAM,EAAE;QAC7D,EAAE,KAAK,EAAE,OAAO,EAAK,IAAI,EAAE,UAAU,EAAS,KAAK,EAAE,OAAO,EAAE;QAC9D,EAAE,KAAK,EAAE,SAAS,EAAG,IAAI,EAAE,YAAY,EAAO,KAAK,EAAE,SAAS,EAAE;QAChE,EAAE,KAAK,EAAE,QAAQ,EAAI,IAAI,EAAE,iBAAiB,EAAE,KAAK,EAAE,KAAK,EAAE;KAC/D;AAEkB,IAAA,KAAK,GAAI,MAAM,CAAY,iBAAiB,CAAC,KAAK;8EAAC;AACnD,IAAA,KAAK,GAAI,MAAM,CAAC,iBAAiB,CAAC,KAAK;8EAAC;AACxC,IAAA,MAAM,GAAG,MAAM,CAAC,iBAAiB,CAAC,MAAM;+EAAC;;IAGzC,QAAQ,GAAK,MAAM,CAAC,EAAE;iFAAC;;IAEvB,UAAU,GAAG,MAAM,CAAC,EAAE;mFAAC;;IAEvB,QAAQ,GAAK,MAAM,CAAgB,IAAI;iFAAC;;AAGxC,IAAA,UAAU,GAAG,QAAQ,CAAS,MAAK;QAClD,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,eAAe,EAAE;QACzC,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI,KAAK,OAAO,EAAE;YACnC,MAAM,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,aAAa,EAAE;YACrC,OAAO,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,IAAI,IAAI,OAAO;QACtE;AACA,QAAA,OAAO,YAAY;IACvB,CAAC;mFAAC;AAEF,IAAA,WAAA,GAAA;;;;QAII,MAAM,CAAC,MAAK;AACR,YAAA,IAAI,CAAC,KAAK,CAAC,eAAe,EAAE;AAC5B,YAAA,IAAI,CAAC,KAAK,CAAC,aAAa,EAAE;YAC1B,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,EAAE,OAAO,EAAE;YAC3C,IAAI,IAAI,IAAI,IAAI;gBAAE;YAClB,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC;YAC1B,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC;YAC1B,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC;;;AAG5B,YAAA,IAAI,IAAI,CAAC,KAAK,KAAK,QAAQ,IAAI,OAAO,IAAI,CAAC,OAAO,KAAK,QAAQ,EAAE;gBAC7D,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC;gBACjC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC;YACnC;AAAO,iBAAA,IAAI,IAAI,CAAC,KAAK,KAAK,QAAQ,EAAE;AAChC,gBAAA,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;YAC3B;AACA,YAAA,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC;AAC3B,QAAA,CAAC,CAAC;IACN;AAEU,IAAA,OAAO,CAAC,KAAgB,EAAA,EAAU,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC;AACvE,IAAA,OAAO,CAAC,KAAa,EAAA,EAAa,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC;AACvE,IAAA,QAAQ,CAAC,KAAa,EAAA,EAAY,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC;;IAGxE,QAAQ,GAAA;QACd,MAAM,MAAM,GAAG,kBAAkB,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC;AAClD,QAAA,IAAI,CAAC,MAAM,CAAC,EAAE,EAAE;YACZ,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC;YAC/B;QACJ;AACA,QAAA,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC;QACvB,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC;AAC7B,QAAA,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC;QACxB,IAAI,CAAC,KAAK,EAAE;IAChB;;IAGU,MAAM,MAAM,CAAC,KAAY,EAAA;AAC/B,QAAA,MAAM,KAAK,GAAG,KAAK,CAAC,MAA0B;QAC9C,MAAM,IAAI,GAAG,KAAK,CAAC,KAAK,GAAG,CAAC,CAAC,IAAI,IAAI;;AAErC,QAAA,KAAK,CAAC,KAAK,GAAG,EAAE;QAChB,IAAI,IAAI,KAAK,IAAI;YAAE;AACnB,QAAA,IAAI;YACA,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,MAAM,IAAI,CAAC,IAAI,EAAE,CAAC;YACpC,IAAI,CAAC,QAAQ,EAAE;QACnB;AAAE,QAAA,MAAM;AACJ,YAAA,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,0BAA0B,CAAC;QACjD;IACJ;IAEQ,KAAK,GAAA;AACT,QAAA,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,EAAE;;;;AAI1B,QAAA,IAAI,KAAK,KAAK,QAAQ,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC,IAAI,EAAE,KAAK,EAAE;YAAE;AAE3D,QAAA,MAAM,IAAI,GAAa;YACnB,KAAK;AACL,YAAA,KAAK,EAAI,IAAI,CAAC,KAAK,EAAE;AACrB,YAAA,MAAM,EAAG,IAAI,CAAC,MAAM,EAAE;AACtB,YAAA,OAAO,EAAE,KAAK,KAAK,QAAQ,GAAG,IAAI,CAAC,UAAU,EAAE,GAAG,SAAS;SAC9D;QACD,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,EAAE,OAAO,CAAC,IAAI,CAAC;IACtC;uGA1GS,iBAAiB,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAAjB,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,QAAA,EAAA,IAAA,EAAA,iBAAiB,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,+BAAA,EAAA,QAAA,EAAA,EAAA,EAAA,QAAA,EAlIhB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAgET,IAAA,CAAA,EAAA,QAAA,EAAA,IAAA,EAAA,MAAA,EAAA,CAAA,snFAAA,CAAA,EAAA,eAAA,EAAA,EAAA,CAAA,uBAAA,CAAA,MAAA,EAAA,CAAA;;2FAkEQ,iBAAiB,EAAA,UAAA,EAAA,CAAA;kBAtI7B,SAAS;AACI,YAAA,IAAA,EAAA,CAAA,EAAA,QAAA,EAAA,+BAA+B,cAC7B,IAAI,EAAA,eAAA,EACC,uBAAuB,CAAC,MAAM,EAAA,QAAA,EACrC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAgET,IAAA,CAAA,EAAA,MAAA,EAAA,CAAA,snFAAA,CAAA,EAAA;;;AChFL;;;;;;;;;;;;;;;;;;;;;;;;;;;AA2BG;MASU,qBAAqB,CAAA;AACb,IAAA,KAAK,GAAG,MAAM,CAAC,uBAAuB,CAAC;IAE/C,MAAM,GAAG,KAAK,CAAC,QAAQ;+EAAsB;IAE7C,YAAY,GAAG,MAAM,CAAS,CAAC;qFAAC;AACzC;;;;AAIG;IACc,aAAa,GAAG,MAAM,CAAU,KAAK;sFAAC;AAE9C,IAAA,OAAO,GAAG,QAAQ,CAAC,MAAM,IAAI,CAAC,YAAY,EAAE,KAAK,IAAI,CAAC,MAAM,EAAE,CAAC,OAAO;gFAAC;;IAGxE,QAAQ,GAAG,KAAK;IAChB,YAAY,GAAkB,IAAI;IAE1C,QAAQ,GAAA;AACJ,QAAA,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC;IAChD;AAEA,IAAA,MAAM,WAAW,GAAA;;;;AAIb,QAAA,MAAM,IAAI,CAAC,YAAY,EAAE;IAC7B;AAEA,IAAA,UAAU,KAAmE;AAE7E,IAAA,MAAM,YAAY,GAAA;AACd,QAAA,IAAI,IAAI,CAAC,aAAa,EAAE,EAAE;AACtB,YAAA,MAAM,IAAI,CAAC,aAAa,EAAE;QAC9B;IACJ;AAEA,IAAA,aAAa,CAAC,KAAa,EAAA;AACvB,QAAA,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,KAAK,CAAC;AAC5B,QAAA,IAAI,CAAC,YAAY,GAAG,KAAK;;;AAGzB,QAAA,KAAK,IAAI,CAAC,mBAAmB,EAAE;IACnC;AAEA,IAAA,MAAM,cAAc,GAAA;;;;AAIhB,QAAA,MAAM,IAAI,CAAC,YAAY,EAAE;QAEzB,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE;QAClC,IAAI,MAAM,KAAK,IAAI;YAAE;;;;AAKrB,QAAA,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,KAAK,CAAC;QAC7B,MAAM,CAAC,cAAc,EAAE;AACvB,QAAA,IAAI,CAAC,KAAK,CAAC,aAAa,CAAC,IAAI,CAAC;IAClC;AAEA,IAAA,MAAM,MAAM,GAAA;AACR,QAAA,MAAM,IAAI,CAAC,YAAY,EAAE;AACzB,QAAA,MAAM,IAAI,CAAC,aAAa,EAAE;QAC1B,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE;QAClC,MAAM,EAAE,cAAc,EAAE;AACxB,QAAA,IAAI,CAAC,KAAK,CAAC,aAAa,CAAC,IAAI,CAAC;IAClC;AAEA,IAAA,MAAM,KAAK,GAAA;AACP,QAAA,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC;QAC5C,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,OAAO;AACzC,QAAA,MAAM,IAAI,CAAC,mBAAmB,EAAE;IACpC;AAEQ,IAAA,MAAM,mBAAmB,GAAA;QAC7B,IAAI,IAAI,CAAC,QAAQ;YAAE;AACnB,QAAA,IAAI,CAAC,QAAQ,GAAG,IAAI;AACpB,QAAA,IAAI;AACA,YAAA,OAAO,IAAI,CAAC,YAAY,KAAK,IAAI,EAAE;AAC/B,gBAAA,MAAM,KAAK,GAAG,IAAI,CAAC,YAAY;AAC/B,gBAAA,IAAI,CAAC,YAAY,GAAG,IAAI;AACxB,gBAAA,MAAM,IAAI,CAAC,YAAY,CAAC,KAAK,CAAC;YAClC;QACJ;gBAAU;AACN,YAAA,IAAI,CAAC,QAAQ,GAAG,KAAK;QACzB;IACJ;AAEQ,IAAA,MAAM,YAAY,GAAA;;;;QAItB,OAAO,IAAI,CAAC,QAAQ,IAAI,IAAI,CAAC,YAAY,KAAK,IAAI,EAAE;AAChD,YAAA,MAAM,OAAO,CAAC,OAAO,EAAE;YACvB,IAAI,IAAI,CAAC,YAAY,KAAK,IAAI,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE;AAC9C,gBAAA,MAAM,IAAI,CAAC,mBAAmB,EAAE;YACpC;QACJ;IACJ;IAEQ,MAAM,YAAY,CAAC,KAAa,EAAA;QACpC,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE;QAClC,IAAI,MAAM,KAAK,IAAI;YAAE;AAErB,QAAA,IAAI,IAAI,CAAC,aAAa,EAAE,EAAE;AACtB,YAAA,MAAM,MAAM,CAAC,IAAI,EAAE;AACnB,YAAA,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,KAAK,CAAC;QACjC;QAEA,IAAI,KAAK,KAAK,IAAI,CAAC,MAAM,EAAE,CAAC,OAAO,EAAE;;;YAGjC;QACJ;AAEA,QAAA,MAAM,MAAM,GAAG,EAAE,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,QAAQ,GAAG,KAAK,EAAkB;AAClE,QAAA,MAAM,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,UAAU,EAAE,MAAM,CAAC;AAC1D,QAAA,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,IAAI,CAAC;IAChC;AAEQ,IAAA,MAAM,aAAa,GAAA;AACvB,QAAA,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE;YAAE;QAC3B,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE;QAClC,IAAI,MAAM,KAAK,IAAI;YAAE;AACrB,QAAA,MAAM,MAAM,CAAC,IAAI,EAAE;AACnB,QAAA,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,KAAK,CAAC;IACjC;uGAjIS,qBAAqB,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAArB,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,QAAA,EAAA,IAAA,EAAA,qBAAqB,mOC9ClC,8tCAgCA,EAAA,MAAA,EAAA,CAAA,2oBAAA,CAAA,EAAA,eAAA,EAAA,EAAA,CAAA,uBAAA,CAAA,MAAA,EAAA,CAAA;;2FDca,qBAAqB,EAAA,UAAA,EAAA,CAAA;kBARjC,SAAS;AACI,YAAA,IAAA,EAAA,CAAA,EAAA,QAAA,EAAA,mCAAmC,cACjC,IAAI,EAAA,eAAA,EACC,uBAAuB,CAAC,MAAM,WACtC,EAAE,EAAA,QAAA,EAAA,8tCAAA,EAAA,MAAA,EAAA,CAAA,2oBAAA,CAAA,EAAA;;;AEnCf;;;;;;;;AAQG;MASU,qBAAqB,CAAA;AACX,IAAA,KAAK,GAAG,MAAM,CAAC,uBAAuB,CAAC;IAEjD,MAAM,GAAG,KAAK,CAAC,QAAQ;+EAAsB;IAE7C,SAAS,GAAG,MAAM,CAAU,KAAK;kFAAC;AAClC,IAAA,WAAW,GAAG,QAAQ,CAAC,MAAM,IAAI,CAAC,SAAS,EAAE,GAAG,QAAQ,GAAG,OAAO;oFAAC;IAE5E,QAAQ,GAAA;QACJ,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE;QAClC,IAAI,MAAM,KAAK,IAAI;YAAE;AACrB,QAAA,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,UAAU,CAAC,CAAC;IAClE;AAEA,IAAA,MAAM,MAAM,GAAA;QACR,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE;QAClC,IAAI,MAAM,KAAK,IAAI;YAAE;AAErB,QAAA,IAAI,IAAI,CAAC,SAAS,EAAE,EAAE;YAClB,MAAM,MAAM,CAAC,YAAY,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,UAAU,CAAC;AACnD,YAAA,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,KAAK,CAAC;QAC7B;aAAO;YACH,MAAM,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,UAAU,CAAC;AAClD,YAAA,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC;QAC5B;IACJ;IAEA,SAAS,GAAA;AACL,QAAA,IAAI,CAAC,KAAK,CAAC,aAAa,CAAC,IAAI,CAAC;IAClC;uGA7BS,qBAAqB,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAArB,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,QAAA,EAAA,IAAA,EAAA,qBAAqB,mOCxBlC,ytBAmBA,EAAA,MAAA,EAAA,CAAA,ipCAAA,CAAA,EAAA,eAAA,EAAA,EAAA,CAAA,uBAAA,CAAA,MAAA,EAAA,CAAA;;2FDKa,qBAAqB,EAAA,UAAA,EAAA,CAAA;kBARjC,SAAS;AACI,YAAA,IAAA,EAAA,CAAA,EAAA,QAAA,EAAA,mCAAmC,cACjC,IAAI,EAAA,eAAA,EACC,uBAAuB,CAAC,MAAM,WACtC,EAAE,EAAA,QAAA,EAAA,ytBAAA,EAAA,MAAA,EAAA,CAAA,ipCAAA,CAAA,EAAA;;;AEbf;;;;;;AAMG;MA0GU,kBAAkB,CAAA;AACR,IAAA,KAAK,GAAG,MAAM,CAAC,uBAAuB,CAAC;AAEvC,IAAA,MAAM,GAAuD;QAC5E,EAAE,IAAI,EAAE,MAAM,EAAM,IAAI,EAAE,WAAW,EAAS,KAAK,EAAE,MAAM,EAAE;QAC7D,EAAE,IAAI,EAAE,SAAS,EAAG,IAAI,EAAE,WAAW,EAAS,KAAK,EAAE,SAAS,EAAE;QAChE,EAAE,IAAI,EAAE,UAAU,EAAE,IAAI,EAAE,aAAa,EAAO,KAAK,EAAE,UAAU,EAAE;QACjE,EAAE,IAAI,EAAE,MAAM,EAAM,IAAI,EAAE,aAAa,EAAO,KAAK,EAAE,MAAM,EAAE;QAC7D,EAAE,IAAI,EAAE,OAAO,EAAK,IAAI,EAAE,gBAAgB,EAAI,KAAK,EAAE,OAAO,EAAE;KACjE;AAEkB,IAAA,SAAS,GAAyC;AACjE,QAAA,EAAE,KAAK,EAAE,OAAO,EAAG,KAAK,EAAE,OAAO,EAAE;AACnC,QAAA,EAAE,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,QAAQ,EAAE;AACpC,QAAA,EAAE,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,QAAQ,EAAE;KACvC;AAEkB,IAAA,QAAQ,GAAM,MAAM,CAAW,iBAAiB,CAAC,IAAI;iFAAC;AACtD,IAAA,IAAI,GAAU,MAAM,CAAC,qBAAqB,CAAC,IAAI;6EAAC;AAChD,IAAA,KAAK,GAAS,MAAM,CAAC,iBAAiB,CAAC,MAAM;8EAAC;AAC9C,IAAA,KAAK,GAAS,MAAM,CAAC,iBAAiB,CAAC,KAAK;8EAAC;AAC7C,IAAA,MAAM,GAAQ,MAAM,CAAC,qBAAqB,CAAC,MAAM;+EAAC;AAClD,IAAA,WAAW,GAAG,MAAM,CAAC,qBAAqB,CAAC,WAAW;oFAAC;IACvD,OAAO,GAAO,MAAM,CAAC,CAAC;gFAAC;;AAGvB,IAAA,YAAY,GAAG,QAAQ,CAAC,MAAM,IAAI,CAAC,KAAK,CAAC,eAAe,EAAE,KAAK,OAAO;qFAAC;AAE1F,IAAA,WAAA,GAAA;;;;;QAKI,MAAM,CAAC,MAAK;YACR,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,eAAe,EAAE;YACzC,MAAM,EAAE,GAAK,IAAI,CAAC,KAAK,CAAC,aAAa,EAAE;AACvC,YAAA,IAAI,IAAI,KAAK,OAAO,IAAI,EAAE,KAAK,IAAI;gBAAE;YACrC,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE;AAClC,YAAA,MAAM,KAAK,GAAG,MAAM,EAAE,oBAAoB,EAAE;YAC5C,IAAI,KAAK,IAAI,IAAI;gBAAE;AACnB,YAAA,IAAI,KAAK,CAAC,QAAQ,CAAC,KAAK,SAAS,IAAI,KAAK,CAAC,QAAQ,CAAC,KAAK,EAAE;AAAE,gBAAA,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC;AACrG,YAAA,IAAI,KAAK,CAAC,aAAa,CAAC,KAAK,SAAS;AAAE,gBAAA,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC,CAAC;AAC1F,YAAA,IAAI,KAAK,CAAC,SAAS,CAAC,KAAK,SAAS;AAAM,gBAAA,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC;;;AAGlF,YAAA,MAAM,CAAC,GAAG,MAAM,EAAE,mBAAmB,EAAE;AACvC,YAAA,IAAI,CAAC,IAAI,IAAI,EAAE;gBACX,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC;gBACzB,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC;gBACtB,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC;gBACxB,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC;YAC3B;AACJ,QAAA,CAAC,CAAC;IACN;AAEU,IAAA,GAAG,CAAC,IAAe,EAAA;QACzB,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,EAAE,QAAQ,CAAC,IAAI,EAAE;AAChC,YAAA,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,EAAE,WAAW,EAAE,IAAI,CAAC,WAAW,EAAE;AACzE,YAAA,QAAQ,EAAE,IAAI,CAAC,WAAW,EAAE;AAC/B,SAAA,CAAC;IACN;AAEU,IAAA,UAAU,CAAC,CAAW,EAAA,EAAW,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC,CAAC;AACzE,IAAA,MAAM,CAAC,CAAS,EAAA,EAAiB,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAK,IAAI,CAAC,SAAS,EAAE,CAAC,CAAC;AACzE,IAAA,OAAO,CAAC,CAAS,EAAA,EAAgB,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAI,IAAI,CAAC,SAAS,EAAE,CAAC,CAAC;AACzE,IAAA,OAAO,CAAC,CAAS,EAAA,EAAgB,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAI,IAAI,CAAC,SAAS,EAAE,CAAC,CAAC;IACzE,QAAQ,CAAC,CAAS,EAAA,EAAe,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAM,IAAI,CAAC,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;IAC9F,aAAa,CAAC,CAAS,EAAA,EAAU,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,cAAc,CAAC,EAAE,WAAW,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;IACnG,SAAS,CAAC,CAAS,EAAA,EAAc,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAK,IAAI,CAAC,cAAc,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;IAEjG,WAAW,GAAA;AACf,QAAA,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,QAAQ,EAAE,EAAE,KAAK,EAAE,IAAI,CAAC,IAAI,EAAE,EAAE,MAAM,EAAE,IAAI,CAAC,KAAK,EAAE,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,EAAE;IACnG;IAEQ,SAAS,GAAA;QACb,IAAI,IAAI,CAAC,YAAY,EAAE;AAAE,YAAA,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,EAAE,mBAAmB,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC;IACzF;AAEQ,IAAA,cAAc,CAAC,KAAsC,EAAA;QACzD,IAAI,IAAI,CAAC,YAAY,EAAE;YAAE,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,EAAE,kBAAkB,CAAC,KAAK,CAAC;IAC3E;uGAhFS,kBAAkB,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAAlB,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,QAAA,EAAA,IAAA,EAAA,kBAAkB,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,gCAAA,EAAA,QAAA,EAAA,EAAA,EAAA,QAAA,EArGjB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA+DT,IAAA,CAAA,EAAA,QAAA,EAAA,IAAA,EAAA,MAAA,EAAA,CAAA,4hDAAA,CAAA,EAAA,eAAA,EAAA,EAAA,CAAA,uBAAA,CAAA,MAAA,EAAA,CAAA;;2FAsCQ,kBAAkB,EAAA,UAAA,EAAA,CAAA;kBAzG9B,SAAS;AACI,YAAA,IAAA,EAAA,CAAA,EAAA,QAAA,EAAA,gCAAgC,cAC9B,IAAI,EAAA,eAAA,EACC,uBAAuB,CAAC,MAAM,EAAA,QAAA,EACrC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA+DT,IAAA,CAAA,EAAA,MAAA,EAAA,CAAA,4hDAAA,CAAA,EAAA;;;AC1EL;;;;;AAKG;MAuHU,iBAAiB,CAAA;AACP,IAAA,KAAK,GAAG,MAAM,CAAC,uBAAuB,CAAC;IAEvC,KAAK,GAAI,kBAAkB;AAC3B,IAAA,MAAM,GAAG;AACxB,QAAA,EAAE,KAAK,EAAE,MAAiB,EAAE,IAAI,EAAE,cAAc,EAAE;AAClD,QAAA,EAAE,KAAK,EAAE,QAAiB,EAAE,IAAI,EAAE,gBAAgB,EAAE;AACpD,QAAA,EAAE,KAAK,EAAE,OAAiB,EAAE,IAAI,EAAE,eAAe,EAAE;KACtD;AAEkB,IAAA,SAAS,GAAyC;AACjE,QAAA,EAAE,KAAK,EAAE,OAAO,EAAG,KAAK,EAAE,OAAO,EAAE;AACnC,QAAA,EAAE,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,QAAQ,EAAE;AACpC,QAAA,EAAE,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,QAAQ,EAAE;KACvC;AAEkB,IAAA,IAAI,GAAS,MAAM,CAAC,oBAAoB,CAAC,IAAI;6EAAC;AAC9C,IAAA,UAAU,GAAG,MAAM,CAAS,oBAAoB,CAAC,UAAU;mFAAC;AAC5D,IAAA,QAAQ,GAAK,MAAM,CAAC,oBAAoB,CAAC,QAAQ;iFAAC;AAClD,IAAA,QAAQ,GAAK,MAAM,CAAW,iBAAiB,CAAC,IAAI;iFAAC;AACrD,IAAA,IAAI,GAAS,MAAM,CAAC,oBAAoB,CAAC,IAAI;6EAAC;AAC9C,IAAA,KAAK,GAAQ,MAAM,CAAC,iBAAiB,CAAC,MAAM;8EAAC;AAC7C,IAAA,KAAK,GAAQ,MAAM,CAAC,iBAAiB,CAAC,KAAK;8EAAC;IAC5C,IAAI,GAAS,MAAM,CAAC,KAAK;6EAAC;IAC1B,MAAM,GAAO,MAAM,CAAC,KAAK;+EAAC;IAC1B,SAAS,GAAI,MAAM,CAA8B,MAAM;kFAAC;AAExD,IAAA,WAAW,GAAG,QAAQ,CAAC,MAAM,IAAI,CAAC,KAAK,CAAC,eAAe,EAAE,KAAK,MAAM;oFAAC;AAExF,IAAA,WAAA,GAAA;QACI,MAAM,CAAC,MAAK;YACR,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,eAAe,EAAE;YACzC,MAAM,EAAE,GAAK,IAAI,CAAC,KAAK,CAAC,aAAa,EAAE;AACvC,YAAA,IAAI,IAAI,KAAK,MAAM,IAAI,EAAE,KAAK,IAAI;gBAAE;YACpC,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE;AAClC,YAAA,MAAM,KAAK,GAAG,MAAM,EAAE,oBAAoB,EAAE;YAC5C,IAAI,KAAK,IAAI,IAAI;gBAAE;AACnB,YAAA,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC;AAC1C,YAAA,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC,CAAC;AACrE,YAAA,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC;AAC/D,YAAA,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,QAAQ,CAAC,KAAK,MAAM,CAAC;AACjE,YAAA,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,WAAW,CAAC,IAAI,QAAQ,CAAC,KAAK,QAAQ,CAAC;AACpE,YAAA,IAAI,CAAC,SAAS,CAAC,GAAG,CAAE,MAAM,CAAC,KAAK,CAAC,WAAW,CAAC,IAAI,MAAM,CAAiC,CAAC;;;AAGzF,YAAA,MAAM,CAAC,GAAG,MAAM,EAAE,mBAAmB,EAAE;AACvC,YAAA,IAAI,CAAC,IAAI,IAAI,EAAE;gBACX,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC;gBACzB,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC;gBACtB,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC;gBACxB,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC;YAC3B;AACJ,QAAA,CAAC,CAAC;IACN;IAEU,GAAG,GAAA;AACT,QAAA,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,EAAE,OAAO,CAAC;AACzB,YAAA,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,IAAI,MAAM;AAC3B,YAAA,UAAU,EAAE,IAAI,CAAC,UAAU,EAAE;AAC7B,YAAA,QAAQ,EAAE,IAAI,CAAC,QAAQ,EAAE;AACzB,YAAA,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE;AACjB,YAAA,QAAQ,EAAE,IAAI,CAAC,WAAW,EAAE;AAC5B,YAAA,UAAU,EAAE,IAAI,CAAC,IAAI,EAAE,GAAG,MAAM,GAAG,QAAQ;AAC3C,YAAA,SAAS,EAAE,IAAI,CAAC,MAAM,EAAE,GAAG,QAAQ,GAAG,QAAQ;AAC9C,YAAA,SAAS,EAAE,IAAI,CAAC,SAAS,EAAE;AAC9B,SAAA,CAAC;IACN;IAEU,MAAM,CAAC,CAAS,EAAA,EAAgB,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAO,IAAI,CAAC,KAAK,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;IACjF,YAAY,CAAC,CAAS,EAAA,EAAU,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,UAAU,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;IACvF,UAAU,CAAC,CAAS,EAAA,EAAY,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAG,IAAI,CAAC,KAAK,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;AACrF,IAAA,UAAU,CAAC,CAAW,EAAA,EAAU,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAG,IAAI,CAAC,SAAS,EAAE,CAAC,CAAC;AAC1E,IAAA,MAAM,CAAC,CAAS,EAAA,EAAgB,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAO,IAAI,CAAC,SAAS,EAAE,CAAC,CAAC;AAC1E,IAAA,OAAO,CAAC,CAAS,EAAA,EAAe,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAM,IAAI,CAAC,SAAS,EAAE,CAAC,CAAC;AAC1E,IAAA,OAAO,CAAC,CAAS,EAAA,EAAe,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAM,IAAI,CAAC,SAAS,EAAE,CAAC,CAAC;IAC1E,OAAO,CAAC,CAA8B,EAAA,EAAU,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,SAAS,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;IAErG,UAAU,GAAA;AAChB,QAAA,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;QACzB,IAAI,CAAC,KAAK,CAAC,EAAE,UAAU,EAAE,IAAI,CAAC,IAAI,EAAE,GAAG,MAAM,GAAG,QAAQ,EAAE,CAAC;IAC/D;IACU,YAAY,GAAA;AAClB,QAAA,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;QAC3B,IAAI,CAAC,KAAK,CAAC,EAAE,SAAS,EAAE,IAAI,CAAC,MAAM,EAAE,GAAG,QAAQ,GAAG,QAAQ,EAAE,CAAC;IAClE;IAEQ,WAAW,GAAA;AACf,QAAA,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,QAAQ,EAAE,EAAE,KAAK,EAAE,IAAI,CAAC,IAAI,EAAE,EAAE,MAAM,EAAE,IAAI,CAAC,KAAK,EAAE,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,EAAE;IACnG;IAEQ,SAAS,GAAA;QACb,IAAI,IAAI,CAAC,WAAW,EAAE;AAAE,YAAA,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,EAAE,mBAAmB,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC;IACxF;AAEQ,IAAA,KAAK,CAAC,KAAsC,EAAA;QAChD,IAAI,IAAI,CAAC,WAAW,EAAE;YAAE,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,EAAE,kBAAkB,CAAC,KAAK,CAAC;IAC1E;uGAhGS,iBAAiB,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAAjB,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,QAAA,EAAA,IAAA,EAAA,iBAAiB,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,+BAAA,EAAA,QAAA,EAAA,EAAA,EAAA,QAAA,EAlHhB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA4ET,IAAA,CAAA,EAAA,QAAA,EAAA,IAAA,EAAA,MAAA,EAAA,CAAA,2lDAAA,CAAA,EAAA,eAAA,EAAA,EAAA,CAAA,uBAAA,CAAA,MAAA,EAAA,CAAA;;2FAsCQ,iBAAiB,EAAA,UAAA,EAAA,CAAA;kBAtH7B,SAAS;AACI,YAAA,IAAA,EAAA,CAAA,EAAA,QAAA,EAAA,+BAA+B,cAC7B,IAAI,EAAA,eAAA,EACC,uBAAuB,CAAC,MAAM,EAAA,QAAA,EACrC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA4ET,IAAA,CAAA,EAAA,MAAA,EAAA,CAAA,2lDAAA,CAAA,EAAA;;;ACvFL;;;;AAIG;MAqFU,oBAAoB,CAAA;AACV,IAAA,KAAK,GAAG,MAAM,CAAC,uBAAuB,CAAC;AAEvC,IAAA,MAAM,GAAK,IAAI,CAAC,KAAK,CAAC,MAAM;AAC5B,IAAA,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,aAAa;AAEnC,IAAA,QAAQ,GAAG,QAAQ,CAAmB,MAAK;AAC1D,QAAA,MAAM,EAAE,GAAG,IAAI,CAAC,QAAQ,EAAE;AAC1B,QAAA,OAAO,EAAE,KAAK,IAAI,GAAG,IAAI,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,IAAI,IAAI,CAAC;IAC9E,CAAC;iFAAC;AAEQ,IAAA,QAAQ,CAAC,IAAuB,EAAA;QACtC,OAAO,IAAI,KAAK,OAAO,GAAG,UAAU,GAAG,IAAI,KAAK,MAAM,GAAG,UAAU,GAAG,aAAa;IACvF;AAEU,IAAA,MAAM,CAAC,EAAU,EAAA,EAAU,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,EAAE,WAAW,CAAC,EAAE,CAAC,CAAC,CAAC;AACjE,IAAA,MAAM,CAAC,EAAU,EAAA,EAAU,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,EAAE,WAAW,CAAC,EAAE,CAAC,CAAC,CAAC;IACjE,OAAO,CAAC,EAAU,EAAE,GAAkB,IAAU,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,EAAE,YAAY,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC,CAAC;IAC5F,UAAU,CAAC,EAAU,EAAE,KAAa,IAAU,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,EAAE,eAAe,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC,CAAC;IAC/F,aAAa,CAAC,KAAgB,EAAA,EAAU,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,EAAE,kBAAkB,CAAC,KAAK,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC;uGAnB5G,oBAAoB,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAApB,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,QAAA,EAAA,IAAA,EAAA,oBAAoB,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,kCAAA,EAAA,QAAA,EAAA,EAAA,EAAA,QAAA,EAhFnB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA+CT,IAAA,CAAA,EAAA,QAAA,EAAA,IAAA,EAAA,MAAA,EAAA,CAAA,g8CAAA,CAAA,EAAA,eAAA,EAAA,EAAA,CAAA,uBAAA,CAAA,MAAA,EAAA,CAAA;;2FAiCQ,oBAAoB,EAAA,UAAA,EAAA,CAAA;kBApFhC,SAAS;AACI,YAAA,IAAA,EAAA,CAAA,EAAA,QAAA,EAAA,kCAAkC,cAChC,IAAI,EAAA,eAAA,EACC,uBAAuB,CAAC,MAAM,EAAA,QAAA,EACrC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA+CT,IAAA,CAAA,EAAA,MAAA,EAAA,CAAA,g8CAAA,CAAA,EAAA;;;ACtCL;;;;;;;;;;;;;;;;;;;;;AAqBG;MAUU,0BAA0B,CAAA;IACnC,SAAS,GAAQ,KAAK,CAAC,QAAQ;kFAAU;IACzC,cAAc,GAAG,KAAK,CAAC,QAAQ;uFAAU;;IAGhC,WAAW,GAAG,MAAM,EAAqB;AAClD;;;;;;AAMG;IACM,MAAM,GAAQ,MAAM,EAAS;AAEnB,IAAA,KAAK,GAAG,MAAM,CAAC,uBAAuB,CAAC;AAGzC,IAAA,WAAW;AAE5B;;;;;AAKG;IACK,SAAS,GAAG,KAAK;AAEzB,IAAA,WAAA,GAAA;;;;;AAKI,QAAA,MAAM,QAAQ,GAAG,MAAM,CAAC,mBAAmB,CAAC;QAC5C,QAAQ,CAAC,QAAQ,CAAC;AACd,YAAA,EAAE,EAAS,MAAM;AACjB,YAAA,KAAK,EAAM,MAAM;AACjB,YAAA,IAAI,EAAO,SAAS;AACpB,YAAA,QAAQ,EAAG,WAAW;AACtB,YAAA,SAAS,EAAE,iBAAiB;AAC/B,SAAA,CAAC;QACF,QAAQ,CAAC,QAAQ,CAAC;AACd,YAAA,EAAE,EAAS,QAAQ;AACnB,YAAA,KAAK,EAAM,QAAQ;AACnB,YAAA,IAAI,EAAO,oBAAoB;AAC/B,YAAA,QAAQ,EAAG,WAAW;AACtB,YAAA,SAAS,EAAE,mBAAmB;AACjC,SAAA,CAAC;QACF,QAAQ,CAAC,QAAQ,CAAC;AACd,YAAA,EAAE,EAAS,MAAM;AACjB,YAAA,KAAK,EAAM,MAAM;AACjB,YAAA,IAAI,EAAO,wBAAwB;AACnC,YAAA,QAAQ,EAAG,WAAW;AACtB,YAAA,SAAS,EAAE,iBAAiB;AAC/B,SAAA,CAAC;;;;QAIF,QAAQ,CAAC,QAAQ,CAAC;AACd,YAAA,EAAE,EAAS,QAAQ;AACnB,YAAA,KAAK,EAAM,QAAQ;AACnB,YAAA,IAAI,EAAO,iBAAiB;AAC5B,YAAA,QAAQ,EAAG,WAAW;AACtB,YAAA,SAAS,EAAE,mBAAmB;AACjC,SAAA,CAAC;;;;QAIF,QAAQ,CAAC,QAAQ,CAAC;AACd,YAAA,EAAE,EAAS,MAAM;AACjB,YAAA,KAAK,EAAM,MAAM;AACjB,YAAA,IAAI,EAAO,SAAS;AACpB,YAAA,QAAQ,EAAG,WAAW;AACtB,YAAA,SAAS,EAAE,iBAAiB;AAC/B,SAAA,CAAC;;;QAIF,QAAQ,CAAC,QAAQ,CAAC;AACd,YAAA,EAAE,EAAS,OAAO;AAClB,YAAA,KAAK,EAAM,QAAQ;;;;;;;AAOnB,YAAA,IAAI,EAAO,aAAa;AACxB,YAAA,QAAQ,EAAG,QAAQ;AACnB,YAAA,SAAS,EAAE,kBAAkB;AAChC,SAAA,CAAC;QACF,QAAQ,CAAC,QAAQ,CAAC;AACd,YAAA,EAAE,EAAS,MAAM;AACjB,YAAA,KAAK,EAAM,MAAM;AACjB,YAAA,IAAI,EAAO,UAAU;AACrB,YAAA,QAAQ,EAAG,QAAQ;AACnB,YAAA,SAAS,EAAE,iBAAiB;AAC/B,SAAA,CAAC;QACF,QAAQ,CAAC,QAAQ,CAAC;AACd,YAAA,EAAE,EAAS,QAAQ;AACnB,YAAA,KAAK,EAAM,QAAQ;AACnB,YAAA,IAAI,EAAO,UAAU;AACrB,YAAA,QAAQ,EAAG,QAAQ;AACnB,YAAA,SAAS,EAAE,oBAAoB;AAClC,SAAA,CAAC;;;;;;AAOF,QAAA,MAAM,aAAa,GAAyB;YACxC,EAAE,IAAI,EAAE,QAAQ,EAAE,UAAU,EAAE,YAAY,EAAE,KAAK,EAAE,YAAY;AAC7D,gBAAA,IAAI,EAAE,QAAQ,EAAE,GAAG,EAAE,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,IAAI,EAAE,IAAI;AAC3C,gBAAA,OAAO,EAAE,CAAC,EAAE,QAAQ,EAAE,YAAY,EAAE;YACtC,EAAE,IAAI,EAAE,QAAQ,EAAE,UAAU,EAAE,UAAU,EAAE,KAAK,EAAE,UAAU;AACzD,gBAAA,IAAI,EAAE,gBAAgB,EAAE,GAAG,EAAE,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,IAAI,EAAE,IAAI;AACnD,gBAAA,OAAO,EAAE,CAAC,EAAE,QAAQ,EAAE,UAAU,EAAE;YACpC,EAAE,IAAI,EAAE,QAAQ,EAAE,UAAU,EAAE,YAAY,EAAE,KAAK,EAAE,YAAY;AAC7D,gBAAA,IAAI,EAAE,iBAAiB,EAAE,GAAG,EAAE,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,IAAI,EAAE,IAAI;AACpD,gBAAA,OAAO,EAAE,CAAC,EAAE,QAAQ,EAAE,YAAY,EAAE;YACtC,EAAE,IAAI,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM;AACjD,gBAAA,IAAI,EAAE,UAAU,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,IAAI,EAAE,IAAI;AAC5C,gBAAA,OAAO,EAAE,CAAC,EAAE,QAAQ,EAAE,MAAM,EAAE;SACnC;AACD,QAAA,KAAK,MAAM,MAAM,IAAI,aAAa,EAAE;YAChC,QAAQ,CAAC,QAAQ,CAAC;AACd,gBAAA,EAAE,EAAS,CAAA,OAAA,EAAU,MAAM,CAAC,UAAU,CAAA,CAAE;gBACxC,KAAK,EAAM,MAAM,CAAC,KAAK;gBACvB,IAAI,EAAO,MAAM,CAAC,IAAI;AACtB,gBAAA,QAAQ,EAAG,QAAQ;AACnB,gBAAA,SAAS,EAAE,qBAAqB;gBAChC,MAAM,EAAK,EAAE,MAAM,EAAE;AACxB,aAAA,CAAC;QACN;AAEA,QAAA,MAAM,aAAa,GAAyB;AACxC,YAAA,EAAE,IAAI,EAAE,QAAQ,EAAE,UAAU,EAAE,OAAO,EAAM,KAAK,EAAE,OAAO,EAAM,IAAI,EAAE,YAAY,EAAO;AACxF,YAAA,EAAE,IAAI,EAAE,QAAQ,EAAE,UAAU,EAAE,WAAW,EAAE,KAAK,EAAE,WAAW,EAAE,IAAI,EAAE,iBAAiB,EAAE;AACxF,YAAA,EAAE,IAAI,EAAE,QAAQ,EAAE,UAAU,EAAE,SAAS,EAAI,KAAK,EAAE,SAAS,EAAI,IAAI,EAAE,UAAU,EAAS;SAC3F;AACD,QAAA,KAAK,MAAM,MAAM,IAAI,aAAa,EAAE;YAChC,QAAQ,CAAC,QAAQ,CAAC;AACd,gBAAA,EAAE,EAAS,CAAA,OAAA,EAAU,MAAM,CAAC,UAAU,CAAA,CAAE;gBACxC,KAAK,EAAM,MAAM,CAAC,KAAK;gBACvB,IAAI,EAAO,MAAM,CAAC,IAAI;AACtB,gBAAA,QAAQ,EAAG,QAAQ;AACnB,gBAAA,SAAS,EAAE,qBAAqB;gBAChC,MAAM,EAAK,EAAE,MAAM,EAAE;AACxB,aAAA,CAAC;QACN;IACJ;AAEA;;;;;;;;;;;AAWG;IACH,oBAAoB,GAAA;AAChB,QAAA,IAAI,CAAC,KAAK,CAAC,aAAa,CAAC,IAAI,CAAC;IAClC;AAEA;;;;;;;AAOG;IACH,KAAK,GAAA;AACD,QAAA,IAAI,CAAC,WAAW,CAAC,KAAK,EAAE;IAC5B;AAEA,IAAA,MAAM,eAAe,GAAA;QACjB,MAAM,SAAS,GAAG,IAAI,CAAC,WAAW,CAAC,mBAAmB,EAAE;AAExD,QAAA,IAAI;AACA,YAAA,MAAM,IAAI,CAAC,KAAK,CAAC,gBAAgB,CAC7B,SAAS,EACT,IAAI,CAAC,SAAS,EAAE,EAChB,IAAI,CAAC,cAAc,EAAE,CACxB;AAED,YAAA,IAAI,IAAI,CAAC,SAAS,EAAE;AAChB,gBAAA,IAAI,CAAC,KAAK,CAAC,aAAa,EAAE;gBAC1B;YACJ;YAEA,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE;AAClC,YAAA,IAAI,MAAM,KAAK,IAAI,EAAE;AACjB,gBAAA,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,MAAM,CAAC;YACjC;QACJ;QAAE,OAAO,GAAG,EAAE;YACV,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,YAAY,KAAK,GAAG,GAAG,GAAG,IAAI,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;QACzE;IACJ;IAEA,WAAW,GAAA;AACP,QAAA,IAAI,CAAC,SAAS,GAAG,IAAI;AACrB,QAAA,IAAI,CAAC,KAAK,CAAC,aAAa,EAAE;IAC9B;uGAhNS,0BAA0B,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAA1B,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,QAAA,EAAA,IAAA,EAAA,0BAA0B,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,qBAAA,EAAA,MAAA,EAAA,EAAA,SAAA,EAAA,EAAA,iBAAA,EAAA,WAAA,EAAA,UAAA,EAAA,WAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,cAAA,EAAA,EAAA,iBAAA,EAAA,gBAAA,EAAA,UAAA,EAAA,gBAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,EAAA,OAAA,EAAA,EAAA,WAAA,EAAA,aAAA,EAAA,MAAA,EAAA,QAAA,EAAA,EAAA,SAAA,EAJxB,CAAC,uBAAuB,CAAC,EAAA,WAAA,EAAA,CAAA,EAAA,YAAA,EAAA,aAAA,EAAA,KAAA,EAAA,IAAA,EAAA,SAAA,EAqBzB,oBAAoB,EAAA,WAAA,EAAA,IAAA,EAAA,MAAA,EAAA,IAAA,EAAA,CAAA,EAAA,QAAA,EAAA,EAAA,EAAA,QAAA,ECxEnC,kPAQA,EAAA,MAAA,EAAA,CAAA,8PAAA,CAAA,EAAA,YAAA,EAAA,CAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,ED0Cc,mBAAmB,EAAA,QAAA,EAAA,iCAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAE,oBAAoB,6EAAE,qBAAqB,EAAA,QAAA,EAAA,mCAAA,EAAA,CAAA,EAAA,eAAA,EAAA,EAAA,CAAA,uBAAA,CAAA,MAAA,EAAA,CAAA;;2FAKjE,0BAA0B,EAAA,UAAA,EAAA,CAAA;kBATtC,SAAS;AACI,YAAA,IAAA,EAAA,CAAA,EAAA,QAAA,EAAA,qBAAqB,cACnB,IAAI,EAAA,eAAA,EACC,uBAAuB,CAAC,MAAM,EAAA,OAAA,EACtC,CAAC,mBAAmB,EAAE,oBAAoB,EAAE,qBAAqB,CAAC,EAAA,SAAA,EAChE,CAAC,uBAAuB,CAAC,EAAA,QAAA,EAAA,kPAAA,EAAA,MAAA,EAAA,CAAA,8PAAA,CAAA,EAAA;;sBAqBnC,SAAS;AAAC,gBAAA,IAAA,EAAA,CAAA,oBAAoB,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE;;;AE5DrD;;;;;;;AAOG;MA2DU,+BAA+B,CAAA;AACvB,IAAA,SAAS,GAAG,MAAM,CAAqB,SAAS,CAAC;AAC/C,IAAA,IAAI,GAAM,MAAM,CAAuB,WAAW,CAAC;IAEtE,SAAS,GAAA,EAAW,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC;IAChD,QAAQ,GAAA,EAAY,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC;uGALxC,+BAA+B,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAA/B,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,QAAA,EAAA,IAAA,EAAA,+BAA+B,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,8CAAA,EAAA,QAAA,EAAA,EAAA,EAAA,QAAA,EAtD9B;;;;;;;;;;;;;;;;;;;AAmBT,IAAA,CAAA,EAAA,QAAA,EAAA,IAAA,EAAA,MAAA,EAAA,CAAA,4jBAAA,CAAA,EAAA,eAAA,EAAA,EAAA,CAAA,uBAAA,CAAA,MAAA,EAAA,CAAA;;2FAmCQ,+BAA+B,EAAA,UAAA,EAAA,CAAA;kBA1D3C,SAAS;AACI,YAAA,IAAA,EAAA,CAAA,EAAA,QAAA,EAAA,8CAA8C,cAC5C,IAAI,EAAA,eAAA,EACC,uBAAuB,CAAC,MAAM,EAAA,QAAA,EACrC;;;;;;;;;;;;;;;;;;;AAmBT,IAAA,CAAA,EAAA,MAAA,EAAA,CAAA,4jBAAA,CAAA,EAAA;;;ACtBL;;;;;;;AAOG;MA2FU,qBAAqB,CAAA;AACb,IAAA,SAAS,GAAG,MAAM,CAAkD,SAAS,CAAC;AAC5E,IAAA,IAAI,GAAM,MAAM,CAAa,WAAW,CAAC;IAEnD,QAAQ,GAAI,MAAM,CAAS,EAAE;iFAAC;AAC9B,IAAA,SAAS,GAAG,QAAQ,CAAC,MAAM,IAAI,CAAC,QAAQ,EAAE,CAAC,IAAI,EAAE,KAAK,EAAE;kFAAC;IAElE,QAAQ,GAAA;AACJ,QAAA,MAAM,IAAI,GAAG,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,cAAc,CAAC;QACzD,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;IAC9E;IAEA,SAAS,GAAA;AACL,QAAA,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE;YAAE;AACvB,QAAA,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,QAAQ,EAAE,IAAI,CAAC,QAAQ,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC;IAC9D;IAEA,QAAQ,GAAA;AACJ,QAAA,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,SAAS,CAAC;IACnC;AAEQ,IAAA,aAAa,CAAC,cAAsB,EAAA;QACxC,MAAM,MAAM,GAAG,cAAc,CAAC,WAAW,CAAC,GAAG,CAAC;AAC9C,QAAA,IAAI,MAAM,IAAI,CAAC,EAAE;YACb,OAAO,cAAc,GAAG,SAAS;QACrC;QACA,MAAM,IAAI,GAAG,cAAc,CAAC,KAAK,CAAC,CAAC,EAAE,MAAM,CAAC;QAC5C,MAAM,GAAG,GAAI,cAAc,CAAC,KAAK,CAAC,MAAM,CAAC;AACzC,QAAA,OAAO,IAAI,GAAG,SAAS,GAAG,GAAG;IACjC;;AAGQ,IAAA,gBAAgB,CAAC,IAAY,EAAA;QACjC,MAAM,MAAM,GAAG,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC;QACpC,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,MAAM,CAAC,GAAG,IAAI;QACtD,OAAO,IAAI,GAAG,MAAM;IACxB;uGApCS,qBAAqB,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAArB,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,QAAA,EAAA,IAAA,EAAA,qBAAqB,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,oCAAA,EAAA,QAAA,EAAA,EAAA,EAAA,QAAA,EArFpB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAoCT,IAAA,CAAA,EAAA,QAAA,EAAA,IAAA,EAAA,MAAA,EAAA,CAAA,44BAAA,CAAA,EAAA,YAAA,EAAA,CAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EArCS,WAAW,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAA,EAAA,CAAA,oBAAA,EAAA,QAAA,EAAA,wSAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAA,EAAA,CAAA,eAAA,EAAA,QAAA,EAAA,2CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAA,EAAA,CAAA,OAAA,EAAA,QAAA,EAAA,qDAAA,EAAA,MAAA,EAAA,CAAA,MAAA,EAAA,UAAA,EAAA,SAAA,EAAA,gBAAA,CAAA,EAAA,OAAA,EAAA,CAAA,eAAA,CAAA,EAAA,QAAA,EAAA,CAAA,SAAA,CAAA,EAAA,CAAA,EAAA,eAAA,EAAA,EAAA,CAAA,uBAAA,CAAA,MAAA,EAAA,CAAA;;2FAsFZ,qBAAqB,EAAA,UAAA,EAAA,CAAA;kBA1FjC,SAAS;+BACI,oCAAoC,EAAA,UAAA,EAClC,IAAI,EAAA,eAAA,EACC,uBAAuB,CAAC,MAAM,EAAA,OAAA,EACtC,CAAC,WAAW,CAAC,EAAA,QAAA,EACZ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAoCT,IAAA,CAAA,EAAA,MAAA,EAAA,CAAA,44BAAA,CAAA,EAAA;;;AClEL;;;;;;;;;;;;;;;;;;;;;;;;AAwBG;MAEU,sBAAsB,CAAA;AACd,IAAA,IAAI,GAAG,MAAM,CAAC,UAAU,CAAC;AAE1C;;;;AAIG;IACH,MAAM,iBAAiB,CAAC,MAIvB,EAAA;AACG,QAAA,MAAM,IAAI,GAAG,IAAI,QAAQ,EAAE;AAC3B,QAAA,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,QAAQ,CAAC;AAEjD,QAAA,OAAO,cAAc,CACjB,IAAI,CAAC,IAAI,CAAC,IAAI,CACV,CAAA,cAAA,EAAiB,MAAM,CAAC,SAAS,CAAA,QAAA,CAAU,EAC3C,IAAI,CACP,CACJ;IACL;AAEA;;;;AAIG;IACH,MAAM,YAAY,CAAC,MAKlB,EAAA;AACG,QAAA,MAAM,IAAI,GAAG,IAAI,QAAQ,EAAE;AAC3B,QAAA,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,QAAQ,CAAC;QACjD,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,IAAI,CAAC;AAChC,QAAA,IAAI,CAAC,MAAM,CAAC,WAAW,EAAE,MAAM,CAAC,SAAS,GAAG,GAAG,GAAG,GAAG,CAAC;AAEtD,QAAA,OAAO,cAAc,CACjB,IAAI,CAAC,IAAI,CAAC,IAAI,CAAkB,0BAA0B,EAAE,IAAI,CAAC,CACpE;IACL;uGA3CS,sBAAsB,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,UAAA,EAAA,CAAA;AAAtB,IAAA,OAAA,KAAA,GAAA,EAAA,CAAA,qBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,QAAA,EAAA,QAAA,EAAA,EAAA,EAAA,IAAA,EAAA,sBAAsB,cADT,MAAM,EAAA,CAAA;;2FACnB,sBAAsB,EAAA,UAAA,EAAA,CAAA;kBADlC,UAAU;mBAAC,EAAE,UAAU,EAAE,MAAM,EAAE;;;ACJlC;;;;;;;;;;;;;;;;;;;;;;;;;AAyBG;MASU,8BAA8B,CAAA;AACtB,IAAA,SAAS,GAAK,MAAM,CAAC,MAAM,CAAC;AAC5B,IAAA,SAAS,GAAK,MAAM,CAAyC,SAAS,CAAC;AACvE,IAAA,WAAW,GAAG,MAAM,CAAC,sBAAsB,CAAC;AAC5C,IAAA,KAAK,GAAS,MAAM,CAAC,YAAY,CAAC;AAClC,IAAA,IAAI,GAAU,MAAM,CAAC,UAAU,CAAC;AAChC,IAAA,GAAG,GAAW,MAAM,CAAC,qBAAqB,CAAC;AAC3C,IAAA,OAAO,GAAO,MAAM,CAAC,oBAAoB,CAAC;AAC1C,IAAA,OAAO,GAAO,MAAM,CAAC,qBAAqB,CAAC;AAC3C,IAAA,UAAU,GAAI,MAAM,CAAC,UAAU,CAAC;AAE9B,IAAA,IAAI,GAAG,MAAM,CAA4B,WAAW,CAAC;IAE/D,KAAK,GAAU,MAAM,CAAY,WAAW;8EAAC;IAC7C,YAAY,GAAG,MAAM,CAAgB,IAAI;qFAAC;AAEnD;;;;;;AAMG;IACM,iBAAiB,GAAG,MAAM,CAAgB,IAAI;0FAAC;;IAGhD,cAAc,GAAkB,IAAI;AAE5C;;;;AAIG;IACK,MAAM,GAA6B,IAAI;AAG9B,IAAA,KAAK;IAEb,aAAa,GAAG,MAAM,CAAU,KAAK;sFAAC;IACtC,QAAQ,GAAQ,QAAQ,CAAC,MAAM,IAAI,CAAC,KAAK,EAAE,KAAK,QAAQ;iFAAC;;AAEzD,IAAA,OAAO,GAAS,QAAQ,CAAC,MAAK;QACnC,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,IAAI,IAAI,CAAC,KAAK,EAAE,KAAK,SAAS;AAAE,YAAA,OAAO,KAAK;AACrE,QAAA,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI;QACtB,IAAI,IAAI,CAAC,OAAO,KAAK,KAAK,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ;AAAE,YAAA,OAAO,KAAK;AAC/D,QAAA,OAAO,IAAI;IACf,CAAC;gFAAC;;AAEO,IAAA,SAAS,GAAO,QAAQ,CAC7B,MAAM,IAAI,CAAC,aAAa,EAAE,IAAI,IAAI,CAAC,KAAK,EAAE,KAAK,SAAS;kFAC3D;IACQ,QAAQ,GAAQ,QAAQ,CAAC,MAAM,IAAI,CAAC,KAAK,EAAE,KAAK,QAAQ;iFAAC;;AAGzD,IAAA,QAAQ,GAAG,QAAQ,CACxB,MAAM,IAAI,CAAC,IAAI,CAAC,OAAO,KAAK,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ;iFAC3F;;AAEQ,IAAA,QAAQ,GAAG,QAAQ,CACxB,MAAM,IAAI,CAAC,IAAI,CAAC,OAAO,KAAK,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ;iFAC3F;AAEQ,IAAA,eAAe,GAAG,QAAQ,CAAC,MAAK;QACrC,MAAM,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,KAAK;AAC9B,cAAE,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC;cAChB,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,IAAI,IAAI;;;;;AAKvC,QAAA,IAAI,GAAG,IAAI,IAAI,IAAI,GAAG,CAAC,KAAK,IAAI,IAAI,IAAI,GAAG,CAAC,MAAM,IAAI,IAAI;AAAE,YAAA,OAAO,EAAE;QACrE,OAAO,CAAA,EAAG,GAAG,CAAC,KAAK,MAAM,GAAG,CAAC,MAAM,CAAA,CAAE;IACzC,CAAC;wFAAC;AAEF;;;;;;;;AAQG;IACM,YAAY,GAAG,MAAM,CAAC,KAAK;qFAAC;AAErC,IAAA,IACI,eAAe,GAAA;AACf,QAAA,OAAO,IAAI,CAAC,YAAY,EAAE;IAC9B;IAEA,gBAAgB,GAAA;AACZ,QAAA,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC;IACvC;AAEA;;;;;;AAMG;AAEO,IAAA,UAAU,CAAC,KAAiB,EAAA;AAClC,QAAA,MAAM,MAAM,GAAG,KAAK,CAAC,MAA4B;AACjD,QAAA,IAAI,MAAM,EAAE,OAAO,CAAC,4CAA4C,CAAC;YAAE;QACnE,IAAI,CAAC,gBAAgB,EAAE;IAC3B;AAEA,IAAA,WAAA,GAAA;;;;QAII,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,EAAE,MAAM,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC;;;;;;AAO1E,QAAA,MAAM,CAAC,CAAC,SAAS,KAAI;AACjB,YAAA,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE;gBAAE;YAC1B,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,MAAK;AACtC,gBAAA,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,KAAK,CAAC;AAC5B,gBAAA,OAAO,IAAI;AACf,YAAA,CAAC,CAAC;YACF,SAAS,CAAC,UAAU,CAAC;AACzB,QAAA,CAAC,CAAC;;;;;;QAOF,IAAI,QAAQ,GAAG,IAAI;QACnB,MAAM,CAAC,MAAK;YACR,IAAI,CAAC,YAAY,EAAE;YACnB,IAAI,QAAQ,EAAE;gBACV,QAAQ,GAAG,KAAK;gBAChB;YACJ;;;AAGA,YAAA,UAAU,CAAC,MAAM,IAAI,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC;AAC7C,QAAA,CAAC,CAAC;IACN;AAEA,IAAA,MAAM,QAAQ,GAAA;AACV,QAAA,IAAI;;;;;;;;YAQA,IAAI,IAAI,CAAC,IAAI,CAAC,OAAO,KAAK,KAAK,EAAE;gBAC7B,MAAM,IAAI,GAAG,MAAM,cAAc,CAC7B,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,EAAE,YAAY,EAAE,MAAM,EAAE,CAAC,CACpE;gBACD,IAAI,CAAC,cAAc,GAAG,GAAG,CAAC,eAAe,CAAC,IAAI,CAAC;gBAC/C,IAAI,CAAC,iBAAiB,CAAC,GAAG,CAAC,IAAI,CAAC,cAAc,CAAC;YACnD;iBAAO;AACH,gBAAA,IAAI,CAAC,iBAAiB,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC;YAC3D;AACA,YAAA,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,SAAS,CAAC;QAC7B;QAAE,OAAO,GAAG,EAAE;AACV,YAAA,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC;AACvB,YAAA,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,wBAAwB,GAAG,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC;QAC7E;IACJ;IAEA,WAAW,GAAA;AACP,QAAA,IAAI,IAAI,CAAC,cAAc,KAAK,IAAI,EAAE;AAC9B,YAAA,GAAG,CAAC,eAAe,CAAC,IAAI,CAAC,cAAc,CAAC;AACxC,YAAA,IAAI,CAAC,cAAc,GAAG,IAAI;QAC9B;IACJ;AAEA,IAAA,aAAa,CAAC,MAAyB,EAAA;AACnC,QAAA,IAAI,CAAC,MAAM,GAAG,MAAM;AACpB,QAAA,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,IAAI,CAAC;IAChC;AAEA,IAAA,YAAY,CAAC,GAAU,EAAA;AACnB,QAAA,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC;QACvB,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC;IACtC;AAEA,IAAA,MAAM,MAAM,GAAA;AACR,QAAA,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE;YAAE;;;QAIrB,MAAM,gBAAgB,GAClB,IAAI,CAAC,eAAe,EAAE,IAAI,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,QAAQ,EAAE,EAAE,KAAK,CAAC,KAAK,KAAK;QAEjF,MAAM,UAAU,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,CAAU,+BAA+B,EAAE;AAC7E,YAAA,IAAI,EAAE;AACF,gBAAA,QAAQ,EAAE,IAAI,CAAC,QAAQ,EAAE;AACzB,gBAAA,UAAU,EAAE;AACR,sBAAE;AACF,sBAAE,SAAS;AAClB,aAAA;AACD,YAAA,aAAa,EAAE,2BAA2B;AAC7C,SAAA,CAAC;QACF,MAAM,SAAS,GAAG,MAAM,cAAc,CAAC,UAAU,CAAC,MAAM,CAAC;QACzD,IAAI,SAAS,KAAK,IAAI;YAAE;AAExB,QAAA,MAAM,IAAI,CAAC,WAAW,CAAC,WAAW,CAAC;IACvC;AAEA,IAAA,MAAM,QAAQ,GAAA;AACV,QAAA,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE;YAAE;;;QAIvB,MAAM,QAAQ,GACV,IAAI,CAAC,eAAe,EAAE,IAAI,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,QAAQ,EAAE,EAAE,KAAK,CAAC,KAAK,KAAK;QAEjF,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,CACjC,qBAAqB,EACrB;YACI,IAAI,EAAE,EAAE,cAAc,EAAE,IAAI,CAAC,QAAQ,EAAE,EAAE,QAAQ,EAAE;AACnD,YAAA,aAAa,EAAE,2BAA2B;AAC7C,SAAA,CACJ;QACD,MAAM,MAAM,GAAG,MAAM,cAAc,CAAC,SAAS,CAAC,MAAM,CAAC;QACrD,IAAI,MAAM,KAAK,SAAS;YAAE;QAE1B,MAAM,IAAI,CAAC,WAAW,CAAC,aAAa,EAAE,MAAM,CAAC,QAAQ,CAAC;IAC1D;AAEA;;;;;;;;AAQG;IACH,QAAQ,GAAA;AACJ,QAAA,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE;YAAE;AAEtB,QAAA,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,EAAE;YAClB,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC;YAE3C;QACJ;AAEA,QAAA,IAAI,CAAC,OAAO,CAAC,cAAc,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC,SAAS,CAAC,CAAC,OAAO,KAAI;AAC/D,YAAA,IAAI,OAAO;gBAAE,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC;AAC5D,QAAA,CAAC,CAAC;IACN;;IAGQ,QAAQ,GAAA;QACZ,OAAO,IAAI,CAAC,MAAM,EAAE,OAAO,EAAE,IAAI,KAAK;IAC1C;AAEQ,IAAA,MAAM,WAAW,CACrB,IAAiC,EACjC,QAAiB,EAAA;AAEjB,QAAA,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM;QAC1B,IAAI,MAAM,KAAK,IAAI;YAAE;AAErB,QAAA,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC;AAExB,QAAA,IAAI;;;;AAIA,YAAA,IAAI,CAAC,KAAK,EAAE,oBAAoB,EAAE;AAElC,YAAA,MAAM,MAAM,GAAG,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,QAAQ,EAAE,EAAE,MAAM,CAAC,QAAQ,EAAE,CAAC;YACpE,MAAM,IAAI,GAAK,MAAM,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC;YAEhD,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,KAAK;AACjC,kBAAE,MAAM,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM;AAC9D,kBAAE,MAAM,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,CAAC;AAEjE,YAAA,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,KAAK,WAAW,GAAG,aAAa,GAAG,mBAAmB,CAAC;AAC9E,YAAA,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,MAAM,CAAC;QAChC;QAAE,OAAO,KAAK,EAAE;AACZ,YAAA,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,SAAS,CAAC;AACzB,YAAA,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,eAAe,GAAG,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;AAC7D,YAAA,OAAO,CAAC,KAAK,CAAC,oCAAoC,EAAE,KAAK,CAAC;QAC9D;IACJ;IAEQ,MAAM,SAAS,CACnB,IAA8D,EAC9D,IAAiC,EACjC,IAAU,EACV,WAA+B,EAC/B,MAAsB,EAAA;AAEtB,QAAA,IAAI,IAAI,KAAK,WAAW,EAAE;;;;;YAKtB,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,WAAW,CAAC,iBAAiB,CAAC;gBACtD,IAAI;AACJ,gBAAA,SAAS,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI;AAC1B,gBAAA,QAAQ,EAAG,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ,EAAE,MAAM,CAAC;AAC/D,aAAA,CAAC;YACF,OAAO;AACH,gBAAA,IAAI,EAAO,OAAO;AAClB,gBAAA,IAAI,EAAO,WAAW;gBACtB,SAAS,EAAE,OAAO,QAAQ,CAAC,EAAE,KAAK,QAAQ,IAAI,QAAQ,CAAC,EAAE,KAAK,EAAE,GAAG,QAAQ,CAAC,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI;aACnG;QACL;;;;;;;QAQA,MAAM,SAAS,GAAG,IAAI,CAAC,eAAe,CAAC,WAAW,IAAI,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;AACzG,QAAA,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,IAAI,IAAI,CAAC,IAAI,gBAAgB;QAC7E,MAAM,OAAO,GAAK,IAAI,CAAC,QAAQ,CAAC,SAAS,EAAE,SAAS,CAAC;QACrD,MAAM,QAAQ,GAAI,MAAM,IAAI,CAAC,WAAW,CAAC,YAAY,CAAC;YAClD,IAAI;AACJ,YAAA,IAAI,EAAO,OAAO;AAClB,YAAA,SAAS,EAAE,KAAK;AAChB,YAAA,QAAQ,EAAG,SAAS;AACvB,SAAA,CAAC;QACF,OAAO;AACH,YAAA,IAAI,EAAO,OAAO;AAClB,YAAA,IAAI,EAAO,aAAa;YACxB,SAAS,EAAE,OAAO,QAAQ,CAAC,EAAE,KAAK,QAAQ,IAAI,QAAQ,CAAC,EAAE,KAAK,EAAE,GAAG,QAAQ,CAAC,EAAE,GAAG,SAAS;SAC7F;IACL;IAEQ,MAAM,OAAO,CACjB,IAA4D,EAC5D,IAAiC,EACjC,IAAU,EACV,WAA+B,EAC/B,MAAsB,EAAA;AAEtB,QAAA,IAAI,IAAI,KAAK,WAAW,EAAE;;;;AAItB,YAAA,MAAM,IAAI,CAAC,WAAW,CAAC,YAAY,CAAC;gBAChC,IAAI;AACJ,gBAAA,IAAI,EAAO,IAAI,CAAC,IAAI,CAAC,IAAI;AACzB,gBAAA,SAAS,EAAE,IAAI;AACf,gBAAA,QAAQ,EAAG,IAAI,CAAC,IAAI,CAAC,QAAQ;AAChC,aAAA,CAAC;AACF,YAAA,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,OAAO,EAAE,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE;QACxE;QAEA,MAAM,SAAS,GAAG,IAAI,CAAC,eAAe,CAAC,WAAW,IAAI,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;AACxG,QAAA,MAAM,OAAO,GAAK,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,SAAS,CAAC;AAChE,QAAA,MAAM,IAAI,CAAC,WAAW,CAAC,YAAY,CAAC;YAChC,IAAI;AACJ,YAAA,IAAI,EAAO,OAAO;AAClB,YAAA,SAAS,EAAE,KAAK;AAChB,YAAA,QAAQ,EAAG,SAAS;AACvB,SAAA,CAAC;AACF,QAAA,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,aAAa,EAAE,OAAO,EAAE,OAAO,EAAE;IACnE;AAEA;;;;;;AAMG;AACK,IAAA,aAAa,CAAC,KAAc,EAAA;QAChC,IAAI,KAAK,KAAK,IAAI,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE;AAC7C,YAAA,MAAM,MAAM,GAAI,KAA8B,CAAC,MAAM;AACrD,YAAA,IAAI,OAAO,MAAM,KAAK,QAAQ,EAAE;gBAC5B,IAAI,MAAM,KAAK,GAAG;AAAE,oBAAA,OAAO,yBAAyB;gBACpD,IAAI,MAAM,KAAK,GAAG;AAAE,oBAAA,OAAO,uBAAuB;gBAClD,IAAI,MAAM,KAAK,GAAG;AAAE,oBAAA,OAAO,0CAA0C;gBACrE,IAAI,MAAM,KAAK,CAAC;AAAI,oBAAA,OAAO,eAAe;gBAC1C,OAAO,CAAA,KAAA,EAAQ,MAAM,CAAA,CAAE;YAC3B;AACA,YAAA,MAAM,OAAO,GAAI,KAA+B,CAAC,OAAO;AACxD,YAAA,IAAI,OAAO,OAAO,KAAK,QAAQ,IAAI,OAAO,KAAK,EAAE;AAAE,gBAAA,OAAO,OAAO;QACrE;QACA,IAAI,KAAK,YAAY,KAAK,IAAI,KAAK,CAAC,OAAO,KAAK,EAAE;YAAE,OAAO,KAAK,CAAC,OAAO;AACxE,QAAA,OAAO,eAAe;IAC1B;AAEA;;;;;;;;AAQG;IACK,YAAY,CAAC,QAAgB,EAAE,QAAiB,EAAA;AACpD,QAAA,IAAI,QAAQ;AAAE,YAAA,OAAO,KAAK;QAC1B,OAAO,QAAQ,KAAK,WAAW,GAAG,KAAK,GAAG,MAAM;IACpD;;IAGQ,eAAe,GAAA;QACnB,OAAO,IAAI,CAAC,MAAM,EAAE,QAAQ,EAAE,IAAI,KAAK;IAC3C;AAEA;;;;AAIG;IACK,eAAe,CAAC,IAAY,EAAE,MAAsB,EAAA;QACxD,MAAM,GAAG,GAAG,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC;QACjC,MAAM,GAAG,GAAG,GAAG,GAAG,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,WAAW,EAAE,GAAG,EAAE;AACxD,QAAA,IAAI,MAAM,KAAK,KAAK,IAAK,GAAG,KAAK,MAAM;AAAE,YAAA,OAAO,IAAI;AACpD,QAAA,IAAI,MAAM,KAAK,MAAM,KAAK,GAAG,KAAK,MAAM,IAAI,GAAG,KAAK,OAAO,CAAC;AAAE,YAAA,OAAO,IAAI;QACzE,MAAM,IAAI,GAAG,GAAG,GAAG,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,GAAG,IAAI;AAChD,QAAA,OAAO,IAAI,IAAI,MAAM,KAAK,KAAK,GAAG,MAAM,GAAG,MAAM,CAAC;IACtD;AAEQ,IAAA,gBAAgB,CAAC,MAAc,EAAA;QACnC,MAAM,MAAM,GAAG,MAAM,CAAC,WAAW,CAAC,GAAG,CAAC;QACtC,IAAI,MAAM,IAAI,CAAC;YAAE,OAAO,MAAM,GAAG,SAAS;AAC1C,QAAA,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,MAAM,CAAC,GAAG,SAAS,GAAG,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC;IACrE;AAEQ,IAAA,SAAS,CAAC,IAAmB,EAAA;AACjC,QAAA,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI,KAAK,EAAE;AAAE,YAAA,OAAO,IAAI;QAC7C,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC;QACxC,MAAM,GAAG,GAAG,OAAO,CAAC,WAAW,CAAC,GAAG,CAAC;QACpC,IAAI,GAAG,IAAI,CAAC;AAAE,YAAA,OAAO,GAAG;QACxB,OAAO,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC;IAChC;IAEQ,QAAQ,CAAC,MAAc,EAAE,IAAY,EAAA;QACzC,MAAM,IAAI,GAAI,MAAM,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC;QACxC,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC;AACtC,QAAA,OAAO,CAAA,EAAG,IAAI,CAAA,CAAA,EAAI,KAAK,EAAE;IAC7B;uGA3bS,8BAA8B,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAA9B,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,QAAA,EAAA,IAAA,EAAA,8BAA8B,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,0BAAA,EAAA,IAAA,EAAA,EAAA,SAAA,EAAA,EAAA,UAAA,EAAA,oBAAA,EAAA,EAAA,UAAA,EAAA,EAAA,qCAAA,EAAA,sBAAA,EAAA,EAAA,EAAA,WAAA,EAAA,CAAA,EAAA,YAAA,EAAA,OAAA,EAAA,KAAA,EAAA,IAAA,EAAA,SAAA,EAmC5B,0BAA0B,EAAA,WAAA,EAAA,IAAA,EAAA,CAAA,EAAA,QAAA,EAAA,EAAA,EAAA,QAAA,EC9FzC,grGAgFA,65EDzBc,0BAA0B,EAAA,QAAA,EAAA,qBAAA,EAAA,MAAA,EAAA,CAAA,WAAA,EAAA,gBAAA,CAAA,EAAA,OAAA,EAAA,CAAA,aAAA,EAAA,QAAA,CAAA,EAAA,CAAA,EAAA,eAAA,EAAA,EAAA,CAAA,uBAAA,CAAA,MAAA,EAAA,CAAA;;2FAI3B,8BAA8B,EAAA,UAAA,EAAA,CAAA;kBAR1C,SAAS;+BACI,0BAA0B,EAAA,UAAA,EACxB,IAAI,EAAA,eAAA,EACC,uBAAuB,CAAC,MAAM,EAAA,OAAA,EACtC,CAAC,0BAA0B,CAAC,EAAA,QAAA,EAAA,grGAAA,EAAA,MAAA,EAAA,CAAA,q2EAAA,CAAA,EAAA;;sBAuCpC,SAAS;uBAAC,0BAA0B;;sBAkDpC,WAAW;uBAAC,qCAAqC;;sBAgBjD,YAAY;uBAAC,UAAU,EAAE,CAAC,QAAQ,CAAC;;;AEhKxC;;;;;;;;;AASG;;ACTH;;AAEG;;;;"}