@snowcone-app/canvas 0.1.10 → 0.1.12

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.
Files changed (48) hide show
  1. package/dist/{CanvasStateV1-BmE5V6me.cjs → CanvasStateV1-C4hC1MCe.cjs} +5 -5
  2. package/dist/{CanvasStateV1-BmE5V6me.cjs.map → CanvasStateV1-C4hC1MCe.cjs.map} +1 -1
  3. package/dist/{CanvasStateV1-CD3Q94F4.js → CanvasStateV1-CJU_xYW5.js} +3 -3
  4. package/dist/{CanvasStateV1-CD3Q94F4.js.map → CanvasStateV1-CJU_xYW5.js.map} +1 -1
  5. package/dist/{HybridHistoryManager-BV6XV0nD.js → HybridHistoryManager-jBBnVim8.js} +54 -54
  6. package/dist/{HybridHistoryManager-BV6XV0nD.js.map → HybridHistoryManager-jBBnVim8.js.map} +1 -1
  7. package/dist/{ElementFactory-Ckv6sSev.js → ImportManager-Oqu2yB54.js} +595 -378
  8. package/dist/ImportManager-Oqu2yB54.js.map +1 -0
  9. package/dist/{ElementFactory-DEjwp-Wg.cjs → ImportManager-W1eWhfyM.cjs} +5 -5
  10. package/dist/ImportManager-W1eWhfyM.cjs.map +1 -0
  11. package/dist/ThemeContext-BMNQKl1c.cjs +2 -0
  12. package/dist/{ThemeContext-4mJ_y0Me.cjs.map → ThemeContext-BMNQKl1c.cjs.map} +1 -1
  13. package/dist/ThemeContext-wj-wSO7J.js +1158 -0
  14. package/dist/{ThemeContext-H0Z-MqqR.js.map → ThemeContext-wj-wSO7J.js.map} +1 -1
  15. package/dist/advanced.js +5 -32
  16. package/dist/advanced.js.map +1 -1
  17. package/dist/advanced.mjs +588 -15069
  18. package/dist/advanced.mjs.map +1 -1
  19. package/dist/components/embed/KitLayout.d.ts +22 -0
  20. package/dist/components/embed/UndoRedoControls.d.ts +3 -0
  21. package/dist/compose-Dqh2f8tS.js +22222 -0
  22. package/dist/compose-Dqh2f8tS.js.map +1 -0
  23. package/dist/compose-HDJp4Z_d.cjs +60 -0
  24. package/dist/compose-HDJp4Z_d.cjs.map +1 -0
  25. package/dist/index.js +1 -1
  26. package/dist/index.js.map +1 -1
  27. package/dist/index.mjs +595 -513
  28. package/dist/index.mjs.map +1 -1
  29. package/dist/internals.js +1 -1
  30. package/dist/internals.js.map +1 -1
  31. package/dist/internals.mjs +101 -102
  32. package/dist/internals.mjs.map +1 -1
  33. package/dist/style.css.d.ts +4 -0
  34. package/dist/testing.js +1 -1
  35. package/dist/testing.mjs +11 -11
  36. package/package.json +8 -4
  37. package/dist/ElementFactory-Ckv6sSev.js.map +0 -1
  38. package/dist/ElementFactory-DEjwp-Wg.cjs.map +0 -1
  39. package/dist/ImportManager-64OYjELO.js +0 -222
  40. package/dist/ImportManager-64OYjELO.js.map +0 -1
  41. package/dist/ImportManager-wSzrR-5a.cjs +0 -2
  42. package/dist/ImportManager-wSzrR-5a.cjs.map +0 -1
  43. package/dist/ThemeContext-4mJ_y0Me.cjs +0 -2
  44. package/dist/ThemeContext-H0Z-MqqR.js +0 -1077
  45. package/dist/compose-DHBRwi_A.cjs +0 -33
  46. package/dist/compose-DHBRwi_A.cjs.map +0 -1
  47. package/dist/compose-DIPiisIw.js +0 -7690
  48. package/dist/compose-DIPiisIw.js.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ImportManager-Oqu2yB54.js","sources":["../src/theme.ts","../src/components/CanvasEditor/renderers/renderingConstants.ts","../src/core/TransformHandles.ts","../src/core/ResizeHandler.ts","../src/core/ResizePipeline.ts","../src/core/InteractionStateMachine.ts","../src/core/RotationAnchorResolver.ts","../src/core/SpatialGrid.ts","../src/core/AlignmentSnapSystem.ts","../src/core/SpacingSystem.ts","../src/utils/TextureManager.ts","../src/core/ArtboardRenderer.ts","../src/types/guards.ts","../src/rendering/ElementRenderUtils.ts","../src/rendering/CompositingRenderer.ts","../src/rendering/mask-utils.ts","../src/effects/mask-presets.ts","../src/rendering/MaskRenderer.ts","../src/effects/DistressGenerator.ts","../src/effects/distress-textures.ts","../src/effects/DistressTextureCache.ts","../src/rendering/DistressTextureRenderer.ts","../src/core/SelectionRenderer.ts","../src/core/HoverRenderer.ts","../src/core/InteractionFeedbackRenderer.ts","../src/core/EditModeRenderer.ts","../src/core/CanvasRenderer.ts","../src/rendering/element-serializer.ts","../src/workers/export-worker.bundle.string.js","../src/utils/WorkerExportManager.ts","../src/utils/ExportManager.ts","../src/core/ElementFactory.ts","../src/utils/ImportManager.ts"],"sourcesContent":["/**\n * Theme constants for the application\n * Centralized color palette and design tokens\n */\n\nimport { getThemeAccentColor, getThemeAccentHoverColorWithAlpha } from './constants.js';\n\nexport const colors = {\n // Primary brand color (dynamically from theme)\n get primary() {\n return getThemeAccentColor();\n },\n\n // Accent colors\n accent: {\n blue: '#0066FF',\n purple: '#8B5CF6',\n orange: '#F97316',\n },\n\n // UI colors\n background: '#f5f5f5',\n surface: '#ffffff',\n border: '#e5e5e5',\n\n // Text colors\n text: {\n primary: '#1f2937',\n secondary: '#6b7280',\n tertiary: '#9ca3af',\n },\n\n // State colors\n success: '#10b981',\n warning: '#f59e0b',\n error: '#ef4444',\n info: '#3b82f6',\n\n // Interaction states (dynamically from theme)\n get hover() {\n return getThemeAccentHoverColorWithAlpha(0.1);\n },\n get active() {\n return getThemeAccentHoverColorWithAlpha(0.2);\n },\n disabled: '#d1d5db',\n};\n\nexport const theme = {\n colors,\n\n // Spacing scale (in pixels)\n spacing: {\n xs: 4,\n sm: 8,\n md: 16,\n lg: 24,\n xl: 32,\n xxl: 48,\n },\n\n // Border radius\n borderRadius: {\n sm: 4,\n md: 8,\n lg: 12,\n full: 9999,\n },\n\n // Typography\n fontSize: {\n xs: 12,\n sm: 14,\n base: 16,\n lg: 18,\n xl: 20,\n xxl: 24,\n },\n\n // Z-index layers\n zIndex: {\n base: 0,\n dropdown: 10,\n modal: 100,\n tooltip: 1000,\n editor: 1000,\n },\n\n // Canvas-specific\n canvas: {\n get selectionColor() {\n return getThemeAccentColor();\n },\n get snapGuideColor() {\n return getThemeAccentColor();\n },\n get rotationHandleColor() {\n return getThemeAccentColor();\n },\n handleSize: 8,\n handleHoverSize: 10,\n snapThreshold: 8, // pixels\n snapGuideDash: [5, 5],\n snapGuideWidth: 1,\n selectionPadding: 1, // pixels - visual padding around selection box\n\n // Spacing indicators\n spacingIndicatorColor: '#FF0000', // Red for spacing measurement lines\n spacingIndicatorWidth: 1.5, // Slightly thicker than snap guides\n spacingDetectionThreshold: 50, // Show spacing within 50px\n spacingLabelFontSize: 11,\n spacingLabelFontFamily: \"-apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif\",\n spacingLabelBackground: '#FFFFFF', // White background for labels\n },\n};\n\nexport default theme;\n","/**\n * Shared rendering constants for canvas UI elements\n * Provides DRY (Don't Repeat Yourself) constants for consistent rendering\n * All values should be divided by zoom to maintain visual consistency at different zoom levels\n */\n\n/**\n * Line width for selection borders, handles, and UI elements\n * Should be divided by zoom: lineWidth = SELECTION_LINE_WIDTH / zoom\n */\nexport const SELECTION_LINE_WIDTH = 2;\n\n/**\n * Corner resize handle radius\n * Should be divided by zoom: radius = HANDLE_RADIUS / zoom\n */\nexport const HANDLE_RADIUS = 6;\n\n/**\n * Rotation handle radius (larger than corner handles)\n * Should be divided by zoom: radius = ROTATION_HANDLE_RADIUS / zoom\n */\nexport const ROTATION_HANDLE_RADIUS = 16;\n\n/**\n * Dash pattern for dotted lines (multi-selection group bounds)\n * Should be divided by zoom: setLineDash([DASH_SIZE / zoom, DASH_GAP / zoom])\n */\nexport const DASH_SIZE = 5;\nexport const DASH_GAP = 5;\n\n/**\n * Rotation handle icon scale factor\n */\nexport const ROTATION_ICON_SCALE = 0.5;\n\n/**\n * Helper function to get zoom-adjusted line width\n */\nexport function getLineWidth(zoom: number): number {\n return SELECTION_LINE_WIDTH / zoom;\n}\n\n/**\n * Helper function to get zoom-adjusted handle radius\n */\nexport function getHandleRadius(zoom: number): number {\n return HANDLE_RADIUS / zoom;\n}\n\n/**\n * Helper function to get zoom-adjusted rotation handle radius\n */\nexport function getRotationHandleRadius(zoom: number): number {\n return ROTATION_HANDLE_RADIUS / zoom;\n}\n\n/**\n * Helper function to get zoom-adjusted dash pattern\n */\nexport function getDashPattern(zoom: number): number[] {\n return [DASH_SIZE / zoom, DASH_GAP / zoom];\n}\n\n/**\n * Renders the rotation handle icon (refresh-ccw icon from Lucide)\n * Internal helper - use renderRotationHandle for complete handle rendering\n * @param ctx - Canvas rendering context\n * @param x - X position of the rotation handle center (in current coordinate space)\n * @param y - Y position of the rotation handle center (in current coordinate space)\n * @param zoom - Current zoom level (scales icon to maintain consistent screen size)\n */\nfunction renderRotationHandleIcon(\n ctx: CanvasRenderingContext2D,\n x: number,\n y: number,\n zoom: number\n): void {\n ctx.save();\n\n // Draw refresh-ccw icon (Lucide icon)\n // Scale inversely with zoom to maintain constant screen size\n const scale = ROTATION_ICON_SCALE / zoom;\n ctx.translate(x, y);\n ctx.scale(scale, scale);\n\n ctx.strokeStyle = '#000';\n ctx.lineWidth = 1.5; // Consistent line width for clean appearance\n ctx.lineCap = 'round';\n ctx.lineJoin = 'round';\n\n // Center the icon (24x24 viewBox)\n ctx.translate(-12, -12);\n\n // Path 1: M21 12a9 9 0 0 0-9-9 9.75 9.75 0 0 0-6.74 2.74L3 8\n ctx.beginPath();\n ctx.moveTo(21, 12);\n ctx.arc(12, 12, 9, 0, -Math.PI / 2, true);\n ctx.bezierCurveTo(3.5, 4.5, 4, 6, 3, 8);\n ctx.stroke();\n\n // Path 2: M3 3v5h5 (arrow at top-left)\n ctx.beginPath();\n ctx.moveTo(3, 3);\n ctx.lineTo(3, 8);\n ctx.lineTo(8, 8);\n ctx.stroke();\n\n // Path 3: M3 12a9 9 0 0 0 9 9 9.75 9.75 0 0 0 6.74-2.74L21 16\n ctx.beginPath();\n ctx.moveTo(3, 12);\n ctx.arc(12, 12, 9, Math.PI, Math.PI / 2, true);\n ctx.bezierCurveTo(20.5, 19.5, 20, 18, 21, 16);\n ctx.stroke();\n\n // Path 4: M16 16h5v5 (arrow at bottom-right)\n ctx.beginPath();\n ctx.moveTo(16, 16);\n ctx.lineTo(21, 16);\n ctx.lineTo(21, 21);\n ctx.stroke();\n\n ctx.restore();\n}\n\n/**\n * Renders complete rotation handle (circle background + icon)\n * Provides consistent rotation handle rendering across single and multi-selection\n * Works in world coordinate space with zoom compensation for UI elements\n *\n * @param ctx - Canvas rendering context\n * @param x - X position in world coordinates\n * @param y - Y position in world coordinates\n * @param zoom - Current zoom level (default 1.0)\n * @param accentColor - Border color (default from theme)\n * @param isHovering - Whether handle is being hovered (increases border width)\n */\nexport function renderRotationHandle(\n ctx: CanvasRenderingContext2D,\n x: number,\n y: number,\n zoom: number = 1.0,\n accentColor: string = '#3b82f6',\n isHovering: boolean = false\n): void {\n const rotationHandleRadius = getRotationHandleRadius(zoom);\n ctx.save();\n\n // Circle background - white fill with accent border\n ctx.fillStyle = '#fff';\n ctx.strokeStyle = accentColor;\n ctx.lineWidth = isHovering ? getLineWidth(zoom) * 1.25 : getLineWidth(zoom);\n\n ctx.beginPath();\n ctx.arc(x, y, rotationHandleRadius, 0, Math.PI * 2);\n ctx.fill();\n ctx.stroke();\n\n // Draw rotation icon\n renderRotationHandleIcon(ctx, x, y, zoom);\n\n ctx.restore();\n}\n","/**\n * TransformHandles - Manages rendering and interaction with transform handles\n * Provides consistent resize and rotation behavior across all text elements\n */\n\nimport { calculateResizeHandles, calculateRotationHandlePosition, getCursorForWorldPosition, hitTestCircle } from './GeometryUtils.js';\nimport type { BaseElement } from './BaseElement.js';\nimport type { HandleInfo, Point } from '../types/index.js';\nimport { theme } from '../theme.js';\nimport { getThemeAccentColor } from '../constants.js';\nimport {\n HANDLE_RADIUS as BASE_HANDLE_RADIUS,\n ROTATION_ICON_SCALE,\n} from '../components/CanvasEditor/renderers/renderingConstants.js';\nimport { CORNER_HANDLE_HIT_RADIUS } from '../constants.js';\n\nconst HANDLE_SIZE = BASE_HANDLE_RADIUS * 2;\n\nexport class TransformHandles {\n resizeHandles: HandleInfo[];\n rotationHandle: Point | null;\n elementRotation: number;\n rotationAnchor: Point;\n\n constructor() {\n this.resizeHandles = [];\n this.rotationHandle = null;\n this.elementRotation = 0;\n this.rotationAnchor = { x: 0, y: 0 };\n }\n\n /**\n * Update handle positions for an element\n * @param element - The element to update handles for\n * @param zoom - Current zoom level (used to maintain consistent rotation handle distance in screen space)\n */\n update(element: BaseElement, zoom: number = 1.0): void {\n // For crop mode, use getBoundingBox() to get the original image bounds\n // For normal mode, use getVisualBoundingBox() to get the visible bounds\n const isCropping = 'isCropping' in element && element.isCropping;\n const bbox = isCropping ? element.getBoundingBox() : element.getVisualBoundingBox();\n const rotationAnchor = element.getRotationAnchor();\n const enabledAnchors = element.getEnabledAnchors();\n\n // Store rotation info for rendering\n this.elementRotation = element.rotation;\n this.rotationAnchor = rotationAnchor;\n\n // Apply visual padding to expand the bounding box for handle positioning\n // This places handles on the padded selection border\n const padding = theme.canvas.selectionPadding;\n const paddedBbox = {\n x: bbox.x - padding,\n y: bbox.y - padding,\n width: bbox.width + padding * 2,\n height: bbox.height + padding * 2,\n };\n\n // Calculate all resize handles using padded bbox\n // This places handles at corners of the padded selection box\n const allHandles = calculateResizeHandles(paddedBbox, element.rotation, rotationAnchor);\n\n // Filter to only enabled anchors\n // Also hide side handles when element is rotated (they look awkward sticking out)\n const isRotated = Math.abs(element.rotation % 360) > 0.1;\n this.resizeHandles = allHandles.filter((handle) => {\n if (!enabledAnchors.includes(handle.anchor)) return false;\n // Hide side handles when rotated\n if (isRotated && handle.anchor.includes('middle')) return false;\n return true;\n });\n\n // Calculate rotation handle using padded bbox with zoom-adjusted distance\n // Scale distance inversely with zoom to maintain consistent screen space distance\n // At zoom=0.33, use 70/0.33 = 212px world distance → 70px screen distance\n this.rotationHandle = calculateRotationHandlePosition(\n paddedBbox,\n element.rotation,\n rotationAnchor,\n zoom\n );\n }\n\n /**\n * Render all handles\n * @param renderRotationInCanvas - If false, skip canvas rendering of rotation handle (for React-based rendering)\n */\n render(\n ctx: CanvasRenderingContext2D,\n showRotationHandle: boolean = true,\n rotationAngle: number = 0,\n isRotating: boolean = false,\n isHoveringRotation: boolean = false,\n hoveredResizeHandle: HandleInfo | null = null,\n isResizing: boolean = false,\n activeResizeHandle: HandleInfo | null = null,\n zoom: number = 1.0,\n renderRotationInCanvas: boolean = true\n ): void {\n // Render resize handles\n this.resizeHandles.forEach((handle) => {\n // When resizing, only show the active handle\n if (isResizing && activeResizeHandle) {\n if (handle.anchor !== activeResizeHandle.anchor) {\n return; // Skip non-active handles\n }\n }\n\n const isHovered = !!(hoveredResizeHandle && hoveredResizeHandle.anchor === handle.anchor);\n const isActive = !!(isResizing && activeResizeHandle && activeResizeHandle.anchor === handle.anchor);\n this.renderResizeHandle(ctx, handle, isHovered, isActive, zoom);\n });\n\n // Render rotation handle only if using canvas rendering (not React component)\n if (renderRotationInCanvas && showRotationHandle && this.rotationHandle && !isRotating && !isResizing) {\n this.renderRotationHandle(ctx, this.rotationHandle, isHoveringRotation, zoom);\n }\n\n // Show tooltip with angle when rotating (only if using canvas rendering)\n if (renderRotationInCanvas && showRotationHandle && this.rotationHandle && isRotating) {\n this.renderRotationTooltip(ctx, this.rotationHandle, rotationAngle, zoom);\n }\n }\n\n /**\n * Render a single resize handle\n * Corner handles are circles, side handles are rounded rectangles\n */\n renderResizeHandle(\n ctx: CanvasRenderingContext2D,\n handle: HandleInfo,\n isHovered: boolean = false,\n isActive: boolean = false,\n zoom: number = 1.0\n ): void {\n ctx.save();\n\n // Scale handle position by zoom (convert world to screen coordinates)\n const handleX = handle.x * zoom;\n const handleY = handle.y * zoom;\n\n // Check if this is a side handle (middle-left, middle-right, etc.)\n const isSideHandle = handle.anchor.includes('middle');\n\n if (isSideHandle) {\n // Determine if this is a top/bottom or left/right handle\n const isTopBottom = handle.anchor === 'middle-top' || handle.anchor === 'middle-bottom';\n\n // Rotate side handles to align with element rotation\n ctx.translate(handleX, handleY);\n // Use negative angle for clockwise rotation (matching UI convention)\n ctx.rotate((-this.elementRotation * Math.PI) / 180);\n\n // For top/bottom handles, rotate an additional 90 degrees\n if (isTopBottom) {\n ctx.rotate(Math.PI / 2);\n }\n\n ctx.translate(-handleX, -handleY);\n\n // Draw rounded rectangle for side handles (taller than wide)\n const width = HANDLE_SIZE * 0.6; // Narrower\n const height = HANDLE_SIZE * 1.4; // Taller\n const radius = width / 2; // Fully rounded top and bottom (pill shape)\n const x = handleX - width / 2;\n const y = handleY - height / 2;\n\n // White fill with theme accent border\n ctx.fillStyle = '#fff';\n ctx.strokeStyle = getThemeAccentColor(ctx.canvas);\n ctx.lineWidth = isHovered || isActive ? 2.5 : 2;\n\n ctx.beginPath();\n ctx.roundRect(x, y, width, height, radius);\n ctx.fill();\n ctx.stroke();\n } else {\n // White fill with theme accent border\n ctx.fillStyle = '#fff';\n ctx.strokeStyle = getThemeAccentColor(ctx.canvas);\n ctx.lineWidth = isHovered || isActive ? 2.5 : 2;\n\n // Draw circle for corner handles - use shared constant for consistency\n ctx.beginPath();\n ctx.arc(handleX, handleY, BASE_HANDLE_RADIUS, 0, Math.PI * 2);\n ctx.fill();\n ctx.stroke();\n }\n\n ctx.restore();\n }\n\n /**\n * Render the rotation handle (with refresh-ccw icon)\n * Works in screen space (positions multiplied by zoom, fixed pixel sizes)\n */\n renderRotationHandle(ctx: CanvasRenderingContext2D, handle: Point, isHovering: boolean = false, zoom: number = 1.0): void {\n ctx.save();\n\n // Scale handle position by zoom (convert world to screen coordinates)\n const handleX = handle.x * zoom;\n const handleY = handle.y * zoom;\n\n const visualRadius = BASE_HANDLE_RADIUS * 2.67; // 16px for rotation handle\n\n // Circle background - white fill with theme accent border\n ctx.fillStyle = '#fff';\n ctx.strokeStyle = getThemeAccentColor(ctx.canvas);\n ctx.lineWidth = isHovering ? 2.5 : 2;\n\n ctx.beginPath();\n ctx.arc(handleX, handleY, visualRadius, 0, Math.PI * 2);\n ctx.fill();\n ctx.stroke();\n\n // Draw refresh-ccw icon (Lucide icon)\n const scale = ROTATION_ICON_SCALE;\n ctx.translate(handleX, handleY);\n ctx.scale(scale, scale);\n\n ctx.strokeStyle = '#000';\n ctx.lineWidth = 1.5; // Consistent line width for clean appearance\n ctx.lineCap = 'round';\n ctx.lineJoin = 'round';\n\n // Center the icon (24x24 viewBox)\n ctx.translate(-12, -12);\n\n // Path 1: M21 12a9 9 0 0 0-9-9 9.75 9.75 0 0 0-6.74 2.74L3 8\n ctx.beginPath();\n ctx.moveTo(21, 12);\n ctx.arc(12, 12, 9, 0, -Math.PI / 2, true);\n ctx.bezierCurveTo(3.5, 4.5, 4, 6, 3, 8);\n ctx.stroke();\n\n // Path 2: M3 3v5h5 (arrow at top-left)\n ctx.beginPath();\n ctx.moveTo(3, 3);\n ctx.lineTo(3, 8);\n ctx.lineTo(8, 8);\n ctx.stroke();\n\n // Path 3: M3 12a9 9 0 0 0 9 9 9.75 9.75 0 0 0 6.74-2.74L21 16\n ctx.beginPath();\n ctx.moveTo(3, 12);\n ctx.arc(12, 12, 9, Math.PI, Math.PI / 2, true);\n ctx.bezierCurveTo(20.5, 19.5, 20, 18, 21, 16);\n ctx.stroke();\n\n // Path 4: M16 16h5v5 (arrow at bottom-right)\n ctx.beginPath();\n ctx.moveTo(16, 16);\n ctx.lineTo(21, 16);\n ctx.lineTo(21, 21);\n ctx.stroke();\n\n ctx.restore();\n }\n\n /**\n * Render rotation tooltip (angle display while rotating)\n */\n renderRotationTooltip(ctx: CanvasRenderingContext2D, handle: Point, angle: number, zoom: number = 1.0): void {\n ctx.save();\n\n const angleText = `${Math.round(angle)}°`;\n const tooltipWidth = angleText.length * 8 + 12;\n const tooltipHeight = 22;\n // Scale handle position by zoom (convert world to screen coordinates)\n const tooltipX = handle.x * zoom;\n const tooltipY = handle.y * zoom - 35;\n\n // Shadow\n ctx.shadowColor = 'rgba(0,0,0,0.3)';\n ctx.shadowBlur = 3;\n ctx.shadowOffsetY = 1;\n\n // Background\n ctx.fillStyle = '#333';\n ctx.beginPath();\n ctx.roundRect(tooltipX - tooltipWidth / 2, tooltipY, tooltipWidth, tooltipHeight, 3);\n ctx.fill();\n\n // Reset shadow\n ctx.shadowColor = 'transparent';\n ctx.shadowBlur = 0;\n ctx.shadowOffsetY = 0;\n\n // Text\n ctx.fillStyle = '#fff';\n ctx.font = '12px Arial';\n ctx.textAlign = 'center';\n ctx.textBaseline = 'middle';\n ctx.fillText(angleText, tooltipX, tooltipY + tooltipHeight / 2);\n\n ctx.restore();\n }\n\n /**\n * Test if a point hits any resize handle\n * @param zoom - Current zoom level (radius scales inversely with zoom)\n */\n hitTestResize(x: number, y: number, zoom: number = 1.0): HandleInfo | null {\n // Hit test radius needs to scale inversely with zoom\n // Use larger CORNER_HANDLE_HIT_RADIUS for comfortable touch interaction\n const radius = CORNER_HANDLE_HIT_RADIUS / zoom;\n\n for (const handle of this.resizeHandles) {\n if (hitTestCircle(x, y, handle.x, handle.y, radius)) {\n return handle;\n }\n }\n return null;\n }\n\n /**\n * Test if a point hits the rotation handle\n * @param zoom - Current zoom level (radius scales inversely with zoom)\n */\n hitTestRotation(x: number, y: number, zoom: number = 1.0): boolean {\n if (!this.rotationHandle) return false;\n // Hit test radius needs to scale inversely with zoom\n const radius = (BASE_HANDLE_RADIUS * 2.67 + 2) / zoom; // 16px + 2px padding\n return hitTestCircle(x, y, this.rotationHandle.x, this.rotationHandle.y, radius);\n }\n\n /**\n * Get rotation handle position (for React-based rendering)\n */\n getRotationHandlePosition(): Point | null {\n return this.rotationHandle;\n }\n\n /**\n * Get cursor style for a resize handle, adjusted for the element's current rotation.\n * @param handle - The resize handle to get cursor for\n * @param rotation - Element rotation in degrees\n */\n getCursor(handle: HandleInfo, rotation: number): string {\n const handleType = handle.anchor.includes('middle') ? 'edge' : 'corner';\n return getCursorForWorldPosition(\n handle.x,\n handle.y,\n this.rotationAnchor.x,\n this.rotationAnchor.y,\n handleType,\n rotation,\n handle.anchor\n );\n }\n}\n\nexport default TransformHandles;\n","/**\n * ResizeHandler - Encapsulates complex resize logic\n * Handles fixed-corner resize with rotation for all transform types\n */\n\nimport { Transform } from './Transform.js';\nimport type { ImageElement } from './ImageElement.js';\nimport type { TextElement } from './TextElement.js';\nimport type { Point, ResizeAnchor, TransformStartData } from '../types/index.js';\n\ninterface HandleInfo {\n anchor: ResizeAnchor;\n type?: string;\n cursor?: string;\n x?: number;\n y?: number;\n}\n\nexport class ResizeHandler {\n /**\n * Calculate new dimensions and position for a resize operation\n */\n static calculateResize({\n element,\n handle,\n dx,\n dy,\n startData,\n snapSystem,\n }: {\n element: TextElement;\n handle: HandleInfo;\n dx: number;\n dy: number;\n startData: TransformStartData;\n snapSystem?: { activeSnaps?: { x?: unknown; y?: unknown } } | null;\n }): { element: TextElement; isFrozen?: boolean; unfrozenDimensions?: { width: number; height: number } } {\n // Transform delta to local coordinates (inverse transform: world → local)\n const transform = new Transform(element);\n const localDelta = transform.worldDeltaToLocal(dx, dy);\n const localDx = localDelta.dx;\n const localDy = localDelta.dy;\n\n // Use visual bbox dimensions since handles are positioned there\n const startVisualWidth = startData.visualWidth ?? startData.width ?? 0;\n const startVisualHeight = startData.visualHeight ?? startData.height ?? 0;\n const startBboxWidth = startData.width ?? 0;\n const startBboxHeight = startData.height ?? 0;\n\n let newVisualWidth = startVisualWidth;\n let newVisualHeight = startVisualHeight;\n\n // Calculate new visual dimensions based on which handle is being dragged\n // For corner handles, ONLY use the perpendicular axis to that edge\n if (handle.anchor.includes('right')) {\n // Right side: only use local X-axis movement\n newVisualWidth = startVisualWidth + localDx;\n } else if (handle.anchor.includes('left')) {\n // Left side: only use local X-axis movement (inverted)\n newVisualWidth = startVisualWidth - localDx;\n }\n\n // Only update height for handles that should change height (not horizontal side handles)\n // For corner handles, ONLY use the perpendicular axis to that edge\n if (handle.anchor !== 'middle-left' && handle.anchor !== 'middle-right') {\n if (handle.anchor.includes('bottom')) {\n // Bottom side: only use local Y-axis movement\n newVisualHeight = startVisualHeight + localDy;\n } else if (handle.anchor.includes('top')) {\n // Top side: only use local Y-axis movement (inverted)\n newVisualHeight = startVisualHeight - localDy;\n }\n }\n\n // Calculate new dimensions based on handle type\n let newWidth, newHeight;\n\n // Special handling for side handles: use direct drag distance instead of scale\n // This is critical because visual bbox != actual bbox for elements with transformData.width\n if (handle.anchor === 'middle-left' || handle.anchor === 'middle-right') {\n // For horizontal side handles: apply width change directly to bbox width\n const widthChange = newVisualWidth - startVisualWidth;\n newWidth = startBboxWidth + widthChange;\n newHeight = startBboxHeight; // Keep original bbox height\n } else if (handle.anchor === 'middle-top' || handle.anchor === 'middle-bottom') {\n // For vertical side handles: apply height change directly to bbox height\n const heightChange = newVisualHeight - startVisualHeight;\n newWidth = startBboxWidth; // Keep original bbox width\n newHeight = startBboxHeight + heightChange;\n } else {\n // For corner handles: use scale factors\n const scaleX = newVisualWidth / startVisualWidth;\n const scaleY = newVisualHeight / startVisualHeight;\n newWidth = startBboxWidth * scaleX;\n newHeight = startBboxHeight * scaleY;\n }\n\n // Save unfrozen dimensions BEFORE applying freeze\n const unfrozenVisualWidth = newVisualWidth;\n const unfrozenVisualHeight = newVisualHeight;\n\n // Freeze dimensions for images when sticky snap is active to maintain aspect ratio\n let freezeApplied = false;\n if (snapSystem && element.transformType === 'image') {\n const anchor = handle.anchor ?? '';\n const isCornerResizeHandle =\n anchor === 'top-left' || anchor === 'top-right' || anchor === 'bottom-left' || anchor === 'bottom-right';\n const isCropHandle = anchor.startsWith('crop-');\n\n if (isCornerResizeHandle && !isCropHandle) {\n const snapX = snapSystem.activeSnaps?.x;\n const snapY = snapSystem.activeSnaps?.y;\n const hasActiveSnap = Boolean(snapX) || Boolean(snapY);\n\n if (hasActiveSnap) {\n const frozenState = [snapX, snapY].find((state): state is { frozenWidth?: number; frozenHeight?: number } =>\n typeof state === 'object' && state !== null && 'frozenWidth' in state\n );\n\n if (frozenState) {\n const imageElement = element as unknown as ImageElement;\n const imageStartTransform = startData.transformData as unknown as ImageElement['transformData'] | undefined;\n\n const targetWidth = frozenState.frozenWidth ?? imageElement.transformData?.width ?? startBboxWidth;\n\n const aspectRatio =\n imageElement.imageAspectRatio ||\n (imageStartTransform?.width && imageStartTransform?.height\n ? imageStartTransform.width / imageStartTransform.height\n : null);\n\n let targetHeight = frozenState.frozenHeight;\n if (targetHeight === undefined || targetHeight === null) {\n if (aspectRatio && aspectRatio !== 0) {\n targetHeight = targetWidth / aspectRatio;\n } else if (imageElement.transformData?.height) {\n targetHeight = imageElement.transformData.height;\n } else {\n targetHeight = startBboxHeight;\n }\n }\n\n const widthScaleFromStart = startBboxWidth !== 0 ? targetWidth / startBboxWidth : 1;\n const heightScaleFromStart = startBboxHeight !== 0 ? targetHeight / startBboxHeight : 1;\n\n newVisualWidth = startVisualWidth * widthScaleFromStart;\n newVisualHeight = startVisualHeight * heightScaleFromStart;\n\n newWidth = targetWidth;\n newHeight = targetHeight;\n freezeApplied = true;\n }\n }\n }\n }\n\n // Clamp to minimum sizes\n newWidth = Math.max(50, newWidth);\n newHeight = Math.max(40, newHeight);\n\n // Clone the element for updates\n const updatedElement = element.clone();\n\n\n // Apply the resize to the element\n // For ImageElement in crop mode, this returns false if resize is frozen at bounds\n const resizeApplied = updatedElement.resize(handle.anchor, newWidth, newHeight, startData);\n\n // Scale stroke width proportionally for corner resizes (all element types)\n // Side handles don't scale stroke — only changing one axis shouldn't affect uniform stroke width\n const isCorner = !handle.anchor.includes('middle');\n if (isCorner && updatedElement.stroke?.enabled && startData.strokeWidth !== undefined && startData.strokeWidth > 0) {\n const startW = startData.width ?? 1;\n const startH = startData.height ?? 1;\n // Geometric mean: standard for scaling a 1D property under 2D transformation\n // Avoids the upward bias of arithmetic mean on asymmetric resizes\n const strokeScale = Math.sqrt((newWidth / startW) * (newHeight / startH));\n // Round to tenths to minimize drift across multiple resize operations\n const scaledStrokeWidth = Math.max(1, Math.round(startData.strokeWidth * strokeScale * 10) / 10);\n updatedElement.stroke = { ...updatedElement.stroke, width: scaledStrokeWidth };\n }\n\n const isFrozen = freezeApplied || resizeApplied === false;\n\n // Calculate fixed corner position adjustment (only for corner handles)\n // Side handles are handled by the element's resize() method\n // Skip position adjustment for images in crop mode and groups - they handle positioning internally\n const isCornerHandle = handle.anchor.includes('top') || handle.anchor.includes('bottom');\n const isCroppingImage = 'isCropping' in updatedElement && updatedElement.isCropping;\n const isGroup = 'isGroup' in updatedElement && updatedElement.isGroup;\n if (isCornerHandle && !isCroppingImage && !isGroup) {\n const rotationAnchor = element.getRotationAnchor();\n const positionOffset = this._calculateFixedCornerOffset({\n element,\n updatedElement,\n handle,\n rotationAnchor,\n });\n\n // Apply position adjustment\n updatedElement.x += positionOffset.x;\n updatedElement.y += positionOffset.y;\n }\n\n return {\n element: updatedElement,\n isFrozen,\n // For snap system to detect break-free: dimensions before freeze was applied\n unfrozenDimensions: freezeApplied ? { width: unfrozenVisualWidth, height: unfrozenVisualHeight } : undefined,\n };\n }\n\n /**\n * Calculate position offset to keep opposite corner fixed\n * Uses visual bounding box and rotation anchor for proper rotated resize\n * @private\n */\n static _calculateFixedCornerOffset({\n element,\n updatedElement,\n handle,\n rotationAnchor,\n }: {\n element: TextElement;\n updatedElement: TextElement;\n handle: HandleInfo;\n rotationAnchor: Point;\n }): Point {\n // Create transforms for both the start and updated elements\n const startTransform = new Transform(element);\n\n // Get precomputed cos/sin for forward transform (local → world)\n const { cos: cosRot, sin: sinRot } = startTransform.getRenderingCosSin();\n\n // Use VISUAL BOUNDING BOX dimensions for fixed corner calculations\n //\n // Critical: Handles are positioned at getVisualBoundingBox() corners (see TransformHandles.js:41)\n // We MUST use the same bbox here to ensure the math aligns correctly. If we used getBoundingBox()\n // instead, there would be a mismatch when visual bbox != actual bbox (e.g., multi-line text),\n // causing the corner to slip away from the mouse cursor during resize.\n const startBbox = element.getVisualBoundingBox();\n const newBbox = updatedElement.getVisualBoundingBox();\n\n // Get rotation anchors (center points around which rotation happens)\n const startRotationAnchor = rotationAnchor; // Passed in from before resize\n const newRotationAnchor = updatedElement.getRotationAnchor();\n\n // Determine which corner should stay fixed (in local coords)\n const fixedLocal = this._getFixedLocalCoords(handle.anchor, startBbox.width, startBbox.height);\n\n // Calculate the fixed corner's position in world coordinates\n // Step 1: Position relative to bbox top-left\n const localX = fixedLocal.x;\n const localY = fixedLocal.y;\n\n // Step 2: Bbox position relative to rotation anchor\n const bboxOffsetX = startBbox.x - startRotationAnchor.x;\n const bboxOffsetY = startBbox.y - startRotationAnchor.y;\n\n // Step 3: Corner position relative to rotation anchor (in local space)\n const cornerRelX = bboxOffsetX + localX;\n const cornerRelY = bboxOffsetY + localY;\n\n // Step 4: Rotate this position around rotation anchor\n const rotatedX = cornerRelX * cosRot - cornerRelY * sinRot;\n const rotatedY = cornerRelX * sinRot + cornerRelY * cosRot;\n\n // Step 5: Transform to world coordinates\n const fixedWorldX = startRotationAnchor.x + rotatedX;\n const fixedWorldY = startRotationAnchor.y + rotatedY;\n\n // Now calculate where that corner is after resize\n const newFixedLocal = this._getFixedLocalCoords(handle.anchor, newBbox.width, newBbox.height);\n\n // Repeat the process with new dimensions\n const newLocalX = newFixedLocal.x;\n const newLocalY = newFixedLocal.y;\n\n const newBboxOffsetX = newBbox.x - newRotationAnchor.x;\n const newBboxOffsetY = newBbox.y - newRotationAnchor.y;\n\n const newCornerRelX = newBboxOffsetX + newLocalX;\n const newCornerRelY = newBboxOffsetY + newLocalY;\n\n const newRotatedX = newCornerRelX * cosRot - newCornerRelY * sinRot;\n const newRotatedY = newCornerRelX * sinRot + newCornerRelY * cosRot;\n\n const currentFixedWorldX = newRotationAnchor.x + newRotatedX;\n const currentFixedWorldY = newRotationAnchor.y + newRotatedY;\n\n // Return offset to keep fixed corner in place\n return {\n x: fixedWorldX - currentFixedWorldX,\n y: fixedWorldY - currentFixedWorldY,\n };\n }\n\n /**\n * Get local coordinates of the fixed point for a given handle\n * @private\n */\n static _getFixedLocalCoords(anchor: ResizeAnchor, width: number, height: number): Point {\n const coords = { x: 0, y: 0 };\n\n switch (anchor) {\n case 'top-left':\n coords.x = width;\n coords.y = height;\n break;\n case 'top-right':\n coords.x = 0;\n coords.y = height;\n break;\n case 'bottom-left':\n coords.x = width;\n coords.y = 0;\n break;\n case 'bottom-right':\n coords.x = 0;\n coords.y = 0;\n break;\n case 'middle-left':\n coords.x = width;\n coords.y = height / 2;\n break;\n case 'middle-right':\n coords.x = 0;\n coords.y = height / 2;\n break;\n case 'middle-top':\n coords.x = width / 2;\n coords.y = height;\n break;\n case 'middle-bottom':\n coords.x = width / 2;\n coords.y = 0;\n break;\n }\n\n return coords;\n }\n}\n\nexport default ResizeHandler;\n","/**\n * ResizePipeline - Unified resize pipeline with hook points\n *\n * Provides a single entry point for resize operations with\n * hooks for snapping and other modifications.\n */\n\nimport { ResizeHandler } from './ResizeHandler.js';\nimport type { BaseElement } from './BaseElement.js';\nimport type { TextElement } from './TextElement.js';\nimport type { TransformStartData, ResizeAnchor } from '../types/index.js';\n\ntype HookStage = 'beforeResize' | 'afterResize' | 'beforePositionUpdate' | 'afterPositionUpdate';\n\ninterface HandleInfo {\n anchor: ResizeAnchor;\n type?: string;\n cursor?: string;\n x?: number;\n y?: number;\n}\n\ninterface ResizeParams {\n element: TextElement;\n handle: HandleInfo;\n dx: number;\n dy: number;\n startData: TransformStartData;\n allElements?: BaseElement[] | null;\n snapSystem?: { activeSnaps?: { x?: unknown; y?: unknown } } | null;\n}\n\ninterface ResizeResult {\n element: TextElement;\n isFrozen?: boolean;\n unfrozenDimensions?: { width: number; height: number };\n handle?: HandleInfo;\n startData?: TransformStartData;\n}\n\ninterface PositionUpdateData {\n position: { x: number; y: number };\n element: BaseElement;\n}\n\ntype HookFn<T> = (data: T) => T | undefined;\n\nexport class ResizePipeline {\n hooks: Record<HookStage, HookFn<unknown>[]>;\n\n constructor() {\n this.hooks = {\n beforeResize: [],\n afterResize: [],\n beforePositionUpdate: [],\n afterPositionUpdate: [],\n };\n }\n\n /**\n * Add a hook at a specific stage\n * @param stage - 'beforeResize', 'afterResize', 'beforePositionUpdate', 'afterPositionUpdate'\n * @param fn - Hook function\n */\n addHook(stage: HookStage, fn: HookFn<unknown>): void {\n if (!this.hooks[stage]) {\n throw new Error(`Invalid hook stage: ${stage}`);\n }\n this.hooks[stage].push(fn);\n }\n\n /**\n * Remove a hook\n */\n removeHook(stage: HookStage, fn: HookFn<unknown>): void {\n if (!this.hooks[stage]) return;\n const index = this.hooks[stage].indexOf(fn);\n if (index !== -1) {\n this.hooks[stage].splice(index, 1);\n }\n }\n\n /**\n * Clear all hooks at a stage\n */\n clearHooks(stage: HookStage): void {\n if (!this.hooks[stage]) return;\n this.hooks[stage] = [];\n }\n\n /**\n * Clear all hooks\n */\n clearAllHooks(): void {\n (Object.keys(this.hooks) as HookStage[]).forEach((stage) => {\n this.hooks[stage] = [];\n });\n }\n\n /**\n * Run hooks at a specific stage\n */\n runHooks<T>(stage: HookStage, data: T): T {\n if (!this.hooks[stage]) return data;\n\n return this.hooks[stage].reduce((acc: T, fn: HookFn<unknown>) => {\n const result = fn(acc);\n return result !== undefined ? (result as T) : acc;\n }, data);\n }\n\n /**\n * Execute resize with hooks\n */\n executeResize(params: ResizeParams): ResizeResult {\n\n // Run before hooks\n const beforeParams = this.runHooks('beforeResize', params);\n\n\n // Calculate new dimensions using ResizeHandler\n // Pass snapSystem so it can check for frozen dimensions\n let result: ResizeResult = ResizeHandler.calculateResize({\n ...beforeParams,\n snapSystem: params.snapSystem,\n });\n\n\n // Pass handle info and startData to afterResize hooks (needed for snapping)\n result.handle = params.handle;\n result.startData = params.startData;\n\n // Run after resize hooks (SNAPPING ADJUSTS ELEMENT HERE)\n result = this.runHooks('afterResize', result);\n\n return result;\n }\n\n /**\n * Execute position update with hooks\n * Used for drag operations\n */\n executePositionUpdate(position: { x: number; y: number }, element: BaseElement): { x: number; y: number } {\n // Run before hooks\n const beforeData = this.runHooks<PositionUpdateData>('beforePositionUpdate', { position, element });\n\n // Run after hooks (SNAPPING GOES HERE)\n const afterData = this.runHooks<PositionUpdateData>('afterPositionUpdate', beforeData);\n\n return afterData.position;\n }\n}\n\n/**\n * Singleton instance for the application\n * This allows hooking into resize operations globally\n */\nexport const globalResizePipeline = new ResizePipeline();\n","/**\n * InteractionStateMachine - Manages canvas interaction states\n *\n * Provides clean state transitions for drag/resize/rotate operations\n * and injection points for snapping functionality.\n */\n\nimport { calculateAngle } from './GeometryUtils.js';\nimport type { BaseElement } from './BaseElement.js';\nimport type { GroupElement } from './GroupElement.js';\nimport type { CustomTransform } from '../transforms/CustomTransform.js';\nimport type { ResizePipeline } from './ResizePipeline.js';\nimport type { ResizeAnchor, BoundingBox, Point, InteractionMode, ImageTransformData, TransformStartData } from '../types/index.js';\n\ntype State = 'IDLE' | 'DRAGGING' | 'RESIZING' | 'ROTATING' | 'PINCHING';\n\ninterface HandleInfo {\n anchor: ResizeAnchor;\n type?: string;\n cursor?: string;\n x?: number;\n y?: number;\n}\n\ninterface RotationStartData {\n startAngle: number;\n currentRotation: number;\n elementData: TransformStartData;\n}\n\ninterface PinchStartData {\n /** Snapshot of the element's transform at gesture start. */\n elementData: TransformStartData;\n /** Midpoint of the two pointers in world coords at gesture start. */\n startCentroid: Point;\n /** Distance between the two pointers at gesture start, in world units. */\n startDistance: number;\n /** Angle of the vector from p1 → p2 at gesture start, in radians. */\n startAngle: number;\n}\n\n/**\n * Output of `updatePinch` — the raw gesture state. PinchHandler\n * consumes this together with the element snapshot in\n * `getPinchContext()` to produce the next element.\n */\nexport interface PinchGesture {\n /** Distance ratio (current / start). 1.0 = no scale change. */\n scale: number;\n /** Angle delta in radians (current - start). 0 = no rotate change. */\n rotationDelta: number;\n /** Gesture centroid at start (world coords). */\n startCentroid: Point;\n /** Gesture centroid right now (world coords). */\n currentCentroid: Point;\n}\n\ninterface InteractionContextData {\n mode: InteractionMode | null;\n dragMode?: string | null;\n startX: number;\n startY: number;\n startData: TransformStartData | RotationStartData | null;\n activeHandle: HandleInfo | null;\n element: BaseElement | null;\n}\n\ninterface SnapHandler {\n snapPosition?: (position: Point, element: BaseElement, allElements: BaseElement[] | null) => Point;\n snapRotation?: (rotation: number, element: BaseElement) => number;\n}\n\nexport interface ActiveChildContext {\n group: GroupElement;\n childId: string;\n}\n\nexport interface CropGroupContext {\n group: BaseElement;\n childIndex: number;\n}\n\nexport class InteractionStateMachine {\n state: State;\n context: InteractionContextData;\n snapHandler: SnapHandler | null;\n resizePipeline: ResizePipeline | null;\n /** Context for interactions targeting a child within a group */\n _activeChildContext?: ActiveChildContext;\n /** Context for crop mode interactions on group children */\n _cropGroupContext?: CropGroupContext;\n\n constructor(resizePipeline: ResizePipeline | null = null) {\n this.state = 'IDLE';\n this.context = {\n mode: null,\n startX: 0,\n startY: 0,\n startData: null,\n activeHandle: null,\n element: null,\n };\n\n // Hook for snapping logic\n this.snapHandler = null;\n\n // Resize pipeline for hooking into resize operations\n this.resizePipeline = resizePipeline;\n }\n\n /**\n * Set snap handler for position/dimension snapping\n */\n setSnapHandler(handler: SnapHandler | null): void {\n this.snapHandler = handler;\n }\n\n /**\n * Set resize pipeline for hooking into resize operations\n */\n setResizePipeline(pipeline: ResizePipeline | null): void {\n this.resizePipeline = pipeline;\n }\n\n /**\n * Get current state\n */\n getState(): State {\n return this.state;\n }\n\n /**\n * Get current context\n */\n getContext(): InteractionContextData {\n return this.context;\n }\n\n /**\n * Check if currently interacting\n */\n isInteracting(): boolean {\n return this.state !== 'IDLE';\n }\n\n /**\n * Start drag operation\n */\n startDrag(element: BaseElement, mouseX: number, mouseY: number, dragMode: string | null = null): void {\n this.state = 'DRAGGING';\n\n // Get base start data\n const baseStartData = element.getTransformStartData();\n\n // For crop image drag, also store crop values\n let startData: TransformStartData = baseStartData;\n if (dragMode === 'crop-image-drag' && element.transformData) {\n const imageTransformData = element.transformData as ImageTransformData;\n startData = {\n ...baseStartData,\n cropX: imageTransformData.cropX,\n cropY: imageTransformData.cropY,\n cropWidth: imageTransformData.cropWidth,\n cropHeight: imageTransformData.cropHeight,\n };\n }\n\n this.context = {\n mode: 'drag',\n dragMode: dragMode, // 'crop-image-drag' for moving image within crop, null for normal drag\n startX: mouseX,\n startY: mouseY,\n startData: startData,\n activeHandle: null,\n element: element,\n };\n }\n\n /**\n * Get drag mode\n */\n getDragMode(): string | null | undefined {\n return this.context.dragMode;\n }\n\n /**\n * Reset drag start position (for incremental dragging)\n */\n resetDragStart(mouseX: number, mouseY: number): void {\n if (this.state !== 'DRAGGING') return;\n this.context.startX = mouseX;\n this.context.startY = mouseY;\n }\n\n /**\n * Update drag operation\n * Returns updated position { x, y }\n */\n updateDrag(mouseX: number, mouseY: number, allElements: BaseElement[] | null = null): Point {\n if (this.state !== 'DRAGGING') {\n throw new Error('Cannot update drag: not in DRAGGING state');\n }\n\n const dx = mouseX - this.context.startX;\n const dy = mouseY - this.context.startY;\n\n const dragStartData = this.context.startData as TransformStartData;\n let newX = dragStartData.x + dx;\n let newY = dragStartData.y + dy;\n\n // Apply snapping if handler is set\n if (this.snapHandler && this.snapHandler.snapPosition && this.context.element) {\n const snapped = this.snapHandler.snapPosition({ x: newX, y: newY }, this.context.element, allElements);\n newX = snapped.x;\n newY = snapped.y;\n }\n\n return { x: newX, y: newY };\n }\n\n /**\n * Start resize operation\n */\n startResize(\n element: BaseElement,\n handle: HandleInfo,\n mouseX: number,\n mouseY: number,\n bbox: BoundingBox,\n visualBbox: BoundingBox\n ): void {\n this.state = 'RESIZING';\n const startData = element.getTransformStartData();\n\n // Clone the element and set lock on the CLONE to avoid visual jump\n // This prevents modifying the element in the main elements array before drag starts\n const elementForResize = element.clone();\n const isCornerHandle =\n handle.anchor === 'top-left' ||\n handle.anchor === 'top-right' ||\n handle.anchor === 'bottom-left' ||\n handle.anchor === 'bottom-right';\n if (isCornerHandle && startData.lineCount !== undefined && elementForResize.transformType === 'custom') {\n (elementForResize as CustomTransform)._lockedLineCount = startData.lineCount;\n }\n\n this.context = {\n mode: 'resize',\n startX: mouseX,\n startY: mouseY,\n startData: {\n ...startData,\n visualX: visualBbox.x,\n visualY: visualBbox.y,\n visualWidth: visualBbox.width,\n visualHeight: visualBbox.height,\n bboxX: bbox.x,\n bboxY: bbox.y,\n },\n activeHandle: handle,\n element: elementForResize, // Use the cloned element with lock already set\n };\n }\n\n /**\n * Update resize operation\n * Returns { dx, dy } deltas\n */\n updateResize(mouseX: number, mouseY: number): { dx: number; dy: number } {\n if (this.state !== 'RESIZING') {\n throw new Error('Cannot update resize: not in RESIZING state');\n }\n\n const dx = mouseX - this.context.startX;\n const dy = mouseY - this.context.startY;\n\n return { dx, dy };\n }\n\n /**\n * Adjust the resize start position to account for snap corrections\n * This prevents dx/dy from accumulating when a snap is locked\n */\n adjustResizeStart(deltaX: number, deltaY: number): void {\n if (this.state !== 'RESIZING') {\n return;\n }\n\n // Adjust the start position by the snap correction amount\n // This way, future dx/dy calculations will account for the snap\n this.context.startX += deltaX;\n this.context.startY += deltaY;\n }\n\n /**\n * Get resize context for ResizeHandler\n */\n getResizeContext(): { element: BaseElement; handle: HandleInfo; startData: TransformStartData } {\n if (this.state !== 'RESIZING') {\n throw new Error('Cannot get resize context: not in RESIZING state');\n }\n\n return {\n element: this.context.element!,\n handle: this.context.activeHandle!,\n startData: this.context.startData as TransformStartData,\n };\n }\n\n /**\n * Update the element in resize context (to preserve state between frames)\n * This is critical for ImageElement crop mode where _lastValidCropState needs to persist\n */\n updateResizeElement(element: BaseElement): void {\n if (this.state !== 'RESIZING') {\n return;\n }\n this.context.element = element;\n }\n\n /**\n * Reset resize start data to current element state (for unfreezing)\n * This updates startData to use the current element dimensions, preventing jumps\n */\n resetResizeStartData(element: BaseElement, mouseX: number, mouseY: number): void {\n if (this.state !== 'RESIZING') {\n return;\n }\n\n const bbox = element.getBoundingBox();\n const visualBbox = element.getVisualBoundingBox();\n const startData = element.getTransformStartData();\n\n // Update the context with new start data based on current element state\n this.context.startX = mouseX;\n this.context.startY = mouseY;\n this.context.startData = {\n ...startData,\n visualX: visualBbox.x,\n visualY: visualBbox.y,\n visualWidth: visualBbox.width,\n visualHeight: visualBbox.height,\n bboxX: bbox.x,\n bboxY: bbox.y,\n };\n\n }\n\n /**\n * Start rotation operation\n */\n startRotate(element: BaseElement, mouseX: number, mouseY: number, startAngle: number, currentRotation: number): void {\n this.state = 'ROTATING';\n this.context = {\n mode: 'rotate',\n startX: mouseX,\n startY: mouseY,\n startData: {\n startAngle: startAngle,\n currentRotation: currentRotation,\n elementData: element.getTransformStartData(),\n },\n activeHandle: null,\n element: element,\n };\n }\n\n /**\n * Update rotation operation\n * Returns updated rotation angle in degrees\n */\n updateRotate(mouseX: number, mouseY: number, centerX: number, centerY: number): number {\n if (this.state !== 'ROTATING') {\n throw new Error('Cannot update rotate: not in ROTATING state');\n }\n\n const rotStartData = this.context.startData as RotationStartData;\n const angle = calculateAngle(centerX, centerY, mouseX, mouseY);\n const rotationDelta = ((angle - rotStartData.startAngle) * 180) / Math.PI;\n\n // Negate delta so: dragging right (clockwise) = negative rotation, left (counterclockwise) = positive\n let newRotation = rotStartData.currentRotation - rotationDelta;\n\n // Normalize to -180 to +180 range\n // First normalize to 0-360, then shift to -180 to +180\n newRotation = ((newRotation % 360) + 360) % 360;\n if (newRotation > 180) {\n newRotation -= 360;\n }\n\n // Apply rotation snapping if handler is set\n if (this.snapHandler && this.snapHandler.snapRotation && this.context.element) {\n return this.snapHandler.snapRotation(newRotation, this.context.element);\n }\n\n return newRotation;\n }\n\n /**\n * Get rotation context\n */\n getRotationContext(): { startAngle: number; currentRotation: number } {\n if (this.state !== 'ROTATING') {\n throw new Error('Cannot get rotation context: not in ROTATING state');\n }\n\n const rotStartData = this.context.startData as RotationStartData;\n return {\n startAngle: rotStartData.startAngle,\n currentRotation: rotStartData.currentRotation,\n };\n }\n\n /**\n * Start a two-finger pinch gesture on `element`. Captures the\n * gesture's start centroid / distance / angle and the element's\n * full transform snapshot — `updatePinch` then derives the\n * gesture's scale + rotation delta against this snapshot every\n * frame. PinchHandler consumes both via `getPinchContext()` to\n * produce the next element.\n */\n startPinch(element: BaseElement, p1: Point, p2: Point): void {\n this.state = 'PINCHING';\n\n const startCentroid: Point = {\n x: (p1.x + p2.x) / 2,\n y: (p1.y + p2.y) / 2,\n };\n const dx = p2.x - p1.x;\n const dy = p2.y - p1.y;\n const startDistance = Math.hypot(dx, dy);\n const startAngle = Math.atan2(dy, dx);\n\n const startData: PinchStartData = {\n elementData: element.getTransformStartData(),\n startCentroid,\n startDistance,\n startAngle,\n };\n\n this.context = {\n mode: 'pinch',\n startX: startCentroid.x,\n startY: startCentroid.y,\n startData: startData as unknown as TransformStartData, // see InteractionContextData typing\n activeHandle: null,\n element: element.clone(),\n };\n }\n\n /**\n * Update pinch gesture for the latest two-pointer positions.\n * Returns the raw gesture state (scale ratio, rotation delta,\n * centroid positions). The caller (PinchHandler) is responsible\n * for applying this to the element — keeping the math out of the\n * state machine mirrors how `updateResize` returns `{dx, dy}` and\n * lets `ResizeHandler` do the geometry.\n *\n * Scale is clamped to a small floor so degenerate single-finger\n * coalesces (e.g. fingers landing on the same pixel for one\n * frame) don't produce zero / NaN dimensions.\n */\n updatePinch(p1: Point, p2: Point): PinchGesture {\n if (this.state !== 'PINCHING') {\n throw new Error('Cannot update pinch: not in PINCHING state');\n }\n\n const pinchStartData = this.context.startData as unknown as PinchStartData;\n\n const currentCentroid: Point = {\n x: (p1.x + p2.x) / 2,\n y: (p1.y + p2.y) / 2,\n };\n const dx = p2.x - p1.x;\n const dy = p2.y - p1.y;\n const currentDistance = Math.hypot(dx, dy);\n const currentAngle = Math.atan2(dy, dx);\n\n // Floor protects against zero / negative scale producing\n // degenerate geometry. No upper clamp — the existing handle\n // resize has none either, and aggressive pinch-in is a\n // legitimate gesture.\n const safeStartDistance = Math.max(pinchStartData.startDistance, 0.0001);\n const rawScale = currentDistance / safeStartDistance;\n const scale = Math.max(rawScale, 0.05);\n\n const rotationDelta = currentAngle - pinchStartData.startAngle;\n\n return {\n scale,\n rotationDelta,\n startCentroid: pinchStartData.startCentroid,\n currentCentroid,\n };\n }\n\n /**\n * Get the element snapshot + pinch start data (used by\n * PinchHandler.calculatePinch). Mirrors `getResizeContext`.\n */\n getPinchContext(): { element: BaseElement; startData: TransformStartData } {\n if (this.state !== 'PINCHING') {\n throw new Error('Cannot get pinch context: not in PINCHING state');\n }\n\n const pinchStartData = this.context.startData as unknown as PinchStartData;\n return {\n element: this.context.element!,\n startData: pinchStartData.elementData,\n };\n }\n\n /**\n * End current interaction\n */\n end(): void {\n this.state = 'IDLE';\n this.context = {\n mode: null,\n startX: 0,\n startY: 0,\n startData: null,\n activeHandle: null,\n element: null,\n };\n }\n\n /**\n * Cancel current interaction (no commit)\n */\n cancel(): void {\n this.end();\n }\n\n /**\n * Get active handle (for resize mode)\n */\n getActiveHandle(): HandleInfo | null {\n return this.context.activeHandle;\n }\n\n /**\n * Get mode ('drag', 'resize', 'rotate', or null)\n */\n getMode(): InteractionMode | null {\n return this.context.mode;\n }\n}\n","/**\n * RotationAnchorResolver - Consistent rotation anchor resolution\n *\n * Provides a unified way to determine rotation anchors and snap points\n * for all transform types, with clear precedence rules.\n */\n\nimport { RotationUtils } from './RotationUtils.js';\nimport type { BaseElement } from './BaseElement.js';\nimport type { Point } from '../types/index.js';\n\n/** Named anchor points for snap alignment */\ninterface SnapAnchors {\n topLeft: Point;\n topRight: Point;\n bottomLeft: Point;\n bottomRight: Point;\n topCenter: Point;\n rightCenter: Point;\n bottomCenter: Point;\n leftCenter: Point;\n center: Point;\n rotation: Point;\n [key: string]: Point;\n}\n\n/** Edge line represented by start and end points */\ninterface EdgeLine {\n start: Point;\n end: Point;\n}\n\nexport class RotationAnchorResolver {\n /**\n * Resolve rotation anchor with clear precedence:\n * 1. Transform's getRotationAnchor() if overridden\n * 2. Center of visual bounding box (default)\n */\n static resolve(element: BaseElement): Point {\n // All elements should have getRotationAnchor() method\n // This is the single source of truth for rotation\n return element.getRotationAnchor();\n }\n\n /**\n * Get all snap-able anchor points for an element\n * Used for alignment snapping feature\n *\n * Returns 9 standard anchor points plus the rotation anchor:\n * - 4 corners (top-left, top-right, bottom-left, bottom-right)\n * - 4 edge midpoints (top, right, bottom, left)\n * - 1 center\n * - 1 rotation anchor (may be same as center)\n */\n static getSnapAnchors(element: BaseElement): SnapAnchors {\n const bbox = element.getVisualBoundingBox();\n\n // Calculate basic 9 anchor points from visual bbox\n const anchors: SnapAnchors = {\n // Corners\n topLeft: { x: bbox.x, y: bbox.y },\n topRight: { x: bbox.x + bbox.width, y: bbox.y },\n bottomLeft: { x: bbox.x, y: bbox.y + bbox.height },\n bottomRight: { x: bbox.x + bbox.width, y: bbox.y + bbox.height },\n\n // Edge midpoints\n topCenter: { x: bbox.x + bbox.width / 2, y: bbox.y },\n rightCenter: { x: bbox.x + bbox.width, y: bbox.y + bbox.height / 2 },\n bottomCenter: { x: bbox.x + bbox.width / 2, y: bbox.y + bbox.height },\n leftCenter: { x: bbox.x, y: bbox.y + bbox.height / 2 },\n\n // Center\n center: { x: bbox.x + bbox.width / 2, y: bbox.y + bbox.height / 2 },\n\n // Rotation anchor (may differ from center for some transforms)\n rotation: this.resolve(element),\n };\n\n // If element is rotated, transform all anchor points\n if (element.rotation !== 0) {\n const rotationAnchor = anchors.rotation;\n const angleRad = RotationUtils.toRadiansInverse(element.rotation);\n\n // Transform all anchors except rotation anchor itself\n Object.keys(anchors).forEach((key) => {\n if (key === 'rotation') return; // Don't transform rotation anchor\n\n const point = anchors[key];\n const dx = point.x - rotationAnchor.x;\n const dy = point.y - rotationAnchor.y;\n\n // Rotate around rotation anchor\n const rotatedX = dx * Math.cos(angleRad) - dy * Math.sin(angleRad);\n const rotatedY = dx * Math.sin(angleRad) + dy * Math.cos(angleRad);\n\n anchors[key] = {\n x: rotationAnchor.x + rotatedX,\n y: rotationAnchor.y + rotatedY,\n };\n });\n }\n\n return anchors;\n }\n\n /**\n * Get edge lines for an element (for edge-to-edge snapping)\n *\n * Returns 4 lines representing the element's edges:\n * - top: left to right\n * - right: top to bottom\n * - bottom: right to left\n * - left: bottom to top\n */\n static getEdgeLines(element: BaseElement): Record<string, EdgeLine> {\n const anchors = this.getSnapAnchors(element);\n\n return {\n top: {\n start: anchors.topLeft,\n end: anchors.topRight,\n },\n right: {\n start: anchors.topRight,\n end: anchors.bottomRight,\n },\n bottom: {\n start: anchors.bottomRight,\n end: anchors.bottomLeft,\n },\n left: {\n start: anchors.bottomLeft,\n end: anchors.topLeft,\n },\n };\n }\n\n /**\n * Get all anchor types as array (for iteration)\n */\n static getAnchorTypes(): string[] {\n return [\n 'topLeft',\n 'topCenter',\n 'topRight',\n 'rightCenter',\n 'bottomRight',\n 'bottomCenter',\n 'bottomLeft',\n 'leftCenter',\n 'center',\n 'rotation',\n ];\n }\n\n /**\n * Check if an element has a custom rotation anchor\n * (different from center of visual bbox)\n */\n static hasCustomRotationAnchor(element: BaseElement): boolean {\n const bbox = element.getVisualBoundingBox();\n const center = {\n x: bbox.x + bbox.width / 2,\n y: bbox.y + bbox.height / 2,\n };\n\n const rotationAnchor = this.resolve(element);\n\n // Check if rotation anchor differs from center (with small epsilon for float comparison)\n const epsilon = 0.001;\n return Math.abs(rotationAnchor.x - center.x) > epsilon || Math.abs(rotationAnchor.y - center.y) > epsilon;\n }\n}\n","/**\n * SpatialGrid - Grid-based spatial index for O(1) amortized position lookups.\n *\n * Used by AlignmentSnapSystem to avoid scanning all elements when looking\n * for snap candidates. Points are bucketed into grid cells of fixed size.\n * Queries check only the cells that overlap the search radius, giving\n * O(1) amortized lookup when the number of results is small relative to\n * the total item count.\n */\n\n/** An item stored in the spatial grid. */\nexport interface SpatialGridItem {\n x: number;\n y: number;\n id: string;\n}\n\nexport class SpatialGrid {\n private cellSize: number;\n private cells: Map<string, Set<SpatialGridItem>>;\n /** Reverse index: id -> set of cell keys that contain items with that id */\n private idIndex: Map<string, Set<string>>;\n\n constructor(cellSize: number) {\n this.cellSize = cellSize;\n this.cells = new Map();\n this.idIndex = new Map();\n }\n\n /** Clear all entries */\n clear(): void {\n this.cells.clear();\n this.idIndex.clear();\n }\n\n /** Insert a point into the grid */\n insert(item: SpatialGridItem): void {\n const key = this.getCellKey(item.x, item.y);\n let cell = this.cells.get(key);\n if (!cell) {\n cell = new Set();\n this.cells.set(key, cell);\n }\n cell.add(item);\n\n // Update reverse index\n let keys = this.idIndex.get(item.id);\n if (!keys) {\n keys = new Set();\n this.idIndex.set(item.id, keys);\n }\n keys.add(key);\n }\n\n /** Remove all items with matching id */\n removeById(id: string): void {\n const keys = this.idIndex.get(id);\n if (!keys) return;\n\n for (const key of keys) {\n const cell = this.cells.get(key);\n if (!cell) continue;\n for (const item of cell) {\n if (item.id === id) {\n cell.delete(item);\n }\n }\n if (cell.size === 0) {\n this.cells.delete(key);\n }\n }\n this.idIndex.delete(id);\n }\n\n /**\n * Query all items within `radius` of point (x, y), excluding given id.\n *\n * Checks all cells that overlap the axis-aligned bounding box\n * [x - radius, x + radius] x [y - radius, y + radius].\n * Each candidate is then distance-checked against the radius.\n */\n queryNear(\n x: number,\n y: number,\n radius: number,\n excludeId?: string,\n ): SpatialGridItem[] {\n const results: SpatialGridItem[] = [];\n\n const minCellX = Math.floor((x - radius) / this.cellSize);\n const maxCellX = Math.floor((x + radius) / this.cellSize);\n const minCellY = Math.floor((y - radius) / this.cellSize);\n const maxCellY = Math.floor((y + radius) / this.cellSize);\n\n for (let cx = minCellX; cx <= maxCellX; cx++) {\n for (let cy = minCellY; cy <= maxCellY; cy++) {\n const key = `${cx},${cy}`;\n const cell = this.cells.get(key);\n if (!cell) continue;\n\n for (const item of cell) {\n if (excludeId !== undefined && item.id === excludeId) continue;\n const dx = item.x - x;\n const dy = item.y - y;\n if (dx * dx + dy * dy <= radius * radius) {\n results.push(item);\n }\n }\n }\n }\n\n return results;\n }\n\n /**\n * Query all items whose coordinate on `axis` is within `radius` of the\n * given value, excluding a given id. Unlike `queryNear` (Euclidean),\n * this checks only one axis -- essential for alignment snapping where\n * two anchors may be far apart on one axis but perfectly aligned on\n * the other.\n *\n * For axis='x': finds items where |item.x - value| <= radius\n * For axis='y': finds items where |item.y - value| <= radius\n *\n * Scans all cells in the band along the target axis.\n */\n queryNearAxis(\n axis: 'x' | 'y',\n value: number,\n radius: number,\n excludeId?: string,\n ): SpatialGridItem[] {\n const results: SpatialGridItem[] = [];\n\n if (axis === 'x') {\n // We need all cells whose X index is in [floor((value-radius)/cs), floor((value+radius)/cs)]\n const minCellX = Math.floor((value - radius) / this.cellSize);\n const maxCellX = Math.floor((value + radius) / this.cellSize);\n\n for (const [key, cell] of this.cells) {\n const commaIdx = key.indexOf(',');\n const cellX = parseInt(key.substring(0, commaIdx), 10);\n if (cellX < minCellX || cellX > maxCellX) continue;\n\n for (const item of cell) {\n if (excludeId !== undefined && item.id === excludeId) continue;\n if (Math.abs(item.x - value) <= radius) {\n results.push(item);\n }\n }\n }\n } else {\n const minCellY = Math.floor((value - radius) / this.cellSize);\n const maxCellY = Math.floor((value + radius) / this.cellSize);\n\n for (const [key, cell] of this.cells) {\n const commaIdx = key.indexOf(',');\n const cellY = parseInt(key.substring(commaIdx + 1), 10);\n if (cellY < minCellY || cellY > maxCellY) continue;\n\n for (const item of cell) {\n if (excludeId !== undefined && item.id === excludeId) continue;\n if (Math.abs(item.y - value) <= radius) {\n results.push(item);\n }\n }\n }\n }\n\n return results;\n }\n\n /** Rebuild from a full list of items (clears existing data first) */\n rebuild(items: SpatialGridItem[]): void {\n this.clear();\n for (const item of items) {\n this.insert(item);\n }\n }\n\n /** Get the cell key for a given world-space coordinate */\n private getCellKey(x: number, y: number): string {\n return `${Math.floor(x / this.cellSize)},${Math.floor(y / this.cellSize)}`;\n }\n}\n","/**\n * AlignmentSnapSystem - Handles alignment snapping for elements\n *\n * Detects when elements are near alignment with other elements and snaps them\n * to common alignment points (edges, centers, etc.)\n */\n\nimport { RotationUtils } from './RotationUtils.js';\nimport { RotationAnchorResolver } from './RotationAnchorResolver.js';\nimport { isNear } from './GeometryUtils.js';\nimport { theme } from '../theme.js';\nimport { SpatialGrid } from './SpatialGrid.js';\nimport type { SpatialGridItem } from './SpatialGrid.js';\nimport type { BaseElement } from './BaseElement.js';\nimport type { ImageElement } from './ImageElement.js';\nimport type { Point, SnapGuide, ResizeAnchor, AnyTransformData } from '../types/index.js';\n\n// ============================================================================\n// Local Type Definitions for AlignmentSnapSystem\n// ============================================================================\n\n/**\n * Represents an element with the properties accessed during snap operations.\n * Extends BaseElement with optional text/image-specific properties that the\n * snap system reads via duck-typing.\n */\ninterface SnapElement extends BaseElement {\n /** Font size (present on TextElement and its subclasses) */\n fontSize?: number;\n /** Direct width property (present on some element types) */\n width?: number;\n /** Direct height property (present on some element types) */\n height?: number;\n /** Image aspect ratio (present on ImageElement) */\n imageAspectRatio?: number;\n /** Whether the image is in crop mode (present on ImageElement) */\n isCropping?: boolean;\n /** Override clone to return SnapElement */\n clone(): SnapElement;\n}\n\n/** Named anchor points returned by RotationAnchorResolver.getSnapAnchors() */\ntype SnapAnchors = Record<string, Point>;\n\n/** Resize handle info passed through the resize pipeline */\ninterface SnapHandleInfo {\n anchor: ResizeAnchor | string;\n type?: string;\n cursor?: string;\n x?: number;\n y?: number;\n}\n\n/** Start data captured at the beginning of a resize operation */\ninterface ResizeStartData {\n fontSize?: number;\n width: number;\n height: number;\n visualWidth?: number;\n visualHeight?: number;\n x?: number;\n y?: number;\n rotation?: number;\n transformData?: Partial<AnyTransformData>;\n}\n\n/** Result from the resize pipeline, passed into snapDimensions */\ninterface ResizeResult {\n element: SnapElement;\n handle: SnapHandleInfo;\n startData: ResizeStartData | null;\n isFrozen?: boolean;\n unfrozenDimensions?: { width: number; height: number };\n snapAdjustment?: { dx: number; dy: number };\n isInStickySnap?: boolean;\n}\n\n/** A detected snap on either X or Y axis during position snap */\ninterface PositionSnap {\n snapTo: number;\n offset: number;\n distance: number;\n guide: SnapGuideExtended;\n}\n\n/** A detected snap on either X or Y axis during resize snap */\ninterface ResizeSnap {\n distance: number;\n snapTo: number;\n currentValue: number;\n guide: SnapGuideExtended;\n}\n\n/** Extended guide info including movingKey and otherKey for tracking */\ninterface SnapGuideExtended {\n type: string;\n x?: number;\n y?: number;\n y1?: number;\n y2?: number;\n x1?: number;\n x2?: number;\n movingKey: string;\n otherKey: string;\n}\n\n/** Result from _processStickySnap */\ninterface StickySnapResult {\n snapDelta: number;\n bestSnap: ResizeSnap | null;\n}\n\ninterface SnapState {\n snapTo: number;\n anchorKey: string;\n frozenFontSize: number;\n frozenWidth: number;\n frozenHeight: number;\n frozenPosition: Point;\n isPositionBasedSnap: boolean;\n}\n\ninterface AlignmentSnapSystemOptions {\n snapThreshold?: number;\n enabled?: boolean;\n showGuides?: boolean;\n stickyThreshold?: number;\n}\n\n// ============================================================================\n// Helper Functions for accessing optional transform data properties\n// ============================================================================\n\n/** Safely get width from transform data (only some transform types have it) */\nfunction getTransformDataWidth(element: SnapElement): number | undefined {\n const td = element.transformData;\n if (td && 'width' in td && typeof (td as { width?: number }).width === 'number') {\n return (td as { width: number }).width;\n }\n return undefined;\n}\n\n/** Safely get height from transform data (only some transform types have it) */\nfunction getTransformDataHeight(element: SnapElement): number | undefined {\n const td = element.transformData;\n if (td && 'height' in td && typeof (td as { height?: number }).height === 'number') {\n return (td as { height: number }).height;\n }\n return undefined;\n}\n\n/** Safely set width on transform data */\nfunction setTransformDataWidth(element: SnapElement, value: number): boolean {\n const td = element.transformData;\n if (td && 'width' in td) {\n (td as { width: number }).width = value;\n return true;\n }\n return false;\n}\n\n/** Safely set height on transform data */\nfunction setTransformDataHeight(element: SnapElement, value: number): boolean {\n const td = element.transformData;\n if (td && 'height' in td) {\n (td as { height: number }).height = value;\n return true;\n }\n return false;\n}\n\nexport class AlignmentSnapSystem {\n snapThreshold: number;\n enabled: boolean;\n showGuides: boolean;\n guides: SnapGuide[];\n activeSnaps: {\n x: SnapState | null;\n y: SnapState | null;\n };\n stickyThreshold: number;\n\n /** Spatial grid for O(1) amortized snap candidate lookup */\n private _spatialGrid: SpatialGrid;\n /** Map from grid item compound key to anchor metadata */\n private _anchorMetadata: Map<string, { elementId: string; anchorKey: string; point: Point }>;\n\n /**\n * ADR-0060: extra rectangular regions injected as snap targets in\n * addition to the canvas elements. Used by spread-mode focused-piece\n * editing so dragged elements snap to the FOCUSED PIECE'S center /\n * edges / corners instead of the full artboard. Each rect produces\n * 9 anchor points (corners, edge midpoints, center) — exactly the\n * shape `RotationAnchorResolver.getSnapAnchors` produces for an\n * un-rotated element. The id is used to scope the synthetic\n * \"element id\" so grid-item keys stay unique.\n */\n private _extraSnapRects: Array<{\n id: string;\n x: number;\n y: number;\n width: number;\n height: number;\n }> = [];\n\n constructor(options: AlignmentSnapSystemOptions = {}) {\n this.snapThreshold = options.snapThreshold || theme.canvas.snapThreshold;\n this.enabled = options.enabled !== false;\n this.showGuides = options.showGuides !== false;\n\n // Active snap guides to render\n this.guides = [];\n\n // Sticky snap state - tracks active snaps\n this.activeSnaps = {\n x: null, // { snapTo: number, anchorKey: string, frozenFontSize: number, frozenWidth: number, frozenPosition: {x, y}, isPositionBasedSnap: boolean }\n y: null, // { snapTo: number, anchorKey: string, frozenFontSize: number, frozenWidth: number, frozenPosition: {x, y}, isPositionBasedSnap: boolean }\n };\n\n // Dead zone for sticky snapping (pixels)\n // Once snapped, need to move this far to break free\n this.stickyThreshold = options.stickyThreshold || 15;\n\n // Spatial grid: cell size = 2x snap threshold for good bucket distribution\n this._spatialGrid = new SpatialGrid(Math.max(this.snapThreshold * 2, 16));\n this._anchorMetadata = new Map();\n }\n\n /**\n * Enable or disable snapping\n */\n setEnabled(enabled: boolean): void {\n this.enabled = enabled;\n }\n\n /**\n * Set snap threshold in pixels\n */\n setSnapThreshold(threshold: number): void {\n this.snapThreshold = threshold;\n // Rebuild spatial grid with new cell size proportional to threshold\n this._spatialGrid = new SpatialGrid(Math.max(threshold * 2, 16));\n }\n\n /**\n * Get current snap guides for rendering\n */\n getGuides(): SnapGuide[] {\n return this.guides;\n }\n\n /**\n * Clear all snap guides\n */\n clearGuides(): void {\n this.guides = [];\n }\n\n /**\n * Clear sticky snap state\n */\n clearSnapState(): void {\n this.activeSnaps.x = null;\n this.activeSnaps.y = null;\n }\n\n /**\n * ADR-0060: replace the set of extra snap rects (focused-piece bounds\n * etc.). Pass `[]` to clear. Effective on the next snap operation.\n */\n setExtraSnapRects(\n rects: Array<{ id: string; x: number; y: number; width: number; height: number }>,\n ): void {\n this._extraSnapRects = rects;\n }\n\n /**\n * Populate the spatial grid with anchor points from the given elements.\n * Each element produces ~9 anchor points (corners, edge midpoints, center).\n * The grid enables O(1) amortized lookup of nearby anchors by axis.\n *\n * Also folds in `_extraSnapRects` (set via `setExtraSnapRects`) so\n * a focused piece in spread mode contributes its corners / edges /\n * center as snap targets even though there's no real BaseElement.\n */\n private _populateSpatialGrid(elements: BaseElement[]): void {\n this._spatialGrid.clear();\n this._anchorMetadata.clear();\n\n for (const element of elements) {\n const anchors: SnapAnchors = RotationAnchorResolver.getSnapAnchors(element);\n for (const [anchorKey, point] of Object.entries(anchors) as Array<[string, Point]>) {\n const compoundKey = `${element.id}:${anchorKey}`;\n const gridItem: SpatialGridItem = {\n x: point.x,\n y: point.y,\n id: compoundKey,\n };\n this._spatialGrid.insert(gridItem);\n this._anchorMetadata.set(compoundKey, {\n elementId: element.id,\n anchorKey,\n point,\n });\n }\n }\n\n for (const rect of this._extraSnapRects) {\n const cx = rect.x + rect.width / 2;\n const cy = rect.y + rect.height / 2;\n const x2 = rect.x + rect.width;\n const y2 = rect.y + rect.height;\n const anchors: SnapAnchors = {\n topLeft: { x: rect.x, y: rect.y },\n topRight: { x: x2, y: rect.y },\n bottomLeft: { x: rect.x, y: y2 },\n bottomRight: { x: x2, y: y2 },\n topCenter: { x: cx, y: rect.y },\n rightCenter: { x: x2, y: cy },\n bottomCenter: { x: cx, y: y2 },\n leftCenter: { x: rect.x, y: cy },\n center: { x: cx, y: cy },\n // No `rotation` anchor — extras are un-rotated by definition.\n };\n const elementId = `__snap-rect:${rect.id}`;\n for (const [anchorKey, point] of Object.entries(anchors) as Array<[string, Point]>) {\n const compoundKey = `${elementId}:${anchorKey}`;\n this._spatialGrid.insert({\n x: point.x,\n y: point.y,\n id: compoundKey,\n });\n this._anchorMetadata.set(compoundKey, {\n elementId,\n anchorKey,\n point,\n });\n }\n }\n }\n\n /**\n * Snap a position during drag operation\n */\n snapPosition(position: Point, element: BaseElement, allElements: BaseElement[] | null): Point {\n if (!this.enabled || !allElements) {\n this.clearGuides();\n return position;\n }\n\n // Create a temporary element at the new position for anchor calculation\n const tempElement = element.clone();\n tempElement.x = position.x;\n tempElement.y = position.y;\n\n // Get anchors for the element being moved\n const movingAnchors: SnapAnchors = RotationAnchorResolver.getSnapAnchors(tempElement);\n\n // Get other elements (exclude the one being moved)\n const otherElements = allElements.filter((s) => s.id !== element.id);\n\n // Populate spatial grid with anchor points from other elements\n this._populateSpatialGrid(otherElements);\n\n // Find best snap for X and Y independently\n // Also collect ALL nearby snaps to show multiple guide lines\n let bestSnapX: PositionSnap | null = null;\n let bestSnapY: PositionSnap | null = null;\n let minDistX = Infinity;\n let minDistY = Infinity;\n\n const allXSnaps: PositionSnap[] = []; // Collect all X snaps within threshold\n const allYSnaps: PositionSnap[] = []; // Collect all Y snaps within threshold\n const newGuides: SnapGuideExtended[] = [];\n\n // Use spatial grid to find nearby anchors for each moving anchor\n for (const [movingKey, movingAnchor] of Object.entries(movingAnchors) as Array<[string, Point]>) {\n // Query X-axis candidates: anchors whose X is within snapThreshold\n const xCandidates = this._spatialGrid.queryNearAxis('x', movingAnchor.x, this.snapThreshold);\n for (const candidate of xCandidates) {\n const meta = this._anchorMetadata.get(candidate.id);\n if (!meta) continue;\n const otherAnchor = meta.point;\n const otherKey = meta.anchorKey;\n\n const distX = Math.abs(movingAnchor.x - otherAnchor.x);\n if (distX < this.snapThreshold) {\n const xSnap: PositionSnap = {\n snapTo: otherAnchor.x,\n offset: movingAnchor.x - position.x, // How far anchor is from element position\n distance: distX,\n guide: {\n type: 'vertical',\n x: otherAnchor.x,\n y1: Math.min(movingAnchor.y, otherAnchor.y) - 50,\n y2: Math.max(movingAnchor.y, otherAnchor.y) + 50,\n movingKey,\n otherKey,\n },\n };\n allXSnaps.push(xSnap);\n\n if (distX < minDistX) {\n minDistX = distX;\n bestSnapX = xSnap;\n }\n }\n }\n\n // Query Y-axis candidates: anchors whose Y is within snapThreshold\n const yCandidates = this._spatialGrid.queryNearAxis('y', movingAnchor.y, this.snapThreshold);\n for (const candidate of yCandidates) {\n const meta = this._anchorMetadata.get(candidate.id);\n if (!meta) continue;\n const otherAnchor = meta.point;\n const otherKey = meta.anchorKey;\n\n const distY = Math.abs(movingAnchor.y - otherAnchor.y);\n if (distY < this.snapThreshold) {\n const ySnap: PositionSnap = {\n snapTo: otherAnchor.y,\n offset: movingAnchor.y - position.y,\n distance: distY,\n guide: {\n type: 'horizontal',\n y: otherAnchor.y,\n x1: Math.min(movingAnchor.x, otherAnchor.x) - 50,\n x2: Math.max(movingAnchor.x, otherAnchor.x) + 50,\n movingKey,\n otherKey,\n },\n };\n allYSnaps.push(ySnap);\n\n if (distY < minDistY) {\n minDistY = distY;\n bestSnapY = ySnap;\n }\n }\n }\n }\n\n // Apply snapping\n let snappedX = position.x;\n let snappedY = position.y;\n\n if (bestSnapX) {\n snappedX = bestSnapX.snapTo - bestSnapX.offset;\n }\n\n if (bestSnapY) {\n snappedY = bestSnapY.snapTo - bestSnapY.offset;\n }\n\n // Show guides for ALL snaps that are within threshold (to show multiple aligned edges)\n // Deduplicate by snap position to avoid showing the same line multiple times\n const xSnapsByPosition = new Map<number, PositionSnap>();\n const ySnapsByPosition = new Map<number, PositionSnap>();\n\n for (const xSnap of allXSnaps) {\n const existing = xSnapsByPosition.get(xSnap.snapTo);\n if (!existing || xSnap.distance < existing.distance) {\n xSnapsByPosition.set(xSnap.snapTo, xSnap);\n }\n }\n\n for (const ySnap of allYSnaps) {\n const existing = ySnapsByPosition.get(ySnap.snapTo);\n if (!existing || ySnap.distance < existing.distance) {\n ySnapsByPosition.set(ySnap.snapTo, ySnap);\n }\n }\n\n // Add all unique snap guides\n for (const xSnap of xSnapsByPosition.values()) {\n newGuides.push(xSnap.guide);\n }\n\n for (const ySnap of ySnapsByPosition.values()) {\n newGuides.push(ySnap.guide);\n }\n\n this.guides = newGuides as SnapGuide[];\n\n return { x: snappedX, y: snappedY };\n }\n\n /**\n * Calculate what the frozen font size should be at the snap point\n * This ensures consistent font size regardless of which side of threshold you enter from\n */\n _calculateFrozenFontSizeAtSnap(element: SnapElement, snapDeltaX: number, _snapDeltaY: number, handle: SnapHandleInfo | null, startData: ResizeStartData | null): number {\n if (!startData) return element.fontSize ?? 0;\n\n // Only corner handles affect font size\n const anchorStr = handle?.anchor ? String(handle.anchor) : '';\n const isCornerHandle = handle && (anchorStr.includes('top') || anchorStr.includes('bottom'));\n if (!isCornerHandle) {\n return startData.fontSize ?? 0; // Side handles keep original font size\n }\n\n // Calculate what the width will be at the snap point\n const currentWidth = getTransformDataWidth(element) ?? element.width ?? startData.width;\n\n // For right-side resize, positive snapDeltaX means we're adding width\n // For left-side resize, negative snapDeltaX means we're adding width\n let targetWidthAtSnap = currentWidth;\n\n if (anchorStr.includes('right') && snapDeltaX !== 0) {\n targetWidthAtSnap = currentWidth + snapDeltaX;\n } else if (anchorStr.includes('left') && snapDeltaX !== 0) {\n targetWidthAtSnap = currentWidth - snapDeltaX;\n }\n\n // Calculate scale factor at snap point relative to start\n const scale = targetWidthAtSnap / startData.width;\n\n // Calculate frozen font size at snap point\n const frozenFontSize = (startData.fontSize ?? 0) * scale;\n\n\n return frozenFontSize;\n }\n\n /**\n * Check if this will be a position-based snap (vs dimension-based)\n * Position-based snaps adjust position to align edges when dimensions can't be modified\n * Used for text elements where height is derived, not settable\n */\n _isPositionBasedSnap(element: SnapElement, axis: 'x' | 'y'): boolean {\n if (axis === 'x') {\n // X-axis snaps modify width, which is always settable for text elements\n return false;\n } else if (axis === 'y') {\n // Y-axis snaps need to modify height\n // For text elements, height is derived (not settable), so we use position-based snap\n // Check if height property exists as a settable value\n const hasSettableHeight =\n (getTransformDataHeight(element) !== undefined) ||\n (element.height !== undefined && typeof element.height === 'number');\n return !hasSettableHeight;\n }\n return false;\n }\n\n /**\n * Determine which snap keys to use based on the resize handle\n */\n _getSnapKeysForHandle(handle: SnapHandleInfo | null): string[] {\n if (!handle || !handle.anchor) {\n // Fallback to corner anchors only (no center points for resize)\n return ['topLeft', 'topRight', 'bottomLeft', 'bottomRight'];\n }\n\n // For corner handles, only check the corner being moved\n // This prevents unnecessary snap freezing when the fixed corner happens to align with other elements\n if (handle.anchor === 'top-left' || handle.anchor === 'topLeft') {\n return ['topLeft'];\n } else if (handle.anchor === 'top-right' || handle.anchor === 'topRight') {\n return ['topRight'];\n } else if (handle.anchor === 'bottom-left' || handle.anchor === 'bottomLeft') {\n return ['bottomLeft'];\n } else if (handle.anchor === 'bottom-right' || handle.anchor === 'bottomRight') {\n return ['bottomRight'];\n }\n\n // For edge handles, only check the two corners on that edge\n if (handle.anchor.includes('left')) {\n return ['topLeft', 'bottomLeft'];\n } else if (handle.anchor.includes('right')) {\n return ['topRight', 'bottomRight'];\n } else if (handle.anchor.includes('top')) {\n return ['topLeft', 'topRight'];\n } else if (handle.anchor.includes('bottom')) {\n return ['bottomLeft', 'bottomRight'];\n }\n\n return [];\n }\n\n /**\n * Get all possible target snap keys (corners only, no center points)\n */\n _getTargetSnapKeys(): string[] {\n return ['topLeft', 'topRight', 'bottomLeft', 'bottomRight'];\n }\n\n /**\n * Find all X-axis snaps within threshold.\n * Uses the spatial grid (pre-populated via _populateSpatialGrid) for\n * O(1) amortized lookup instead of scanning all other elements.\n */\n _findXSnaps(movingAnchors: SnapAnchors, _otherElements: BaseElement[], snapKeys: string[], targetSnapKeys: string[]): ResizeSnap[] {\n const xSnaps: ResizeSnap[] = [];\n const targetSnapKeysSet = new Set(targetSnapKeys);\n\n for (const movingKey of snapKeys) {\n const movingAnchor = movingAnchors[movingKey];\n if (!movingAnchor) continue;\n\n // Query the spatial grid for anchors whose X is within threshold\n const candidates = this._spatialGrid.queryNearAxis('x', movingAnchor.x, this.snapThreshold);\n\n for (const candidate of candidates) {\n const meta = this._anchorMetadata.get(candidate.id);\n if (!meta) continue;\n\n // Only consider target snap keys (corners for resize)\n if (!targetSnapKeysSet.has(meta.anchorKey)) continue;\n\n const otherAnchor = meta.point;\n const otherKey = meta.anchorKey;\n\n const distX = Math.abs(movingAnchor.x - otherAnchor.x);\n if (distX < this.snapThreshold) {\n xSnaps.push({\n distance: distX,\n snapTo: otherAnchor.x,\n currentValue: movingAnchor.x,\n guide: {\n type: 'vertical',\n x: otherAnchor.x,\n y1: Math.min(movingAnchor.y, otherAnchor.y) - 50,\n y2: Math.max(movingAnchor.y, otherAnchor.y) + 50,\n movingKey,\n otherKey,\n },\n });\n }\n }\n }\n\n return xSnaps;\n }\n\n /**\n * Find all Y-axis snaps within threshold.\n * Uses the spatial grid (pre-populated via _populateSpatialGrid) for\n * O(1) amortized lookup instead of scanning all other elements.\n */\n _findYSnaps(movingAnchors: SnapAnchors, _otherElements: BaseElement[], snapKeys: string[], targetSnapKeys: string[]): ResizeSnap[] {\n const ySnaps: ResizeSnap[] = [];\n const targetSnapKeysSet = new Set(targetSnapKeys);\n\n for (const movingKey of snapKeys) {\n const movingAnchor = movingAnchors[movingKey];\n if (!movingAnchor) continue;\n\n // Query the spatial grid for anchors whose Y is within threshold\n const candidates = this._spatialGrid.queryNearAxis('y', movingAnchor.y, this.snapThreshold);\n\n for (const candidate of candidates) {\n const meta = this._anchorMetadata.get(candidate.id);\n if (!meta) continue;\n\n // Only consider target snap keys (corners for resize)\n if (!targetSnapKeysSet.has(meta.anchorKey)) continue;\n\n const otherAnchor = meta.point;\n const otherKey = meta.anchorKey;\n\n const distY = Math.abs(movingAnchor.y - otherAnchor.y);\n if (distY < this.snapThreshold) {\n ySnaps.push({\n distance: distY,\n snapTo: otherAnchor.y,\n currentValue: movingAnchor.y,\n guide: {\n type: 'horizontal',\n y: otherAnchor.y,\n x1: Math.min(movingAnchor.x, otherAnchor.x) - 50,\n x2: Math.max(movingAnchor.x, otherAnchor.x) + 50,\n movingKey,\n otherKey,\n },\n });\n }\n }\n }\n\n return ySnaps;\n }\n\n /**\n * Sort snaps by distance and prioritize based on handle anchor\n */\n _prioritizeSnaps(snaps: ResizeSnap[], handle: SnapHandleInfo | null, axis: 'x' | 'y'): void {\n if (!handle || !handle.anchor) {\n snaps.sort((a, b) => a.distance - b.distance);\n return;\n }\n\n if (axis === 'x') {\n if (handle.anchor.includes('left')) {\n snaps.sort((a, b) => {\n const aPriority = a.guide.movingKey.includes('left') ? -1000 : 0;\n const bPriority = b.guide.movingKey.includes('left') ? -1000 : 0;\n return a.distance + aPriority - (b.distance + bPriority);\n });\n } else if (handle.anchor.includes('right')) {\n snaps.sort((a, b) => {\n const aPriority = a.guide.movingKey.includes('right') ? -1000 : 0;\n const bPriority = b.guide.movingKey.includes('right') ? -1000 : 0;\n return a.distance + aPriority - (b.distance + bPriority);\n });\n } else {\n snaps.sort((a, b) => a.distance - b.distance);\n }\n } else if (axis === 'y') {\n if (handle.anchor.includes('top')) {\n snaps.sort((a, b) => {\n const aPriority = a.guide.movingKey.includes('top') ? -1000 : 0;\n const bPriority = b.guide.movingKey.includes('top') ? -1000 : 0;\n return a.distance + aPriority - (b.distance + bPriority);\n });\n } else if (handle.anchor.includes('bottom')) {\n snaps.sort((a, b) => {\n const aPriority = a.guide.movingKey.includes('bottom') ? -1000 : 0;\n const bPriority = b.guide.movingKey.includes('bottom') ? -1000 : 0;\n return a.distance + aPriority - (b.distance + bPriority);\n });\n } else {\n snaps.sort((a, b) => a.distance - b.distance);\n }\n }\n }\n\n /**\n * Create a guide visualization for an active snap\n */\n _createGuideForSnap(snap: SnapState, anchorKey: string, movingAnchors: SnapAnchors, otherElements: BaseElement[], axis: 'x' | 'y'): ResizeSnap | null {\n const trackedAnchor = movingAnchors[anchorKey];\n if (!trackedAnchor) return null;\n\n if (axis === 'x') {\n // Find min/max Y from all elements on this snap line\n // Include ALL anchor points of moving element for full guide extent\n let minY = Infinity;\n let maxY = -Infinity;\n\n // Check all anchor points of the moving element\n for (const anchor of Object.values(movingAnchors)) {\n if (Math.abs(anchor.x - snap.snapTo) < 5) {\n minY = Math.min(minY, anchor.y);\n maxY = Math.max(maxY, anchor.y);\n }\n }\n\n // Check all anchor points of other elements\n for (const otherElement of otherElements) {\n const otherAnchors: SnapAnchors = RotationAnchorResolver.getSnapAnchors(otherElement) as SnapAnchors;\n for (const anchor of Object.values(otherAnchors)) {\n if (Math.abs(anchor.x - snap.snapTo) < 5) {\n minY = Math.min(minY, anchor.y);\n maxY = Math.max(maxY, anchor.y);\n }\n }\n }\n\n // Fallback if no anchors found\n if (!isFinite(minY) || !isFinite(maxY)) {\n minY = trackedAnchor.y;\n maxY = trackedAnchor.y;\n }\n\n return {\n snapTo: snap.snapTo,\n currentValue: trackedAnchor.x,\n distance: 0,\n guide: {\n type: 'vertical',\n x: snap.snapTo,\n y1: minY - 50,\n y2: maxY + 50,\n movingKey: anchorKey,\n otherKey: 'snap',\n },\n };\n } else if (axis === 'y') {\n // Find min/max X from all elements on this snap line\n // Include ALL anchor points of moving element for full guide extent\n let minX = Infinity;\n let maxX = -Infinity;\n\n // Check all anchor points of the moving element\n for (const anchor of Object.values(movingAnchors)) {\n if (Math.abs(anchor.y - snap.snapTo) < 5) {\n minX = Math.min(minX, anchor.x);\n maxX = Math.max(maxX, anchor.x);\n }\n }\n\n // Check all anchor points of other elements\n for (const otherElement of otherElements) {\n const otherAnchors: SnapAnchors = RotationAnchorResolver.getSnapAnchors(otherElement) as SnapAnchors;\n for (const anchor of Object.values(otherAnchors)) {\n if (Math.abs(anchor.y - snap.snapTo) < 5) {\n minX = Math.min(minX, anchor.x);\n maxX = Math.max(maxX, anchor.x);\n }\n }\n }\n\n // Fallback if no anchors found\n if (!isFinite(minX) || !isFinite(maxX)) {\n minX = trackedAnchor.x;\n maxX = trackedAnchor.x;\n }\n\n return {\n snapTo: snap.snapTo,\n currentValue: trackedAnchor.y,\n distance: 0,\n guide: {\n type: 'horizontal',\n y: snap.snapTo,\n x1: minX - 50,\n x2: maxX + 50,\n movingKey: anchorKey,\n otherKey: 'snap',\n },\n };\n }\n\n return null;\n }\n\n /**\n * Calculate aspect-ratio-aware sticky threshold for a given axis\n * Wide elements move faster horizontally, tall elements move faster vertically\n * Adjust threshold to compensate for this velocity difference\n */\n _getAdjustedStickyThreshold(axis: 'x' | 'y', element: SnapElement): number {\n const bbox = element.getVisualBoundingBox();\n const aspectRatio = bbox.width / bbox.height;\n\n // Base threshold\n let adjustedThreshold = this.stickyThreshold;\n\n if (axis === 'x') {\n // For wide elements (aspect > 1), horizontal edges move faster\n // Reduce X threshold proportionally to aspect ratio\n if (aspectRatio > 1) {\n adjustedThreshold = this.stickyThreshold / Math.sqrt(aspectRatio);\n }\n } else if (axis === 'y') {\n // For tall elements (aspect < 1), vertical edges move faster\n // Reduce Y threshold proportionally to inverse aspect ratio\n if (aspectRatio < 1) {\n adjustedThreshold = this.stickyThreshold * Math.sqrt(aspectRatio);\n }\n }\n\n return adjustedThreshold;\n }\n\n /**\n * Calculate what dimensions should be when edge reaches snap point\n * This ensures frozen dimensions match the geometry at the snap position\n *\n * The key insight: When a snap is first detected (edge within 5px of guideline),\n * we need to freeze dimensions at what they WILL BE when the edge reaches the snap point,\n * not what they ARE at the moment of detection. This prevents visual \"jumps\" during\n * corner resize because position compensation expects dimensions to match the snap point.\n *\n * @param element - The element being resized\n * @param axis - 'x' or 'y' axis of the snap\n * @param snapDelta - Distance to move to reach snap point (can be positive or negative)\n * @param anchorKey - Which anchor is snapping (e.g., 'topRight', 'bottomLeft', etc.)\n * @param handle - The resize handle being dragged\n * @returns {Object} { frozenWidth, frozenHeight } - Dimensions at snap point\n */\n _calculateFrozenDimensionsAtSnap(\n element: SnapElement,\n axis: 'x' | 'y',\n snapDelta: number,\n anchorKey: string,\n _handle: SnapHandleInfo | null\n ): { frozenWidth: number; frozenHeight: number } {\n const currentWidth = getTransformDataWidth(element) ?? element.width ?? 0;\n const currentHeight = getTransformDataHeight(element) ?? element.height ?? 0;\n\n let finalWidth = currentWidth;\n let finalHeight = currentHeight;\n\n const isImageElement = element.transformType === 'image';\n const aspectRatio = isImageElement\n ? element.imageAspectRatio || (currentWidth && currentHeight ? currentWidth / currentHeight : null)\n : null;\n\n // Determine which edge is snapping based on anchorKey (case-insensitive check)\n const anchorLower = anchorKey.toLowerCase();\n\n if (axis === 'x') {\n if (anchorLower.includes('right')) {\n // Right edge snapping: width increases by snapDelta\n finalWidth = currentWidth + snapDelta;\n if (isImageElement && aspectRatio) {\n finalHeight = finalWidth / aspectRatio;\n }\n } else if (anchorLower.includes('left')) {\n // Left edge snapping: width changes by -snapDelta\n finalWidth = currentWidth - snapDelta;\n if (isImageElement && aspectRatio) {\n finalHeight = finalWidth / aspectRatio;\n }\n }\n } else if (axis === 'y') {\n if (anchorLower.includes('bottom')) {\n // Bottom edge snapping: height increases by snapDelta\n finalHeight = currentHeight + snapDelta;\n if (isImageElement && aspectRatio) {\n finalWidth = finalHeight * aspectRatio;\n }\n } else if (anchorLower.includes('top')) {\n // Top edge snapping: height changes by -snapDelta\n finalHeight = currentHeight - snapDelta;\n if (isImageElement && aspectRatio) {\n finalWidth = finalHeight * aspectRatio;\n }\n }\n }\n\n\n return { frozenWidth: finalWidth, frozenHeight: finalHeight };\n }\n\n /**\n * Process sticky snapping for a single axis\n * @returns {Object} { snapDelta, bestSnap }\n */\n _processStickySnap(\n axis: 'x' | 'y',\n movingAnchors: SnapAnchors,\n snaps: ResizeSnap[],\n element: SnapElement,\n handle: SnapHandleInfo | null,\n startData: ResizeStartData | null,\n otherElements: BaseElement[]\n ): StickySnapResult {\n const activeSnap = this.activeSnaps[axis];\n let snapDelta = 0;\n let bestSnap: ResizeSnap | null = null;\n\n if (activeSnap) {\n // We have an active snap - check if we're still within sticky range\n const trackedAnchor = movingAnchors[activeSnap.anchorKey];\n\n if (trackedAnchor) {\n const currentValue = axis === 'x' ? trackedAnchor.x : trackedAnchor.y;\n const rawDistance = Math.abs(currentValue - activeSnap.snapTo);\n\n // Use aspect-ratio-aware threshold\n const adjustedThreshold = this._getAdjustedStickyThreshold(axis, element);\n\n if (axis === 'x') {\n } else if (axis === 'y') {\n // Bounding box available for debugging if needed\n }\n\n if (rawDistance < adjustedThreshold) {\n // Still within sticky range - keep locked to snap point\n snapDelta = activeSnap.snapTo - currentValue;\n\n // For text elements with Y-axis snap, height is derived (not settable)\n // Don't recalculate frozen font size - keep it completely locked\n // This prevents feedback loop: fontSize change → height change → edge moves → new snapDelta\n const shouldRecalculateFontSize = !(axis === 'y' && activeSnap.isPositionBasedSnap);\n\n if (shouldRecalculateFontSize) {\n // Recalculate frozen font size based on current snap delta\n const recalculatedFontSize = this._calculateFrozenFontSizeAtSnap(\n element,\n axis === 'x' ? snapDelta : 0,\n axis === 'y' ? snapDelta : 0,\n handle,\n startData\n );\n\n if (recalculatedFontSize !== activeSnap.frozenFontSize) {\n activeSnap.frozenFontSize = recalculatedFontSize;\n }\n }\n\n if (axis === 'x') {\n }\n\n // Create guide for visualization\n bestSnap = this._createGuideForSnap(activeSnap, activeSnap.anchorKey, movingAnchors, otherElements, axis);\n } else {\n // Moved too far - break free from snap\n const previousSnap = activeSnap;\n this.activeSnaps[axis] = null;\n\n // Check if we should start a new snap (use base snapThreshold for initial snap detection)\n if (snaps.length > 0 && snaps[0].distance < this.snapThreshold) {\n bestSnap = snaps[0];\n snapDelta = bestSnap.snapTo - bestSnap.currentValue;\n\n // If re-entering the EXACT SAME snap (same anchor AND same snap position), preserve frozen state\n // Otherwise, calculate fresh frozen state for the new snap\n const shouldPreserveFreeze =\n previousSnap &&\n previousSnap.anchorKey === bestSnap.guide.movingKey &&\n Math.abs(previousSnap.snapTo - bestSnap.snapTo) < 1; // Same snap line (within 1px)\n\n const frozenFontSize = shouldPreserveFreeze\n ? previousSnap.frozenFontSize\n : this._calculateFrozenFontSizeAtSnap(\n element,\n axis === 'x' ? snapDelta : 0,\n axis === 'y' ? snapDelta : 0,\n handle,\n startData\n );\n\n const isPositionBased = this._isPositionBasedSnap(element, axis);\n // For position-based snaps, frozen position must include the snap delta\n // because we achieve alignment by adjusting position, not dimensions\n let frozenPos;\n if (shouldPreserveFreeze) {\n frozenPos = previousSnap.frozenPosition;\n } else if (isPositionBased) {\n // Include snap adjustment in frozen position for position-based snaps\n frozenPos = {\n x: axis === 'x' ? element.x + snapDelta : element.x,\n y: axis === 'y' ? element.y + snapDelta : element.y,\n };\n } else {\n frozenPos = { x: element.x, y: element.y };\n }\n\n // Calculate frozen dimensions at snap point (not at threshold entry)\n // This prevents visual \"jumps\" during corner resize\n const frozenDimensions = this._calculateFrozenDimensionsAtSnap(\n element,\n axis as 'x' | 'y',\n snapDelta,\n bestSnap.guide.movingKey,\n handle\n );\n\n this.activeSnaps[axis] = {\n snapTo: bestSnap.snapTo,\n anchorKey: bestSnap.guide.movingKey,\n frozenFontSize,\n frozenWidth: frozenDimensions.frozenWidth,\n frozenHeight: frozenDimensions.frozenHeight,\n frozenPosition: frozenPos,\n isPositionBasedSnap: isPositionBased,\n };\n }\n }\n } else {\n // Anchor no longer exists - clear the snap\n this.activeSnaps[axis] = null;\n }\n } else if (snaps.length > 0 && snaps[0].distance < this.snapThreshold) {\n // New snap - enter sticky snap mode\n bestSnap = snaps[0];\n snapDelta = bestSnap.snapTo - bestSnap.currentValue;\n\n // Check if we're re-entering the EXACT SAME snap (same anchor AND same snap position)\n const existingSnap = this.activeSnaps[axis];\n const shouldPreserveFreeze =\n existingSnap &&\n existingSnap.anchorKey === bestSnap.guide.movingKey &&\n Math.abs(existingSnap.snapTo - bestSnap.snapTo) < 1; // Same snap line (within 1px)\n\n const frozenFontSize = shouldPreserveFreeze\n ? existingSnap.frozenFontSize\n : this._calculateFrozenFontSizeAtSnap(\n element,\n axis === 'x' ? snapDelta : 0,\n axis === 'y' ? snapDelta : 0,\n handle,\n startData\n );\n\n const isPositionBased = this._isPositionBasedSnap(element, axis);\n // For position-based snaps, frozen position must include the snap delta\n // because we achieve alignment by adjusting position, not dimensions\n let frozenPos;\n if (shouldPreserveFreeze) {\n frozenPos = existingSnap.frozenPosition;\n } else if (isPositionBased) {\n // Include snap adjustment in frozen position for position-based snaps\n frozenPos = {\n x: axis === 'x' ? element.x + snapDelta : element.x,\n y: axis === 'y' ? element.y + snapDelta : element.y,\n };\n } else {\n frozenPos = { x: element.x, y: element.y };\n }\n\n // Calculate frozen dimensions at snap point (not at threshold entry)\n // This prevents visual \"jumps\" during corner resize\n const frozenDimensions = this._calculateFrozenDimensionsAtSnap(\n element,\n axis as 'x' | 'y',\n snapDelta,\n bestSnap.guide.movingKey,\n handle\n );\n\n this.activeSnaps[axis] = {\n snapTo: bestSnap.snapTo,\n anchorKey: bestSnap.guide.movingKey,\n frozenFontSize,\n frozenWidth: frozenDimensions.frozenWidth,\n frozenHeight: frozenDimensions.frozenHeight,\n frozenPosition: frozenPos,\n isPositionBasedSnap: isPositionBased,\n };\n }\n\n return { snapDelta, bestSnap };\n }\n\n /**\n * Adjust element for right edge resize\n */\n _adjustElementForRightResize(element: SnapElement, snapDeltaX: number, handle: SnapHandleInfo): void {\n // Store visual bbox before adjustment\n const beforeVisualBbox = element.getVisualBoundingBox();\n\n // For images, dimensions will be frozen later, so don't adjust width here\n const isImageElement = element.transformType === 'image';\n\n // Adjust width in transformData (skip for images as dimensions are frozen)\n if (!isImageElement) {\n const tdWidth = getTransformDataWidth(element);\n if (tdWidth !== undefined) {\n setTransformDataWidth(element, tdWidth + snapDeltaX);\n } else if (element.width !== undefined) {\n element.width += snapDeltaX;\n }\n }\n\n // For SIDE handles (middle-right), adjust position for center-based elements\n // The center shifts by half the width change to keep the left edge fixed\n if (handle.anchor === 'middle-right') {\n const rotationRad = RotationUtils.toRadiansInverse(element.rotation);\n const cos = Math.cos(rotationRad);\n const sin = Math.sin(rotationRad);\n element.x += (snapDeltaX / 2) * cos;\n element.y += (snapDeltaX / 2) * sin;\n\n } else {\n // For CORNER handles, we need to adjust position to keep the opposite (left) edge fixed\n // This is because the width change affects the visual bbox, which affects positioning\n\n // For images, skip compensation since width won't change (frozen dimensions)\n if (!isImageElement) {\n // Get the new visual bbox after width adjustment\n const afterVisualBbox = element.getVisualBoundingBox();\n\n // Calculate how much the left edge moved due to the width change\n const leftEdgeShift = afterVisualBbox.x - beforeVisualBbox.x;\n\n // Compensate by adjusting position to keep left edge in place\n if (leftEdgeShift !== 0) {\n element.x -= leftEdgeShift;\n\n }\n } else {\n }\n }\n\n }\n\n /**\n * Adjust element for left edge resize\n */\n _adjustElementForLeftResize(element: SnapElement, snapDeltaX: number, handle: SnapHandleInfo): void {\n // Store visual bbox before adjustment\n const beforeVisualBbox = element.getVisualBoundingBox();\n\n // For images, dimensions will be frozen later, so don't adjust width here\n // This prevents position compensation from seeing a width change that will be undone\n const isImageElement = element.transformType === 'image';\n\n // Adjust width first (skip for images as dimensions are frozen)\n if (!isImageElement) {\n const tdWidth = getTransformDataWidth(element);\n if (tdWidth !== undefined) {\n setTransformDataWidth(element, tdWidth - snapDeltaX);\n } else if (element.width !== undefined) {\n element.width -= snapDeltaX;\n }\n }\n\n // For SIDE handles (middle-left), adjust position for center-based elements\n // The center shifts by half the width change to keep the right edge fixed\n // When left edge moves right (positive snapDeltaX), width decreases, center moves right\n // When left edge moves left (negative snapDeltaX), width increases, center moves left\n if (handle.anchor === 'middle-left') {\n const rotationRad = RotationUtils.toRadiansInverse(element.rotation);\n const cos = Math.cos(rotationRad);\n const sin = Math.sin(rotationRad);\n\n // Width change is -snapDeltaX, so center shift is -snapDeltaX/2\n // But we want the center to move in the SAME direction as the left edge\n // So we add +snapDeltaX/2\n element.x += (snapDeltaX / 2) * cos;\n element.y += (snapDeltaX / 2) * sin;\n\n } else {\n // For CORNER handles, we need to adjust position to keep the opposite (right) edge fixed\n // This is because the width change affects the visual bbox, which affects positioning\n\n // First apply the direct position adjustment for the snap\n element.x += snapDeltaX;\n\n // For non-images, also compensate position to keep opposite edge fixed\n // For images, dimensions will be frozen so width won't actually change,\n // making the compensation unnecessary (and causing incorrect positioning)\n if (!isImageElement) {\n // Get the new visual bbox after width and position adjustment\n const afterVisualBbox = element.getVisualBoundingBox();\n\n // Calculate how much the right edge moved due to the width change\n const rightEdgeShift =\n afterVisualBbox.x + afterVisualBbox.width - (beforeVisualBbox.x + beforeVisualBbox.width);\n\n // Compensate by adjusting position to keep right edge in place\n if (rightEdgeShift !== 0) {\n element.x -= rightEdgeShift;\n\n }\n } else {\n }\n }\n\n }\n\n /**\n * Adjust element for bottom edge resize\n */\n _adjustElementForBottomResize(element: SnapElement, snapDeltaY: number, handle: SnapHandleInfo): void {\n // Store visual bbox before adjustment\n const beforeVisualBbox = element.getVisualBoundingBox();\n\n // For images, dimensions will be frozen later, so don't adjust height here\n const isImageElement = element.transformType === 'image';\n\n // Adjust height in transformData (skip for images as dimensions are frozen)\n if (!isImageElement) {\n const tdHeight = getTransformDataHeight(element);\n if (tdHeight !== undefined) {\n setTransformDataHeight(element, tdHeight + snapDeltaY);\n } else if (element.height !== undefined) {\n element.height += snapDeltaY;\n }\n }\n\n // Get bbox after height adjustment to check if height is settable\n const afterVisualBbox = element.getVisualBoundingBox();\n const heightChanged = Math.abs(afterVisualBbox.height - beforeVisualBbox.height) > 0.01;\n\n // For SIDE handles (middle-bottom), adjust position for center-based elements\n // The center shifts by half the height change to keep the top edge fixed\n if (handle.anchor === 'middle-bottom') {\n const rotationRad = RotationUtils.toRadiansInverse(element.rotation);\n const cos = Math.cos(rotationRad);\n const sin = Math.sin(rotationRad);\n // Height increases downward, so we move in the perpendicular direction\n element.x -= (snapDeltaY / 2) * sin;\n element.y += (snapDeltaY / 2) * cos;\n\n } else {\n // For CORNER handles with settable height, compensate position to keep top edge fixed\n // For images, dimensions will be frozen so height won't change,\n // making the compensation unnecessary\n if (!isImageElement && heightChanged) {\n const topEdgeShift = afterVisualBbox.y - beforeVisualBbox.y;\n\n if (topEdgeShift !== 0) {\n element.y -= topEdgeShift;\n\n }\n } else if (isImageElement) {\n } else {\n // For CORNER handles with derived height (like text elements),\n // adjust position directly to align the bottom edge\n element.y += snapDeltaY;\n\n }\n }\n\n }\n\n /**\n * Adjust element for top edge resize\n */\n _adjustElementForTopResize(element: SnapElement, snapDeltaY: number, handle: SnapHandleInfo): void {\n // Store visual bbox before adjustment\n const beforeVisualBbox = element.getVisualBoundingBox();\n\n // For images, dimensions will be frozen later, so don't adjust height here\n const isImageElement = element.transformType === 'image';\n\n // Adjust height in transformData (skip for images as dimensions are frozen)\n if (!isImageElement) {\n const tdHeight = getTransformDataHeight(element);\n if (tdHeight !== undefined) {\n setTransformDataHeight(element, tdHeight - snapDeltaY);\n } else if (element.height !== undefined) {\n element.height -= snapDeltaY;\n }\n }\n\n // Get bbox after height adjustment to check if height is settable\n const afterVisualBbox = element.getVisualBoundingBox();\n const heightChanged = Math.abs(afterVisualBbox.height - beforeVisualBbox.height) > 0.01;\n\n // For SIDE handles (middle-top), adjust position for center-based elements\n // The center shifts by half the height change to keep the bottom edge fixed\n if (handle.anchor === 'middle-top') {\n const rotationRad = RotationUtils.toRadiansInverse(element.rotation);\n const cos = Math.cos(rotationRad);\n const sin = Math.sin(rotationRad);\n\n // Height change is -snapDeltaY, center shift follows top edge movement\n element.x -= (snapDeltaY / 2) * sin;\n element.y += (snapDeltaY / 2) * cos;\n\n } else {\n // For CORNER handles, adjust position based on whether height is settable\n\n // For images, height will be frozen (dimension won't change)\n // so we only apply direct position adjustment, not compensation\n const shouldCompensate = !isImageElement && heightChanged;\n\n // First apply the direct position adjustment for the snap\n element.y += snapDeltaY;\n\n if (shouldCompensate) {\n // For CORNER handles with settable height, compensate to keep bottom edge fixed\n // Get the new visual bbox after height and position adjustment\n const newVisualBbox = element.getVisualBoundingBox();\n\n // Calculate how much the bottom edge moved due to the height change\n const bottomEdgeShift = newVisualBbox.y + newVisualBbox.height - (beforeVisualBbox.y + beforeVisualBbox.height);\n\n // Compensate by adjusting position to keep bottom edge in place\n if (bottomEdgeShift !== 0) {\n element.y -= bottomEdgeShift;\n\n }\n } else if (isImageElement) {\n } else {\n // For text elements with derived height\n }\n }\n\n }\n\n /**\n * Snap dimensions during resize operation\n *\n * @param {object} result - Resize result AFTER ResizeHandler processes it\n * @param {array} allElements - All elements in the scene\n * @param {object} startData - Original data from when resize started (for font size preservation)\n * @returns {object} Modified resize result with adjusted element\n */\n snapDimensions(result: ResizeResult, allElements: BaseElement[] | null, startData: ResizeStartData | null = null): ResizeResult {\n if (!this.enabled || !allElements) {\n this.clearGuides();\n return result;\n }\n\n const { element } = result;\n const handle = result.handle;\n\n // Get anchors for the resized element\n // For images with frozen dimensions, we need to use unfrozen dimensions for distance checking\n // Otherwise the snap can never be broken because the anchors don't move\n let movingAnchors: SnapAnchors;\n const isImageElement = element.transformType === 'image';\n const hasActiveSnap = this.activeSnaps.x !== null || this.activeSnaps.y !== null;\n\n if (isImageElement && hasActiveSnap && result.isFrozen && result.unfrozenDimensions) {\n // Use unfrozen dimensions from ResizeHandler for anchor calculation\n // This allows detecting when user is trying to break free from snap\n const tempElement = element.clone();\n\n if (tempElement.transformData) {\n // Use the visual dimensions that would exist without freeze\n const visualBbox = element.getVisualBoundingBox();\n const frozenVisualWidth = visualBbox.width;\n const frozenVisualHeight = visualBbox.height;\n\n // Calculate scale from frozen to unfrozen\n const startBboxWidth = startData?.width ?? element.width ?? 0;\n const startBboxHeight = startData?.height ?? element.height ?? 0;\n const startVisualWidth = startData?.visualWidth ?? frozenVisualWidth;\n const startVisualHeight = startData?.visualHeight ?? frozenVisualHeight;\n\n // Unfrozen dimensions are in visual space\n const scaleX = result.unfrozenDimensions.width / startVisualWidth;\n const scaleY = result.unfrozenDimensions.height / startVisualHeight;\n\n // Apply to bbox dimensions\n setTransformDataWidth(tempElement, startBboxWidth * scaleX);\n setTransformDataHeight(tempElement, startBboxHeight * scaleY);\n\n }\n\n movingAnchors = RotationAnchorResolver.getSnapAnchors(tempElement) as SnapAnchors;\n } else {\n movingAnchors = RotationAnchorResolver.getSnapAnchors(element) as SnapAnchors;\n }\n\n // Get other elements (exclude the one being resized)\n const otherElements = allElements.filter((s) => s.id !== element.id);\n\n if (otherElements.length === 0) {\n this.clearGuides();\n return result;\n }\n\n // Populate spatial grid with anchor points from other elements\n this._populateSpatialGrid(otherElements);\n\n // Determine which anchors to check based on handle position\n const snapKeys = this._getSnapKeysForHandle(handle);\n const targetSnapKeys = this._getTargetSnapKeys();\n\n // Find all snaps within threshold (uses spatial grid internally)\n const xSnaps = this._findXSnaps(movingAnchors, otherElements, snapKeys, targetSnapKeys);\n const ySnaps = this._findYSnaps(movingAnchors, otherElements, snapKeys, targetSnapKeys);\n\n // Prioritize snaps based on handle position\n this._prioritizeSnaps(xSnaps, handle, 'x');\n this._prioritizeSnaps(ySnaps, handle, 'y');\n\n // Process sticky snapping for both axes\n const xSnapResult = this._processStickySnap('x', movingAnchors, xSnaps, element, handle, startData, otherElements);\n const ySnapResult = this._processStickySnap('y', movingAnchors, ySnaps, element, handle, startData, otherElements);\n\n const snapDeltaX = xSnapResult.snapDelta;\n const snapDeltaY = ySnapResult.snapDelta;\n const bestSnapX = xSnapResult.bestSnap;\n const bestSnapY = ySnapResult.bestSnap;\n\n // Set guides for active snaps\n const newGuides: SnapGuideExtended[] = [];\n if (bestSnapX) newGuides.push(bestSnapX.guide);\n if (bestSnapY) newGuides.push(bestSnapY.guide);\n\n this.guides = newGuides as SnapGuide[];\n\n if (newGuides.length > 0) {\n }\n\n // For images, ResizeHandler already applied frozen dimensions during calculateResize\n // So we should NOT adjust anything here - just return the element as-is\n // Adjusting here would cause a \"double adjustment\" and visual jump\n // isImageElement already declared above\n const isCornerResize =\n handle &&\n (handle.anchor === 'top-left' ||\n handle.anchor === 'top-right' ||\n handle.anchor === 'bottom-left' ||\n handle.anchor === 'bottom-right');\n\n if (isImageElement && isCornerResize && (snapDeltaX !== 0 || snapDeltaY !== 0)) {\n return result;\n }\n\n // If we have snaps, adjust the element position to achieve snapping\n if (snapDeltaX !== 0 || snapDeltaY !== 0) {\n\n // Clone the element to apply adjustments\n const snappedElement = element.clone();\n\n // IMPORTANT: Preserve frozen state from when sticky snap was first activated\n // During sticky snap, we freeze fontSize, width (for Y snaps), and position (x,y) to prevent micro-adjustments\n const frozenState = this.activeSnaps.x || this.activeSnaps.y;\n const preservedFontSize = frozenState?.frozenFontSize ?? element.fontSize ?? 0;\n const preservedWidth = frozenState?.frozenWidth ?? getTransformDataWidth(element) ?? element.width ?? 0;\n const preservedHeight = frozenState?.frozenHeight ?? getTransformDataHeight(element) ?? element.height ?? 0;\n const preservedPosition = frozenState?.frozenPosition ?? { x: element.x, y: element.y };\n\n\n // Skip position adjustments for image elements in crop mode resizing the frame\n // The crop center position is carefully calculated in ImageElement.resize() and must not be modified\n const isImageCropMode = snappedElement.isCropping && !String(handle.anchor).startsWith('crop-');\n\n if (!isImageCropMode) {\n // Apply element adjustments based on which edge is actually snapped (not which handle is dragged)\n // This fixes the bug where dragging center-right handle on a left-edge-snapped element\n // would incorrectly apply right edge adjustment instead of left edge adjustment\n if (handle && handle.anchor) {\n // Horizontal adjustments - determine which edge is snapped from the active snap anchor key\n if (snapDeltaX !== 0) {\n const xSnapAnchor = this.activeSnaps.x?.anchorKey;\n const xSnapAnchorLower = xSnapAnchor?.toLowerCase();\n if (xSnapAnchorLower && xSnapAnchorLower.includes('right')) {\n this._adjustElementForRightResize(snappedElement, snapDeltaX, handle);\n } else if (xSnapAnchorLower && xSnapAnchorLower.includes('left')) {\n this._adjustElementForLeftResize(snappedElement, snapDeltaX, handle);\n } else {\n snappedElement.x += snapDeltaX;\n }\n }\n\n // Vertical adjustments - determine which edge is snapped from the active snap anchor key\n if (snapDeltaY !== 0) {\n const ySnapAnchor = this.activeSnaps.y?.anchorKey;\n const ySnapAnchorLower = ySnapAnchor?.toLowerCase();\n if (ySnapAnchorLower && ySnapAnchorLower.includes('bottom')) {\n this._adjustElementForBottomResize(snappedElement, snapDeltaY, handle);\n } else if (ySnapAnchorLower && ySnapAnchorLower.includes('top')) {\n this._adjustElementForTopResize(snappedElement, snapDeltaY, handle);\n } else {\n snappedElement.y += snapDeltaY;\n }\n }\n } else {\n // Fallback: just move position\n snappedElement.x += snapDeltaX;\n snappedElement.y += snapDeltaY;\n }\n }\n\n // Restore the frozen state to prevent micro-adjustments\n // During sticky snap, we completely freeze fontSize\n // But we must preserve position adjustments made by snap compensation\n\n if (snappedElement.fontSize !== undefined) {\n snappedElement.fontSize = preservedFontSize;\n }\n\n // Width/Height freeze logic for images and elements with aspect ratios\n // For images: freeze BOTH dimensions when either axis snaps to maintain aspect ratio\n // For text: Only freeze width for position-based Y snaps (width affects text wrapping)\n const isImageElement2 = snappedElement.transformType === 'image';\n const hasActiveSnap2 = this.activeSnaps.x !== null || this.activeSnaps.y !== null;\n\n if (isImageElement2 && hasActiveSnap2) {\n // For images with active snap: Freeze BOTH dimensions to maintain aspect ratio\n if (getTransformDataWidth(snappedElement) !== undefined) {\n // Update frozen dimensions if they've changed significantly (when snap is first activated)\n // This ensures frozen dimensions match the snapped dimensions, not the pre-snap dimensions\n const activeSnapState = this.activeSnaps.x || this.activeSnaps.y;\n let finalWidth = preservedWidth;\n let finalHeight = preservedHeight;\n\n if (activeSnapState) {\n // Use the frozen dimensions that were calculated at snap point\n // DO NOT update them based on current dimensions - they were already calculated correctly\n // in _calculateFrozenDimensionsAtSnap to match the geometry at the snap point\n finalWidth = activeSnapState.frozenWidth ?? finalWidth;\n finalHeight = activeSnapState.frozenHeight ?? finalHeight;\n\n }\n\n const tdWidth = getTransformDataWidth(element);\n const tdHeight = getTransformDataHeight(element);\n const imageAspectRatio =\n (snappedElement as ImageElement).imageAspectRatio ||\n (tdWidth && tdHeight\n ? tdWidth / tdHeight\n : null);\n\n if (imageAspectRatio && imageAspectRatio !== 0) {\n finalHeight = finalWidth / imageAspectRatio;\n }\n\n // Apply the frozen dimensions to prevent aspect ratio drift\n setTransformDataWidth(snappedElement, finalWidth);\n setTransformDataHeight(snappedElement, finalHeight);\n\n if (activeSnapState) {\n activeSnapState.frozenWidth = finalWidth;\n activeSnapState.frozenHeight = finalHeight;\n }\n\n }\n } else {\n // For text elements: Only freeze width for position-based Y snaps\n // For Y snaps, width affects derived height (text wrapping), so must freeze\n // For X snaps, we're actively adjusting width to align edges, so don't freeze\n const yIsPositionBasedSnap = this.activeSnaps.y?.isPositionBasedSnap || false;\n if (yIsPositionBasedSnap) {\n if (getTransformDataWidth(snappedElement) !== undefined) {\n setTransformDataWidth(snappedElement, preservedWidth);\n } else if (snappedElement.width !== undefined) {\n snappedElement.width = preservedWidth;\n }\n }\n }\n\n // Position freeze logic:\n // 1. If no snap: restore frozen position\n // 2. If position-based snap: restore frozen position (includes snap adjustment)\n // 3. If dimension-based snap: keep compensated position (for edge alignment)\n // 4. EXCEPTION: Side handles NEVER freeze (center-based, must update continuously)\n // 5. EXCEPTION: Image crop mode NEVER freezes position (crop center calculated precisely in resize)\n const isHorizontalSideHandle = handle && (handle.anchor === 'middle-left' || handle.anchor === 'middle-right');\n const isVerticalSideHandle = handle && (handle.anchor === 'middle-top' || handle.anchor === 'middle-bottom');\n\n const xIsPositionBasedSnap = this.activeSnaps.x?.isPositionBasedSnap || false;\n const yIsPositionBasedSnap = this.activeSnaps.y?.isPositionBasedSnap || false;\n\n // Freeze X: no snap OR position-based snap (frozen position includes alignment)\n // BUT skip for image crop mode - the crop center is precisely calculated in ImageElement.resize()\n if (\n (snapDeltaX === 0 || xIsPositionBasedSnap) &&\n !isHorizontalSideHandle &&\n !isVerticalSideHandle &&\n !isImageCropMode\n ) {\n snappedElement.x = preservedPosition.x;\n }\n\n // Freeze Y: no snap OR position-based snap (frozen position includes alignment)\n // BUT skip for image crop mode - the crop center is precisely calculated in ImageElement.resize()\n if (\n (snapDeltaY === 0 || yIsPositionBasedSnap) &&\n !isVerticalSideHandle &&\n !isHorizontalSideHandle &&\n !isImageCropMode\n ) {\n snappedElement.y = preservedPosition.y;\n }\n\n\n return {\n ...result,\n element: snappedElement,\n snapAdjustment: { dx: snapDeltaX, dy: snapDeltaY },\n // Flag to indicate we're in sticky snap mode (used to freeze font size)\n isInStickySnap: true,\n };\n }\n\n return result;\n }\n\n /**\n * Snap rotation (for future implementation)\n */\n snapRotation(rotation: number, _element: BaseElement, _allElements?: BaseElement[]): number {\n if (!this.enabled) return rotation;\n\n // Common rotation angles to snap to\n const commonAngles = [0, 45, 90, 135, 180, 225, 270, 315, 360];\n const snapAngle = 5; // degrees\n\n for (const angle of commonAngles) {\n if (isNear(rotation, angle, snapAngle)) {\n return angle;\n }\n }\n\n return rotation;\n }\n}\n","/**\n * SpacingSystem - Detects and displays spacing between elements during drag operations\n *\n * Shows red measurement lines with distance labels when elements are close to each other\n * but not snapped. Provides visual feedback for consistent spacing.\n */\n\nimport { SPACING_SNAP_THRESHOLD } from '../constants.js';\nimport type { BaseElement } from './BaseElement.js';\nimport type { SpacingIndicator } from '../types/index.js';\n\ninterface SpacingSystemOptions {\n detectionThreshold?: number;\n minDistance?: number;\n enabled?: boolean;\n showLabels?: boolean;\n}\n\nexport class SpacingSystem {\n detectionThreshold: number;\n minDistance: number;\n enabled: boolean;\n showLabels: boolean;\n indicators: SpacingIndicator[];\n lastSnapTarget: { x: number; y: number } | null = null;\n\n constructor(options: SpacingSystemOptions = {}) {\n this.detectionThreshold = options.detectionThreshold || 100; // Show spacing within 50px\n this.minDistance = options.minDistance || 10; // Don't show spacing if closer than 10px (snap zone)\n this.enabled = options.enabled !== false;\n this.showLabels = options.showLabels !== false;\n this.indicators = [];\n }\n\n /**\n * Enable or disable spacing detection\n */\n setEnabled(enabled: boolean): void {\n this.enabled = enabled;\n }\n\n /**\n * Set detection threshold in pixels\n */\n setDetectionThreshold(threshold: number): void {\n this.detectionThreshold = threshold;\n }\n\n /**\n * Get current spacing indicators for rendering\n */\n getIndicators(): SpacingIndicator[] {\n return this.indicators;\n }\n\n /**\n * Clear all spacing indicators\n */\n clearIndicators(): void {\n this.indicators = [];\n this.lastSnapTarget = null;\n }\n\n /**\n * Snap position to match consistent spacing patterns\n * Returns adjusted position if spacing snap is detected, otherwise returns original position\n */\n snapToSpacing(\n position: { x: number; y: number },\n movingElement: BaseElement,\n allElements: BaseElement[] | null\n ): { x: number; y: number } {\n if (!this.enabled || !allElements) {\n return position;\n }\n\n const snapThreshold = SPACING_SNAP_THRESHOLD;\n\n // Get other elements (exclude the one being moved)\n const otherElements = allElements.filter((s) => s.id !== movingElement.id);\n if (otherElements.length === 0) {\n return position;\n }\n\n // Create a temporary element at the new position\n const tempElement = movingElement.clone();\n tempElement.x = position.x;\n tempElement.y = position.y;\n const movingBBox = tempElement.getVisualBoundingBox();\n\n // Calculate offset between element position and visual bounding box\n // This is important for elements where the visual bbox doesn't start at (x, y)\n const visualOffsetX = movingBBox.x - position.x;\n const visualOffsetY = movingBBox.y - position.y;\n\n let snapX = position.x;\n let snapY = position.y;\n let didSnapX = false;\n let didSnapY = false;\n\n // Find elements in horizontal alignment (for vertical spacing snap)\n const horizontallyAligned = otherElements.filter((s) => {\n const bbox = s.getVisualBoundingBox();\n const horizontalOverlap = !(movingBBox.x + movingBBox.width < bbox.x || movingBBox.x > bbox.x + bbox.width);\n return horizontalOverlap;\n });\n\n // Sort by y position\n horizontallyAligned.sort((a, b) => {\n const bboxA = a.getVisualBoundingBox();\n const bboxB = b.getVisualBoundingBox();\n return bboxA.y - bboxB.y;\n });\n\n // Check for consistent vertical spacing pattern\n if (horizontallyAligned.length >= 1) {\n\n // Find the closest element above and below the moving element first\n let closestAbove: BaseElement | null = null;\n let closestBelow: BaseElement | null = null;\n\n for (const element of horizontallyAligned) {\n const bbox = element.getVisualBoundingBox();\n\n // Element is above moving element\n if (bbox.y + bbox.height <= movingBBox.y) {\n if (!closestAbove || bbox.y > closestAbove.getVisualBoundingBox().y) {\n closestAbove = element;\n }\n }\n // Element is below moving element\n else if (bbox.y >= movingBBox.y + movingBBox.height) {\n if (!closestBelow || bbox.y < closestBelow.getVisualBoundingBox().y) {\n closestBelow = element;\n }\n }\n }\n\n // Collect all gaps between adjacent elements\n const gaps: number[] = [];\n for (let i = 0; i < horizontallyAligned.length - 1; i++) {\n const bbox1 = horizontallyAligned[i].getVisualBoundingBox();\n const bbox2 = horizontallyAligned[i + 1].getVisualBoundingBox();\n const gap = bbox2.y - (bbox1.y + bbox1.height);\n gaps.push(gap);\n }\n\n\n // Try to find a spacing pattern to snap to\n // Priority: use the gap from the closest adjacent element if it appears elsewhere\n let targetGap: number | null = null;\n\n if (closestAbove) {\n const aboveBBox = closestAbove.getVisualBoundingBox();\n const currentGap = movingBBox.y - (aboveBBox.y + aboveBBox.height);\n\n // Check if this gap matches any existing gap in the layout\n for (const gap of gaps) {\n if (Math.abs(currentGap - gap) <= snapThreshold) {\n targetGap = gap;\n break;\n }\n }\n }\n\n if (!targetGap && closestBelow) {\n const belowBBox = closestBelow.getVisualBoundingBox();\n const currentGap = belowBBox.y - (movingBBox.y + movingBBox.height);\n\n // Check if this gap matches any existing gap in the layout\n for (const gap of gaps) {\n if (Math.abs(currentGap - gap) <= snapThreshold) {\n targetGap = gap;\n break;\n }\n }\n }\n\n if (targetGap !== null && targetGap > 0) {\n // Check if moving element should snap between closestAbove and closestBelow\n if (closestAbove) {\n const aboveBBox = closestAbove.getVisualBoundingBox();\n const currentGap = movingBBox.y - (aboveBBox.y + aboveBBox.height);\n const gapDiff = Math.abs(currentGap - targetGap);\n\n\n if (gapDiff <= snapThreshold) {\n // Snap to match the pattern gap\n // targetVisualY is where the visual bbox top should be\n const targetVisualY = aboveBBox.y + aboveBBox.height + targetGap;\n // Convert from visual bbox Y to element Y by subtracting the offset\n const targetElementY = targetVisualY - visualOffsetY;\n snapY = targetElementY;\n didSnapY = true;\n }\n }\n\n if (!didSnapY && closestBelow) {\n const belowBBox = closestBelow.getVisualBoundingBox();\n const currentGap = belowBBox.y - (movingBBox.y + movingBBox.height);\n const gapDiff = Math.abs(currentGap - targetGap);\n\n\n if (gapDiff <= snapThreshold) {\n // Snap to match the pattern gap\n // targetVisualY is where the visual bbox top should be\n const targetVisualY = belowBBox.y - movingBBox.height - targetGap;\n // Convert from visual bbox Y to element Y by subtracting the offset\n const targetElementY = targetVisualY - visualOffsetY;\n snapY = targetElementY;\n didSnapY = true;\n }\n }\n }\n }\n\n // Find elements in vertical alignment (for horizontal spacing snap)\n const verticallyAligned = otherElements.filter((s) => {\n const bbox = s.getVisualBoundingBox();\n const verticalOverlap = !(movingBBox.y + movingBBox.height < bbox.y || movingBBox.y > bbox.y + bbox.height);\n return verticalOverlap;\n });\n\n // Sort by x position\n verticallyAligned.sort((a, b) => {\n const bboxA = a.getVisualBoundingBox();\n const bboxB = b.getVisualBoundingBox();\n return bboxA.x - bboxB.x;\n });\n\n // Check for consistent horizontal spacing pattern\n if (verticallyAligned.length >= 1) {\n // Find the closest element left and right of the moving element first\n let closestLeft: BaseElement | null = null;\n let closestRight: BaseElement | null = null;\n\n for (const element of verticallyAligned) {\n const bbox = element.getVisualBoundingBox();\n\n // Element is to the left of moving element\n if (bbox.x + bbox.width <= movingBBox.x) {\n if (!closestLeft || bbox.x > closestLeft.getVisualBoundingBox().x) {\n closestLeft = element;\n }\n }\n // Element is to the right of moving element\n else if (bbox.x >= movingBBox.x + movingBBox.width) {\n if (!closestRight || bbox.x < closestRight.getVisualBoundingBox().x) {\n closestRight = element;\n }\n }\n }\n\n // Collect all gaps between adjacent elements\n const gaps: number[] = [];\n for (let i = 0; i < verticallyAligned.length - 1; i++) {\n const bbox1 = verticallyAligned[i].getVisualBoundingBox();\n const bbox2 = verticallyAligned[i + 1].getVisualBoundingBox();\n const gap = bbox2.x - (bbox1.x + bbox1.width);\n gaps.push(gap);\n }\n\n // Try to find a spacing pattern to snap to\n let targetGap: number | null = null;\n\n if (closestLeft) {\n const leftBBox = closestLeft.getVisualBoundingBox();\n const currentGap = movingBBox.x - (leftBBox.x + leftBBox.width);\n\n // Check if this gap matches any existing gap in the layout\n for (const gap of gaps) {\n if (Math.abs(currentGap - gap) <= snapThreshold) {\n targetGap = gap;\n break;\n }\n }\n }\n\n if (!targetGap && closestRight) {\n const rightBBox = closestRight.getVisualBoundingBox();\n const currentGap = rightBBox.x - (movingBBox.x + movingBBox.width);\n\n // Check if this gap matches any existing gap in the layout\n for (const gap of gaps) {\n if (Math.abs(currentGap - gap) <= snapThreshold) {\n targetGap = gap;\n break;\n }\n }\n }\n\n if (targetGap !== null && targetGap > 0) {\n // Check if moving element should snap between closestLeft and closestRight\n if (closestLeft) {\n const leftBBox = closestLeft.getVisualBoundingBox();\n const currentGap = movingBBox.x - (leftBBox.x + leftBBox.width);\n const gapDiff = Math.abs(currentGap - targetGap);\n\n if (gapDiff <= snapThreshold) {\n // Snap to match the pattern gap\n // targetVisualX is where the visual bbox left should be\n const targetVisualX = leftBBox.x + leftBBox.width + targetGap;\n // Convert from visual bbox X to element X by subtracting the offset\n const targetElementX = targetVisualX - visualOffsetX;\n snapX = targetElementX;\n didSnapX = true;\n }\n }\n\n if (!didSnapX && closestRight) {\n const rightBBox = closestRight.getVisualBoundingBox();\n const currentGap = rightBBox.x - (movingBBox.x + movingBBox.width);\n const gapDiff = Math.abs(currentGap - targetGap);\n\n if (gapDiff <= snapThreshold) {\n // Snap to match the pattern gap\n // targetVisualX is where the visual bbox left should be\n const targetVisualX = rightBBox.x - movingBBox.width - targetGap;\n // Convert from visual bbox X to element X by subtracting the offset\n const targetElementX = targetVisualX - visualOffsetX;\n snapX = targetElementX;\n didSnapX = true;\n }\n }\n }\n }\n\n this.lastSnapTarget = didSnapX || didSnapY ? { x: snapX, y: snapY } : null;\n\n if (didSnapX || didSnapY) {\n }\n\n return { x: snapX, y: snapY };\n }\n\n /**\n * Detect spacing between a moving element and other elements\n * Returns spacing indicators for the closest elements in each direction\n * Also detects consistent spacing patterns (e.g., evenly spaced rows/columns)\n * @param showAllMeasurements - When true (Alt key held), shows all spacing measurements, not just to moving element\n */\n detectSpacing(\n movingElement: BaseElement,\n allElements: BaseElement[] | null,\n showAllMeasurements: boolean = false\n ): SpacingIndicator[] {\n if (!this.enabled || !allElements) {\n this.clearIndicators();\n return [];\n }\n\n // Get other elements (exclude the one being moved)\n const otherElements = allElements.filter((s) => s.id !== movingElement.id);\n\n if (otherElements.length === 0) {\n this.clearIndicators();\n return [];\n }\n\n // Get the bounding box of the moving element\n const movingBBox = movingElement.getVisualBoundingBox();\n\n // Track all nearby elements in each direction (not just closest)\n const leftElements: Array<{ element: BaseElement; distance: number }> = [];\n const rightElements: Array<{ element: BaseElement; distance: number }> = [];\n const topElements: Array<{ element: BaseElement; distance: number }> = [];\n const bottomElements: Array<{ element: BaseElement; distance: number }> = [];\n\n // Find the closest element in each direction\n for (const otherElement of otherElements) {\n const otherBBox = otherElement.getVisualBoundingBox();\n\n // Calculate distances between edges\n // Left: distance from moving element's left edge to other element's right edge\n const distanceToLeft = movingBBox.x - (otherBBox.x + otherBBox.width);\n // Right: distance from moving element's right edge to other element's left edge\n const distanceToRight = otherBBox.x - (movingBBox.x + movingBBox.width);\n // Top: distance from moving element's top edge to other element's bottom edge\n const distanceToTop = movingBBox.y - (otherBBox.y + otherBBox.height);\n // Bottom: distance from moving element's bottom edge to other element's top edge\n const distanceToBottom = otherBBox.y - (movingBBox.y + movingBBox.height);\n\n // Check if elements overlap vertically (for horizontal spacing)\n const verticalOverlap = !(\n movingBBox.y + movingBBox.height < otherBBox.y || movingBBox.y > otherBBox.y + otherBBox.height\n );\n\n // Check if elements overlap horizontally (for vertical spacing)\n const horizontalOverlap = !(\n movingBBox.x + movingBBox.width < otherBBox.x || movingBBox.x > otherBBox.x + otherBBox.width\n );\n\n // Left spacing (other element is to the left)\n // Collect all nearby elements, not just the closest\n if (distanceToLeft >= this.minDistance && distanceToLeft < this.detectionThreshold && verticalOverlap) {\n leftElements.push({ element: otherElement, distance: distanceToLeft });\n }\n\n // Right spacing (other element is to the right)\n if (distanceToRight >= this.minDistance && distanceToRight < this.detectionThreshold && verticalOverlap) {\n rightElements.push({ element: otherElement, distance: distanceToRight });\n }\n\n // Top spacing (other element is above)\n if (distanceToTop >= this.minDistance && distanceToTop < this.detectionThreshold && horizontalOverlap) {\n topElements.push({ element: otherElement, distance: distanceToTop });\n }\n\n // Bottom spacing (other element is below)\n if (distanceToBottom >= this.minDistance && distanceToBottom < this.detectionThreshold && horizontalOverlap) {\n bottomElements.push({ element: otherElement, distance: distanceToBottom });\n }\n }\n\n // Sort elements by distance in each direction\n leftElements.sort((a, b) => a.distance - b.distance);\n rightElements.sort((a, b) => a.distance - b.distance);\n topElements.sort((a, b) => a.distance - b.distance);\n bottomElements.sort((a, b) => a.distance - b.distance);\n\n const newIndicators: SpacingIndicator[] = [];\n\n // If Alt key is pressed, ONLY show all measurements (not regular spacing detection)\n if (showAllMeasurements) {\n const allMeasurements = this.detectAllMeasurements(movingElement, allElements);\n newIndicators.push(...allMeasurements);\n } else {\n // Regular spacing detection (only when Alt is NOT pressed)\n // Detect consistent spacing patterns and create indicators\n // Horizontal spacing (left and right)\n if (leftElements.length > 0) {\n const indicators = this.detectConsistentSpacing(movingElement, movingBBox, leftElements, 'left', otherElements);\n newIndicators.push(...indicators);\n }\n\n if (rightElements.length > 0) {\n const indicators = this.detectConsistentSpacing(\n movingElement,\n movingBBox,\n rightElements,\n 'right',\n otherElements\n );\n newIndicators.push(...indicators);\n }\n\n // Vertical spacing (top and bottom)\n if (topElements.length > 0) {\n const indicators = this.detectConsistentSpacing(movingElement, movingBBox, topElements, 'top', otherElements);\n newIndicators.push(...indicators);\n }\n\n if (bottomElements.length > 0) {\n const indicators = this.detectConsistentSpacing(\n movingElement,\n movingBBox,\n bottomElements,\n 'bottom',\n otherElements\n );\n newIndicators.push(...indicators);\n }\n }\n\n this.indicators = newIndicators;\n return newIndicators;\n }\n\n /**\n * Detect spacing from hovered element to ALL nearby elements (when Alt key is held)\n * Shows measurements from the hovered element to other elements within detection threshold\n */\n private detectAllMeasurements(hoveredElement: BaseElement, allElements: BaseElement[]): SpacingIndicator[] {\n const indicators: SpacingIndicator[] = [];\n const hoveredBBox = hoveredElement.getVisualBoundingBox();\n\n // Get other elements\n const otherElements = allElements.filter((s) => s.id !== hoveredElement.id);\n\n // Show measurements FROM the hovered element TO all nearby elements\n // For Alt+hover, use a much larger detection threshold (3x normal) to show more measurements\n const altHoverThreshold = this.detectionThreshold * 3; // 300px instead of 100px\n\n // Track horizontal and vertical measurement counts separately to alternate offsets\n let horizontalCount = 0;\n let verticalCount = 0;\n\n for (const element of otherElements) {\n const elementBBox = element.getVisualBoundingBox();\n\n // Calculate distance from hovered element to this element\n const distanceToElement = Math.min(\n Math.abs(hoveredBBox.x - (elementBBox.x + elementBBox.width)), // left\n Math.abs(elementBBox.x - (hoveredBBox.x + hoveredBBox.width)), // right\n Math.abs(hoveredBBox.y - (elementBBox.y + elementBBox.height)), // top\n Math.abs(elementBBox.y - (hoveredBBox.y + hoveredBBox.height)) // bottom\n );\n\n\n if (distanceToElement > altHoverThreshold) {\n continue; // Skip elements that are too far away\n }\n\n // Calculate horizontal gap\n let horizontalGap = 0;\n let showHorizontal = false;\n let hx1 = 0,\n hx2 = 0,\n hy = 0;\n\n // Offset to prevent overlapping with vertical measurements\n // Alternate up/down for each horizontal measurement\n const horizontalOffsetMultiplier = horizontalCount % 2 === 0 ? 1 : -1;\n const horizontalOffset = -30 * horizontalOffsetMultiplier; // Alternate: -30px or +30px\n\n // Element is to the right (gap between right edge of hovered and left edge of element)\n if (elementBBox.x >= hoveredBBox.x + hoveredBBox.width) {\n horizontalGap = elementBBox.x - (hoveredBBox.x + hoveredBBox.width);\n if (horizontalGap >= this.minDistance) {\n showHorizontal = true;\n hx1 = hoveredBBox.x + hoveredBBox.width;\n hx2 = elementBBox.x;\n // Use the vertical center between the two elements to spread them out\n hy = (hoveredBBox.y + hoveredBBox.height / 2 + elementBBox.y + elementBBox.height / 2) / 2 + horizontalOffset;\n }\n }\n // Element is to the left (gap between left edge of hovered and right edge of element)\n else if (hoveredBBox.x >= elementBBox.x + elementBBox.width) {\n horizontalGap = hoveredBBox.x - (elementBBox.x + elementBBox.width);\n if (horizontalGap >= this.minDistance) {\n showHorizontal = true;\n hx1 = elementBBox.x + elementBBox.width;\n hx2 = hoveredBBox.x;\n // Use the vertical center between the two elements to spread them out\n hy = (hoveredBBox.y + hoveredBBox.height / 2 + elementBBox.y + elementBBox.height / 2) / 2 + horizontalOffset;\n }\n } else {\n }\n\n if (showHorizontal) {\n indicators.push({\n type: 'horizontal',\n distance: Math.round(horizontalGap),\n x1: hx1,\n x2: hx2,\n y: hy,\n labelX: (hx1 + hx2) / 2,\n labelY: hy,\n isAltHover: true,\n });\n horizontalCount++; // Increment for next horizontal measurement\n }\n\n // Calculate vertical gap\n let verticalGap = 0;\n let showVertical = false;\n let vx = 0,\n vy1 = 0,\n vy2 = 0;\n\n // Offset to prevent overlapping with horizontal measurements\n // Alternate left/right for each vertical measurement\n const verticalOffsetMultiplier = verticalCount % 2 === 0 ? 1 : -1;\n const verticalOffset = 30 * verticalOffsetMultiplier; // Alternate: +30px or -30px\n\n // Element is below (gap between bottom edge of hovered and top edge of element)\n if (elementBBox.y >= hoveredBBox.y + hoveredBBox.height) {\n verticalGap = elementBBox.y - (hoveredBBox.y + hoveredBBox.height);\n if (verticalGap >= this.minDistance) {\n showVertical = true;\n // Use the horizontal center between the two elements to spread them out\n vx = (hoveredBBox.x + hoveredBBox.width / 2 + elementBBox.x + elementBBox.width / 2) / 2 + verticalOffset;\n vy1 = hoveredBBox.y + hoveredBBox.height;\n vy2 = elementBBox.y;\n }\n }\n // Element is above (gap between top edge of hovered and bottom edge of element)\n else if (hoveredBBox.y >= elementBBox.y + elementBBox.height) {\n verticalGap = hoveredBBox.y - (elementBBox.y + elementBBox.height);\n if (verticalGap >= this.minDistance) {\n showVertical = true;\n // Use the horizontal center between the two elements to spread them out\n vx = (hoveredBBox.x + hoveredBBox.width / 2 + elementBBox.x + elementBBox.width / 2) / 2 + verticalOffset;\n vy1 = elementBBox.y + elementBBox.height;\n vy2 = hoveredBBox.y;\n }\n }\n\n if (showVertical) {\n indicators.push({\n type: 'vertical',\n distance: Math.round(verticalGap),\n x: vx,\n y1: vy1,\n y2: vy2,\n labelX: vx,\n labelY: (vy1 + vy2) / 2,\n isAltHover: true,\n });\n verticalCount++; // Increment for next vertical measurement\n }\n }\n\n return indicators;\n }\n\n /**\n * Detect consistent spacing patterns (e.g., evenly spaced rows/columns)\n * and create indicators for all matching spacings\n */\n private detectConsistentSpacing(\n movingElement: BaseElement,\n movingBBox: { x: number; y: number; width: number; height: number },\n nearbyElements: Array<{ element: BaseElement; distance: number }>,\n direction: 'left' | 'right' | 'top' | 'bottom',\n allElements: BaseElement[]\n ): SpacingIndicator[] {\n const indicators: SpacingIndicator[] = [];\n const spacingTolerance = 16; // Consider spacings within 16px as \"matching\"\n\n // Get the closest element\n const closest = nearbyElements[0];\n const closestDistance = closest.distance;\n const closestBBox = closest.element.getVisualBoundingBox();\n\n // Check if this spacing would snap (for visual indicator)\n const wouldSnap = this.checkIfWouldSnap(movingBBox, closestDistance, direction, allElements);\n\n // ALWAYS add indicator for the moving element to the closest element first\n // Mark it as snap target if it would snap\n this.addIndicatorForDirection(indicators, movingBBox, closestBBox, closestDistance, direction, wouldSnap);\n\n if (direction === 'left' || direction === 'right') {\n // Horizontal spacing - look for elements in a row with consistent spacing\n // Find other elements that align vertically and have similar spacing between them\n\n // Get all elements in the same horizontal band\n const alignedElements = allElements.filter((s) => {\n if (s.id === movingElement.id) return false;\n const bbox = s.getVisualBoundingBox();\n const verticalOverlap = !(movingBBox.y + movingBBox.height < bbox.y || movingBBox.y > bbox.y + bbox.height);\n return verticalOverlap;\n });\n\n // Sort by x position\n alignedElements.sort((a, b) => {\n const bboxA = a.getVisualBoundingBox();\n const bboxB = b.getVisualBoundingBox();\n return bboxA.x - bboxB.x;\n });\n\n // Find patterns of consistent spacing\n if (direction === 'left') {\n // Look for elements to the left with consistent spacing\n for (let i = 0; i < alignedElements.length - 1; i++) {\n const element1 = alignedElements[i];\n const element2 = alignedElements[i + 1];\n const bbox1 = element1.getVisualBoundingBox();\n const bbox2 = element2.getVisualBoundingBox();\n\n const gap = bbox2.x - (bbox1.x + bbox1.width);\n\n // Check if this gap matches our target spacing\n if (Math.abs(gap - closestDistance) <= spacingTolerance && gap >= this.minDistance) {\n // Found a matching spacing - show indicator\n const y1 = Math.max(bbox1.y, bbox2.y);\n const y2 = Math.min(bbox1.y + bbox1.height, bbox2.y + bbox2.height);\n const y = (y1 + y2) / 2;\n\n indicators.push({\n type: 'horizontal',\n distance: Math.round(gap),\n x1: bbox1.x + bbox1.width,\n x2: bbox2.x,\n y,\n labelX: (bbox1.x + bbox1.width + bbox2.x) / 2,\n labelY: y,\n });\n }\n }\n } else {\n // direction === 'right'\n // Look for elements to the right with consistent spacing\n for (let i = 0; i < alignedElements.length - 1; i++) {\n const element1 = alignedElements[i];\n const element2 = alignedElements[i + 1];\n const bbox1 = element1.getVisualBoundingBox();\n const bbox2 = element2.getVisualBoundingBox();\n\n const gap = bbox2.x - (bbox1.x + bbox1.width);\n\n if (Math.abs(gap - closestDistance) <= spacingTolerance && gap >= this.minDistance) {\n const y1 = Math.max(bbox1.y, bbox2.y);\n const y2 = Math.min(bbox1.y + bbox1.height, bbox2.y + bbox2.height);\n const y = (y1 + y2) / 2;\n\n indicators.push({\n type: 'horizontal',\n distance: Math.round(gap),\n x1: bbox1.x + bbox1.width,\n x2: bbox2.x,\n y,\n labelX: (bbox1.x + bbox1.width + bbox2.x) / 2,\n labelY: y,\n });\n }\n }\n }\n } else {\n // Vertical spacing - look for elements in a column with consistent spacing\n\n // Get all elements in the same vertical band\n const alignedElements = allElements.filter((s) => {\n if (s.id === movingElement.id) return false;\n const bbox = s.getVisualBoundingBox();\n const horizontalOverlap = !(movingBBox.x + movingBBox.width < bbox.x || movingBBox.x > bbox.x + bbox.width);\n return horizontalOverlap;\n });\n\n // Sort by y position\n alignedElements.sort((a, b) => {\n const bboxA = a.getVisualBoundingBox();\n const bboxB = b.getVisualBoundingBox();\n return bboxA.y - bboxB.y;\n });\n\n // Find patterns of consistent spacing\n if (direction === 'top') {\n // Look for elements above with consistent spacing\n for (let i = 0; i < alignedElements.length - 1; i++) {\n const element1 = alignedElements[i];\n const element2 = alignedElements[i + 1];\n const bbox1 = element1.getVisualBoundingBox();\n const bbox2 = element2.getVisualBoundingBox();\n\n const gap = bbox2.y - (bbox1.y + bbox1.height);\n\n if (Math.abs(gap - closestDistance) <= spacingTolerance && gap >= this.minDistance) {\n const x1 = Math.max(bbox1.x, bbox2.x);\n const x2 = Math.min(bbox1.x + bbox1.width, bbox2.x + bbox2.width);\n const x = (x1 + x2) / 2;\n\n indicators.push({\n type: 'vertical',\n distance: Math.round(gap),\n x,\n y1: bbox1.y + bbox1.height,\n y2: bbox2.y,\n labelX: x,\n labelY: (bbox1.y + bbox1.height + bbox2.y) / 2,\n });\n }\n }\n } else {\n // direction === 'bottom'\n // Look for elements below with consistent spacing\n for (let i = 0; i < alignedElements.length - 1; i++) {\n const element1 = alignedElements[i];\n const element2 = alignedElements[i + 1];\n const bbox1 = element1.getVisualBoundingBox();\n const bbox2 = element2.getVisualBoundingBox();\n\n const gap = bbox2.y - (bbox1.y + bbox1.height);\n\n if (Math.abs(gap - closestDistance) <= spacingTolerance && gap >= this.minDistance) {\n const x1 = Math.max(bbox1.x, bbox2.x);\n const x2 = Math.min(bbox1.x + bbox1.width, bbox2.x + bbox2.width);\n const x = (x1 + x2) / 2;\n\n indicators.push({\n type: 'vertical',\n distance: Math.round(gap),\n x,\n y1: bbox1.y + bbox1.height,\n y2: bbox2.y,\n labelX: x,\n labelY: (bbox1.y + bbox1.height + bbox2.y) / 2,\n });\n }\n }\n }\n }\n\n return indicators;\n }\n\n /**\n * Check if spacing would snap to a pattern\n */\n private checkIfWouldSnap(\n movingBBox: { x: number; y: number; width: number; height: number },\n currentDistance: number,\n direction: 'left' | 'right' | 'top' | 'bottom',\n allElements: BaseElement[]\n ): boolean {\n const snapThreshold = SPACING_SNAP_THRESHOLD;\n\n\n if (direction === 'top' || direction === 'bottom') {\n // Check vertical spacing pattern\n const horizontallyAligned = allElements.filter((s) => {\n const bbox = s.getVisualBoundingBox();\n const horizontalOverlap = !(movingBBox.x + movingBBox.width < bbox.x || movingBBox.x > bbox.x + bbox.width);\n return horizontalOverlap;\n });\n\n\n // Need at least 1 other element to establish a pattern\n if (horizontallyAligned.length >= 1) {\n // Sort by y position\n horizontallyAligned.sort((a, b) => {\n const bboxA = a.getVisualBoundingBox();\n const bboxB = b.getVisualBoundingBox();\n return bboxA.y - bboxB.y;\n });\n\n const gaps: number[] = [];\n for (let i = 0; i < horizontallyAligned.length - 1; i++) {\n const bbox1 = horizontallyAligned[i].getVisualBoundingBox();\n const bbox2 = horizontallyAligned[i + 1].getVisualBoundingBox();\n const gap = bbox2.y - (bbox1.y + bbox1.height);\n gaps.push(gap);\n }\n\n // If we have at least 1 gap, we can establish a pattern\n if (gaps.length > 0) {\n const avgGap = gaps.reduce((a, b) => a + b, 0) / gaps.length;\n const gapDiff = Math.abs(currentDistance - avgGap);\n const wouldSnap = gapDiff <= snapThreshold;\n return wouldSnap;\n }\n }\n return false;\n } else {\n // Check horizontal spacing pattern\n const verticallyAligned = allElements.filter((s) => {\n const bbox = s.getVisualBoundingBox();\n const verticalOverlap = !(movingBBox.y + movingBBox.height < bbox.y || movingBBox.y > bbox.y + bbox.height);\n return verticalOverlap;\n });\n\n // Need at least 1 other element to establish a pattern\n if (verticallyAligned.length >= 1) {\n // Sort by x position\n verticallyAligned.sort((a, b) => {\n const bboxA = a.getVisualBoundingBox();\n const bboxB = b.getVisualBoundingBox();\n return bboxA.x - bboxB.x;\n });\n\n const gaps: number[] = [];\n for (let i = 0; i < verticallyAligned.length - 1; i++) {\n const bbox1 = verticallyAligned[i].getVisualBoundingBox();\n const bbox2 = verticallyAligned[i + 1].getVisualBoundingBox();\n const gap = bbox2.x - (bbox1.x + bbox1.width);\n gaps.push(gap);\n }\n\n // If we have at least 1 gap, we can establish a pattern\n if (gaps.length > 0) {\n const avgGap = gaps.reduce((a, b) => a + b, 0) / gaps.length;\n const gapDiff = Math.abs(currentDistance - avgGap);\n const wouldSnap = gapDiff <= snapThreshold;\n return wouldSnap;\n }\n }\n return false;\n }\n\n return false;\n }\n\n /**\n * Helper method to add a spacing indicator in a specific direction\n */\n private addIndicatorForDirection(\n indicators: SpacingIndicator[],\n movingBBox: { x: number; y: number; width: number; height: number },\n otherBBox: { x: number; y: number; width: number; height: number },\n distance: number,\n direction: 'left' | 'right' | 'top' | 'bottom',\n isSnapTarget: boolean = false\n ): void {\n if (direction === 'left') {\n const y1 = Math.max(movingBBox.y, otherBBox.y);\n const y2 = Math.min(movingBBox.y + movingBBox.height, otherBBox.y + otherBBox.height);\n const y = (y1 + y2) / 2;\n\n indicators.push({\n type: 'horizontal',\n distance: Math.round(distance),\n x1: otherBBox.x + otherBBox.width,\n x2: movingBBox.x,\n y,\n labelX: (otherBBox.x + otherBBox.width + movingBBox.x) / 2,\n labelY: y,\n isSnapTarget,\n });\n } else if (direction === 'right') {\n const y1 = Math.max(movingBBox.y, otherBBox.y);\n const y2 = Math.min(movingBBox.y + movingBBox.height, otherBBox.y + otherBBox.height);\n const y = (y1 + y2) / 2;\n\n indicators.push({\n type: 'horizontal',\n distance: Math.round(distance),\n x1: movingBBox.x + movingBBox.width,\n x2: otherBBox.x,\n y,\n labelX: (movingBBox.x + movingBBox.width + otherBBox.x) / 2,\n labelY: y,\n isSnapTarget,\n });\n } else if (direction === 'top') {\n const x1 = Math.max(movingBBox.x, otherBBox.x);\n const x2 = Math.min(movingBBox.x + movingBBox.width, otherBBox.x + otherBBox.width);\n const x = (x1 + x2) / 2;\n\n indicators.push({\n type: 'vertical',\n distance: Math.round(distance),\n x,\n y1: otherBBox.y + otherBBox.height,\n y2: movingBBox.y,\n labelX: x,\n labelY: (otherBBox.y + otherBBox.height + movingBBox.y) / 2,\n isSnapTarget,\n });\n } else if (direction === 'bottom') {\n const x1 = Math.max(movingBBox.x, otherBBox.x);\n const x2 = Math.min(movingBBox.x + movingBBox.width, otherBBox.x + otherBBox.width);\n const x = (x1 + x2) / 2;\n\n indicators.push({\n type: 'vertical',\n distance: Math.round(distance),\n x,\n y1: movingBBox.y + movingBBox.height,\n y2: otherBBox.y,\n labelX: x,\n labelY: (movingBBox.y + movingBBox.height + otherBBox.y) / 2,\n isSnapTarget,\n });\n }\n }\n}\n","/**\n * TextureManager - Loads and caches background textures\n * Provides texture loading for artboard backgrounds\n */\n\nimport { createLogger } from './logger';\n\nconst logger = createLogger('TextureManager');\n\nexport interface TextureInfo {\n id: string;\n name: string;\n url: string;\n category?: string;\n presetColor: string; // Base color for this texture preset\n}\n\nexport class TextureManager {\n private static cache = new Map<string, HTMLImageElement>();\n private static loading = new Map<string, Promise<HTMLImageElement>>();\n\n /**\n * Available built-in textures\n */\n static readonly TEXTURES: TextureInfo[] = [\n {\n id: 'glass-frame',\n name: 'Glass Frame',\n url: '/textures/glass-frame.svg',\n category: 'glass',\n presetColor: '#ccc', // Light gray\n },\n ];\n\n /**\n * Load a texture by ID or URL\n */\n static async loadTexture(idOrUrl: string): Promise<HTMLImageElement> {\n\n // Check if already cached\n if (this.cache.has(idOrUrl)) {\n return this.cache.get(idOrUrl)!;\n }\n\n // Check if already loading\n if (this.loading.has(idOrUrl)) {\n return this.loading.get(idOrUrl)!;\n }\n\n // Resolve URL from ID if needed\n const url = this.resolveTextureUrl(idOrUrl);\n\n // Create loading promise\n const loadingPromise = new Promise<HTMLImageElement>((resolve, reject) => {\n const img = new Image();\n img.crossOrigin = 'anonymous';\n\n img.onload = () => {\n // Cache the loaded image\n this.cache.set(idOrUrl, img);\n this.cache.set(url, img);\n this.loading.delete(idOrUrl);\n this.loading.delete(url);\n resolve(img);\n };\n\n img.onerror = () => {\n logger.error('Failed to load texture:', url);\n this.loading.delete(idOrUrl);\n this.loading.delete(url);\n reject(new Error(`Failed to load texture: ${url}`));\n };\n\n img.src = url;\n });\n\n // Store loading promise\n this.loading.set(idOrUrl, loadingPromise);\n if (url !== idOrUrl) {\n this.loading.set(url, loadingPromise);\n }\n\n return loadingPromise;\n }\n\n /**\n * Get a texture synchronously (returns null if not loaded)\n */\n static getTexture(idOrUrl: string): HTMLImageElement | null {\n const url = this.resolveTextureUrl(idOrUrl);\n return this.cache.get(idOrUrl) || this.cache.get(url) || null;\n }\n\n /**\n * Preload multiple textures\n */\n static async preloadTextures(idsOrUrls: string[]): Promise<void> {\n await Promise.all(idsOrUrls.map((id) => this.loadTexture(id)));\n }\n\n /**\n * Preload all built-in textures\n */\n static async preloadAllTextures(): Promise<void> {\n await this.preloadTextures(this.TEXTURES.map((t) => t.id));\n }\n\n /**\n * Clear cache\n */\n static clearCache(): void {\n this.cache.clear();\n this.loading.clear();\n }\n\n /**\n * Resolve texture URL from ID\n */\n private static resolveTextureUrl(idOrUrl: string): string {\n // If it's already a URL, return as-is\n if (\n idOrUrl.startsWith('http://') ||\n idOrUrl.startsWith('https://') ||\n idOrUrl.startsWith('/') ||\n idOrUrl.startsWith('data:')\n ) {\n return idOrUrl;\n }\n\n // Look up built-in texture by ID\n const texture = this.TEXTURES.find((t) => t.id === idOrUrl);\n if (texture) {\n return texture.url;\n }\n\n // Default: treat as relative URL\n return `/textures/${idOrUrl}`;\n }\n\n /**\n * Get texture info by ID\n */\n static getTextureInfo(id: string): TextureInfo | undefined {\n return this.TEXTURES.find((t) => t.id === id);\n }\n\n /**\n * Get all available textures\n */\n static getAllTextures(): TextureInfo[] {\n return [...this.TEXTURES];\n }\n\n /**\n * Get textures by category\n */\n static getTexturesByCategory(category: string): TextureInfo[] {\n return this.TEXTURES.filter((t) => t.category === category);\n }\n\n /**\n * Get preset color for a texture\n * Each texture has a fixed color that's part of its preset\n */\n static getTexturePresetColor(textureId: string): string {\n const texture = this.TEXTURES.find((t) => t.id === textureId);\n return texture?.presetColor || '#ffffff';\n }\n}\n","/**\n * ArtboardRenderer - Renders artboards on the canvas\n * Handles artboard background, border, label, and selection state\n */\n\nimport { ArtboardElement } from './ArtboardElement.js';\nimport { TextureManager } from '../utils/TextureManager.js';\nimport { createLogger } from '../utils/logger.js';\nimport {\n getThemeAccentColor,\n getThemeArtboardBorderColor,\n getThemeArtboardLabelColor,\n} from '../constants.js';\n\nconst logger = createLogger('ArtboardRenderer');\n\nexport interface ArtboardRenderOptions {\n showLabel?: boolean;\n showBorder?: boolean;\n borderColor?: string;\n borderWidth?: number;\n labelFontSize?: number;\n labelColor?: string;\n labelPadding?: number;\n selectedBorderColor?: string;\n selectedBorderWidth?: number;\n showPreviewBackground?: boolean; // Enable preview background rendering (never exported)\n borderRadius?: number; // Override border radius for artboard corners (in pixels)\n}\n\nconst DEFAULT_OPTIONS: Required<ArtboardRenderOptions> = {\n showLabel: true,\n showBorder: true,\n borderColor: '', // '' = use getThemeArtboardBorderColor() at render time\n borderWidth: 1,\n labelFontSize: 14,\n labelColor: '', // '' = use getThemeArtboardLabelColor() at render time\n labelPadding: 8,\n selectedBorderColor: '', // '' = use getThemeAccentColor() at render time\n selectedBorderWidth: 2,\n showPreviewBackground: true, // Show preview by default in editor\n borderRadius: 0, // Default to no border radius (sharp corners)\n};\n\nexport class ArtboardRenderer {\n private options: Required<ArtboardRenderOptions>;\n\n constructor(options: ArtboardRenderOptions = {}) {\n this.options = { ...DEFAULT_OPTIONS, ...options };\n }\n\n /**\n * Render an artboard\n */\n render(ctx: CanvasRenderingContext2D, artboard: ArtboardElement, isSelected: boolean = false): void {\n\n ctx.save();\n\n // Render background\n this.renderBackground(ctx, artboard);\n\n // Render border\n if (this.options.showBorder) {\n this.renderBorder(ctx, artboard, isSelected);\n }\n\n // Render label\n if (this.options.showLabel) {\n this.renderLabel(ctx, artboard, isSelected);\n }\n\n ctx.restore();\n }\n\n /**\n * Render artboard background\n * Optionally renders preview background color for t-shirt design preview\n * Preview background is NEVER exported - only shown in editor\n * Background is clipped to the artboard's clipShape\n */\n private renderBackground(ctx: CanvasRenderingContext2D, artboard: ArtboardElement): void {\n // Save context before clipping\n ctx.save();\n\n // Apply clip path for background rendering (respects clipShape)\n this.applyClipPath(ctx, artboard);\n\n // Render preview background if enabled and set (for t-shirt color preview)\n if (\n this.options.showPreviewBackground &&\n artboard.previewBackgroundColor &&\n artboard.previewBackgroundColor !== 'transparent'\n ) {\n ctx.fillStyle = artboard.previewBackgroundColor;\n ctx.fillRect(artboard.x, artboard.y, artboard.width, artboard.height);\n }\n\n // Render actual artboard background on top\n if (artboard.backgroundType === 'texture' && artboard.backgroundTexture) {\n // Render texture background\n this.renderTextureBackground(ctx, artboard);\n } else if (artboard.backgroundType === 'transparent' || artboard.backgroundColor === 'transparent') {\n // Draw checkerboard pattern for transparent background\n this.renderCheckerboard(ctx, artboard.x, artboard.y, artboard.width, artboard.height);\n } else {\n // Render solid color background\n ctx.fillStyle = artboard.backgroundColor;\n ctx.fillRect(artboard.x, artboard.y, artboard.width, artboard.height);\n }\n\n // Restore context after background\n ctx.restore();\n }\n\n /**\n * Render texture background\n * Renders preset color as base layer, then texture on top\n */\n private renderTextureBackground(\n ctx: CanvasRenderingContext2D,\n artboard: ArtboardElement\n ): void {\n const texture = TextureManager.getTexture(artboard.backgroundTexture!);\n\n // First, render the preset color as the base layer\n const presetColor = TextureManager.getTexturePresetColor(artboard.backgroundTexture!);\n ctx.fillStyle = presetColor;\n ctx.fillRect(artboard.x, artboard.y, artboard.width, artboard.height);\n\n if (!texture || !texture.complete) {\n // Texture not loaded yet - load it asynchronously\n TextureManager.loadTexture(artboard.backgroundTexture!).catch((err) => {\n logger.error('Failed to load texture:', err);\n });\n\n // Preset color already rendered above, just return\n return;\n }\n\n\n // Save context\n ctx.save();\n\n // Create clipping path\n ctx.beginPath();\n ctx.rect(artboard.x, artboard.y, artboard.width, artboard.height);\n ctx.clip();\n\n // Draw texture on top of the preset color\n ctx.drawImage(texture, artboard.x, artboard.y, artboard.width, artboard.height);\n\n // Restore context\n ctx.restore();\n }\n\n /**\n * Render a checkerboard pattern for transparent backgrounds\n */\n private renderCheckerboard(\n ctx: CanvasRenderingContext2D,\n x: number,\n y: number,\n width: number,\n height: number\n ): void {\n const squareSize = 16;\n const lightColor = '#ffffff';\n const darkColor = '#d0d0d0';\n\n // Save context\n ctx.save();\n\n // Create clipping path\n ctx.beginPath();\n ctx.rect(x, y, width, height);\n ctx.clip();\n\n // Fill entire area with light color first\n ctx.fillStyle = lightColor;\n ctx.fillRect(x, y, width, height);\n\n // Draw only dark squares on top (every other square)\n ctx.fillStyle = darkColor;\n for (let row = 0; row < Math.ceil(height / squareSize); row++) {\n for (let col = 0; col < Math.ceil(width / squareSize); col++) {\n // Only draw dark squares (when row + col is odd)\n if ((row + col) % 2 === 1) {\n ctx.fillRect(x + col * squareSize, y + row * squareSize, squareSize, squareSize);\n }\n }\n }\n\n // Restore context\n ctx.restore();\n }\n\n /**\n * Render artboard border (respects clipShape and borderRadius option)\n */\n private renderBorder(ctx: CanvasRenderingContext2D, artboard: ArtboardElement, isSelected: boolean): void {\n const { x, y, width, height, clipShape } = artboard;\n\n const borderColor = this.options.borderColor || getThemeArtboardBorderColor();\n const selectedBorderColor = this.options.selectedBorderColor || getThemeAccentColor();\n ctx.strokeStyle = isSelected ? selectedBorderColor : borderColor;\n ctx.lineWidth = isSelected ? this.options.selectedBorderWidth : this.options.borderWidth;\n\n ctx.beginPath();\n\n // Draw border following the clip shape or borderRadius option\n if (!clipShape || clipShape === 'rectangle') {\n if (this.options.borderRadius > 0) {\n const radius = Math.min(this.options.borderRadius, Math.min(width, height) / 2);\n this.roundedRect(ctx, x, y, width, height, radius);\n } else {\n ctx.rect(x, y, width, height);\n }\n } else if (clipShape === 'circle') {\n const centerX = x + width / 2;\n const centerY = y + height / 2;\n const radius = Math.min(width, height) / 2;\n ctx.arc(centerX, centerY, radius, 0, Math.PI * 2);\n } else if (typeof clipShape === 'object' && clipShape.type === 'rounded') {\n const radius = Math.min(clipShape.radius, Math.min(width, height) / 2);\n this.roundedRect(ctx, x, y, width, height, radius);\n } else if (typeof clipShape === 'object' && clipShape.type === 'path') {\n // For custom paths, stroke the path\n try {\n const path = new Path2D(clipShape.d);\n ctx.save();\n ctx.translate(x, y);\n ctx.stroke(path);\n ctx.restore();\n return; // Path2D stroke handles it\n } catch (e) {\n logger.warn('Invalid SVG path for border, falling back to rectangle:', e);\n ctx.rect(x, y, width, height);\n }\n }\n\n ctx.stroke();\n }\n\n /**\n * Render artboard label (name + dimensions)\n */\n private renderLabel(ctx: CanvasRenderingContext2D, artboard: ArtboardElement, isSelected: boolean): void {\n const fontSize = this.options.labelFontSize;\n const padding = this.options.labelPadding;\n\n // Label text\n const labelText = `${artboard.name} (${Math.round(artboard.width)} × ${Math.round(artboard.height)})`;\n\n // Label position (above artboard)\n const labelX = artboard.x;\n const labelY = artboard.y - padding;\n\n // Render label text\n ctx.font = `${fontSize}px -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif`;\n const selectedBorderColor = this.options.selectedBorderColor || getThemeAccentColor();\n const labelColor = this.options.labelColor || getThemeArtboardLabelColor();\n ctx.fillStyle = isSelected ? selectedBorderColor : labelColor;\n ctx.textAlign = 'left';\n ctx.textBaseline = 'bottom';\n\n ctx.fillText(labelText, labelX, labelY);\n }\n\n /**\n * Render multiple artboards\n */\n renderMultiple(ctx: CanvasRenderingContext2D, artboards: ArtboardElement[], selectedId: string | null): void {\n // Render artboards in order (bottom to top)\n artboards.forEach((artboard) => {\n const isSelected = artboard.id === selectedId;\n this.render(ctx, artboard, isSelected);\n });\n }\n\n /**\n * Clip rendering to artboard bounds (respects clipShape)\n * Use this to clip element rendering to stay within artboard\n */\n clipToArtboard(ctx: CanvasRenderingContext2D, artboard: ArtboardElement): void {\n ctx.save();\n this.applyClipPath(ctx, artboard);\n }\n\n /**\n * Apply clip path based on artboard's clipShape\n * This creates the clip region for the given artboard\n * If borderRadius option is set and no special clipShape, uses rounded rectangle\n */\n applyClipPath(ctx: CanvasRenderingContext2D, artboard: ArtboardElement): void {\n const { x, y, width, height, clipShape } = artboard;\n\n // Debug: log borderRadius value\n if (this.options.borderRadius > 0) {\n }\n\n ctx.beginPath();\n\n // No clip shape or 'rectangle' = use borderRadius from options if set, otherwise standard rect\n if (!clipShape || clipShape === 'rectangle') {\n if (this.options.borderRadius > 0) {\n const radius = Math.min(this.options.borderRadius, Math.min(width, height) / 2);\n this.roundedRect(ctx, x, y, width, height, radius);\n } else {\n ctx.rect(x, y, width, height);\n }\n } else if (clipShape === 'circle') {\n // Circle inscribed in artboard\n const centerX = x + width / 2;\n const centerY = y + height / 2;\n const radius = Math.min(width, height) / 2;\n ctx.arc(centerX, centerY, radius, 0, Math.PI * 2);\n } else if (typeof clipShape === 'object' && clipShape.type === 'rounded') {\n // Rounded rectangle\n const radius = Math.min(clipShape.radius, Math.min(width, height) / 2);\n this.roundedRect(ctx, x, y, width, height, radius);\n } else if (typeof clipShape === 'object' && clipShape.type === 'path') {\n // Custom SVG path - use Path2D for parsing\n try {\n const path = new Path2D(clipShape.d);\n // Translate the path to artboard position\n ctx.translate(x, y);\n ctx.clip(path);\n ctx.translate(-x, -y);\n return; // Path2D handles the clip itself\n } catch (e) {\n logger.warn('Invalid SVG path, falling back to rectangle:', e);\n ctx.rect(x, y, width, height);\n }\n }\n\n ctx.clip();\n }\n\n /**\n * Draw a rounded rectangle path\n * Helper method for rounded clip shapes\n */\n private roundedRect(\n ctx: CanvasRenderingContext2D,\n x: number,\n y: number,\n width: number,\n height: number,\n radius: number\n ): void {\n // Use built-in roundRect if available\n if (typeof ctx.roundRect === 'function') {\n ctx.roundRect(x, y, width, height, radius);\n } else {\n // Fallback for older browsers\n ctx.moveTo(x + radius, y);\n ctx.lineTo(x + width - radius, y);\n ctx.arcTo(x + width, y, x + width, y + radius, radius);\n ctx.lineTo(x + width, y + height - radius);\n ctx.arcTo(x + width, y + height, x + width - radius, y + height, radius);\n ctx.lineTo(x + radius, y + height);\n ctx.arcTo(x, y + height, x, y + height - radius, radius);\n ctx.lineTo(x, y + radius);\n ctx.arcTo(x, y, x + radius, y, radius);\n }\n }\n\n /**\n * Restore after clipping\n */\n restoreClip(ctx: CanvasRenderingContext2D): void {\n ctx.restore();\n }\n\n /**\n * Render artboard outline (for dragging/resizing preview)\n */\n renderOutline(\n ctx: CanvasRenderingContext2D,\n x: number,\n y: number,\n width: number,\n height: number,\n isDragging: boolean = false\n ): void {\n ctx.save();\n\n // Dashed outline\n ctx.setLineDash([5, 5]);\n ctx.strokeStyle = isDragging ? '#0066cc' : '#999';\n ctx.lineWidth = 1;\n\n ctx.strokeRect(x, y, width, height);\n\n ctx.restore();\n }\n\n /**\n * Render resize handles for artboard\n */\n renderResizeHandles(ctx: CanvasRenderingContext2D, artboard: ArtboardElement): void {\n const handleSize = 8;\n const { x, y, width, height } = artboard;\n\n // Define handle positions (corners only for artboards)\n const handles = [\n { x: x, y: y }, // top-left\n { x: x + width, y: y }, // top-right\n { x: x, y: y + height }, // bottom-left\n { x: x + width, y: y + height }, // bottom-right\n ];\n\n ctx.save();\n\n handles.forEach((handle) => {\n // White fill with blue border\n ctx.fillStyle = '#fff';\n ctx.strokeStyle = '#0066cc';\n ctx.lineWidth = 2;\n\n ctx.fillRect(handle.x - handleSize / 2, handle.y - handleSize / 2, handleSize, handleSize);\n ctx.strokeRect(handle.x - handleSize / 2, handle.y - handleSize / 2, handleSize, handleSize);\n });\n\n ctx.restore();\n }\n\n /**\n * Update options\n */\n setOptions(options: Partial<ArtboardRenderOptions>): void {\n this.options = { ...this.options, ...options };\n }\n\n /**\n * Get current options\n */\n getOptions(): ArtboardRenderOptions {\n return { ...this.options };\n }\n\n /**\n * Create export-safe renderer\n * Returns a new renderer instance with preview background disabled\n * Use this when exporting to ensure preview background is never included\n */\n static createForExport(options: ArtboardRenderOptions = {}): ArtboardRenderer {\n return new ArtboardRenderer({\n ...options,\n showPreviewBackground: false, // CRITICAL: Never show preview in exports\n });\n }\n\n /**\n * Check if preview background would be rendered for given artboard\n */\n willRenderPreviewBackground(artboard: ArtboardElement): boolean {\n return !!(\n this.options.showPreviewBackground &&\n artboard.previewBackgroundColor &&\n artboard.previewBackgroundColor !== 'transparent'\n );\n }\n}\n\nexport default ArtboardRenderer;\n","/**\n * Type guards for EditorElement discrimination\n *\n * These guards use instanceof checks against the concrete element classes,\n * matching the pattern established in EditorContext.tsx. They accept\n * BaseElement | EditorElement | undefined | null for maximum flexibility\n * at call sites.\n */\n\nimport { BaseElement } from '../core/BaseElement.js';\nimport { TextElement } from '../core/TextElement.js';\nimport { ImageElement } from '../core/ImageElement.js';\nimport { GroupElement } from '../core/GroupElement.js';\nimport { ShapeElement } from '../core/ShapeElement.js';\nimport { PathElement } from '../core/PathElement.js';\n\ntype Narrowable = BaseElement | TextElement | ImageElement | GroupElement | ShapeElement | PathElement | undefined | null;\n\n/**\n * Type guard: checks if an element is a TextElement (or any text-based transform subclass).\n *\n * TextElement is the base class for all text transforms (custom, circle, arch, wave, etc.),\n * so this returns true for any text-based element regardless of its specific transformType.\n */\nexport function isTextElement(element: Narrowable): element is TextElement {\n return element instanceof TextElement;\n}\n\n/**\n * Type guard: checks if an element is an ImageElement.\n */\nexport function isImageElement(element: Narrowable): element is ImageElement {\n return element instanceof ImageElement;\n}\n\n/**\n * Type guard: checks if an element is a GroupElement.\n */\nexport function isGroupElement(element: Narrowable): element is GroupElement {\n return element instanceof GroupElement;\n}\n\n/**\n * Type guard: checks if an element is a ShapeElement.\n */\nexport function isShapeElement(element: Narrowable): element is ShapeElement {\n return element instanceof ShapeElement;\n}\n\n/**\n * Type guard: checks if an element is a PathElement.\n */\nexport function isPathElement(element: Narrowable): element is PathElement {\n return element instanceof PathElement;\n}\n","/**\n * ElementRenderUtils - Centralized rendering for all element types\n *\n * Provides consistent element rendering across mask, knockout, and export systems.\n * Supports rendering any element type (text, image, shape) with control over\n * fill-only, stroke-only, or both rendering modes.\n */\n\nimport type {\n AnyElementConfig,\n BaseTextElementConfig,\n ImageElementConfig,\n ShapeElementConfig,\n ShapeTransformData,\n RenderingContext,\n} from '../types/index.js';\nimport { renderTextStroke, renderImageStroke } from './StrokeRenderer.js';\nimport { renderTextFillOnly } from './canvas-renderer.js';\n\n/**\n * Rendering mode options\n */\nexport type RenderMode = 'fill' | 'stroke' | 'both';\n\n/**\n * Options for element rendering\n */\nexport interface ElementRenderOptions {\n mode?: RenderMode;\n renderingContext?: RenderingContext;\n // For images: optional loaded image object (avoids re-loading)\n loadedImage?: HTMLImageElement;\n}\n\n/**\n * Main dispatcher: Render any element type based on its transformType\n */\nexport function renderElement(\n ctx: CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D,\n element: AnyElementConfig,\n options: ElementRenderOptions = {}\n): void {\n const mode = options.mode || 'both';\n\n\n // Position and rotate the element\n ctx.save();\n ctx.translate(element.x || 0, element.y || 0);\n ctx.rotate((-(element.rotation || 0) * Math.PI) / 180);\n\n // Dispatch to appropriate renderer based on transformType\n switch (element.transformType) {\n case 'image':\n renderImageElement(ctx, element as ImageElementConfig, mode, options);\n break;\n\n case 'shape':\n renderShapeElement(ctx, element as ShapeElementConfig, mode, options);\n break;\n\n case 'group':\n // Groups don't render content themselves\n // In mask/knockout context, skip group rendering\n break;\n\n default:\n // All text transform types (custom, circle, arch, lean, ascend, wave, flag, etc.)\n renderTextElement(ctx, element, mode, options);\n break;\n }\n\n ctx.restore();\n}\n\n/**\n * Render text element (all text transform types)\n */\nfunction renderTextElement(\n ctx: CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D,\n element: AnyElementConfig,\n mode: RenderMode,\n options: ElementRenderOptions\n): void {\n // Narrow to text element config to access text properties\n const textElement = element as BaseTextElementConfig;\n const text = textElement.text || '';\n if (!text) return;\n\n // Render stroke BEFORE fill for outer-stroke effect.\n // Canvas strokeText draws centered on the glyph outline; drawing fill on top\n // covers the inner half, leaving only the outer half visible as a clean outline.\n if ((mode === 'stroke' || mode === 'both') && element.stroke?.enabled) {\n ctx.save();\n renderTextStroke(ctx, element, { ...options.renderingContext, positionApplied: true });\n ctx.restore();\n }\n\n // Render fill (on top of stroke, covering the inner half)\n if (mode === 'fill' || mode === 'both') {\n ctx.save();\n renderTextFillOnly(ctx, {\n text,\n fontSize: textElement.fontSize || 24,\n fontFamily: textElement.fontFamily || 'Arial',\n bold: textElement.bold || false,\n italic: textElement.italic || false,\n textAlign: textElement.textAlign || 'center',\n color: textElement.color || '#000000',\n });\n ctx.restore();\n }\n}\n\n/**\n * Render image element\n */\nfunction renderImageElement(\n ctx: CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D,\n element: ImageElementConfig,\n mode: RenderMode,\n options: ElementRenderOptions\n): void {\n if (!element.transformData) return;\n\n const transformData = element.transformData;\n\n // For fill mode, we need to render the actual image\n // This is simplified - in production you'd need to handle image loading\n if (mode === 'fill' || mode === 'both') {\n // Create image path for clipping\n createImagePath(ctx, element);\n\n // If we have a loaded image, draw it\n if (options.loadedImage) {\n ctx.save();\n ctx.clip();\n\n // Apply flip transformations\n const flipH = transformData.flipHorizontal ? -1 : 1;\n const flipV = transformData.flipVertical ? -1 : 1;\n ctx.scale(flipH, flipV);\n\n // Draw the image\n const width = transformData.width ?? 100;\n const height = transformData.height ?? 100;\n\n ctx.drawImage(options.loadedImage, -width / 2, -height / 2, width, height);\n\n ctx.restore();\n } else {\n // No loaded image - just fill the shape with placeholder color\n ctx.fillStyle = '#cccccc';\n ctx.fill();\n }\n }\n\n // Render stroke\n if ((mode === 'stroke' || mode === 'both') && element.stroke?.enabled) {\n ctx.save();\n renderImageStroke(ctx, element, options.renderingContext);\n ctx.restore();\n }\n}\n\n/**\n * Render shape element\n */\nfunction renderShapeElement(\n ctx: CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D,\n element: ShapeElementConfig,\n mode: RenderMode,\n options: ElementRenderOptions\n): void {\n if (!element.transformData) return;\n\n const transformData = element.transformData;\n const isKnockoutRender = options.renderingContext?.isKnockout === true;\n\n // Create the shape path\n ctx.beginPath();\n renderShapePath(ctx, transformData);\n\n // Render fill\n if (mode === 'fill' || mode === 'both') {\n ctx.fillStyle = isKnockoutRender ? '#000000' : transformData.fillColor || '#3b82f6';\n ctx.globalAlpha = isKnockoutRender ? 1.0 : (transformData.fillOpacity ?? 1);\n ctx.fill();\n }\n\n // Render stroke\n if ((mode === 'stroke' || mode === 'both') && element.stroke?.enabled) {\n ctx.save();\n renderShapeStroke(ctx, element, options.renderingContext);\n ctx.restore();\n }\n}\n\n/**\n * Create shape path based on shapeType\n * This is extracted from ShapeElement.render() for reusability\n */\nfunction renderShapePath(\n ctx: CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D,\n transformData: Partial<ShapeTransformData>\n): void {\n const { shapeType } = transformData;\n const width = transformData.width ?? 100;\n const height = transformData.height ?? 100;\n\n switch (shapeType) {\n case 'rectangle':\n renderRectanglePath(ctx, transformData as ShapeTransformData, width, height);\n break;\n case 'circle':\n renderCirclePath(ctx, Math.min(width, height) / 2);\n break;\n case 'ellipse':\n renderEllipsePath(ctx, width / 2, height / 2);\n break;\n case 'star':\n renderStarPath(ctx, transformData as ShapeTransformData, Math.min(width, height) / 2);\n break;\n default:\n // Fallback to rectangle for unsupported shapes\n renderRectanglePath(ctx, transformData as ShapeTransformData, width, height);\n }\n}\n\n/**\n * Rectangle path (with optional border radius)\n */\nfunction renderRectanglePath(\n ctx: CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D,\n transformData: ShapeTransformData,\n width: number,\n height: number\n): void {\n const borderRadius = transformData.borderRadius || 0;\n const x = -width / 2;\n const y = -height / 2;\n\n if (borderRadius > 0) {\n const radius = Math.min((borderRadius / 100) * Math.min(width, height), width / 2, height / 2);\n ctx.roundRect(x, y, width, height, radius);\n } else {\n ctx.rect(x, y, width, height);\n }\n}\n\n/**\n * Circle path\n */\nfunction renderCirclePath(ctx: CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D, radius: number): void {\n ctx.arc(0, 0, radius, 0, Math.PI * 2);\n}\n\n/**\n * Ellipse path\n */\nfunction renderEllipsePath(\n ctx: CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D,\n radiusX: number,\n radiusY: number\n): void {\n ctx.ellipse(0, 0, radiusX, radiusY, 0, 0, Math.PI * 2);\n}\n\n/**\n * Star path\n */\nfunction renderStarPath(\n ctx: CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D,\n transformData: ShapeTransformData,\n outerRadius: number\n): void {\n const points = Math.max(3, Math.min(20, transformData.points || 5));\n const innerRadiusRatio = Math.max(0.1, Math.min(0.9, transformData.innerRadius || 0.4));\n const innerRadius = outerRadius * innerRadiusRatio;\n const angleStep = Math.PI / points;\n const startAngle = -Math.PI / 2; // Start at top\n\n for (let i = 0; i < points * 2; i++) {\n const angle = startAngle + angleStep * i;\n const radius = i % 2 === 0 ? outerRadius : innerRadius;\n const x = Math.cos(angle) * radius;\n const y = Math.sin(angle) * radius;\n\n if (i === 0) {\n ctx.moveTo(x, y);\n } else {\n ctx.lineTo(x, y);\n }\n }\n\n ctx.closePath();\n}\n\n/**\n * Render stroke for shape element\n */\nfunction renderShapeStroke(\n ctx: CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D,\n element: ShapeElementConfig,\n renderingContext?: RenderingContext\n): void {\n if (!element.stroke?.enabled || !element.transformData) return;\n\n const isKnockoutRender = renderingContext?.isKnockout === true;\n\n ctx.save();\n\n // Apply stroke style\n if (isKnockoutRender) {\n ctx.strokeStyle = '#000000';\n ctx.lineWidth = element.stroke.width;\n ctx.lineCap = element.stroke.lineCap || 'butt';\n ctx.lineJoin = element.stroke.lineJoin || 'miter';\n ctx.globalAlpha = 1.0;\n } else {\n ctx.strokeStyle = element.stroke.color;\n ctx.lineWidth = element.stroke.width;\n ctx.lineCap = element.stroke.lineCap || 'butt';\n ctx.lineJoin = element.stroke.lineJoin || 'miter';\n\n if (element.stroke.opacity !== undefined) {\n ctx.globalAlpha = element.stroke.opacity;\n }\n }\n\n if (element.stroke.miterLimit !== undefined) {\n ctx.miterLimit = element.stroke.miterLimit;\n }\n\n if (element.stroke.dashArray && element.stroke.dashArray.length > 0) {\n ctx.setLineDash(element.stroke.dashArray);\n }\n\n // Apply feathering (blur) - only for non-knockout renders\n if (!isKnockoutRender && element.stroke.feather && element.stroke.feather > 0) {\n if ('filter' in ctx) {\n (ctx as CanvasRenderingContext2D).filter = `blur(${element.stroke.feather}px)`;\n }\n }\n\n // Create and stroke the shape path\n ctx.beginPath();\n renderShapePath(ctx, element.transformData);\n ctx.stroke();\n\n ctx.restore();\n}\n\n/**\n * Create image path for clipping/stroking\n * Handles border radius and image bounds\n */\nfunction createImagePath(\n ctx: CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D,\n element: ImageElementConfig\n): void {\n if (!element.transformData) return;\n\n const { borderRadius } = element.transformData;\n const width = element.transformData.width ?? 100;\n const height = element.transformData.height ?? 100;\n const x = -width / 2;\n const y = -height / 2;\n\n ctx.beginPath();\n\n if (borderRadius && borderRadius > 0) {\n const radius = Math.min((borderRadius / 100) * Math.min(width, height), width / 2, height / 2);\n ctx.roundRect(x, y, width, height, radius);\n } else {\n ctx.rect(x, y, width, height);\n }\n}\n","/**\n * CompositingRenderer - Compositing system with dual scope\n *\n * Supports two compositing modes:\n * - 'destination-out' (knockout): Cuts through affected content\n * - 'destination-in' (clip): Keeps only content within the element shape\n *\n * Supports two scopes:\n * - 'group': Compositing affects only siblings within the same group (DEFAULT)\n * - 'artboard': Compositing cuts through ALL layers to artboard background\n *\n * Use cases:\n * - Pillow/Pattern: Pattern layer + group with knockout text (scope: 'group')\n * - T-Shirt: Text with knockout stroke reveals shirt color (scope: 'artboard')\n * - Clip: Content below is masked to element shape (destination-in)\n */\n\nimport type { AnyElementConfig, KnockoutScope } from '../types/index.js';\nimport { renderElement } from './ElementRenderUtils.js';\n\n/** Supported composite operations */\nexport type CompositeOp = 'destination-out' | 'destination-in';\n\n/**\n * Render element with compositing (knockout or clip)\n * This is the main entry point for compositing rendering\n */\nexport function renderWithCompositing(\n ctx: CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D,\n compositingElement: AnyElementConfig,\n allElements: AnyElementConfig[],\n renderElementFn: (\n ctx: CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D,\n element: AnyElementConfig\n ) => void,\n artboardBackgroundColor?: string,\n artboard?: { x: number; y: number; width: number; height: number },\n compositeOp: CompositeOp = 'destination-out'\n): void {\n if (!compositingElement.knockoutParts) return;\n\n // Skip if no parts are actually enabled\n const hasAnyParts = compositingElement.knockoutParts.fill || compositingElement.knockoutParts.stroke;\n\n if (!hasAnyParts) {\n renderElementFn(ctx, compositingElement);\n return;\n }\n\n // Save the context state\n const savedTransform = ctx.getTransform();\n ctx.save();\n\n const scope = compositingElement.knockoutParts.scope || 'group';\n const affectedElements = getAffectedElements(compositingElement, scope, allElements);\n\n // For artboard scope with no affected elements, just render non-compositing parts\n if (affectedElements.length === 0 && scope === 'artboard') {\n renderNonCompositingParts(ctx, compositingElement, renderElementFn);\n ctx.restore();\n return;\n }\n\n // For group scope with no affected elements, render normally\n if (affectedElements.length === 0) {\n renderElementFn(ctx, compositingElement);\n ctx.restore();\n return;\n }\n\n // Use offscreen compositing to preserve artboard background\n const canvas = ctx.canvas;\n const mainTransform = ctx.getTransform();\n const dpr = mainTransform.a;\n\n const offscreen = createOffscreenCanvas(canvas.width, canvas.height);\n const offCtx = offscreen.getContext('2d');\n if (!offCtx) return;\n\n offCtx.scale(dpr, dpr);\n\n // Fill offscreen with artboard background\n if (artboardBackgroundColor && artboard) {\n offCtx.fillStyle = artboardBackgroundColor;\n offCtx.fillRect(artboard.x, artboard.y, artboard.width, artboard.height);\n }\n\n // Render affected elements to offscreen\n for (const element of affectedElements) {\n renderElementFn(offCtx, element);\n }\n\n // Render non-compositing stroke BEFORE fill cutout so the fill compositing\n // also punches through the stroke, leaving only its outer edge visible.\n // Without this, the stroke renders ON TOP of the fill compositing holes,\n // covering them with the stroke's inner half.\n if (compositingElement.knockoutParts.fill && !compositingElement.knockoutParts.stroke && compositingElement.stroke?.enabled) {\n offCtx.save();\n renderElementStroke(offCtx, compositingElement);\n offCtx.restore();\n }\n\n // Apply compositing operation\n offCtx.save();\n offCtx.globalCompositeOperation = compositeOp;\n\n if (compositingElement.knockoutParts.fill) {\n renderElementFill(offCtx, compositingElement, renderElementFn);\n }\n\n if (compositingElement.knockoutParts.stroke) {\n renderElementStroke(offCtx, compositingElement);\n }\n\n offCtx.restore();\n\n // Render non-compositing fill AFTER stroke cutout so it sits on top\n if (!compositingElement.knockoutParts.fill) {\n offCtx.save();\n renderElementFill(offCtx, compositingElement, renderElementFn);\n offCtx.restore();\n }\n\n // Composite offscreen to main canvas\n const logicalWidth = canvas.width / dpr;\n const logicalHeight = canvas.height / dpr;\n ctx.drawImage(offscreen as unknown as CanvasImageSource, 0, 0, logicalWidth, logicalHeight);\n\n // Restore context state\n ctx.restore();\n\n // Verify transform was restored correctly\n const afterRestore = ctx.getTransform();\n if (\n Math.abs(afterRestore.a - savedTransform.a) > 0.001 ||\n Math.abs(afterRestore.d - savedTransform.d) > 0.001 ||\n Math.abs(afterRestore.e - savedTransform.e) > 0.001 ||\n Math.abs(afterRestore.f - savedTransform.f) > 0.001\n ) {\n // Force restore if needed\n ctx.setTransform(\n savedTransform.a,\n savedTransform.b,\n savedTransform.c,\n savedTransform.d,\n savedTransform.e,\n savedTransform.f\n );\n }\n}\n\n/**\n * Render element with knockout compositing (destination-out)\n * Convenience wrapper — backward-compatible entry point\n */\nexport function renderWithKnockout(\n ctx: CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D,\n knockoutElement: AnyElementConfig,\n allElements: AnyElementConfig[],\n renderElementFn: (\n ctx: CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D,\n element: AnyElementConfig\n ) => void,\n artboardBackgroundColor?: string,\n artboard?: { x: number; y: number; width: number; height: number }\n): void {\n renderWithCompositing(ctx, knockoutElement, allElements, renderElementFn, artboardBackgroundColor, artboard, 'destination-out');\n}\n\n/**\n * Render element with clip compositing (destination-in)\n * Keeps only content within the element shape\n */\nexport function renderWithClip(\n ctx: CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D,\n clipElement: AnyElementConfig,\n allElements: AnyElementConfig[],\n renderElementFn: (\n ctx: CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D,\n element: AnyElementConfig\n ) => void,\n artboardBackgroundColor?: string,\n artboard?: { x: number; y: number; width: number; height: number }\n): void {\n renderWithCompositing(ctx, clipElement, allElements, renderElementFn, artboardBackgroundColor, artboard, 'destination-in');\n}\n\n/**\n * Determine which elements are affected by knockout based on scope\n */\nfunction getAffectedElements(\n knockoutElement: AnyElementConfig,\n scope: KnockoutScope,\n allElements: AnyElementConfig[]\n): AnyElementConfig[] {\n if (scope === 'artboard') {\n // Knockout affects ALL elements below this one in z-order\n return getAllElementsBelow(knockoutElement, allElements);\n } else {\n // scope === 'group': Knockout affects only group siblings\n return getGroupSiblings(knockoutElement, allElements);\n }\n}\n\n/**\n * Get all elements below knockout element in z-order\n * Used for 'artboard' scope\n */\nfunction getAllElementsBelow(knockoutElement: AnyElementConfig, allElements: AnyElementConfig[]): AnyElementConfig[] {\n const knockoutIndex = allElements.findIndex((el) => el.id === knockoutElement.id);\n if (knockoutIndex === -1) return [];\n\n // Return all elements that come before this one in the array (rendered below)\n return allElements.slice(0, knockoutIndex);\n}\n\n/**\n * Get sibling elements within the same group\n * Used for 'group' scope\n */\nfunction getGroupSiblings(knockoutElement: AnyElementConfig, allElements: AnyElementConfig[]): AnyElementConfig[] {\n // Find the parent group of the knockout element\n const parentGroup = findParentGroup(knockoutElement, allElements);\n\n if (!parentGroup) {\n // Element is not in a group, fall back to artboard scope behavior\n return getAllElementsBelow(knockoutElement, allElements);\n }\n\n // Get children of the parent group\n if (parentGroup.transformType !== 'group' || !parentGroup.children) {\n return [];\n }\n\n // Find the knockout element's index within the group\n const knockoutIndex = parentGroup.children.findIndex((child) => child.id === knockoutElement.id);\n\n if (knockoutIndex === -1) return [];\n\n // Return all siblings that come before this element (rendered below)\n return parentGroup.children.slice(0, knockoutIndex);\n}\n\n/**\n * Find parent group of an element\n * Recursively searches through group hierarchy\n */\nfunction findParentGroup(element: AnyElementConfig, allElements: AnyElementConfig[]): AnyElementConfig | null {\n for (const candidate of allElements) {\n if (candidate.transformType === 'group' && candidate.children) {\n // Check if element is a direct child\n if (candidate.children.some((child) => child.id === element.id)) {\n return candidate;\n }\n\n // Check nested groups recursively\n const nestedParent = findParentGroup(element, candidate.children);\n if (nestedParent) {\n return nestedParent;\n }\n }\n }\n\n return null;\n}\n\n/**\n * Render element fill (for knockout)\n * This renders ONLY the fill using the centralized renderer\n */\nfunction renderElementFill(\n ctx: CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D,\n element: AnyElementConfig,\n _renderFn: (ctx: CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D, element: AnyElementConfig) => void\n): void {\n // Use centralized renderer in fill-only mode with knockout context\n // This now supports text, images, and shapes\n renderElement(ctx, element, {\n mode: 'fill',\n renderingContext: { isKnockout: true },\n });\n}\n\n/**\n * Render element stroke (for knockout)\n */\nfunction renderElementStroke(\n ctx: CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D,\n element: AnyElementConfig\n): void {\n if (!element.stroke?.enabled) return;\n\n // Use centralized renderer in stroke-only mode with knockout context\n // This now supports text, images, and shapes\n renderElement(ctx, element, {\n mode: 'stroke',\n renderingContext: { isKnockout: true },\n });\n}\n\n/**\n * Render non-compositing parts of element\n */\nfunction renderNonCompositingParts(\n ctx: CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D,\n element: AnyElementConfig,\n renderFn: (ctx: CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D, element: AnyElementConfig) => void\n): void {\n const knockoutParts = element.knockoutParts;\n if (!knockoutParts) {\n renderFn(ctx, element);\n return;\n }\n\n // Render fill if not knocked out\n if (!knockoutParts.fill) {\n ctx.save();\n renderElementFill(ctx, element, renderFn);\n ctx.restore();\n }\n\n // Render stroke if not knocked out\n if (!knockoutParts.stroke && element.stroke?.enabled) {\n ctx.save();\n renderElementStroke(ctx, element);\n ctx.restore();\n }\n}\n\n/**\n * Create offscreen canvas for compositing\n */\nfunction createOffscreenCanvas(width: number, height: number): HTMLCanvasElement | OffscreenCanvas {\n if (typeof OffscreenCanvas !== 'undefined') {\n return new OffscreenCanvas(width, height);\n } else if (typeof document !== 'undefined') {\n const canvas = document.createElement('canvas');\n canvas.width = width;\n canvas.height = height;\n return canvas;\n }\n throw new Error('No canvas context available');\n}\n","/**\n * Mask utility functions\n * Helper functions for mask creation and manipulation\n */\n\nimport type { MaskDefinition, MaskType, AnyElementConfig } from '../types/index.js';\n\n/**\n * Create a new mask definition\n */\nexport function createMask(\n type: MaskType,\n maskElement: AnyElementConfig,\n options: Partial<Omit<MaskDefinition, 'id' | 'type' | 'maskElement'>> = {}\n): MaskDefinition {\n return {\n id: `mask-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`,\n type,\n maskElement,\n inverted: options.inverted || false,\n feather: options.feather || 0,\n opacity: options.opacity !== undefined ? options.opacity : 1.0,\n blendMode: options.blendMode || 'normal',\n };\n}\n\n/**\n * Create a clip mask from text\n */\nexport function createTextClipMask(\n text: string,\n fontSize: number = 100,\n fontFamily: string = 'Anton',\n options: Partial<Omit<MaskDefinition, 'id' | 'type' | 'maskElement'>> = {}\n): MaskDefinition {\n return createMask(\n 'clip',\n {\n transformType: 'custom',\n text,\n fontSize,\n fontFamily,\n x: 0,\n y: 0,\n rotation: 0,\n color: '#000000', // Color doesn't matter for clip masks\n },\n options\n );\n}\n\n/**\n * Create a clip mask from an image.\n * Opaque pixels in the image define the visible area; transparent pixels clip.\n */\nexport function createImageClipMask(\n imageUrl: string,\n width: number = 500,\n height: number = 500,\n options: Partial<Omit<MaskDefinition, 'id' | 'type' | 'maskElement'>> = {}\n): MaskDefinition {\n return createMask(\n 'clip',\n {\n transformType: 'image',\n imageUrl,\n x: 0,\n y: 0,\n rotation: 0,\n transformData: {\n type: 'image',\n width,\n height,\n cropX: 0,\n cropY: 0,\n cropWidth: 1,\n cropHeight: 1,\n flipHorizontal: false,\n flipVertical: false,\n borderRadius: 0,\n },\n },\n options\n );\n}\n\n/**\n * Create an alpha mask from an image.\n * The image's alpha channel controls element visibility.\n */\nexport function createImageAlphaMask(\n imageUrl: string,\n width: number = 500,\n height: number = 500,\n options: Partial<Omit<MaskDefinition, 'id' | 'type' | 'maskElement'>> = {}\n): MaskDefinition {\n return createMask(\n 'alpha',\n {\n transformType: 'image',\n imageUrl,\n x: 0,\n y: 0,\n rotation: 0,\n transformData: {\n type: 'image',\n width,\n height,\n cropX: 0,\n cropY: 0,\n cropWidth: 1,\n cropHeight: 1,\n flipHorizontal: false,\n flipVertical: false,\n borderRadius: 0,\n },\n },\n options\n );\n}\n\n/**\n * Create a luma mask from an image.\n * Bright pixels = visible, dark pixels = hidden.\n */\nexport function createImageLumaMask(\n imageUrl: string,\n width: number = 500,\n height: number = 500,\n options: Partial<Omit<MaskDefinition, 'id' | 'type' | 'maskElement'>> = {}\n): MaskDefinition {\n return createMask(\n 'luma',\n {\n transformType: 'image',\n imageUrl,\n x: 0,\n y: 0,\n rotation: 0,\n transformData: {\n type: 'image',\n width,\n height,\n cropX: 0,\n cropY: 0,\n cropWidth: 1,\n cropHeight: 1,\n flipHorizontal: false,\n flipVertical: false,\n borderRadius: 0,\n },\n },\n options\n );\n}\n\n/**\n * Create a distress mask from image/texture\n */\nexport function createDistressMask(\n textureUrl: string,\n opacity: number = 0.6,\n options: Partial<Omit<MaskDefinition, 'id' | 'type' | 'maskElement'>> = {}\n): MaskDefinition {\n return createMask(\n 'distress',\n {\n transformType: 'image',\n imageUrl: textureUrl,\n x: 0,\n y: 0,\n rotation: 0,\n transformData: {\n type: 'image',\n width: 500,\n height: 500,\n cropX: 0,\n cropY: 0,\n cropWidth: 1,\n cropHeight: 1,\n flipHorizontal: false,\n flipVertical: false,\n borderRadius: 0,\n },\n },\n { ...options, opacity }\n );\n}\n\n/**\n * Calculate relative position for mask element\n * Converts world coordinates to relative coordinates\n */\nexport function calculateRelativePosition(\n parentX: number,\n parentY: number,\n maskWorldX: number,\n maskWorldY: number\n): { x: number; y: number } {\n return {\n x: maskWorldX - parentX,\n y: maskWorldY - parentY,\n };\n}\n\n/**\n * Calculate world position for mask element\n * Converts relative coordinates to world coordinates\n */\nexport function calculateWorldPosition(\n parentX: number,\n parentY: number,\n maskRelativeX: number,\n maskRelativeY: number\n): { x: number; y: number } {\n return {\n x: parentX + maskRelativeX,\n y: parentY + maskRelativeY,\n };\n}\n\n/**\n * Validate mask definition\n */\nexport function isValidMask(mask: MaskDefinition): boolean {\n if (!mask.id || !mask.type) return false;\n if (!mask.maskElement) return false;\n if (mask.opacity !== undefined && (mask.opacity < 0 || mask.opacity > 1)) return false;\n if (mask.feather !== undefined && mask.feather < 0) return false;\n return true;\n}\n\n/**\n * Compute mask dimensions using object-contain scaling.\n *\n * The mask maintains its natural aspect ratio and scales to fit entirely\n * within the parent element's bounding box, plus an optional oversize bleed.\n * This prevents shape masks (star, heart, etc.) from stretching when\n * applied to non-square images, and ensures the full mask shape is visible\n * (no clipping of star points, heart bumps, etc.).\n */\nexport function computeMaskCoverDimensions(\n parentW: number,\n parentH: number,\n maskNaturalW: number,\n maskNaturalH: number,\n oversize: number = 0\n): { width: number; height: number } {\n if (maskNaturalW <= 0 || maskNaturalH <= 0 || parentW <= 0 || parentH <= 0) {\n return { width: parentW + oversize, height: parentH + oversize };\n }\n\n const maskAspect = maskNaturalW / maskNaturalH;\n const parentAspect = parentW / parentH;\n\n let fitW: number;\n let fitH: number;\n\n if (parentAspect > maskAspect) {\n // Parent is wider — constrain by height so mask fits vertically\n fitH = parentH;\n fitW = parentH * maskAspect;\n } else {\n // Parent is taller — constrain by width so mask fits horizontally\n fitW = parentW;\n fitH = parentW / maskAspect;\n }\n\n return {\n width: fitW + oversize,\n height: fitH + oversize,\n };\n}\n\n/**\n * Clone a mask definition\n */\nexport function cloneMask(mask: MaskDefinition): MaskDefinition {\n return {\n ...mask,\n id: `mask-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`,\n maskElement: { ...mask.maskElement },\n };\n}\n\n","/**\n * Built-in mask image presets — procedurally generated SVG shapes\n *\n * Each preset renders an SVG path to a canvas to produce a data URL.\n * The data URL is stored as `imageUrl` and registered with ImageCache\n * so MaskRenderer can find them. A 64x64 thumbnail is also generated.\n */\n\nimport { ImageCache } from '../core/ImageCache.js';\n\n/** Thumbnail size for UI grid */\nconst THUMB_SIZE = 64;\n\n/** Full mask size */\nconst MASK_SIZE = 512;\n\nexport interface MaskImagePreset {\n id: string;\n name: string;\n description: string;\n /** Synthetic key — also used as imageUrl for masks */\n imageUrl: string;\n /** Data URL thumbnail (populated by ensureMaskPresetsReady) */\n thumbnailUrl: string;\n category: 'geometric' | 'organic';\n /** SVG path draw function */\n draw: (ctx: CanvasRenderingContext2D, size: number) => void;\n}\n\n// ── Shape draw functions ────────────────────────────────────────────────────\n\nfunction drawCircle(ctx: CanvasRenderingContext2D, size: number) {\n ctx.beginPath();\n ctx.arc(size / 2, size / 2, size * 0.45, 0, Math.PI * 2);\n ctx.fill();\n}\n\nfunction drawStar(ctx: CanvasRenderingContext2D, size: number) {\n const cx = size / 2, cy = size / 2;\n const outerR = size * 0.45, innerR = outerR * 0.4;\n const points = 5;\n ctx.beginPath();\n for (let i = 0; i < points * 2; i++) {\n const angle = -Math.PI / 2 + (Math.PI / points) * i;\n const r = i % 2 === 0 ? outerR : innerR;\n const x = cx + Math.cos(angle) * r;\n const y = cy + Math.sin(angle) * r;\n if (i === 0) ctx.moveTo(x, y); else ctx.lineTo(x, y);\n }\n ctx.closePath();\n ctx.fill();\n}\n\nfunction drawHeart(ctx: CanvasRenderingContext2D, size: number) {\n const cx = size / 2, s = size * 0.42;\n ctx.beginPath();\n ctx.moveTo(cx, size * 0.82);\n ctx.bezierCurveTo(cx - s * 1.1, size * 0.6, cx - s * 1.3, size * 0.2, cx, size * 0.35);\n ctx.bezierCurveTo(cx + s * 1.3, size * 0.2, cx + s * 1.1, size * 0.6, cx, size * 0.82);\n ctx.closePath();\n ctx.fill();\n}\n\nfunction drawDiamond(ctx: CanvasRenderingContext2D, size: number) {\n const cx = size / 2, cy = size / 2;\n const rx = size * 0.4, ry = size * 0.48;\n ctx.beginPath();\n ctx.moveTo(cx, cy - ry);\n ctx.lineTo(cx + rx, cy);\n ctx.lineTo(cx, cy + ry);\n ctx.lineTo(cx - rx, cy);\n ctx.closePath();\n ctx.fill();\n}\n\nfunction drawHexagon(ctx: CanvasRenderingContext2D, size: number) {\n const cx = size / 2, cy = size / 2, r = size * 0.44;\n ctx.beginPath();\n for (let i = 0; i < 6; i++) {\n const angle = -Math.PI / 2 + (Math.PI / 3) * i;\n const x = cx + Math.cos(angle) * r;\n const y = cy + Math.sin(angle) * r;\n if (i === 0) ctx.moveTo(x, y); else ctx.lineTo(x, y);\n }\n ctx.closePath();\n ctx.fill();\n}\n\nfunction drawShield(ctx: CanvasRenderingContext2D, size: number) {\n const cx = size / 2, w = size * 0.4, top = size * 0.12;\n ctx.beginPath();\n ctx.moveTo(cx, top);\n ctx.lineTo(cx + w, size * 0.25);\n ctx.lineTo(cx + w, size * 0.55);\n ctx.quadraticCurveTo(cx + w * 0.3, size * 0.8, cx, size * 0.9);\n ctx.quadraticCurveTo(cx - w * 0.3, size * 0.8, cx - w, size * 0.55);\n ctx.lineTo(cx - w, size * 0.25);\n ctx.closePath();\n ctx.fill();\n}\n\nfunction drawSplatter(ctx: CanvasRenderingContext2D, size: number) {\n // Pseudo-random splatter using deterministic seed\n const cx = size / 2, cy = size / 2;\n let seed = 42;\n const rand = () => { seed = (seed * 16807 + 0) % 2147483647; return seed / 2147483647; };\n\n // Main blob\n ctx.beginPath();\n ctx.arc(cx, cy, size * 0.28, 0, Math.PI * 2);\n ctx.fill();\n\n // Splatter droplets\n for (let i = 0; i < 30; i++) {\n const angle = rand() * Math.PI * 2;\n const dist = size * 0.15 + rand() * size * 0.3;\n const r = size * 0.02 + rand() * size * 0.06;\n ctx.beginPath();\n ctx.arc(cx + Math.cos(angle) * dist, cy + Math.sin(angle) * dist, r, 0, Math.PI * 2);\n ctx.fill();\n }\n}\n\nfunction drawTornEdge(ctx: CanvasRenderingContext2D, size: number) {\n let seed = 123;\n const rand = () => { seed = (seed * 16807 + 0) % 2147483647; return seed / 2147483647; };\n\n const margin = size * 0.08;\n const steps = 40;\n ctx.beginPath();\n ctx.moveTo(margin, margin);\n\n // Top edge (jagged)\n for (let i = 1; i <= steps; i++) {\n const x = margin + (size - 2 * margin) * (i / steps);\n const y = margin + (rand() - 0.5) * size * 0.08;\n ctx.lineTo(x, y);\n }\n // Right edge\n for (let i = 1; i <= steps; i++) {\n const x = size - margin + (rand() - 0.5) * size * 0.08;\n const y = margin + (size - 2 * margin) * (i / steps);\n ctx.lineTo(x, y);\n }\n // Bottom edge\n for (let i = steps; i >= 0; i--) {\n const x = margin + (size - 2 * margin) * (i / steps);\n const y = size - margin + (rand() - 0.5) * size * 0.08;\n ctx.lineTo(x, y);\n }\n // Left edge\n for (let i = steps; i >= 0; i--) {\n const x = margin + (rand() - 0.5) * size * 0.08;\n const y = margin + (size - 2 * margin) * (i / steps);\n ctx.lineTo(x, y);\n }\n ctx.closePath();\n ctx.fill();\n}\n\nfunction drawPaintStroke(ctx: CanvasRenderingContext2D, size: number) {\n let seed = 77;\n const rand = () => { seed = (seed * 16807 + 0) % 2147483647; return seed / 2147483647; };\n\n const y0 = size * 0.25, y1 = size * 0.75;\n const margin = size * 0.1;\n\n ctx.beginPath();\n ctx.moveTo(margin, y0 + rand() * size * 0.05);\n // Top contour\n for (let i = 1; i <= 10; i++) {\n const x = margin + (size - 2 * margin) * (i / 10);\n const y = y0 + (rand() - 0.5) * size * 0.1;\n ctx.lineTo(x, y);\n }\n // Bottom contour (backwards)\n for (let i = 10; i >= 0; i--) {\n const x = margin + (size - 2 * margin) * (i / 10);\n const y = y1 + (rand() - 0.5) * size * 0.1;\n ctx.lineTo(x, y);\n }\n ctx.closePath();\n ctx.fill();\n}\n\nfunction drawCloud(ctx: CanvasRenderingContext2D, size: number) {\n const cx = size / 2, cy = size * 0.55;\n // Main body\n ctx.beginPath();\n ctx.arc(cx, cy, size * 0.2, 0, Math.PI * 2);\n ctx.fill();\n // Left bump\n ctx.beginPath();\n ctx.arc(cx - size * 0.18, cy + size * 0.02, size * 0.15, 0, Math.PI * 2);\n ctx.fill();\n // Right bump\n ctx.beginPath();\n ctx.arc(cx + size * 0.18, cy + size * 0.02, size * 0.16, 0, Math.PI * 2);\n ctx.fill();\n // Top bump\n ctx.beginPath();\n ctx.arc(cx - size * 0.06, cy - size * 0.14, size * 0.14, 0, Math.PI * 2);\n ctx.fill();\n ctx.beginPath();\n ctx.arc(cx + size * 0.1, cy - size * 0.12, size * 0.12, 0, Math.PI * 2);\n ctx.fill();\n}\n\n// ── Presets array ───────────────────────────────────────────────────────────\n\nexport const MASK_IMAGE_PRESETS: MaskImagePreset[] = [\n // Geometric\n { id: 'circle', name: 'Circle', description: 'Perfect circle', imageUrl: 'builtin-mask:circle', thumbnailUrl: '', category: 'geometric', draw: drawCircle },\n { id: 'star', name: 'Star', description: '5-pointed star', imageUrl: 'builtin-mask:star', thumbnailUrl: '', category: 'geometric', draw: drawStar },\n { id: 'heart', name: 'Heart', description: 'Heart shape', imageUrl: 'builtin-mask:heart', thumbnailUrl: '', category: 'geometric', draw: drawHeart },\n { id: 'diamond', name: 'Diamond', description: 'Diamond/rhombus', imageUrl: 'builtin-mask:diamond', thumbnailUrl: '', category: 'geometric', draw: drawDiamond },\n { id: 'hexagon', name: 'Hexagon', description: 'Regular hexagon', imageUrl: 'builtin-mask:hexagon', thumbnailUrl: '', category: 'geometric', draw: drawHexagon },\n { id: 'shield', name: 'Shield', description: 'Shield/crest shape', imageUrl: 'builtin-mask:shield', thumbnailUrl: '', category: 'geometric', draw: drawShield },\n // Organic\n { id: 'splatter', name: 'Splatter', description: 'Ink splatter', imageUrl: 'builtin-mask:splatter', thumbnailUrl: '', category: 'organic', draw: drawSplatter },\n { id: 'torn-edge', name: 'Torn Edge', description: 'Rough torn paper edge', imageUrl: 'builtin-mask:torn-edge', thumbnailUrl: '', category: 'organic', draw: drawTornEdge },\n { id: 'paint-stroke', name: 'Paint Stroke', description: 'Horizontal brush stroke', imageUrl: 'builtin-mask:paint-stroke', thumbnailUrl: '', category: 'organic', draw: drawPaintStroke },\n { id: 'cloud', name: 'Cloud', description: 'Soft cloud shape', imageUrl: 'builtin-mask:cloud', thumbnailUrl: '', category: 'organic', draw: drawCloud },\n];\n\n// ── Lazy initialization ─────────────────────────────────────────────────────\n\nlet initialized = false;\n\n/**\n * Create a DOM canvas for toDataURL (returns null in worker/SSR contexts).\n */\nfunction createDOMCanvas(width: number, height: number): HTMLCanvasElement | null {\n if (typeof document === 'undefined') return null;\n const canvas = document.createElement('canvas');\n canvas.width = width;\n canvas.height = height;\n return canvas;\n}\n\n/**\n * Generate all mask preset images, register in ImageCache, populate thumbnails.\n * Safe to call during render — idempotent and synchronous.\n * Skips silently during SSR (no document), but will run on client.\n */\nexport function ensureMaskPresetsReady(): void {\n // Skip during SSR but don't set initialized — allow client to run\n if (typeof document === 'undefined') return;\n if (initialized) return;\n initialized = true;\n\n const cache = ImageCache.getInstance();\n\n for (const preset of MASK_IMAGE_PRESETS) {\n // Generate full-size mask\n const maskCanvas = createDOMCanvas(MASK_SIZE, MASK_SIZE);\n if (!maskCanvas) continue;\n const maskCtx = maskCanvas.getContext('2d');\n if (!maskCtx) continue;\n\n maskCtx.fillStyle = 'white';\n preset.draw(maskCtx, MASK_SIZE);\n\n // Convert to data URL and preload via ImageCache\n const dataUrl = maskCanvas.toDataURL('image/png');\n\n // Register with ImageCache: acquire with the synthetic key, then load\n const img = cache.acquire(preset.imageUrl);\n img.crossOrigin = 'anonymous';\n img.src = dataUrl;\n // Don't release — keep alive for mask rendering\n\n // Generate 64x64 thumbnail\n const thumbCanvas = createDOMCanvas(THUMB_SIZE, THUMB_SIZE);\n if (thumbCanvas) {\n const thumbCtx = thumbCanvas.getContext('2d');\n if (thumbCtx) {\n // Dark background, white shape\n thumbCtx.fillStyle = '#1a1a2e';\n thumbCtx.fillRect(0, 0, THUMB_SIZE, THUMB_SIZE);\n thumbCtx.fillStyle = 'white';\n preset.draw(thumbCtx, THUMB_SIZE);\n preset.thumbnailUrl = thumbCanvas.toDataURL('image/png');\n }\n }\n }\n}\n\n/**\n * Get a mask preset by ID.\n */\nexport function getMaskPreset(id: string): MaskImagePreset | undefined {\n return MASK_IMAGE_PRESETS.find((p) => p.id === id);\n}\n\n// ── Worker-compatible bitmap generation ─────────────────────────────────────\n\n/**\n * Generate an ImageBitmap for a builtin mask preset.\n * Works in Web Worker contexts (uses OffscreenCanvas, no DOM).\n * Returns null if the preset ID is not found or OffscreenCanvas is unavailable.\n */\nexport function generateMaskBitmap(builtinUrl: string): ImageBitmap | null {\n if (!builtinUrl.startsWith('builtin-mask:')) return null;\n if (typeof OffscreenCanvas === 'undefined') return null;\n\n const id = builtinUrl.replace('builtin-mask:', '');\n const preset = MASK_IMAGE_PRESETS.find((p) => p.id === id);\n if (!preset) return null;\n\n const canvas = new OffscreenCanvas(MASK_SIZE, MASK_SIZE);\n const ctx = canvas.getContext('2d');\n if (!ctx) return null;\n\n ctx.fillStyle = 'white';\n preset.draw(ctx as unknown as CanvasRenderingContext2D, MASK_SIZE);\n\n return canvas.transferToImageBitmap();\n}\n","/**\n * MaskRenderer - Core mask rendering system\n *\n * Supports 4 mask types:\n * - clip: Hard edge clipping (text, shape)\n * - alpha: Transparency/alpha channel masking\n * - luma: Luminosity-based masking\n * - distress: Texture/grunge masking (HIGH PRIORITY for t-shirt design)\n */\n\nimport type { MaskDefinition, AnyElementConfig, ImageElementConfig, ArtboardImageMask } from '../types/index.js';\nimport { renderElement } from './ElementRenderUtils.js';\nimport { ImageCache } from '../core/ImageCache.js';\nimport { computeMaskCoverDimensions } from './mask-utils.js';\nimport { ensureMaskPresetsReady } from '../effects/mask-presets.js';\nimport { createLogger } from '../utils/logger.js';\n\nconst logger = createLogger('MaskRenderer');\n\n// Mask cache for performance optimization\nconst maskCache = new Map<string, HTMLCanvasElement | OffscreenCanvas>();\n\n// ---------------------------------------------------------------------------\n// Worker Mask Bitmap Registry\n// ---------------------------------------------------------------------------\n// In worker context (no DOM/ImageCache), mask image bitmaps must be\n// pre-loaded and registered here before rendering. The export worker\n// populates this registry before calling renderWithMasks.\n\nconst workerMaskBitmaps = new Map<string, ImageBitmap>();\n\n/**\n * Register a pre-loaded ImageBitmap for a mask image URL.\n * Call from the export worker after fetching mask images.\n */\nexport function registerMaskBitmap(imageUrl: string, bitmap: ImageBitmap): void {\n workerMaskBitmaps.set(imageUrl, bitmap);\n}\n\n/**\n * Clear all registered mask bitmaps (call after export completes).\n */\nexport function clearMaskBitmaps(): void {\n workerMaskBitmaps.clear();\n}\n\n/**\n * Clear mask cache for an element (call when element or masks change)\n */\nexport function invalidateMaskCache(elementId: string): void {\n const keysToDelete: string[] = [];\n maskCache.forEach((_, key) => {\n if (key.startsWith(elementId)) {\n keysToDelete.push(key);\n }\n });\n keysToDelete.forEach((key) => maskCache.delete(key));\n}\n\n/**\n * Clear entire mask cache\n */\nexport function clearMaskCache(): void {\n maskCache.clear();\n}\n\n/**\n * Render element with masks applied\n * This is the main entry point for masked rendering\n */\nexport function renderWithMasks(\n ctx: CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D,\n element: AnyElementConfig,\n renderFn: (ctx: CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D) => void\n): void {\n\n if (!element.masks || element.masks.length === 0) {\n // No masks, render normally\n renderFn(ctx);\n return;\n }\n\n // Create offscreen canvas for element\n const canvas = ctx.canvas;\n const offscreen = createOffscreenCanvas(canvas.width, canvas.height);\n const offCtx = offscreen.getContext('2d');\n if (!offCtx) {\n logger.error('[renderWithMasks] Failed to get offscreen context');\n return;\n }\n\n\n // Copy transform from main canvas to offscreen canvas (DPR scaling, etc.)\n const transform = ctx.getTransform();\n offCtx.setTransform(transform);\n\n // Render element to offscreen canvas\n renderFn(offCtx);\n\n // Apply each mask in order\n for (const mask of element.masks) {\n applyMask(offCtx, mask, element);\n }\n\n // Composite result back to main canvas\n // Reset transform to identity so we draw at device pixel 0,0\n ctx.save();\n ctx.setTransform(1, 0, 0, 1, 0, 0);\n ctx.drawImage(offscreen as unknown as CanvasImageSource, 0, 0);\n ctx.restore();\n}\n\n/**\n * Apply a single mask to the rendered content\n */\nfunction applyMask(\n ctx: CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D,\n mask: MaskDefinition,\n parentElement: AnyElementConfig\n): void {\n switch (mask.type) {\n case 'clip':\n applyClipMask(ctx, mask, parentElement);\n break;\n case 'alpha':\n applyAlphaMask(ctx, mask, parentElement);\n break;\n case 'luma':\n applyLumaMask(ctx, mask, parentElement);\n break;\n case 'distress':\n applyDistressMask(ctx, mask, parentElement);\n break;\n }\n}\n\n/**\n * Apply clip mask (hard edge)\n * Uses destination-in compositing to clip content\n */\nfunction applyClipMask(\n ctx: CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D,\n mask: MaskDefinition,\n parentElement: AnyElementConfig\n): void {\n ctx.save();\n ctx.globalCompositeOperation = mask.inverted ? 'destination-out' : 'destination-in';\n\n // Apply mask opacity if specified\n if (mask.opacity !== undefined) {\n ctx.globalAlpha = mask.opacity;\n }\n\n // Render mask element (positioned relative to parent)\n renderMaskElement(ctx, mask.maskElement, parentElement);\n\n ctx.restore();\n}\n\n/**\n * Apply alpha mask (transparency-based)\n * Similar to clip mask but with alpha channel\n */\nfunction applyAlphaMask(\n ctx: CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D,\n mask: MaskDefinition,\n parentElement: AnyElementConfig\n): void {\n ctx.save();\n ctx.globalCompositeOperation = mask.inverted ? 'destination-out' : 'destination-in';\n\n // Apply mask opacity\n if (mask.opacity !== undefined) {\n ctx.globalAlpha = mask.opacity;\n }\n\n // Render mask element\n renderMaskElement(ctx, mask.maskElement, parentElement);\n\n // Apply feathering (blur) if specified\n if (mask.feather && mask.feather > 0) {\n applyFeathering(ctx, mask.feather);\n }\n\n ctx.restore();\n}\n\n/**\n * Apply luma mask (luminosity-based)\n * Converts mask to grayscale and uses brightness for opacity\n */\nfunction applyLumaMask(\n ctx: CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D,\n mask: MaskDefinition,\n parentElement: AnyElementConfig\n): void {\n // Create offscreen canvas for mask\n const maskCanvas = createOffscreenCanvas(ctx.canvas.width, ctx.canvas.height);\n const maskCtx = maskCanvas.getContext('2d');\n if (!maskCtx) return;\n\n // Render mask element to offscreen\n renderMaskElement(maskCtx, mask.maskElement, parentElement);\n\n // Get image data and convert to luminosity\n const imageData = maskCtx.getImageData(0, 0, maskCanvas.width, maskCanvas.height);\n const data = imageData.data;\n\n for (let i = 0; i < data.length; i += 4) {\n const r = data[i];\n const g = data[i + 1];\n const b = data[i + 2];\n\n // Calculate luminosity (perceived brightness)\n const luma = 0.299 * r + 0.587 * g + 0.114 * b;\n\n // Use luminosity as alpha\n data[i + 3] = mask.inverted ? 255 - luma : luma;\n }\n\n maskCtx.putImageData(imageData, 0, 0);\n\n // Apply mask with opacity\n ctx.save();\n ctx.globalCompositeOperation = 'destination-in';\n if (mask.opacity !== undefined) {\n ctx.globalAlpha = mask.opacity;\n }\n ctx.drawImage(maskCanvas as unknown as CanvasImageSource, 0, 0);\n ctx.restore();\n}\n\n/**\n * Apply distress mask (texture-based grunge effect)\n * HIGH PRIORITY for t-shirt design\n */\nfunction applyDistressMask(\n ctx: CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D,\n mask: MaskDefinition,\n parentElement: AnyElementConfig\n): void {\n // Distress masks work similar to alpha masks but with texture\n ctx.save();\n ctx.globalCompositeOperation = mask.inverted ? 'destination-in' : 'destination-out';\n\n // Apply mask opacity (strength of distress effect)\n if (mask.opacity !== undefined) {\n ctx.globalAlpha = mask.opacity;\n }\n\n // Render distress texture/pattern\n renderMaskElement(ctx, mask.maskElement, parentElement);\n\n // Apply feathering for softer distress edges\n if (mask.feather && mask.feather > 0) {\n applyFeathering(ctx, mask.feather);\n }\n\n ctx.restore();\n}\n\n/**\n * Render mask element positioned relative to parent.\n *\n * For image-type mask elements, loads the image via ImageCache so it\n * renders actual pixels (not a gray placeholder). This is the key\n * enabler for image-based clip/alpha/luma masks.\n */\nfunction renderMaskElement(\n ctx: CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D,\n maskElement: AnyElementConfig,\n parentElement: AnyElementConfig\n): void {\n // Position mask relative to parent element\n const parentX = parentElement.x || 0;\n const parentY = parentElement.y || 0;\n const maskX = maskElement.x || 0;\n const maskY = maskElement.y || 0;\n\n // Create a copy of the mask element with absolute positioning\n // and inherited parent transform (rotation + scale).\n const absoluteMaskElement: AnyElementConfig = {\n ...maskElement,\n x: parentX + maskX,\n y: parentY + maskY,\n // Inherit parent rotation so mask rotates with the element\n rotation: (maskElement.rotation || 0) + (parentElement.rotation || 0),\n };\n\n // Scale mask to match parent dimensions so the mask covers the full element.\n // The mask is rendered 4px larger (2px per side) to prevent anti-aliased\n // edge outlines via destination-in compositing.\n //\n // For image-type masks with a different aspect ratio than the parent,\n // we use object-contain scaling: the mask shape is drawn at its natural\n // proportions centered within the parent-sized area. The transparent\n // padding around the centered shape ensures destination-in clips the\n // image outside the shape.\n const MASK_OVERSIZE = 4;\n const parentTd = (parentElement as ImageElementConfig).transformData;\n const parentAny = parentElement as unknown as Record<string, unknown>;\n const parentW = parentTd?.width || (parentAny.width as number) || 0;\n const parentH = parentTd?.height || (parentAny.height as number) || 0;\n const maskTd = (maskElement as ImageElementConfig).transformData;\n if (parentW && parentH && maskTd) {\n (absoluteMaskElement as ImageElementConfig).transformData = {\n ...maskTd,\n width: parentW + MASK_OVERSIZE,\n height: parentH + MASK_OVERSIZE,\n };\n }\n\n // For image mask elements, resolve the loaded image so renderElement\n // draws real pixels instead of a gray placeholder.\n let loadedImage: HTMLImageElement | undefined;\n let loadedBitmap: ImageBitmap | undefined;\n if (maskElement.transformType === 'image') {\n const imageConfig = maskElement as ImageElementConfig;\n if (imageConfig.imageUrl) {\n if (typeof document !== 'undefined') {\n // Main thread: use ImageCache. For `builtin-mask:*` URLs the\n // ImageCache only holds the rendered shape after\n // `ensureMaskPresetsReady()` has populated it. The mask-picker\n // panel calls that on mount, but a design loaded with masks\n // already attached (e.g. opening an existing design) never\n // triggers the panel — without this lazy init, the mask\n // resolves to an empty cache entry and `renderElement` falls\n // back to a placeholder rectangle, defeating the mask. The\n // export worker generates these bitmaps procedurally via\n // `preloadMaskImages`; this is the main-thread equivalent.\n if (imageConfig.imageUrl.startsWith('builtin-mask:')) {\n ensureMaskPresetsReady();\n }\n const cache = ImageCache.getInstance();\n const img = cache.acquire(imageConfig.imageUrl);\n if (img.complete && img.naturalWidth > 0) {\n loadedImage = img;\n }\n cache.release(imageConfig.imageUrl);\n } else {\n // Worker context: check the pre-loaded mask bitmap registry\n loadedBitmap = workerMaskBitmaps.get(imageConfig.imageUrl);\n }\n }\n }\n\n // Use the (potentially scaled) dimensions from absoluteMaskElement\n const resolvedTd = (absoluteMaskElement as ImageElementConfig).transformData;\n\n // Check if we need object-contain scaling for this mask image.\n // When the mask's natural aspect ratio differs from the parent's,\n // we draw the mask image centered at its natural proportions within\n // the parent-sized area, with transparent padding around it.\n const maskNaturalW = maskTd?.width || 0;\n const maskNaturalH = maskTd?.height || 0;\n const needsContainScaling = maskNaturalW > 0 && maskNaturalH > 0 && parentW > 0 && parentH > 0\n && Math.abs((maskNaturalW / maskNaturalH) - (parentW / parentH)) > 0.001;\n\n if (loadedBitmap) {\n // Worker path: draw the ImageBitmap directly as the mask\n ctx.save();\n const w = resolvedTd?.width || loadedBitmap.width;\n const h = resolvedTd?.height || loadedBitmap.height;\n ctx.translate(absoluteMaskElement.x || 0, absoluteMaskElement.y || 0);\n ctx.rotate((-(absoluteMaskElement.rotation || 0) * Math.PI) / 180);\n if (needsContainScaling) {\n // Object-contain: draw mask at proportional size, centered\n const contain = computeMaskCoverDimensions(\n w, h, maskNaturalW, maskNaturalH, 0\n );\n ctx.drawImage(loadedBitmap, -contain.width / 2, -contain.height / 2, contain.width, contain.height);\n } else {\n ctx.drawImage(loadedBitmap, -w / 2, -h / 2, w, h);\n }\n ctx.restore();\n } else if (needsContainScaling && loadedImage) {\n // Main thread path with contain scaling: draw the mask image manually\n // at its natural proportions centered within the parent-sized area.\n const w = resolvedTd?.width || parentW;\n const h = resolvedTd?.height || parentH;\n const contain = computeMaskCoverDimensions(\n w, h, maskNaturalW, maskNaturalH, 0\n );\n ctx.save();\n ctx.translate(absoluteMaskElement.x || 0, absoluteMaskElement.y || 0);\n ctx.rotate((-(absoluteMaskElement.rotation || 0) * Math.PI) / 180);\n ctx.drawImage(loadedImage, -contain.width / 2, -contain.height / 2, contain.width, contain.height);\n ctx.restore();\n } else {\n // Main thread path (or fallback): use renderElement with loadedImage\n renderElement(ctx, absoluteMaskElement, { mode: 'both', loadedImage });\n }\n}\n\n/**\n * Apply feathering (blur) to mask edges\n * Only works in regular CanvasRenderingContext2D (not OffscreenCanvas in workers)\n */\nfunction applyFeathering(\n ctx: CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D,\n featherRadius: number\n): void {\n // Feathering via CSS filter only works in main thread canvas context\n if ('filter' in ctx) {\n (ctx as CanvasRenderingContext2D).filter = `blur(${featherRadius}px)`;\n }\n}\n\n/**\n * Create offscreen canvas for mask rendering\n */\nfunction createOffscreenCanvas(width: number, height: number): HTMLCanvasElement | OffscreenCanvas {\n if (typeof OffscreenCanvas !== 'undefined') {\n return new OffscreenCanvas(width, height);\n } else if (typeof document !== 'undefined') {\n const canvas = document.createElement('canvas');\n canvas.width = width;\n canvas.height = height;\n return canvas;\n }\n throw new Error('No canvas context available');\n}\n\n/**\n * Apply artboard-level image mask.\n *\n * Same algorithm as applyArtboardDistressTexture in DistressTextureRenderer.ts:\n * only masks element pixels — artboard background stays solid.\n *\n * Algorithm:\n * 1. Copy the artboard region to an offscreen canvas\n * 2. Load mask image from ImageCache\n * 3. Apply composite op based on maskType + inverted\n * 4. Clear + redraw background + draw masked result\n */\nexport function applyArtboardImageMask(\n ctx: CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D,\n config: ArtboardImageMask,\n artboard: { x: number; y: number; width: number; height: number },\n artboardBackgroundColor?: string\n): void {\n if (!config.enabled || !config.imageUrl || config.opacity <= 0) return;\n\n // Load the mask image from ImageCache\n const cache = ImageCache.getInstance();\n const img = cache.acquire(config.imageUrl);\n if (!img.complete || img.naturalWidth === 0) {\n cache.release(config.imageUrl);\n return; // Still loading — will render next frame\n }\n\n const { x, y, width, height } = artboard;\n\n // Get the current transform to handle DPR + zoom correctly\n const transform = ctx.getTransform();\n\n // Calculate the pixel-space bounds of the artboard\n const pixelX = transform.a * x + transform.e;\n const pixelY = transform.d * y + transform.f;\n const pixelWidth = transform.a * width;\n const pixelHeight = transform.d * height;\n\n const offWidth = Math.ceil(pixelWidth);\n const offHeight = Math.ceil(pixelHeight);\n if (offWidth <= 0 || offHeight <= 0) {\n cache.release(config.imageUrl);\n return;\n }\n\n const offCanvas = createOffscreenCanvas(offWidth, offHeight);\n const offCtx = offCanvas.getContext('2d') as CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D;\n if (!offCtx) {\n cache.release(config.imageUrl);\n return;\n }\n\n // Copy the artboard region from the main canvas\n offCtx.drawImage(\n ctx.canvas,\n pixelX, pixelY, pixelWidth, pixelHeight,\n 0, 0, offWidth, offHeight\n );\n\n // Determine composite operation\n let compositeOp: GlobalCompositeOperation;\n if (config.maskType === 'luma') {\n // Luma needs pixel-level processing; handled below\n compositeOp = 'destination-in';\n } else {\n // clip and alpha both use destination-in/destination-out\n compositeOp = config.inverted ? 'destination-out' : 'destination-in';\n }\n\n if (config.maskType === 'luma') {\n // Luma: convert mask to grayscale alpha, then composite\n const lumaCanvas = createOffscreenCanvas(offWidth, offHeight);\n const lumaCtx = lumaCanvas.getContext('2d') as CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D;\n if (lumaCtx) {\n lumaCtx.drawImage(img, 0, 0, offWidth, offHeight);\n const imageData = lumaCtx.getImageData(0, 0, offWidth, offHeight);\n const data = imageData.data;\n for (let i = 0; i < data.length; i += 4) {\n const luma = 0.299 * data[i] + 0.587 * data[i + 1] + 0.114 * data[i + 2];\n data[i + 3] = config.inverted ? 255 - luma : luma;\n }\n lumaCtx.putImageData(imageData, 0, 0);\n\n offCtx.globalCompositeOperation = 'destination-in';\n offCtx.globalAlpha = config.opacity / 100;\n offCtx.drawImage(lumaCanvas as unknown as CanvasImageSource, 0, 0);\n }\n } else {\n offCtx.globalCompositeOperation = compositeOp;\n offCtx.globalAlpha = config.opacity / 100;\n offCtx.drawImage(img, 0, 0, offWidth, offHeight);\n }\n\n offCtx.globalCompositeOperation = 'source-over';\n offCtx.globalAlpha = 1;\n\n // Clear the artboard region on main canvas\n ctx.save();\n ctx.setTransform(1, 0, 0, 1, 0, 0);\n ctx.clearRect(pixelX, pixelY, pixelWidth, pixelHeight);\n\n // Redraw the artboard background so mask only affects elements\n if (artboardBackgroundColor) {\n ctx.fillStyle = artboardBackgroundColor;\n ctx.fillRect(pixelX, pixelY, pixelWidth, pixelHeight);\n }\n\n // Draw masked result on top\n ctx.drawImage(offCanvas, pixelX, pixelY);\n ctx.restore();\n\n cache.release(config.imageUrl);\n}\n","/**\n * DistressGenerator - Procedural distress texture generation\n * HIGH PRIORITY for t-shirt design\n *\n * Generates vintage/grunge effects:\n * - Worn: Perlin noise + edge wear\n * - Cracked: Crack/fracture patterns\n * - Grunge: Heavy texture overlay\n * - Retro: Halftone + fade effects\n */\n\nimport type { DistressEffect } from '../types/index.js';\n\n/**\n * Simple Perlin noise implementation\n * Used for organic distress patterns\n */\nclass SimplexNoise {\n private perm: number[];\n\n constructor(seed: number = Math.random()) {\n // Generate permutation table based on seed\n this.perm = [];\n for (let i = 0; i < 256; i++) {\n this.perm[i] = i;\n }\n\n // Shuffle using seed\n const random = this.seededRandom(seed);\n for (let i = 255; i > 0; i--) {\n const j = Math.floor(random() * (i + 1));\n [this.perm[i], this.perm[j]] = [this.perm[j], this.perm[i]];\n }\n\n // Extend permutation table\n for (let i = 0; i < 256; i++) {\n this.perm[256 + i] = this.perm[i];\n }\n }\n\n private seededRandom(seed: number): () => number {\n let x = Math.sin(seed++) * 10000;\n return () => {\n x = Math.sin(seed++) * 10000;\n return x - Math.floor(x);\n };\n }\n\n private fade(t: number): number {\n return t * t * t * (t * (t * 6 - 15) + 10);\n }\n\n private lerp(t: number, a: number, b: number): number {\n return a + t * (b - a);\n }\n\n private grad(hash: number, x: number, y: number): number {\n const h = hash & 15;\n const u = h < 8 ? x : y;\n const v = h < 4 ? y : h === 12 || h === 14 ? x : 0;\n return ((h & 1) === 0 ? u : -u) + ((h & 2) === 0 ? v : -v);\n }\n\n noise(x: number, y: number): number {\n const X = Math.floor(x) & 255;\n const Y = Math.floor(y) & 255;\n\n x -= Math.floor(x);\n y -= Math.floor(y);\n\n const u = this.fade(x);\n const v = this.fade(y);\n\n const a = this.perm[X] + Y;\n const b = this.perm[X + 1] + Y;\n\n return this.lerp(\n v,\n this.lerp(u, this.grad(this.perm[a], x, y), this.grad(this.perm[b], x - 1, y)),\n this.lerp(u, this.grad(this.perm[a + 1], x, y - 1), this.grad(this.perm[b + 1], x - 1, y - 1))\n );\n }\n}\n\n/**\n * Generate worn/vintage distress effect\n * Uses Perlin noise for organic edge wear\n */\nexport function generateWornEffect(\n width: number,\n height: number,\n intensity: number,\n seed: number = Date.now()\n): ImageData {\n const canvas = createCanvas(width, height);\n const ctx = canvas.getContext('2d')!;\n const imageData = ctx.createImageData(width, height);\n const data = imageData.data;\n\n const noise = new SimplexNoise(seed);\n const scale = 0.02; // Noise scale\n const threshold = 1 - intensity / 100; // Higher intensity = more distress\n\n for (let y = 0; y < height; y++) {\n for (let x = 0; x < width; x++) {\n const idx = (y * width + x) * 4;\n\n // Generate multi-octave noise for natural look\n let value = 0;\n value += noise.noise(x * scale, y * scale) * 0.5;\n value += noise.noise(x * scale * 2, y * scale * 2) * 0.25;\n value += noise.noise(x * scale * 4, y * scale * 4) * 0.125;\n\n // Normalize to 0-1\n value = (value + 1) / 2;\n\n // Edge wear (more distress at edges)\n const edgeX = Math.min(x / width, (width - x) / width) * 2;\n const edgeY = Math.min(y / height, (height - y) / height) * 2;\n const edgeFactor = Math.min(edgeX, edgeY);\n value *= 0.7 + edgeFactor * 0.3;\n\n // Apply threshold\n const alpha = value > threshold ? 255 : 0;\n\n data[idx] = 255; // R\n data[idx + 1] = 255; // G\n data[idx + 2] = 255; // B\n data[idx + 3] = alpha; // A\n }\n }\n\n return imageData;\n}\n\n/**\n * Generate cracked/fractured distress effect\n * Creates crack patterns using branching algorithm\n */\nexport function generateCrackedEffect(\n width: number,\n height: number,\n intensity: number,\n seed: number = Date.now()\n): ImageData {\n const canvas = createCanvas(width, height);\n const ctx = canvas.getContext('2d')!;\n\n // Clear to transparent\n ctx.clearRect(0, 0, width, height);\n\n // Set up crack drawing\n ctx.strokeStyle = '#000000';\n ctx.lineWidth = 1 + intensity / 50; // Thicker cracks with higher intensity\n ctx.lineCap = 'round';\n\n const random = seededRandom(seed);\n const numCracks = Math.floor((intensity / 100) * 30 + 5); // 5-35 cracks\n\n // Generate multiple crack paths\n for (let i = 0; i < numCracks; i++) {\n const startX = random() * width;\n const startY = random() * height;\n\n drawCrackBranch(ctx, startX, startY, random() * Math.PI * 2, 50 + random() * 100, random, 0);\n }\n\n return ctx.getImageData(0, 0, width, height);\n}\n\n/**\n * Recursively draw crack branch\n */\nfunction drawCrackBranch(\n ctx: CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D,\n x: number,\n y: number,\n angle: number,\n length: number,\n random: () => number,\n depth: number\n): void {\n if (depth > 3 || length < 10) return;\n\n const endX = x + Math.cos(angle) * length;\n const endY = y + Math.sin(angle) * length;\n\n ctx.beginPath();\n ctx.moveTo(x, y);\n ctx.lineTo(endX, endY);\n ctx.stroke();\n\n // Random branching\n if (random() > 0.5) {\n const branchAngle = angle + ((random() - 0.5) * Math.PI) / 2;\n drawCrackBranch(ctx, endX, endY, branchAngle, length * 0.6, random, depth + 1);\n }\n\n if (random() > 0.7) {\n const branchAngle = angle - ((random() - 0.5) * Math.PI) / 2;\n drawCrackBranch(ctx, endX, endY, branchAngle, length * 0.6, random, depth + 1);\n }\n}\n\n/**\n * Generate grunge/heavy texture effect\n * Dense noise pattern for heavy distress\n */\nexport function generateGrungeEffect(\n width: number,\n height: number,\n intensity: number,\n seed: number = Date.now()\n): ImageData {\n const canvas = createCanvas(width, height);\n const ctx = canvas.getContext('2d')!;\n const imageData = ctx.createImageData(width, height);\n const data = imageData.data;\n\n const random = seededRandom(seed);\n const density = (intensity / 100) * 0.5; // 0-50% density\n\n for (let y = 0; y < height; y++) {\n for (let x = 0; x < width; x++) {\n const idx = (y * width + x) * 4;\n\n // Random splatters\n const value = random();\n const alpha = value < density ? 255 : 0;\n\n data[idx] = 0; // R (black)\n data[idx + 1] = 0; // G\n data[idx + 2] = 0; // B\n data[idx + 3] = alpha; // A\n }\n }\n\n return imageData;\n}\n\n/**\n * Generate retro/halftone distress effect\n * Dot pattern with fade\n */\nexport function generateRetroEffect(\n width: number,\n height: number,\n intensity: number,\n seed: number = Date.now()\n): ImageData {\n const canvas = createCanvas(width, height);\n const ctx = canvas.getContext('2d')!;\n ctx.fillStyle = '#000000';\n\n const random = seededRandom(seed);\n const dotSize = 4 + (intensity / 100) * 6; // 4-10px dots\n const spacing = dotSize * 2;\n\n // Draw halftone dots with random intensity\n for (let y = 0; y < height; y += spacing) {\n for (let x = 0; x < width; x += spacing) {\n if (random() < intensity / 100) {\n const size = dotSize * (0.5 + random() * 0.5);\n ctx.beginPath();\n ctx.arc(x, y, size / 2, 0, Math.PI * 2);\n ctx.fill();\n }\n }\n }\n\n return ctx.getImageData(0, 0, width, height);\n}\n\n/**\n * Apply distress effect to existing canvas\n * Composites distress onto rendered content\n */\nexport function applyDistressEffect(\n ctx: CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D,\n distress: DistressEffect\n): void {\n if (!distress.enabled) return;\n\n const width = ctx.canvas.width;\n const height = ctx.canvas.height;\n const seed = distress.seed || Date.now();\n\n let distressData: ImageData;\n\n // Generate distress pattern based on style\n switch (distress.style) {\n case 'worn':\n distressData = generateWornEffect(width, height, distress.intensity, seed);\n break;\n case 'cracked':\n distressData = generateCrackedEffect(width, height, distress.intensity, seed);\n break;\n case 'grunge':\n distressData = generateGrungeEffect(width, height, distress.intensity, seed);\n break;\n case 'retro':\n distressData = generateRetroEffect(width, height, distress.intensity, seed);\n break;\n default:\n return;\n }\n\n // Create temporary canvas for distress\n const tempCanvas = createCanvas(width, height);\n const tempCtx = tempCanvas.getContext('2d')!;\n tempCtx.putImageData(distressData, 0, 0);\n\n // Apply distress using destination-out to remove pixels\n ctx.save();\n ctx.globalCompositeOperation = 'destination-out';\n ctx.globalAlpha = distress.intensity / 100;\n ctx.drawImage(tempCanvas, 0, 0);\n ctx.restore();\n}\n\n/**\n * Create canvas (works in both main thread and worker)\n */\nfunction createCanvas(width: number, height: number): HTMLCanvasElement | OffscreenCanvas {\n if (typeof OffscreenCanvas !== 'undefined') {\n return new OffscreenCanvas(width, height);\n } else if (typeof document !== 'undefined') {\n const canvas = document.createElement('canvas');\n canvas.width = width;\n canvas.height = height;\n return canvas;\n }\n throw new Error('No canvas context available');\n}\n\n/**\n * Seeded random number generator\n */\nfunction seededRandom(seed: number): () => number {\n let x = Math.sin(seed++) * 10000;\n return () => {\n x = Math.sin(seed++) * 10000;\n return x - Math.floor(x);\n };\n}\n","/**\n * Built-in distress texture presets — procedurally generated\n *\n * Each preset uses generators from DistressGenerator.ts to create\n * textures at runtime. No external JPG files needed.\n *\n * Alpha mask convention: RGB=255 (white), A=opacity of knockout.\n * Dark/opaque pixels knock out design pixels, transparent preserves them.\n */\n\nimport {\n generateWornEffect,\n generateCrackedEffect,\n generateGrungeEffect,\n generateRetroEffect,\n} from './DistressGenerator.js';\nimport { registerAlphaMask } from './DistressTextureCache.js';\n\n/** Fixed seed so textures look the same across sessions */\nconst BUILTIN_SEED = 42;\n\n/** Full texture size */\nconst TEX_SIZE = 512;\n\n/** Thumbnail size for UI grid */\nconst THUMB_SIZE = 64;\n\nexport interface DistressTexturePreset {\n id: string;\n name: string;\n /** Synthetic key used for cache lookup (e.g. \"builtin:grunge-heavy\") */\n textureUrl: string;\n /** Data URL thumbnail (populated by ensureBuiltinTexturesReady) */\n thumbnailUrl: string;\n /** Brief description of the texture style */\n description: string;\n /** Generator function for this preset's texture */\n generate: (w: number, h: number) => ImageData;\n}\n\n/**\n * Convert generator output to alpha mask format.\n * Generators may output black RGB with alpha (grunge, cracked, retro)\n * or white RGB with alpha (worn). This normalizes to white RGB + alpha.\n */\nfunction toAlphaMask(imageData: ImageData): ImageData {\n const data = imageData.data;\n for (let i = 0; i < data.length; i += 4) {\n data[i] = 255; // R\n data[i + 1] = 255; // G\n data[i + 2] = 255; // B\n // A stays as-is\n }\n return imageData;\n}\n\n/**\n * Layer two ImageData arrays together (OR their alpha channels).\n * Both must be the same dimensions.\n */\nfunction layerAlpha(a: ImageData, b: ImageData): ImageData {\n const data = a.data;\n const bData = b.data;\n for (let i = 0; i < data.length; i += 4) {\n // Combine: clamp(a + b) for alpha\n data[i] = 255;\n data[i + 1] = 255;\n data[i + 2] = 255;\n data[i + 3] = Math.min(255, data[i + 3] + bData[i + 3]);\n }\n return a;\n}\n\n/**\n * Built-in distress texture presets.\n */\nexport const DISTRESS_TEXTURE_PRESETS: DistressTexturePreset[] = [\n {\n id: 'grunge-heavy',\n name: 'Heavy Grunge',\n textureUrl: 'builtin:grunge-heavy',\n thumbnailUrl: '',\n description: 'Dense random splatters',\n generate: (w, h) => generateGrungeEffect(w, h, 80, BUILTIN_SEED),\n },\n {\n id: 'grunge-fine',\n name: 'Fine Grunge',\n textureUrl: 'builtin:grunge-fine',\n thumbnailUrl: '',\n description: 'Sparse fine grain',\n generate: (w, h) => generateGrungeEffect(w, h, 25, BUILTIN_SEED + 1),\n },\n {\n id: 'concrete',\n name: 'Concrete',\n textureUrl: 'builtin:concrete',\n thumbnailUrl: '',\n description: 'Rough surface via Perlin noise',\n generate: (w, h) => generateWornEffect(w, h, 55, BUILTIN_SEED + 2),\n },\n {\n id: 'paper',\n name: 'Old Paper',\n textureUrl: 'builtin:paper',\n thumbnailUrl: '',\n description: 'Subtle aging',\n generate: (w, h) => generateWornEffect(w, h, 20, BUILTIN_SEED + 3),\n },\n {\n id: 'rust',\n name: 'Rust',\n textureUrl: 'builtin:rust',\n thumbnailUrl: '',\n description: 'Noise + splatter combined',\n generate: (w, h) => {\n const worn = generateWornEffect(w, h, 45, BUILTIN_SEED + 4);\n const grunge = generateGrungeEffect(w, h, 35, BUILTIN_SEED + 5);\n return layerAlpha(toAlphaMask(worn), toAlphaMask(grunge));\n },\n },\n {\n id: 'scratches',\n name: 'Scratches',\n textureUrl: 'builtin:scratches',\n thumbnailUrl: '',\n description: 'Branching crack lines',\n generate: (w, h) => generateCrackedEffect(w, h, 55, BUILTIN_SEED + 6),\n },\n {\n id: 'halftone',\n name: 'Halftone',\n textureUrl: 'builtin:halftone',\n thumbnailUrl: '',\n description: 'Dot grid pattern',\n generate: (w, h) => generateRetroEffect(w, h, 55, BUILTIN_SEED + 7),\n },\n {\n id: 'spray',\n name: 'Spray Paint',\n textureUrl: 'builtin:spray',\n thumbnailUrl: '',\n description: 'Medium random splatter',\n generate: (w, h) => generateGrungeEffect(w, h, 55, BUILTIN_SEED + 8),\n },\n];\n\n/**\n * Get a texture preset by ID\n */\nexport function getDistressTexturePreset(id: string): DistressTexturePreset | undefined {\n return DISTRESS_TEXTURE_PRESETS.find((p) => p.id === id);\n}\n\n// ---------------------------------------------------------------------------\n// Lazy initialization\n// ---------------------------------------------------------------------------\n\nlet initialized = false;\n\n/**\n * Create a canvas (works in both main thread and worker).\n */\nfunction createCanvas(width: number, height: number): HTMLCanvasElement | OffscreenCanvas {\n if (typeof OffscreenCanvas !== 'undefined') {\n return new OffscreenCanvas(width, height);\n }\n const canvas = document.createElement('canvas');\n canvas.width = width;\n canvas.height = height;\n return canvas;\n}\n\n/**\n * Create an HTMLCanvasElement (required for toDataURL).\n * Returns null in worker contexts where document is unavailable.\n */\nfunction createDOMCanvas(width: number, height: number): HTMLCanvasElement | null {\n if (typeof document === 'undefined') return null;\n const canvas = document.createElement('canvas');\n canvas.width = width;\n canvas.height = height;\n return canvas;\n}\n\n/**\n * Generate a data URL thumbnail from ImageData.\n * Must use HTMLCanvasElement (not OffscreenCanvas) for toDataURL support.\n */\nfunction generateThumbnailDataUrl(imageData: ImageData): string {\n // Convert alpha-mask texture into a grayscale thumbnail:\n // High alpha (texture present) → dark pixels, low alpha → white pixels.\n // This matches how tools like Kittl display texture previews.\n\n // First, scale the full-size texture down to thumbnail size\n const fullCanvas = createDOMCanvas(imageData.width, imageData.height);\n if (!fullCanvas) return '';\n const fullCtx = fullCanvas.getContext('2d');\n if (!fullCtx) return '';\n fullCtx.putImageData(imageData, 0, 0);\n\n const canvas = createDOMCanvas(THUMB_SIZE, THUMB_SIZE);\n if (!canvas) return '';\n const ctx = canvas.getContext('2d');\n if (!ctx) return '';\n\n // Draw scaled-down texture to get the alpha values at thumbnail resolution\n ctx.drawImage(fullCanvas, 0, 0, imageData.width, imageData.height, 0, 0, THUMB_SIZE, THUMB_SIZE);\n\n // Read back pixel data and convert alpha → grayscale\n const thumbData = ctx.getImageData(0, 0, THUMB_SIZE, THUMB_SIZE);\n const pixels = thumbData.data;\n for (let i = 0; i < pixels.length; i += 4) {\n // alpha 0 → white (255), alpha 255 → dark gray (~60)\n const a = pixels[i + 3]!;\n const gray = 255 - Math.round((a / 255) * 195);\n pixels[i] = gray; // R\n pixels[i + 1] = gray; // G\n pixels[i + 2] = gray; // B\n pixels[i + 3] = 255; // Fully opaque\n }\n ctx.putImageData(thumbData, 0, 0);\n\n return canvas.toDataURL('image/png');\n}\n\n/**\n * Lazily generate all built-in textures, register them in the cache,\n * and populate thumbnail data URLs. No-ops on subsequent calls.\n */\nexport function ensureBuiltinTexturesReady(): void {\n if (initialized) return;\n initialized = true;\n\n for (const preset of DISTRESS_TEXTURE_PRESETS) {\n // Generate the full-size texture\n const imageData = preset.generate(TEX_SIZE, TEX_SIZE);\n\n // Convert to alpha mask format (white RGB, keep alpha)\n toAlphaMask(imageData);\n\n // Put into a canvas for the cache\n const maskCanvas = createCanvas(TEX_SIZE, TEX_SIZE);\n const maskCtx = maskCanvas.getContext('2d') as CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D;\n if (maskCtx) {\n maskCtx.putImageData(imageData, 0, 0);\n registerAlphaMask(preset.textureUrl, maskCanvas, TEX_SIZE, TEX_SIZE);\n }\n\n // Generate thumbnail data URL (only works in browser context, not worker)\n if (typeof document !== 'undefined') {\n preset.thumbnailUrl = generateThumbnailDataUrl(imageData);\n }\n }\n}\n","/**\n * DistressTextureCache - Loads grayscale JPEG textures and converts them to alpha masks.\n *\n * Dark pixels in the texture → high alpha (will knock out design pixels)\n * Light pixels in the texture → low alpha (will preserve design pixels)\n *\n * Shared between artboard-level and per-element distress texture rendering.\n * Works with both HTMLCanvasElement (preview) and OffscreenCanvas (export worker).\n */\n\n// Circular import: `distress-textures.ts` imports `registerAlphaMask` from\n// here. ES module circularity is fine because we only call this function from\n// inside `getAlphaMask`, not at module init time.\nimport { ensureBuiltinTexturesReady } from './distress-textures.js';\n\ntype CanvasLike = HTMLCanvasElement | OffscreenCanvas;\ntype ContextLike = CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D;\n\ninterface CacheEntry {\n alphaMask: CanvasLike;\n width: number;\n height: number;\n}\n\n/** URLs currently being loaded (prevents duplicate fetches) */\nconst loadingUrls = new Set<string>();\n\n/** Cached alpha masks keyed by texture URL */\nconst cache = new Map<string, CacheEntry>();\n\n/** Callbacks waiting for a URL to finish loading */\nconst pendingCallbacks = new Map<string, Array<() => void>>();\n\n/**\n * Create an offscreen canvas, preferring OffscreenCanvas when available\n * (required for Web Worker export context).\n */\nfunction createCanvas(width: number, height: number): CanvasLike {\n if (typeof OffscreenCanvas !== 'undefined') {\n return new OffscreenCanvas(width, height);\n }\n const canvas = document.createElement('canvas');\n canvas.width = width;\n canvas.height = height;\n return canvas;\n}\n\nfunction getContext(canvas: CanvasLike): ContextLike | null {\n return canvas.getContext('2d') as ContextLike | null;\n}\n\n/**\n * Convert a loaded image's grayscale luminance to an alpha channel.\n * The resulting canvas has:\n * - RGB = white (255,255,255) everywhere\n * - Alpha = inverted luminance (dark source pixels → high alpha → strong knockout)\n *\n * Luminance formula: 0.299R + 0.587G + 0.114B (matches MaskRenderer.applyLumaMask)\n */\nfunction convertToAlphaMask(source: ImageBitmap | HTMLImageElement): CacheEntry {\n const { width, height } = source;\n\n // Draw source image to get pixel data\n const tempCanvas = createCanvas(width, height);\n const tempCtx = getContext(tempCanvas);\n if (!tempCtx) throw new Error('Failed to get 2d context for temp canvas');\n\n tempCtx.drawImage(source, 0, 0);\n const imageData = tempCtx.getImageData(0, 0, width, height);\n const data = imageData.data;\n\n // Convert: luminance → alpha (inverted: dark = high alpha = more knockout)\n for (let i = 0; i < data.length; i += 4) {\n const r = data[i];\n const g = data[i + 1];\n const b = data[i + 2];\n\n // Standard luminance\n const luma = 0.299 * r + 0.587 * g + 0.114 * b;\n\n // Invert: dark source pixels → high alpha (strong knockout)\n const alpha = 255 - luma;\n\n // Set pixel to white with computed alpha\n data[i] = 255; // R\n data[i + 1] = 255; // G\n data[i + 2] = 255; // B\n data[i + 3] = alpha;\n }\n\n // Write to the alpha mask canvas\n const maskCanvas = createCanvas(width, height);\n const maskCtx = getContext(maskCanvas);\n if (!maskCtx) throw new Error('Failed to get 2d context for mask canvas');\n\n maskCtx.putImageData(imageData, 0, 0);\n\n return { alphaMask: maskCanvas, width, height };\n}\n\n/**\n * Get a cached alpha mask for the given texture URL.\n * Returns the cached canvas synchronously if available, or null if still loading.\n * Automatically starts loading if the URL hasn't been requested before.\n */\nexport function getAlphaMask(url: string): CacheEntry | null {\n // Return cached immediately\n const cached = cache.get(url);\n if (cached) return cached;\n\n // CRITICAL: `builtin:*` URLs are synthetic keys for procedurally-generated\n // textures, NOT real network resources. The distress-picker panel calls\n // `ensureBuiltinTexturesReady()` on mount to populate the cache, but a\n // design loaded with a `builtin:` distress texture already attached (no\n // panel ever opened) leaves the cache empty. Without this lazy init we'd\n // fall through to `loadTexture(url)` → `img.src = \"builtin:grunge-heavy\"`\n // → CORS-blocked browser fetch → `onerror` clears `loadingUrls` → next\n // render frame retries the same failed fetch. The result is a CORS-error\n // spam loop that pegs the editor at single-digit FPS and makes every\n // export wait ~20s for the render loop to settle. Match the same fix\n // shape as `MaskRenderer` lazy-calling `ensureMaskPresetsReady()` for\n // `builtin-mask:*` URLs (canvas/CLAUDE.md gotcha #26).\n if (url.startsWith('builtin:')) {\n ensureBuiltinTexturesReady();\n const post = cache.get(url);\n if (post) return post;\n // If `ensureBuiltinTexturesReady` couldn't populate (e.g. unknown\n // preset name), don't try a network load — there's nothing at that URL.\n return null;\n }\n\n // Already loading — just wait\n if (loadingUrls.has(url)) return null;\n\n // Start loading\n loadingUrls.add(url);\n loadTexture(url);\n\n return null;\n}\n\n/**\n * Get a cached alpha mask synchronously (no auto-loading).\n * Returns null if not cached.\n */\nexport function getAlphaMaskSync(url: string): CacheEntry | null {\n return cache.get(url) ?? null;\n}\n\n/**\n * Preload a texture URL so it's ready when needed.\n * Returns a promise that resolves when the texture is cached.\n */\nexport function preloadTexture(url: string): Promise<void> {\n if (cache.has(url)) return Promise.resolve();\n\n return new Promise<void>((resolve) => {\n if (cache.has(url)) {\n resolve();\n return;\n }\n\n // Register callback\n const callbacks = pendingCallbacks.get(url) || [];\n callbacks.push(resolve);\n pendingCallbacks.set(url, callbacks);\n\n if (!loadingUrls.has(url)) {\n loadingUrls.add(url);\n loadTexture(url);\n }\n });\n}\n\n/**\n * Register an already-loaded ImageBitmap as a distress texture (for worker export).\n */\nexport function registerBitmap(url: string, bitmap: ImageBitmap): void {\n if (cache.has(url)) return;\n const entry = convertToAlphaMask(bitmap);\n cache.set(url, entry);\n notifyPending(url);\n}\n\n/**\n * Register a pre-built alpha mask directly (no luminance conversion).\n * Used by procedural generators that already output white RGB + alpha format.\n */\nexport function registerAlphaMask(key: string, canvas: CanvasLike, width: number, height: number): void {\n if (cache.has(key)) return;\n cache.set(key, { alphaMask: canvas, width, height });\n notifyPending(key);\n}\n\n/**\n * Clear the entire cache (e.g., on project reset).\n */\nexport function clearDistressTextureCache(): void {\n cache.clear();\n loadingUrls.clear();\n pendingCallbacks.clear();\n}\n\n/**\n * Remove a specific URL from the cache.\n */\nexport function invalidateTexture(url: string): void {\n cache.delete(url);\n loadingUrls.delete(url);\n}\n\n// ---------------------------------------------------------------------------\n// Internal helpers\n// ---------------------------------------------------------------------------\n\nfunction notifyPending(url: string): void {\n const callbacks = pendingCallbacks.get(url);\n if (callbacks) {\n callbacks.forEach((cb) => cb());\n pendingCallbacks.delete(url);\n }\n}\n\nfunction loadTexture(url: string): void {\n // Use Image element in browser context\n if (typeof document !== 'undefined') {\n const img = new Image();\n img.crossOrigin = 'anonymous';\n img.onload = () => {\n const entry = convertToAlphaMask(img);\n cache.set(url, entry);\n loadingUrls.delete(url);\n notifyPending(url);\n };\n img.onerror = () => {\n loadingUrls.delete(url);\n notifyPending(url);\n };\n img.src = url;\n } else {\n // Worker context — use fetch + createImageBitmap\n fetch(url)\n .then((res) => res.blob())\n .then((blob) => createImageBitmap(blob))\n .then((bitmap) => {\n const entry = convertToAlphaMask(bitmap);\n cache.set(url, entry);\n loadingUrls.delete(url);\n notifyPending(url);\n })\n .catch(() => {\n loadingUrls.delete(url);\n notifyPending(url);\n });\n }\n}\n","/**\n * DistressTextureRenderer - Applies image-based distress textures via compositing.\n *\n * Uses grayscale JPEG textures interpreted as alpha masks to knock out\n * design pixels, creating authentic wear/grunge effects.\n *\n * Two scopes:\n * - Artboard-level: Applied after ALL elements render, before UI layers\n * - Per-element: Applied to individual elements within the rendering pipeline\n *\n * Compositing: draws the alpha mask with `destination-out` on an offscreen canvas\n * (same pattern as knockout in CompositingRenderer.ts).\n */\n\nimport type { ArtboardDistressTexture, DistressEffect } from '../types/index.js';\nimport { getAlphaMask } from '../effects/DistressTextureCache.js';\n\ntype CanvasLike = HTMLCanvasElement | OffscreenCanvas;\ntype ContextLike = CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D;\n\nfunction createOffscreenCanvas(width: number, height: number): CanvasLike {\n if (typeof OffscreenCanvas !== 'undefined') {\n return new OffscreenCanvas(width, height);\n }\n const canvas = document.createElement('canvas');\n canvas.width = width;\n canvas.height = height;\n return canvas;\n}\n\n/**\n * Apply artboard-level distress texture.\n *\n * Only knocks out element pixels — the artboard background stays solid.\n *\n * Algorithm:\n * 1. Copy the current artboard region (background + elements) to an offscreen canvas\n * 2. Draw the alpha mask with `destination-out` to knock holes in everything\n * 3. Clear the artboard region on the main canvas\n * 4. Redraw the artboard background color (fills the holes that were in the bg)\n * 5. Draw the distressed result on top (element holes reveal the fresh background)\n */\nexport function applyArtboardDistressTexture(\n ctx: ContextLike,\n config: ArtboardDistressTexture,\n artboard: { x: number; y: number; width: number; height: number },\n artboardBackgroundColor?: string\n): void {\n if (!config.enabled || !config.textureUrl || config.intensity <= 0) return;\n\n const mask = getAlphaMask(config.textureUrl);\n if (!mask) return; // Still loading — will render next frame\n\n const { x, y, width, height } = artboard;\n\n // Get the current transform to handle DPR + zoom correctly\n const transform = ctx.getTransform();\n\n // Calculate the pixel-space bounds of the artboard\n const pixelX = transform.a * x + transform.e;\n const pixelY = transform.d * y + transform.f;\n const pixelWidth = transform.a * width;\n const pixelHeight = transform.d * height;\n\n // Create offscreen canvas at pixel dimensions\n const offWidth = Math.ceil(pixelWidth);\n const offHeight = Math.ceil(pixelHeight);\n if (offWidth <= 0 || offHeight <= 0) return;\n\n const offCanvas = createOffscreenCanvas(offWidth, offHeight);\n const offCtx = offCanvas.getContext('2d') as ContextLike;\n if (!offCtx) return;\n\n // Copy the artboard region from the main canvas\n offCtx.drawImage(\n ctx.canvas,\n pixelX, pixelY, pixelWidth, pixelHeight,\n 0, 0, offWidth, offHeight\n );\n\n // Apply distress via direct pixel manipulation (deterministic nearest-neighbor).\n const artMaskCtx = mask.alphaMask.getContext('2d') as ContextLike | null;\n if (artMaskCtx) {\n const artIntensity = config.intensity / 100;\n const mData = artMaskCtx.getImageData(0, 0, mask.width, mask.height).data;\n const mW = mask.width;\n const mH = mask.height;\n const content = offCtx.getImageData(0, 0, offWidth, offHeight);\n const cData = content.data;\n\n for (let y = 0; y < offHeight; y++) {\n const my = Math.floor((y / offHeight) * mH);\n for (let x = 0; x < offWidth; x++) {\n const mx = Math.floor((x / offWidth) * mW);\n const maskAlpha = mData[(my * mW + mx) * 4 + 3] / 255;\n const ci = (y * offWidth + x) * 4;\n cData[ci + 3] = Math.round(cData[ci + 3] * (1 - maskAlpha * artIntensity));\n }\n }\n offCtx.putImageData(content, 0, 0);\n } else {\n offCtx.globalCompositeOperation = 'destination-out';\n offCtx.globalAlpha = config.intensity / 100;\n offCtx.drawImage(mask.alphaMask, 0, 0, offWidth, offHeight);\n offCtx.globalCompositeOperation = 'source-over';\n }\n offCtx.globalAlpha = 1;\n\n // Clear the artboard region on main canvas\n ctx.save();\n ctx.setTransform(1, 0, 0, 1, 0, 0);\n ctx.clearRect(pixelX, pixelY, pixelWidth, pixelHeight);\n\n // Redraw the artboard background so distress only affects elements, not the bg\n if (artboardBackgroundColor) {\n ctx.fillStyle = artboardBackgroundColor;\n ctx.fillRect(pixelX, pixelY, pixelWidth, pixelHeight);\n }\n\n // Draw distressed result on top — holes in elements reveal the fresh background\n ctx.drawImage(offCanvas, pixelX, pixelY);\n ctx.restore();\n}\n\n/**\n * Apply per-element distress texture using `destination-out` compositing.\n *\n * Called within the element rendering pipeline when an element has\n * `distressEffect.style === 'custom'` and a `textureUrl`.\n *\n * Works by:\n * 1. Creating an offscreen canvas\n * 2. Rendering the element content via the provided renderFn\n * 3. Drawing the alpha mask with `destination-out` + intensity\n * 4. Drawing the composited result back to the main canvas\n */\nexport function applyElementDistressTexture(\n ctx: ContextLike,\n distress: DistressEffect,\n elementBounds: { x: number; y: number; width: number; height: number },\n renderFn: (offCtx: ContextLike) => void\n): void {\n if (!distress.enabled || distress.style !== 'custom' || !distress.textureUrl) return;\n\n const mask = getAlphaMask(distress.textureUrl);\n if (!mask) {\n // Still loading — render without distress for now\n renderFn(ctx);\n return;\n }\n\n const intensity = distress.textureOpacity ?? (distress.intensity / 100);\n\n // Get the current transform\n const transform = ctx.getTransform();\n\n // Expand bounds to account for rotation and stroke. The provided bounding box\n // is the axis-aligned extent of the *unrotated* content. When the element is\n // rotated, the rendered pixels extend further. The worst case for a rectangle\n // rotated by any angle is the diagonal, so we pad by the difference between\n // the diagonal and the axis-aligned extent, plus extra for strokes.\n const diagonal = Math.sqrt(elementBounds.width ** 2 + elementBounds.height ** 2);\n const extraW = (diagonal - elementBounds.width) / 2;\n const extraH = (diagonal - elementBounds.height) / 2;\n // Add generous stroke padding (elements may have thick strokes)\n const strokePad = 20;\n const padX = extraW + strokePad;\n const padY = extraH + strokePad;\n\n const paddedBounds = {\n x: elementBounds.x - padX,\n y: elementBounds.y - padY,\n width: elementBounds.width + padX * 2,\n height: elementBounds.height + padY * 2,\n };\n\n // Calculate pixel-space bounds (accounting for transform)\n const pixelX = transform.a * paddedBounds.x + transform.e;\n const pixelY = transform.d * paddedBounds.y + transform.f;\n const pixelWidth = transform.a * paddedBounds.width;\n const pixelHeight = transform.d * paddedBounds.height;\n\n const offWidth = Math.ceil(pixelWidth);\n const offHeight = Math.ceil(pixelHeight);\n if (offWidth <= 0 || offHeight <= 0) {\n renderFn(ctx);\n return;\n }\n\n const offCanvas = createOffscreenCanvas(offWidth, offHeight);\n const offCtx = offCanvas.getContext('2d') as ContextLike;\n if (!offCtx) {\n renderFn(ctx);\n return;\n }\n\n // Replicate the main canvas transform, shifted so the padded bounding box\n // top-left maps to (0, 0) in the offscreen canvas. This ensures the render\n // callback (which applies element-relative transforms like translate/rotate)\n // produces pixel-identical output regardless of pan/zoom on the main canvas.\n offCtx.setTransform(\n transform.a, transform.b,\n transform.c, transform.d,\n transform.e - pixelX,\n transform.f - pixelY,\n );\n\n // Render element content into offscreen\n renderFn(offCtx);\n\n // Apply distress via direct pixel manipulation (nearest-neighbor sampling).\n // This is fully deterministic — avoids drawImage scaling interpolation\n // which produces different results across canvas contexts.\n offCtx.setTransform(1, 0, 0, 1, 0, 0);\n const maskCtx = mask.alphaMask.getContext('2d') as ContextLike | null;\n if (maskCtx) {\n const mData = maskCtx.getImageData(0, 0, mask.width, mask.height).data;\n const mW = mask.width;\n const mH = mask.height;\n const content = offCtx.getImageData(0, 0, offWidth, offHeight);\n const cData = content.data;\n\n for (let y = 0; y < offHeight; y++) {\n const my = Math.floor((y / offHeight) * mH);\n for (let x = 0; x < offWidth; x++) {\n const mx = Math.floor((x / offWidth) * mW);\n const maskAlpha = mData[(my * mW + mx) * 4 + 3] / 255;\n const ci = (y * offWidth + x) * 4;\n cData[ci + 3] = Math.round(cData[ci + 3] * (1 - maskAlpha * intensity));\n }\n }\n offCtx.putImageData(content, 0, 0);\n } else {\n // Fallback: use drawImage compositing (may have sub-pixel variance)\n offCtx.globalCompositeOperation = 'destination-out';\n offCtx.globalAlpha = intensity;\n offCtx.drawImage(mask.alphaMask, 0, 0, offWidth, offHeight);\n offCtx.globalCompositeOperation = 'source-over';\n offCtx.globalAlpha = 1;\n }\n\n // Draw composited result back to main canvas\n ctx.save();\n ctx.setTransform(1, 0, 0, 1, 0, 0);\n ctx.drawImage(offCanvas, pixelX, pixelY);\n ctx.restore();\n}\n","/**\n * SelectionRenderer - Selection box, transform handles, and resize info rendering\n *\n * Renders the visual indicators for element selection state:\n * - Selection bounding box around the selected element\n * - Position/size tooltip shown during resize operations\n * - Transform handles (corner, edge, rotation) via TransformHandles delegation\n *\n * Extracted from CanvasRenderer.ts as part of the rendering decomposition.\n * All methods are static to match the original CanvasRenderer pattern.\n */\n\nimport { theme } from '../theme.js';\nimport { RotationUtils } from './RotationUtils.js';\nimport type { BaseElement } from './BaseElement.js';\nimport type { TransformHandles } from './TransformHandles.js';\nimport type { InteractionStateMachine } from './InteractionStateMachine.js';\nimport type { HandleInfo } from '../types/index.js';\n\nimport {\n getThemeAccentColor,\n getThemeTooltipBackground,\n getThemeTooltipForeground,\n getThemeTooltipShadowColor,\n} from '../constants.js';\n\ninterface HoverState {\n type: 'element' | 'resize-handle' | 'rotation-handle' | null;\n data?: BaseElement | HandleInfo | null;\n}\n\nexport class SelectionRenderer {\n /**\n * Render selection box layer\n */\n static renderSelectionLayer(\n ctx: CanvasRenderingContext2D,\n selectedElement: BaseElement | null,\n stateMachine: InteractionStateMachine,\n zoom: number = 1.0\n ): void {\n if (!selectedElement) return;\n\n // Skip rendering selection for hidden elements\n if (selectedElement.visible === false) return;\n\n // Hide selection border while dragging\n const isDragging = stateMachine && stateMachine.getMode() === 'drag';\n if (isDragging) return;\n\n // Skip rendering selection for GroupElement - it renders its own outline\n if ('isGroup' in selectedElement && selectedElement.isGroup) return;\n\n const visualBbox = selectedElement.getVisualBoundingBox();\n const rotationAnchor = selectedElement.getRotationAnchor();\n\n ctx.save();\n\n // Draw bounding box\n ctx.strokeStyle = getThemeAccentColor(ctx.canvas);\n ctx.lineWidth = 2;\n\n // Transform to match element rotation around its rotation anchor (scaled by zoom)\n ctx.translate(rotationAnchor.x * zoom, rotationAnchor.y * zoom);\n ctx.rotate(RotationUtils.toRadians(selectedElement.rotation));\n ctx.translate(-rotationAnchor.x * zoom, -rotationAnchor.y * zoom);\n\n // Apply visual padding to the selection box (doesn't affect snapping/alignment)\n const padding = theme.canvas.selectionPadding;\n ctx.strokeRect(\n (visualBbox.x - padding) * zoom,\n (visualBbox.y - padding) * zoom,\n (visualBbox.width + padding * 2) * zoom,\n (visualBbox.height + padding * 2) * zoom\n );\n\n ctx.restore();\n }\n\n /**\n * Render position and size info below the selected element\n * Only shows dimensions (width x height) while resizing\n */\n static renderPositionSizeInfo(\n ctx: CanvasRenderingContext2D,\n selectedElement: BaseElement | null,\n transformHandles: TransformHandles | null,\n stateMachine: InteractionStateMachine | null,\n zoom: number = 1.0\n ): void {\n if (!selectedElement || !transformHandles?.rotationHandle) return;\n\n // Only show while resizing\n if (stateMachine?.getMode() !== 'resize') return;\n\n const visualBbox = selectedElement.getVisualBoundingBox();\n\n // Get dimensions only\n const width = Math.round(visualBbox.width);\n const height = Math.round(visualBbox.height);\n\n // Format the info text (dimensions only)\n const infoText = `${width} \\u00d7 ${height}`;\n\n // Calculate position: centered horizontally, just above the rotation handle (scaled by zoom)\n const rotationHandle = transformHandles.rotationHandle;\n const tooltipX = rotationHandle.x * zoom;\n const tooltipY = rotationHandle.y * zoom - 20; // Position above rotation handle\n\n ctx.save();\n\n // Set smaller font\n ctx.font = '10px system-ui, -apple-system, sans-serif';\n const textMetrics = ctx.measureText(infoText);\n const tooltipWidth = textMetrics.width + 12; // Smaller padding\n const tooltipHeight = 18; // Smaller height\n\n // Shadow for depth\n ctx.shadowColor = getThemeTooltipShadowColor(ctx.canvas as unknown as HTMLElement);\n ctx.shadowBlur = 4;\n ctx.shadowOffsetY = 1;\n\n // Background\n ctx.fillStyle = getThemeTooltipBackground(ctx.canvas as unknown as HTMLElement);\n ctx.beginPath();\n ctx.roundRect(\n tooltipX - tooltipWidth / 2,\n tooltipY - tooltipHeight / 2,\n tooltipWidth,\n tooltipHeight,\n 3 // Smaller border radius\n );\n ctx.fill();\n\n // Reset shadow\n ctx.shadowColor = 'transparent';\n ctx.shadowBlur = 0;\n ctx.shadowOffsetY = 0;\n\n // Text - use alphabetic baseline for better vertical centering\n ctx.fillStyle = getThemeTooltipForeground(ctx.canvas as unknown as HTMLElement);\n ctx.textAlign = 'center';\n ctx.textBaseline = 'middle';\n ctx.fillText(infoText, tooltipX, tooltipY + 0.5); // Slight offset for optical centering\n\n ctx.restore();\n }\n\n /**\n * Render transform handles layer\n */\n static renderHandlesLayer(\n ctx: CanvasRenderingContext2D,\n selectedElement: BaseElement | null,\n transformHandles: TransformHandles,\n currentRotation: number,\n isRotating: boolean,\n hoverState: HoverState,\n stateMachine: InteractionStateMachine,\n zoom: number = 1.0,\n showRotationHandle: boolean = true\n ): void {\n if (!selectedElement) return;\n\n // Skip rendering handles for hidden elements\n if (selectedElement.visible === false) return;\n\n // Hide handles while dragging\n const isDragging = stateMachine.getMode() === 'drag';\n if (isDragging) return;\n\n const isHoveringRotation = hoverState.type === 'rotation-handle';\n const hoveredResizeHandle = hoverState.type === 'resize-handle' ? (hoverState.data as HandleInfo) : null;\n const isResizing = stateMachine.getMode() === 'resize';\n const activeResizeHandle = isResizing ? (stateMachine.getActiveHandle() as HandleInfo) : null;\n\n transformHandles.render(\n ctx,\n showRotationHandle,\n currentRotation,\n isRotating,\n isHoveringRotation,\n hoveredResizeHandle,\n isResizing,\n activeResizeHandle,\n zoom,\n true // Render rotation handle on canvas (not React)\n );\n }\n}\n","/**\n * HoverRenderer - Hover outline and ring effect rendering\n *\n * Renders visual feedback when hovering over elements:\n * - Element-type-specific outlines (shape, image, group, text)\n * - Hover ring effect for straight text (offscreen canvas compositing)\n * - Hover ring effect for transformed text (circle, wave, arch, etc.)\n * - Character position calculations for each transform type\n *\n * ============================================================================\n * IMPORTANT: This is the HOVER RING EFFECT system\n * ============================================================================\n * - Colored ring/outline that appears when hovering over elements\n * - Uses offscreen canvas compositing with gap effect for text\n * - This is NOT the same as element stroke (StrokeRenderer.ts)\n * - This is NOT the same as selection box (Transform classes)\n *\n * Extracted from CanvasRenderer.ts as part of the rendering decomposition.\n * All methods are static to match the original CanvasRenderer pattern.\n */\n\nimport { RotationUtils } from './RotationUtils.js';\nimport type { BaseElement } from './BaseElement.js';\nimport type { TextElement } from './TextElement.js';\nimport type { CharacterStyle, CircleTransformData, WaveTransformData, FlagTransformData, ArchTransformData, AscendTransformData, LeanTransformData } from '../types/index.js';\n\nimport {\n getThemeAccentHoverColor,\n HORIZONTAL_PADDING,\n WAVE_SKEW_FACTOR,\n} from '../constants.js';\nimport { getFontMetrics, buildFontString, calculateVisualBoundsWithSpaceCollapsing } from './TextMetrics.js';\nimport { splitRichTextIntoLines, wrapRichTextSpans, applySpaceLayoutRules } from '../rendering/canvas-renderer.js';\n\ninterface HoverState {\n type: 'element' | 'resize-handle' | 'rotation-handle' | null;\n data?: BaseElement | null;\n startTime?: number;\n}\n\nexport class HoverRenderer {\n /**\n * Render hover highlights layer with fade-in animation\n * Outlines the actual element shape instead of a rectangular border\n */\n static renderHoverLayer(\n ctx: CanvasRenderingContext2D,\n hoverState: HoverState,\n selectedId: string | null,\n _isAltKeyPressed: boolean = false,\n zoom: number = 1.0,\n artboardBackgroundColor?: string\n ): void {\n if (hoverState.type !== 'element' || !hoverState.data) return;\n if (hoverState.data.id === selectedId) return; // Don't hover selected element\n\n const element = hoverState.data;\n\n ctx.save();\n\n // Calculate fade-in animation (0 to 0.5 opacity over 150ms)\n const FADE_DURATION = 150; // milliseconds\n const TARGET_OPACITY = 0.5;\n let opacity = TARGET_OPACITY;\n\n if (hoverState.startTime) {\n const elapsed = performance.now() - hoverState.startTime;\n const progress = Math.min(elapsed / FADE_DURATION, 1.0);\n opacity = progress * TARGET_OPACITY;\n }\n\n // Use theme hover accent color with animated opacity\n ctx.strokeStyle = getThemeAccentHoverColor(ctx.canvas);\n ctx.globalAlpha = opacity;\n ctx.lineWidth = 3; // Slightly thicker for visibility\n\n // Render element-specific outline based on type\n this.renderElementOutline(ctx, element, zoom, artboardBackgroundColor);\n\n ctx.restore();\n }\n\n /**\n * Render outline for a specific element type\n */\n private static renderElementOutline(\n ctx: CanvasRenderingContext2D,\n element: BaseElement,\n zoom: number = 1.0,\n artboardBackgroundColor?: string\n ): void {\n const rotationAnchor = element.getRotationAnchor();\n\n // Apply element rotation\n ctx.translate(rotationAnchor.x * zoom, rotationAnchor.y * zoom);\n ctx.rotate(RotationUtils.toRadians(element.rotation));\n ctx.translate(-rotationAnchor.x * zoom, -rotationAnchor.y * zoom);\n\n // Handle different element types\n if (element.transformType === 'shape') {\n this.renderShapeOutline(ctx, element, zoom);\n } else if (element.transformType === 'image') {\n this.renderImageOutline(ctx, element, zoom);\n } else if (element.transformType === 'group') {\n this.renderGroupOutline(ctx, element, zoom);\n } else {\n // Text elements (custom, circle, arch, wave, etc.)\n this.renderTextOutline(ctx, element as TextElement, zoom, artboardBackgroundColor);\n }\n }\n\n /**\n * Render outline for shape elements (star, rectangle, circle, etc.)\n * Creates a ring effect with a gap between the element and the stroke\n */\n private static renderShapeOutline(ctx: CanvasRenderingContext2D, element: BaseElement, zoom: number): void {\n const transformData = element.transformData as Record<string, number | string | undefined>;\n const width = (transformData.width as number) * zoom;\n const height = (transformData.height as number) * zoom;\n\n // Ring effect: gap = 2px, stroke = 2px\n // Offset to center of stroke = gap + stroke_width/2 = 2 + 1 = 3px\n const strokeWidth = 2;\n const gap = strokeWidth; // Gap equals stroke width\n const offset = gap + strokeWidth / 2;\n\n ctx.save();\n ctx.translate(element.x * zoom, element.y * zoom);\n\n ctx.beginPath();\n\n switch (transformData.shapeType as string) {\n case 'rectangle': {\n const borderRadius = (transformData.borderRadius as number) || 0;\n const x = -(width + offset * 2) / 2;\n const y = -(height + offset * 2) / 2;\n const w = width + offset * 2;\n const h = height + offset * 2;\n if (borderRadius > 0) {\n const radius = Math.min((borderRadius / 100) * Math.min(w, h), w / 2, h / 2);\n ctx.roundRect(x, y, w, h, radius);\n } else {\n ctx.rect(x, y, w, h);\n }\n break;\n }\n\n case 'circle': {\n const radius = Math.min(width, height) / 2 + offset;\n ctx.arc(0, 0, radius, 0, Math.PI * 2);\n break;\n }\n\n case 'ellipse': {\n const radiusX = ((transformData.radiusX as number) ?? width / 2) + offset;\n const radiusY = ((transformData.radiusY as number) ?? height / 2) + offset;\n ctx.ellipse(0, 0, radiusX, radiusY, 0, 0, Math.PI * 2);\n break;\n }\n\n case 'triangle': {\n const halfWidth = width / 2;\n const halfHeight = height / 2;\n\n // Original vertices\n const triVerts = [\n { x: 0, y: -halfHeight }, // top\n { x: halfWidth, y: halfHeight }, // bottom-right\n { x: -halfWidth, y: halfHeight }, // bottom-left\n ];\n\n // Compute outward unit normals for each edge (counterclockwise winding, y-down)\n const triNormals = triVerts.map((v, i) => {\n const next = triVerts[(i + 1) % 3];\n const dx = next.x - v.x;\n const dy = next.y - v.y;\n const len = Math.sqrt(dx * dx + dy * dy);\n return { x: dy / len, y: -dx / len };\n });\n\n // Offset each vertex along bisector of its two adjacent edge normals\n const offsetVerts = triVerts.map((_v, i) => {\n const n1 = triNormals[(i + 2) % 3]; // previous edge normal\n const n2 = triNormals[i]; // current edge normal\n const bx = n1.x + n2.x;\n const by = n1.y + n2.y;\n const bLen = Math.sqrt(bx * bx + by * by);\n const cosHalf = (bx * n1.x + by * n1.y) / bLen;\n const dist = offset / cosHalf;\n return {\n x: _v.x + (bx / bLen) * dist,\n y: _v.y + (by / bLen) * dist,\n };\n });\n\n ctx.moveTo(offsetVerts[0].x, offsetVerts[0].y);\n ctx.lineTo(offsetVerts[1].x, offsetVerts[1].y);\n ctx.lineTo(offsetVerts[2].x, offsetVerts[2].y);\n ctx.closePath();\n break;\n }\n\n case 'star': {\n const points = (transformData.points as number) ?? 5;\n const innerRadius = (transformData.innerRadius as number) ?? 0.4;\n const outerRadius = Math.min(width, height) / 2 + offset;\n const innerR = outerRadius * innerRadius;\n\n for (let i = 0; i < points * 2; i++) {\n const angle = (i * Math.PI) / points - Math.PI / 2;\n const r = i % 2 === 0 ? outerRadius : innerR;\n const x = r * Math.cos(angle);\n const y = r * Math.sin(angle);\n if (i === 0) {\n ctx.moveTo(x, y);\n } else {\n ctx.lineTo(x, y);\n }\n }\n ctx.closePath();\n break;\n }\n\n case 'polygon': {\n const sides = (transformData.sides as number) ?? 5;\n const radius = Math.min(width, height) / 2 + offset;\n for (let i = 0; i < sides; i++) {\n const angle = (i * 2 * Math.PI) / sides - Math.PI / 2;\n const x = radius * Math.cos(angle);\n const y = radius * Math.sin(angle);\n if (i === 0) {\n ctx.moveTo(x, y);\n } else {\n ctx.lineTo(x, y);\n }\n }\n ctx.closePath();\n break;\n }\n\n case 'line': {\n const halfWidth = width / 2 + offset;\n ctx.moveTo(-halfWidth, 0);\n ctx.lineTo(halfWidth, 0);\n break;\n }\n }\n\n ctx.stroke();\n ctx.restore();\n }\n\n /**\n * Render outline for image elements\n * Creates a ring effect with a gap between the element and the stroke\n */\n private static renderImageOutline(ctx: CanvasRenderingContext2D, element: BaseElement, zoom: number): void {\n // Use visual bounding box which respects crop settings\n const visualBbox = element.getVisualBoundingBox();\n const width = visualBbox.width * zoom;\n const height = visualBbox.height * zoom;\n const borderRadius = (element.transformData as Record<string, unknown>)?.borderRadius as number || 0;\n\n // Ring effect: gap = 2px, stroke = 2px\n // Offset to center of stroke = gap + stroke_width/2 = 2 + 1 = 3px\n const strokeWidth = 2;\n const gap = strokeWidth; // Gap equals stroke width\n const offset = gap + strokeWidth / 2;\n\n ctx.save();\n // Use element.x, element.y which is the center of the visible (cropped) area\n ctx.translate(element.x * zoom, element.y * zoom);\n\n const x = -(width + offset * 2) / 2;\n const y = -(height + offset * 2) / 2;\n const w = width + offset * 2;\n const h = height + offset * 2;\n\n ctx.beginPath();\n if (borderRadius > 0) {\n const radius = Math.min((borderRadius / 100) * Math.min(w, h), w / 2, h / 2);\n ctx.roundRect(x, y, w, h, radius);\n } else {\n ctx.rect(x, y, w, h);\n }\n ctx.stroke();\n\n ctx.restore();\n }\n\n /**\n * Render outline for group elements\n * Creates a ring effect with a gap between the element and the stroke\n */\n private static renderGroupOutline(ctx: CanvasRenderingContext2D, element: BaseElement, zoom: number): void {\n const visualBbox = element.getVisualBoundingBox();\n\n // Ring effect: gap = 2px, stroke = 2px\n // Offset to center of stroke = gap + stroke_width/2 = 2 + 1 = 3px\n const strokeWidth = 2;\n const gap = strokeWidth; // Gap equals stroke width\n const offset = gap + strokeWidth / 2;\n\n const x = visualBbox.x * zoom - offset;\n const y = visualBbox.y * zoom - offset;\n const width = visualBbox.width * zoom + offset * 2;\n const height = visualBbox.height * zoom + offset * 2;\n\n ctx.save();\n ctx.setLineDash([5, 5]); // Dashed outline for groups\n ctx.beginPath();\n ctx.roundRect(x, y, width, height, 8);\n ctx.stroke();\n ctx.restore();\n }\n\n /**\n * Render outline for text elements\n * Creates a ring effect with a gap between text and stroke (ring behind text fill)\n * Supports all transform types: custom, circle, wave, arch, etc.\n */\n private static renderTextOutline(\n ctx: CanvasRenderingContext2D,\n element: TextElement,\n zoom: number,\n _artboardBackgroundColor?: string\n ): void {\n // Delegate to transform-specific hover rendering based on type\n const transformType = element.transformType;\n\n if (\n transformType === 'circle' ||\n transformType === 'wave' ||\n transformType === 'arch' ||\n transformType === 'lean' ||\n transformType === 'ascend' ||\n transformType === 'flag'\n ) {\n // Use transform-specific hover ring effect (follows curved paths)\n this.renderTransformHoverRingEffect(ctx, element as TextElement, zoom);\n } else {\n // Straight text hover ring effect (for 'custom'/straight text)\n this.renderHoverRingEffect(ctx, element, zoom);\n }\n }\n\n /**\n * HOVER RING EFFECT for straight/custom text\n *\n * This is the colored ring that appears when hovering over text elements.\n * Uses offscreen canvas compositing to create a ring with a transparent gap.\n * Supports per-character fonts via rich text spans.\n *\n * NOTE: This is NOT the same as:\n * - Element stroke (StrokeRenderer.ts - only when stroke.enabled = true)\n * - Selection box (dashed rectangle in element.render())\n */\n private static renderHoverRingEffect(ctx: CanvasRenderingContext2D, element: TextElement, zoom: number): void {\n ctx.save();\n\n // Position and scale exactly like the text rendering\n ctx.translate(element.x * zoom, element.y * zoom);\n if (zoom !== 1.0) {\n ctx.scale(zoom, zoom);\n }\n\n // Use the exact same font setup as renderTextFillOnly\n const fontSize = element.fontSize;\n const fontFamily = element.fontFamily;\n const bold = element.bold || false;\n const italic = element.italic || false;\n const textAlign = element.textAlign || 'center';\n\n // Calculate Y position using the EXACT same logic as renderTextFillOnly\n // Support multi-line text with proper line spacing\n const fontMetrics = getFontMetrics(fontSize, fontFamily, bold, italic);\n const lineSpacing = fontSize * 1.2; // Match LINE_HEIGHT_MULTIPLIER from constants.ts\n\n // Ring effect using offscreen canvas for true transparency in gap\n // Render complete effect isolated, then composite onto main canvas\n // Divide by zoom to keep ring visually constant in CSS pixels —\n // the ctx.scale(zoom) above will scale these back to screen size\n const ringWidth = 4 / zoom;\n const gap = 4 / zoom;\n\n // Create offscreen canvas for isolated hover effect rendering\n const tempCanvas = document.createElement('canvas');\n tempCanvas.width = ctx.canvas.width;\n tempCanvas.height = ctx.canvas.height;\n const tempCtx = tempCanvas.getContext('2d');\n if (!tempCtx) {\n ctx.restore();\n return;\n }\n\n // Copy transform to temp context\n tempCtx.setTransform(ctx.getTransform());\n tempCtx.textBaseline = 'alphabetic';\n tempCtx.lineJoin = 'round';\n\n // Check if element has rich text (per-character formatting)\n const richText = element.getRichText ? element.getRichText() : null;\n\n if (richText) {\n // Use rich text spans for per-character font support\n const explicitLines = splitRichTextIntoLines(richText);\n\n // Build wrapped lines with paragraph metadata\n const wrappedLines: Array<{ text: string; style: CharacterStyle }[]> = [];\n const paragraphMetadata: Array<{ isParagraphStart: boolean; isParagraphEnd: boolean }> = [];\n\n explicitLines.forEach((lineSpans) => {\n if (element.transformType === 'custom' && element.transformData) {\n const availableWidth = (element.transformData as Record<string, number>).width - HORIZONTAL_PADDING * 2;\n const wrapped = wrapRichTextSpans(lineSpans, availableWidth, {\n fontSize,\n fontFamily,\n bold,\n italic,\n });\n wrapped.forEach((wLine, wIndex) => {\n wrappedLines.push(wLine);\n // Each explicit-newline paragraph independently tracks its first/last\n // wrapped line. Previously this only marked the global first/last lines,\n // causing space stripping on intermediate paragraphs.\n paragraphMetadata.push({\n isParagraphStart: wIndex === 0,\n isParagraphEnd: wIndex === wrapped.length - 1,\n });\n });\n } else {\n // Single (unwrapped) line is both start and end of its paragraph\n wrappedLines.push(lineSpans);\n paragraphMetadata.push({\n isParagraphStart: true,\n isParagraphEnd: true,\n });\n }\n });\n\n // Calculate total height\n let totalHeight: number;\n if (wrappedLines.length === 0) {\n totalHeight = 0;\n } else if (wrappedLines.length === 1) {\n totalHeight = fontMetrics.height;\n } else {\n totalHeight = (wrappedLines.length - 1) * lineSpacing + fontMetrics.height;\n }\n const topLeftY = -totalHeight / 2;\n\n // Render each line\n wrappedLines.forEach((lineSpans, lineIndex) => {\n const isParagraphStart = paragraphMetadata[lineIndex].isParagraphStart;\n const isParagraphEnd = paragraphMetadata[lineIndex].isParagraphEnd;\n\n // Calculate line width using per-span fonts\n let lineWidth = 0;\n const fullLineText = lineSpans.map((s) => s.text).join('');\n const leadingSpacesCount = fullLineText.match(/^ +/)?.[0].length || 0;\n const trailingSpacesCount = fullLineText.match(/ +$/)?.[0].length || 0;\n\n let charIdx = 0;\n lineSpans.forEach((span) => {\n const spanFontSize = span.style.fontSize !== undefined ? span.style.fontSize : fontSize;\n const spanFontFamily = span.style.fontFamily !== undefined ? span.style.fontFamily : fontFamily;\n const spanBold = span.style.bold !== undefined ? span.style.bold : bold;\n const spanItalic = span.style.italic !== undefined ? span.style.italic : italic;\n\n // Apply visibility rules\n let visibleText = span.text;\n const spanStart = charIdx;\n const spanEnd = charIdx + span.text.length;\n\n if (!isParagraphStart && leadingSpacesCount > 0 && spanStart < leadingSpacesCount) {\n const hiddenChars = Math.min(leadingSpacesCount - spanStart, span.text.length);\n visibleText = visibleText.substring(hiddenChars);\n }\n if (!isParagraphEnd && trailingSpacesCount > 0) {\n const trailingStart = fullLineText.length - trailingSpacesCount;\n if (spanEnd > trailingStart) {\n const leadingTrim = !isParagraphStart && spanStart < leadingSpacesCount\n ? Math.min(leadingSpacesCount - spanStart, span.text.length)\n : 0;\n const visibleChars = Math.max(0, trailingStart - spanStart - leadingTrim);\n visibleText = visibleText.substring(0, visibleChars);\n }\n }\n\n if (visibleText.length > 0) {\n ctx.save();\n ctx.font = buildFontString(spanFontSize, spanFontFamily, spanBold, spanItalic);\n lineWidth += ctx.measureText(visibleText).width;\n ctx.restore();\n }\n\n charIdx += span.text.length;\n });\n\n // Calculate starting X position based on alignment\n let currentX = 0;\n if (textAlign === 'center') {\n currentX = -lineWidth / 2;\n } else if (textAlign === 'right') {\n currentX = -lineWidth;\n }\n\n // Baseline Y for this line\n const baselineY = topLeftY + fontMetrics.ascent + lineIndex * lineSpacing;\n\n // Render each span with ring effect\n charIdx = 0;\n lineSpans.forEach((span) => {\n const spanFontSize = span.style.fontSize !== undefined ? span.style.fontSize : fontSize;\n const spanFontFamily = span.style.fontFamily !== undefined ? span.style.fontFamily : fontFamily;\n // Note: spanColor is not used directly here but is available for ring color customization\n void (span.style.color !== undefined ? span.style.color : element.color || '#333333');\n const spanBold = span.style.bold !== undefined ? span.style.bold : bold;\n const spanItalic = span.style.italic !== undefined ? span.style.italic : italic;\n\n // Apply visibility rules\n let visibleText = span.text;\n const spanStart = charIdx;\n const spanEnd = charIdx + span.text.length;\n\n if (!isParagraphStart && leadingSpacesCount > 0 && spanStart < leadingSpacesCount) {\n const hiddenChars = Math.min(leadingSpacesCount - spanStart, span.text.length);\n visibleText = visibleText.substring(hiddenChars);\n }\n if (!isParagraphEnd && trailingSpacesCount > 0) {\n const trailingStart = fullLineText.length - trailingSpacesCount;\n if (spanEnd > trailingStart) {\n const leadingTrim = !isParagraphStart && spanStart < leadingSpacesCount\n ? Math.min(leadingSpacesCount - spanStart, span.text.length)\n : 0;\n const visibleChars = Math.max(0, trailingStart - spanStart - leadingTrim);\n visibleText = visibleText.substring(0, visibleChars);\n }\n }\n\n charIdx += span.text.length;\n\n if (visibleText.length > 0) {\n // Set font for this span\n tempCtx.font = buildFontString(spanFontSize, spanFontFamily, spanBold, spanItalic);\n tempCtx.textAlign = 'left';\n\n // Step 1: Draw outer stroke on offscreen canvas\n tempCtx.globalCompositeOperation = 'source-over';\n tempCtx.strokeStyle = ctx.strokeStyle; // Use current accent color\n tempCtx.globalAlpha = Math.min(ctx.globalAlpha * 1.6, 0.8);\n tempCtx.lineWidth = (gap + ringWidth) * 2;\n tempCtx.strokeText(visibleText, currentX, baselineY);\n\n // Step 2: Cut out gap area using destination-out\n // This cuts out the gap stroke AND the text shape from the ring\n // The text fill is NOT rendered here - it comes from the original element render\n // This prevents text appearing darker on hover (double-render issue)\n tempCtx.globalCompositeOperation = 'destination-out';\n tempCtx.globalAlpha = 1.0;\n tempCtx.lineWidth = gap * 2;\n tempCtx.strokeText(visibleText, currentX, baselineY);\n tempCtx.fillText(visibleText, currentX, baselineY);\n\n // Note: We intentionally do NOT draw text fill here\n // The original element.render() already drew the text\n // We only composite the ring effect on top\n\n // Advance X position\n currentX += tempCtx.measureText(visibleText).width;\n }\n });\n });\n } else {\n // Fallback: no rich text, use plain text rendering with element-level font\n ctx.font = buildFontString(fontSize, fontFamily, bold, italic);\n tempCtx.font = ctx.font;\n tempCtx.textAlign = textAlign as CanvasTextAlign;\n\n // Get wrapped lines\n let textLines: string[];\n let totalHeight: number;\n\n if (element.transformType === 'custom' && element.transformData) {\n const availableWidth = (element.transformData as Record<string, number>).width - HORIZONTAL_PADDING * 2;\n const { lines } = calculateVisualBoundsWithSpaceCollapsing(\n element.text,\n availableWidth,\n fontSize,\n fontFamily,\n bold,\n italic,\n undefined,\n true\n );\n textLines = lines;\n } else {\n textLines = element.text.split('\\n');\n const hasExplicitNewlines = element.text.includes('\\n');\n textLines = applySpaceLayoutRules(textLines, hasExplicitNewlines);\n }\n\n if (textLines.length === 0) {\n totalHeight = 0;\n } else if (textLines.length === 1) {\n totalHeight = fontMetrics.height;\n } else {\n totalHeight = (textLines.length - 1) * lineSpacing + fontMetrics.height;\n }\n\n const topLeftY = -totalHeight / 2;\n const hasExplicitNewlines = element.text.includes('\\n');\n\n textLines.forEach((line, lineIndex) => {\n const yPos = topLeftY + fontMetrics.ascent + lineIndex * lineSpacing;\n // With explicit newlines, each line is its own paragraph (both start and end).\n // With wrapping only, first line is paragraph start, last is paragraph end.\n const isParagraphStart = hasExplicitNewlines || lineIndex === 0;\n const isParagraphEnd = hasExplicitNewlines || lineIndex === textLines.length - 1;\n\n let visibleText = line;\n if (!isParagraphStart) {\n visibleText = visibleText.replace(/^ +/, '');\n }\n if (!isParagraphEnd) {\n visibleText = visibleText.replace(/ +$/, '');\n }\n\n // Step 1: Draw outer stroke\n tempCtx.globalCompositeOperation = 'source-over';\n tempCtx.strokeStyle = ctx.strokeStyle;\n tempCtx.globalAlpha = Math.min(ctx.globalAlpha * 1.6, 0.8);\n tempCtx.lineWidth = (gap + ringWidth) * 2;\n tempCtx.lineJoin = 'round';\n tempCtx.strokeText(visibleText, 0, yPos);\n\n // Step 2: Cut out gap area\n // This cuts out the gap stroke AND the text shape from the ring\n // The text fill is NOT rendered here - it comes from the original element render\n // This prevents text appearing darker on hover (double-render issue)\n tempCtx.globalCompositeOperation = 'destination-out';\n tempCtx.globalAlpha = 1.0;\n tempCtx.lineWidth = gap * 2;\n tempCtx.strokeText(visibleText, 0, yPos);\n tempCtx.fillText(visibleText, 0, yPos);\n\n // Note: We intentionally do NOT draw text fill here\n // The original element.render() already drew the text\n // We only composite the ring effect on top\n });\n }\n\n // Draw complete hover effect from offscreen canvas to main canvas\n ctx.setTransform(1, 0, 0, 1, 0, 0);\n ctx.drawImage(tempCanvas, 0, 0);\n\n ctx.restore();\n }\n\n /**\n * HOVER RING EFFECT for transformed text (circle, wave, arch, lean, ascend, flag)\n *\n * This is the colored ring that appears when hovering over curved/transformed text.\n * Renders text character-by-character along the transform path with ring effect.\n * Uses offscreen canvas compositing to create a ring with a transparent gap.\n *\n * NOTE: This is NOT the same as:\n * - Element stroke (StrokeRenderer.ts - only when stroke.enabled = true)\n * - Selection box (dashed outline shown by each transform's render() method)\n */\n private static renderTransformHoverRingEffect(ctx: CanvasRenderingContext2D, element: TextElement, zoom: number): void {\n ctx.save();\n\n // Position and scale\n ctx.translate(element.x * zoom, element.y * zoom);\n if (zoom !== 1.0) {\n ctx.scale(zoom, zoom);\n }\n\n // Apply element rotation\n ctx.rotate((-element.rotation * Math.PI) / 180);\n\n // Ring effect settings — divide by zoom for zoom-invariant visual size\n const ringWidth = 4 / zoom;\n const gap = 4 / zoom;\n\n // Create offscreen canvas for isolated hover effect rendering\n const tempCanvas = document.createElement('canvas');\n tempCanvas.width = ctx.canvas.width;\n tempCanvas.height = ctx.canvas.height;\n const tempCtx = tempCanvas.getContext('2d');\n if (!tempCtx) {\n ctx.restore();\n return;\n }\n\n // Copy current transform to temp context\n tempCtx.setTransform(ctx.getTransform());\n\n // Render the transform with hover effect using a helper\n // Pass the current stroke style (color) from the main context\n this.renderTransformWithHoverEffect(tempCtx, element, ringWidth, gap, ctx.strokeStyle as string);\n\n // Draw complete hover effect from offscreen canvas to main canvas\n ctx.setTransform(1, 0, 0, 1, 0, 0); // Reset transform for drawImage\n ctx.drawImage(tempCanvas, 0, 0);\n\n ctx.restore();\n }\n\n /**\n * Helper to render text along a transform path with hover effect\n */\n private static renderTransformWithHoverEffect(\n ctx: CanvasRenderingContext2D,\n element: TextElement,\n ringWidth: number,\n gap: number,\n color: string\n ): void {\n const textEl = element;\n const fontSize = textEl.fontSize;\n const fontFamily = textEl.fontFamily;\n const bold = textEl.bold || false;\n const italic = textEl.italic || false;\n\n // Set up font\n const weight = bold ? 'bold' : 'normal';\n const style = italic ? 'italic' : 'normal';\n ctx.font = `${style} ${weight} ${fontSize}px ${fontFamily}`;\n ctx.textAlign = 'center';\n ctx.textBaseline = 'middle';\n\n // Lean transform uses a global horizontal skew on the whole text block,\n // not per-character positioning. Handle it specially.\n if (textEl.transformType === 'lean') {\n const leanData = textEl.transformData as LeanTransformData;\n const skewAngle = (-leanData.leanAmount * Math.PI) / 4;\n ctx.transform(1, 0, Math.tan(skewAngle), 1, 0, 0);\n\n // Draw the entire text as one block with ring effect\n ctx.globalCompositeOperation = 'source-over';\n ctx.strokeStyle = color;\n ctx.globalAlpha = 0.8;\n ctx.lineWidth = (gap + ringWidth) * 2;\n ctx.lineJoin = 'round';\n ctx.strokeText(textEl.text, 0, 0);\n\n ctx.globalCompositeOperation = 'destination-out';\n ctx.globalAlpha = 1.0;\n ctx.lineWidth = gap * 2;\n ctx.strokeText(textEl.text, 0, 0);\n ctx.fillText(textEl.text, 0, 0);\n return;\n }\n\n // Get character positions based on transform type\n const chars = textEl.text.split('');\n const charWidths = chars.map((char: string) => ctx.measureText(char).width);\n\n // Calculate positions for each character based on transform type\n const positions = this.calculateCharPositions(element, chars, charWidths);\n\n // Two-pass rendering: draw ALL ring strokes first, then cut out ALL gaps+text.\n // This prevents one character's ring from overlapping an adjacent character's text.\n\n // Helper to apply position transform (translate + rotate + skew)\n const applyCharTransform = (pos: { x: number; y: number; angle: number; skewY?: number }) => {\n ctx.translate(pos.x, pos.y);\n if (pos.angle) ctx.rotate(pos.angle);\n if (pos.skewY) ctx.transform(1, pos.skewY, 0, 1, 0, 0);\n };\n\n // Pass 1: Draw all outer ring strokes\n ctx.globalCompositeOperation = 'source-over';\n ctx.strokeStyle = color;\n ctx.globalAlpha = 0.8;\n ctx.lineWidth = (gap + ringWidth) * 2;\n ctx.lineJoin = 'round';\n positions.forEach((pos, i) => {\n ctx.save();\n applyCharTransform(pos);\n ctx.strokeText(chars[i], 0, 0);\n ctx.restore();\n });\n\n // Pass 2: Cut out gap and text shape from the ring\n ctx.globalCompositeOperation = 'destination-out';\n ctx.globalAlpha = 1.0;\n ctx.lineWidth = gap * 2;\n positions.forEach((pos, i) => {\n ctx.save();\n applyCharTransform(pos);\n ctx.strokeText(chars[i], 0, 0);\n ctx.fillText(chars[i], 0, 0);\n ctx.restore();\n });\n }\n\n /**\n * Calculate character positions for different transform types\n *\n * Also used by EditModeRenderer for cursor positioning on transformed text.\n */\n static calculateCharPositions(\n element: TextElement,\n chars: string[],\n charWidths: number[]\n ): Array<{ x: number; y: number; angle: number; skewY?: number }> {\n const transformType = element.transformType;\n const transformData = element.transformData;\n\n if (transformType === 'circle') {\n return this.calculateCirclePositions(transformData as CircleTransformData, chars, charWidths);\n } else if (transformType === 'wave') {\n return this.calculateWavePositions(element, chars, charWidths, transformData as WaveTransformData);\n } else if (transformType === 'arch') {\n return this.calculateArchPositions(element, chars, charWidths, transformData as ArchTransformData);\n } else if (transformType === 'lean') {\n return this.calculateLeanPositions(chars, charWidths);\n } else if (transformType === 'ascend') {\n return this.calculateAscendPositions(element, chars, charWidths, transformData as AscendTransformData);\n } else if (transformType === 'flag') {\n return this.calculateFlagPositions(element, chars, charWidths, transformData as FlagTransformData);\n }\n\n // Default: straight line\n return chars.map(() => ({ x: 0, y: 0, angle: 0 }));\n }\n\n /**\n * Calculate positions for circle transform\n */\n private static calculateCirclePositions(\n transformData: CircleTransformData,\n chars: string[],\n charWidths: number[]\n ): Array<{ x: number; y: number; angle: number }> {\n const positions: Array<{ x: number; y: number; angle: number }> = [];\n const totalWidth = charWidths.reduce((sum, w) => sum + w, 0);\n const radius = transformData.radius * transformData.scale;\n\n if (transformData.reverse) {\n // Bottom text: start from right side and go left\n let currentAngle = Math.PI / 2 + totalWidth / (2 * radius);\n\n chars.forEach((_, i) => {\n const charWidth = charWidths[i];\n const angleStep = charWidth / radius;\n\n const x = Math.cos(currentAngle - angleStep / 2) * radius;\n const y = Math.sin(currentAngle - angleStep / 2) * radius;\n const angle = currentAngle - angleStep / 2 - Math.PI / 2;\n\n positions.push({ x, y, angle });\n currentAngle -= angleStep;\n });\n } else {\n // Top text: start from left side and go right\n let currentAngle = -Math.PI / 2 - totalWidth / (2 * radius);\n\n chars.forEach((_, i) => {\n const charWidth = charWidths[i];\n const angleStep = charWidth / radius;\n\n const x = Math.cos(currentAngle + angleStep / 2) * radius;\n const y = Math.sin(currentAngle + angleStep / 2) * radius;\n const angle = currentAngle + angleStep / 2 + Math.PI / 2;\n\n positions.push({ x, y, angle });\n currentAngle += angleStep;\n });\n }\n\n return positions;\n }\n\n /**\n * Calculate positions for wave transform\n */\n private static calculateWavePositions(\n element: TextElement,\n chars: string[],\n charWidths: number[],\n transformData: WaveTransformData\n ): Array<{ x: number; y: number; angle: number; skewY?: number }> {\n const positions: Array<{ x: number; y: number; angle: number; skewY?: number }> = [];\n const totalWidth = charWidths.reduce((sum, w) => sum + w, 0);\n let currentX = -totalWidth / 2;\n\n chars.forEach((_, i) => {\n const charWidth = charWidths[i];\n const x = currentX + charWidth / 2;\n const normalizedX = x / (transformData.width / 2);\n\n // Calculate y position on sine wave (matches transform-renderer.ts)\n const y = transformData.amplitude * element.fontSize * Math.sin(transformData.frequency * Math.PI * normalizedX);\n\n // Calculate slope for vertical skew (matches transform-renderer.ts)\n const slope =\n transformData.amplitude *\n transformData.frequency *\n Math.PI *\n Math.cos(transformData.frequency * Math.PI * normalizedX);\n\n positions.push({ x, y, angle: 0, skewY: slope * WAVE_SKEW_FACTOR });\n currentX += charWidth;\n });\n\n return positions;\n }\n\n /**\n * Calculate positions for arch transform\n */\n private static calculateArchPositions(\n element: TextElement,\n chars: string[],\n charWidths: number[],\n transformData: ArchTransformData\n ): Array<{ x: number; y: number; angle: number; skewY?: number }> {\n const positions: Array<{ x: number; y: number; angle: number; skewY?: number }> = [];\n const totalWidth = charWidths.reduce((sum, w) => sum + w, 0);\n const radius = transformData.width / 2;\n let currentX = -totalWidth / 2;\n\n chars.forEach((_, i) => {\n const charWidth = charWidths[i];\n const x = currentX + charWidth / 2;\n const normalizedX = x / radius;\n\n // Parabolic curve (matches transform-renderer.ts)\n const y = (Math.pow(normalizedX, 2) - 1) * transformData.archHeight * element.fontSize;\n\n // Slope for vertical skew (matches transform-renderer.ts)\n const slope = 2 * normalizedX * transformData.archHeight;\n const skewFactor = 0.3;\n\n positions.push({ x, y, angle: 0, skewY: slope * skewFactor });\n currentX += charWidth;\n });\n\n return positions;\n }\n\n /**\n * Calculate positions for lean transform\n */\n private static calculateLeanPositions(\n chars: string[],\n charWidths: number[]\n ): Array<{ x: number; y: number; angle: number }> {\n const positions: Array<{ x: number; y: number; angle: number }> = [];\n const totalWidth = charWidths.reduce((sum, w) => sum + w, 0);\n let currentX = -totalWidth / 2;\n\n chars.forEach((_, i) => {\n const charWidth = charWidths[i];\n const x = currentX + charWidth / 2;\n\n // Lean uses skew transform, characters stay on baseline\n positions.push({ x, y: 0, angle: 0 });\n currentX += charWidth;\n });\n\n return positions;\n }\n\n /**\n * Calculate positions for ascend transform\n */\n private static calculateAscendPositions(\n _element: TextElement,\n chars: string[],\n charWidths: number[],\n transformData: AscendTransformData\n ): Array<{ x: number; y: number; angle: number; skewY?: number }> {\n const positions: Array<{ x: number; y: number; angle: number; skewY?: number }> = [];\n const totalWidth = charWidths.reduce((sum, w) => sum + w, 0);\n const angleRad = (transformData.ascendAngle * Math.PI) / 180;\n const slope = Math.tan(angleRad);\n let currentX = -totalWidth / 2;\n\n chars.forEach((_, i) => {\n const charWidth = charWidths[i];\n const x = currentX + charWidth / 2;\n\n // Diagonal line (matches transform-renderer.ts)\n const y = x * slope;\n\n // Skew factor 1.0 for ascend (matches transform-renderer.ts)\n const skewFactor = 1.0;\n\n positions.push({ x, y, angle: 0, skewY: slope * skewFactor });\n currentX += charWidth;\n });\n\n return positions;\n }\n\n /**\n * Calculate positions for flag transform\n */\n private static calculateFlagPositions(\n element: TextElement,\n chars: string[],\n charWidths: number[],\n transformData: FlagTransformData\n ): Array<{ x: number; y: number; angle: number; skewY?: number }> {\n const positions: Array<{ x: number; y: number; angle: number; skewY?: number }> = [];\n const totalWidth = charWidths.reduce((sum, w) => sum + w, 0);\n let currentX = -totalWidth / 2;\n\n chars.forEach((_, i) => {\n const charWidth = charWidths[i];\n const x = currentX + charWidth / 2;\n const normalizedX = x / (transformData.width / 2);\n\n // Flag effect: amplitude increases from center to edges (matches transform-renderer.ts)\n const distanceFromCenter = Math.abs(normalizedX);\n const flagAmplitude = transformData.amplitude * distanceFromCenter;\n\n const y = flagAmplitude * element.fontSize * Math.sin(transformData.frequency * Math.PI * normalizedX);\n\n // Slope for skew (matches transform-renderer.ts)\n const cosComponent =\n flagAmplitude * transformData.frequency * Math.PI * Math.cos(transformData.frequency * Math.PI * normalizedX);\n const sinComponent =\n transformData.amplitude * Math.sign(normalizedX) * Math.sin(transformData.frequency * Math.PI * normalizedX);\n const slope = cosComponent + sinComponent;\n const skewFactor = 0.3;\n\n positions.push({ x, y, angle: 0, skewY: slope * skewFactor });\n currentX += charWidth;\n });\n\n return positions;\n }\n}\n","/**\n * InteractionFeedbackRenderer - Snap guides, spacing indicators, and distance labels\n *\n * Renders visual feedback during user interactions:\n * - Snap guide lines (alignment snapping during drag/resize)\n * - Spacing indicator lines with end caps (distance between elements)\n * - Distance labels with colored background\n *\n * Extracted from CanvasRenderer.ts as part of the rendering decomposition.\n * All methods are static to match the original CanvasRenderer pattern.\n */\n\nimport { theme } from '../theme.js';\nimport type { SnapGuide, SpacingIndicator } from '../types/index.js';\n\nimport {\n getThemeAccentColor,\n getThemeSpacingColor,\n SPACING_LABEL_TEXT_COLOR,\n SPACING_LABEL_BORDER_RADIUS,\n} from '../constants.js';\n\nexport class InteractionFeedbackRenderer {\n /**\n * Render snap guides layer\n */\n static renderSnapGuidesLayer(ctx: CanvasRenderingContext2D, snapGuides: SnapGuide[] = []): void {\n if (snapGuides.length === 0) return;\n\n ctx.save();\n ctx.strokeStyle = getThemeAccentColor(ctx.canvas);\n ctx.lineWidth = theme.canvas.snapGuideWidth;\n ctx.setLineDash(theme.canvas.snapGuideDash);\n\n snapGuides.forEach((guide) => {\n ctx.beginPath();\n\n if (guide.type === 'vertical') {\n // Vertical line\n ctx.moveTo(guide.x ?? 0, guide.y1 ?? 0);\n ctx.lineTo(guide.x ?? 0, guide.y2 ?? 0);\n } else if (guide.type === 'horizontal') {\n // Horizontal line\n ctx.moveTo(guide.x1 ?? 0, guide.y ?? 0);\n ctx.lineTo(guide.x2 ?? 0, guide.y ?? 0);\n } else {\n // Fallback for generic lines\n ctx.moveTo(guide.x1 ?? 0, guide.y1 ?? 0);\n ctx.lineTo(guide.x2 ?? 0, guide.y2 ?? 0);\n }\n\n ctx.stroke();\n });\n\n ctx.restore();\n }\n\n /**\n * Render spacing indicators layer\n */\n static renderSpacingIndicatorsLayer(ctx: CanvasRenderingContext2D, spacingIndicators: SpacingIndicator[] = []): void {\n if (spacingIndicators.length === 0) return;\n\n ctx.save();\n ctx.setLineDash([]); // Solid lines for spacing indicators\n\n spacingIndicators.forEach((indicator) => {\n // Use theme-specific color for all spacing indicators (regular, snap targets, and Alt+hover)\n const spacingColor = getThemeSpacingColor(ctx.canvas);\n ctx.strokeStyle = spacingColor;\n ctx.fillStyle = spacingColor;\n ctx.lineWidth = theme.canvas.spacingIndicatorWidth;\n ctx.beginPath();\n\n if (indicator.type === 'horizontal') {\n // Horizontal spacing line\n const x1 = indicator.x1 ?? 0;\n const x2 = indicator.x2 ?? 0;\n const y = indicator.y ?? 0;\n\n // Draw the main line\n ctx.moveTo(x1, y);\n ctx.lineTo(x2, y);\n ctx.stroke();\n\n // Draw end caps (perpendicular lines at each end)\n const capLength = 6;\n ctx.beginPath();\n ctx.moveTo(x1, y - capLength);\n ctx.lineTo(x1, y + capLength);\n ctx.stroke();\n\n ctx.beginPath();\n ctx.moveTo(x2, y - capLength);\n ctx.lineTo(x2, y + capLength);\n ctx.stroke();\n\n // Draw distance label\n const labelX = indicator.labelX;\n const labelY = indicator.labelY;\n this.renderDistanceLabel(ctx, labelX, labelY, indicator.distance);\n } else if (indicator.type === 'vertical') {\n // Vertical spacing line\n const x = indicator.x ?? 0;\n const y1 = indicator.y1 ?? 0;\n const y2 = indicator.y2 ?? 0;\n\n // Draw the main line\n ctx.moveTo(x, y1);\n ctx.lineTo(x, y2);\n ctx.stroke();\n\n // Draw end caps (perpendicular lines at each end)\n const capLength = 6;\n ctx.beginPath();\n ctx.moveTo(x - capLength, y1);\n ctx.lineTo(x + capLength, y1);\n ctx.stroke();\n\n ctx.beginPath();\n ctx.moveTo(x - capLength, y2);\n ctx.lineTo(x + capLength, y2);\n ctx.stroke();\n\n // Draw distance label\n const labelX = indicator.labelX;\n const labelY = indicator.labelY;\n this.renderDistanceLabel(ctx, labelX, labelY, indicator.distance);\n }\n });\n\n ctx.restore();\n }\n\n /**\n * Render a distance label with background\n */\n static renderDistanceLabel(ctx: CanvasRenderingContext2D, x: number, y: number, distance: number): void {\n const text = `${distance}`;\n ctx.font = `600 ${theme.canvas.spacingLabelFontSize}px ${theme.canvas.spacingLabelFontFamily}`;\n\n // Measure text\n const metrics = ctx.measureText(text);\n const textWidth = metrics.width;\n const textHeight = theme.canvas.spacingLabelFontSize;\n\n // Background padding\n const padding = 4;\n const bgWidth = textWidth + padding * 2;\n const bgHeight = textHeight + padding * 2;\n\n // Draw background with rounded corners\n ctx.fillStyle = getThemeSpacingColor(ctx.canvas);\n ctx.beginPath();\n ctx.roundRect(x - bgWidth / 2, y - bgHeight / 2, bgWidth, bgHeight, SPACING_LABEL_BORDER_RADIUS);\n ctx.fill();\n\n // Draw text\n ctx.fillStyle = SPACING_LABEL_TEXT_COLOR;\n ctx.textAlign = 'center';\n ctx.textBaseline = 'middle';\n ctx.fillText(text, x, y);\n }\n}\n","/**\n * EditModeRenderer - Text editing cursor, selection highlight, and crop UI rendering\n *\n * Renders visual elements for active editing states:\n * - Text cursor (blinking vertical line) for straight and transformed text\n * - Text selection highlighting with proper kerning\n * - iOS-style selection handles for touch devices\n * - Crop box overlay, grid lines, and crop handles\n *\n * Extracted from CanvasRenderer.ts as part of the rendering decomposition.\n * All methods are static to match the original CanvasRenderer pattern.\n */\n\nimport type React from 'react';\nimport { theme } from '../theme.js';\nimport { RotationUtils } from './RotationUtils.js';\nimport {\n CORNER_HANDLE_VISUAL_RADIUS,\n EDGE_HANDLE_VISUAL_LENGTH,\n} from '../constants.js';\nimport type { TextElement } from './TextElement.js';\nimport type { BaseElement } from './BaseElement.js';\nimport type { TransformHandles } from './TransformHandles.js';\nimport { RichText } from '../types/index.js';\nimport type { CharacterStyle, CustomTransformData } from '../types/index.js';\nimport { ImageElement } from './ImageElement.js';\nimport { HoverRenderer } from './HoverRenderer.js';\n\nimport {\n getThemeAccentColor,\n getThemeTextSelectionColor,\n HORIZONTAL_PADDING,\n} from '../constants.js';\nimport { getFontMetrics } from './TextMetrics.js';\nimport { splitRichTextIntoLines, wrapRichTextSpans, renderRichTextFillOnly } from '../rendering/canvas-renderer.js';\n\nexport class EditModeRenderer {\n /**\n * Render edit mode features: cursor and text selection highlight\n * This renders on the main canvas at world coordinates (same as the element)\n */\n static renderEditModeLayer(\n ctx: CanvasRenderingContext2D,\n element: BaseElement | null,\n editModeData: {\n cursorPosition: number;\n selectionStart: number;\n selectionEnd: number;\n editText: string;\n editRichText: RichText | null;\n cursorOpacity: number;\n isTouchDevice?: boolean;\n selectionHandlePositionsRef?: React.MutableRefObject<{\n start: { center: { x: number; y: number }; textEdge: { x: number; y: number } } | null;\n end: { center: { x: number; y: number }; textEdge: { x: number; y: number } } | null;\n }>;\n },\n zoom: number\n ): void {\n if (!element || element.transformType === 'image' || element.transformType === 'group') return;\n\n // After filtering out 'image' and 'group', the remaining elements are text-based\n const textElement = element as TextElement;\n\n const { cursorPosition, selectionStart, selectionEnd, editText, editRichText, cursorOpacity, isTouchDevice, selectionHandlePositionsRef } = editModeData;\n\n // Store zoom for use in selection handle rendering (zoom-invariant tap zones)\n const currentZoom = zoom || 1.0;\n\n // Delegate to transform-specific rendering for non-custom transforms\n const transformType = textElement.transformType;\n if (\n transformType === 'circle' ||\n transformType === 'wave' ||\n transformType === 'arch' ||\n transformType === 'lean' ||\n transformType === 'ascend' ||\n transformType === 'flag'\n ) {\n this.renderTransformEditModeLayer(ctx, textElement, editModeData, currentZoom);\n return;\n }\n\n // Continue with straight text cursor rendering for custom transform\n\n // Get element properties\n const fontSize = textElement.fontSize || 24;\n const fontFamily = textElement.fontFamily || 'Arial';\n const bold = textElement.bold || false;\n const italic = textElement.italic || false;\n const underline = textElement.underline || false;\n const strikethrough = textElement.strikethrough || false;\n const textAlign = textElement.textAlign || 'center';\n\n ctx.save();\n\n // Apply element's transform (position and rotation)\n ctx.translate(textElement.x, textElement.y);\n // Use negative angle for clockwise rotation (matching UI convention)\n // Convert from degrees to radians\n ctx.rotate((-textElement.rotation * Math.PI) / 180);\n\n // Use getFontMetrics to match rendering exactly (uses 'ÁÉÍgjpqy' sample)\n const fontMetrics = getFontMetrics(fontSize, fontFamily, bold, italic);\n const lineBoxHeight = fontMetrics.height;\n\n // Calculate total text height to center vertically (match renderRichTextFillOnly)\n const lineSpacing = fontSize * 1.2; // Match LINE_HEIGHT_MULTIPLIER from constants.ts\n\n // CRITICAL: Use the exact same wrapping logic as rendering\n // Get available width for wrapping (if element is CustomTransform)\n let wrappedLines: Array<{ text: string; style: CharacterStyle }[]>;\n let paragraphMetadata: Array<{ isParagraphStart: boolean; isParagraphEnd: boolean }>;\n\n // Inner box width used for alignment anchoring (mirror renderRichTextFillOnly):\n // defined only when the element has an explicit box, otherwise undefined so\n // left/right alignment falls back to anchor-at-zero.\n let maxWidth: number | undefined;\n\n if (editRichText && textElement.transformType === 'custom' && (textElement.transformData as CustomTransformData).width) {\n // Use rich text wrapping (same as renderRichTextFillOnly)\n const boxWidth = (textElement.transformData as CustomTransformData).width - HORIZONTAL_PADDING * 2;\n maxWidth = boxWidth;\n const explicitLines = splitRichTextIntoLines(editRichText);\n wrappedLines = [];\n paragraphMetadata = [];\n\n explicitLines.forEach((lineSpans) => {\n const wrapped = wrapRichTextSpans(lineSpans, boxWidth, {\n fontSize: textElement.fontSize,\n fontFamily: textElement.fontFamily,\n bold: textElement.bold,\n italic: textElement.italic,\n });\n wrapped.forEach((wrappedLine, idx) => {\n wrappedLines.push(wrappedLine);\n paragraphMetadata.push({\n isParagraphStart: idx === 0,\n isParagraphEnd: idx === wrapped.length - 1,\n });\n });\n });\n } else {\n // Fallback: no wrapping, just split by newlines\n const textLines = editText.split('\\n');\n wrappedLines = textLines.map((line) => [\n {\n text: line,\n style: { fontSize, fontFamily, bold, italic },\n },\n ]);\n paragraphMetadata = wrappedLines.map(() => ({\n isParagraphStart: true, // Each line is its own paragraph\n isParagraphEnd: true,\n }));\n }\n\n // Match rendering formula: lineHeight * (1 + (n-1) * lineSpacing)\n // Note: lineSpacing here is the full line height (fontSize * 1.2), not just the gap\n const totalHeight =\n wrappedLines.length > 1 ? fontMetrics.height + (wrappedLines.length - 1) * lineSpacing : fontMetrics.height;\n\n // Start Y from top of vertically-centered text block (match renderRichTextFillOnly line 613)\n let currentY = -totalHeight / 2;\n\n // Track cursor position and character positions for selection\n let cursorX = 0;\n let cursorY = currentY;\n let cursorHeight = lineBoxHeight;\n\n interface CharPosition {\n x: number;\n y: number;\n width: number;\n height: number;\n }\n const charPositions: CharPosition[] = [];\n\n // CRITICAL: Process wrapped lines directly (not character-by-character from editText)\n // This ensures cursor positions match the actual rendered layout\n let charIndex = 0; // Track position in original editText\n\n wrappedLines.forEach((lineSpans, lineIndex) => {\n const isParagraphStart = paragraphMetadata[lineIndex].isParagraphStart;\n const isParagraphEnd = paragraphMetadata[lineIndex].isParagraphEnd;\n\n // Build line characters with measurements\n const currentLineChars: Array<{ char: string; width: number; fontSize: number; index: number }> = [];\n\n lineSpans.forEach((span) => {\n const chars = Array.from(span.text);\n chars.forEach((char) => {\n // Get character style\n let charFontSize = fontSize;\n let charFontFamily = fontFamily;\n let charBold = bold;\n let charItalic = italic;\n\n if (editRichText && charIndex < editText.length) {\n const charStyle = editRichText.getStyleAt(charIndex);\n charFontSize = charStyle.fontSize || fontSize;\n charFontFamily = charStyle.fontFamily || fontFamily;\n charBold = charStyle.bold !== undefined ? charStyle.bold : bold;\n charItalic = charStyle.italic !== undefined ? charStyle.italic : italic;\n }\n\n // Measure character width\n ctx.save();\n const fontWeight = charBold ? 'bold' : 'normal';\n const fontStyle = charItalic ? 'italic' : 'normal';\n ctx.font = `${fontStyle} ${fontWeight} ${charFontSize}px \"${charFontFamily}\", Arial, sans-serif`;\n const charWidth = ctx.measureText(char).width;\n ctx.restore();\n\n currentLineChars.push({ char, width: charWidth, fontSize: charFontSize, index: charIndex });\n charIndex++;\n });\n });\n\n // Process this wrapped line\n {\n const isFirstLine = lineIndex === 0;\n const isLastLine = lineIndex === wrappedLines.length - 1;\n\n const fullLineText = currentLineChars.map((c) => c.char).join('');\n\n // Calculate leading/trailing space counts for layout rules\n const leadingSpacesCount = fullLineText.match(/^ +/)?.[0].length || 0;\n const trailingSpacesCount = fullLineText.match(/ +$/)?.[0].length || 0;\n\n // Calculate line width using per-character widths (respecting space layout rules)\n let lineWidth = 0;\n for (let j = 0; j < currentLineChars.length; j++) {\n // Skip leading spaces if not first line\n if (!isFirstLine && j < leadingSpacesCount) continue;\n // Skip trailing spaces if not last line\n if (!isLastLine && j >= currentLineChars.length - trailingSpacesCount) continue;\n lineWidth += currentLineChars[j].width;\n }\n\n // Calculate starting X based on alignment (match renderRichTextFillOnly).\n // Anchor to the bounding-box edges, not x=0 — that way the cursor +\n // characters land where the rendered glyphs actually appear.\n let lineX: number;\n if (textAlign === 'center') {\n lineX = -lineWidth / 2;\n } else if (textAlign === 'right') {\n lineX = maxWidth !== undefined ? maxWidth / 2 - lineWidth : -lineWidth;\n } else {\n // left\n lineX = maxWidth !== undefined ? -maxWidth / 2 : 0;\n }\n\n // Position all characters in this line (cursor can navigate through hidden spaces)\n let currentX = lineX;\n\n for (let j = 0; j < currentLineChars.length; j++) {\n const charData = currentLineChars[j];\n\n // Store character position (cursor can navigate to hidden spaces)\n charPositions[charData.index] = {\n x: currentX,\n y: currentY,\n width: charData.width, // All characters keep their width for cursor navigation\n height: charData.fontSize,\n };\n\n // Always advance X (so cursor can move through hidden spaces)\n currentX += charData.width;\n }\n\n // Calculate cursor position with proper kerning support\n // Cursor position N = after character N-1, before character N\n if (currentLineChars.length > 0) {\n const firstCharIndex = currentLineChars[0].index;\n const lastCharIndex = currentLineChars[currentLineChars.length - 1].index;\n\n // Check if cursor is on this line\n // CRITICAL: Don't render cursor at lastCharIndex + 1 if the next line starts there\n // This prevents duplicate cursors at wrap boundaries\n const nextLineExists = lineIndex < wrappedLines.length - 1;\n const nextLineStartsAtEndOfThisLine = nextLineExists && lastCharIndex + 1 === charIndex;\n\n const maxAllowedCursor = nextLineStartsAtEndOfThisLine ? lastCharIndex : lastCharIndex + 1;\n\n if (cursorPosition >= firstCharIndex && cursorPosition <= maxAllowedCursor) {\n if (cursorPosition === firstCharIndex) {\n // Cursor before first character on this line\n cursorX = lineX;\n cursorY = currentY;\n cursorHeight = lineBoxHeight;\n } else {\n // Cursor after some character - sum per-character widths up to cursor\n // Apply space layout rules to match text rendering\n let visibleTextWidth = 0;\n for (let k = 0; k < currentLineChars.length && currentLineChars[k].index < cursorPosition; k++) {\n const c = currentLineChars[k];\n const isSpace = c.char === ' ';\n let isVisible = true;\n if (isSpace) {\n const isLeadingSpace = k < leadingSpacesCount;\n const isTrailingSpace = k >= currentLineChars.length - trailingSpacesCount;\n const leadingHidden = !isParagraphStart && leadingSpacesCount > 0;\n const trailingHidden = !isParagraphEnd && trailingSpacesCount > 0;\n isVisible = !((isLeadingSpace && leadingHidden) || (isTrailingSpace && trailingHidden));\n }\n if (isVisible) {\n visibleTextWidth += c.width;\n }\n }\n\n cursorX = lineX + visibleTextWidth;\n cursorY = currentY;\n cursorHeight = lineBoxHeight;\n }\n }\n }\n\n // Advance to next line (match renderRichTextFillOnly exactly)\n if (lineIndex < wrappedLines.length - 1) {\n // Cumulative advancement: currentY += spacing\n currentY += lineSpacing;\n }\n }\n });\n\n // Render selection highlight (using kerning-aware positioning to match cursor)\n const hasSelection = selectionStart !== selectionEnd;\n\n // Track selection handle positions for iOS-style handles\n let startHandlePos: { x: number; y: number } | null = null;\n let endHandlePos: { x: number; y: number } | null = null;\n\n if (hasSelection) {\n const minSel = Math.min(selectionStart, selectionEnd);\n const maxSel = Math.max(selectionStart, selectionEnd);\n\n ctx.save();\n ctx.fillStyle = getThemeTextSelectionColor(ctx.canvas);\n\n // Re-process wrapped lines to render selection with proper kerning\n let selCharIndex = 0;\n let selCurrentY = -totalHeight / 2;\n\n wrappedLines.forEach((lineSpans, lineIndex) => {\n const isParagraphStart = paragraphMetadata[lineIndex].isParagraphStart;\n const isParagraphEnd = paragraphMetadata[lineIndex].isParagraphEnd;\n const isFirstLine = lineIndex === 0;\n const isLastLine = lineIndex === wrappedLines.length - 1;\n\n // Build line characters with per-character widths and styles\n const lineChars: Array<{ char: string; index: number; width: number; style: CharacterStyle }> = [];\n lineSpans.forEach((span) => {\n Array.from(span.text).forEach((char) => {\n // Get per-character style\n const charStyle = span.style || {};\n const charFontSize = charStyle.fontSize !== undefined ? charStyle.fontSize : fontSize;\n const charFontFamily = charStyle.fontFamily !== undefined ? charStyle.fontFamily : fontFamily;\n const charBold = charStyle.bold !== undefined ? charStyle.bold : bold;\n const charItalic = charStyle.italic !== undefined ? charStyle.italic : italic;\n\n // Measure character width with its specific font\n ctx.save();\n const fontWeight = charBold ? 'bold' : 'normal';\n const fontStyleStr = charItalic ? 'italic' : 'normal';\n ctx.font = `${fontStyleStr} ${fontWeight} ${charFontSize}px \"${charFontFamily}\", Arial, sans-serif`;\n const charWidth = ctx.measureText(char).width;\n ctx.restore();\n\n lineChars.push({ char, index: selCharIndex, width: charWidth, style: charStyle });\n selCharIndex++;\n });\n });\n\n if (lineChars.length > 0) {\n const firstCharIndex = lineChars[0].index;\n const lastCharIndex = lineChars[lineChars.length - 1].index;\n\n // Check if this line has any selected characters\n if (maxSel > firstCharIndex && minSel <= lastCharIndex) {\n ctx.save();\n\n const fullLineText = lineChars.map((c) => c.char).join('');\n\n // Calculate leading/trailing spaces\n const leadingSpacesCount = fullLineText.match(/^ +/)?.[0].length || 0;\n const trailingSpacesCount = fullLineText.match(/ +$/)?.[0].length || 0;\n\n // Calculate line width using per-character widths (respecting space layout rules)\n let lineWidth = 0;\n for (let i = 0; i < lineChars.length; i++) {\n // Skip leading spaces if not first line\n if (!isFirstLine && i < leadingSpacesCount) continue;\n // Skip trailing spaces if not last line\n if (!isLastLine && i >= lineChars.length - trailingSpacesCount) continue;\n lineWidth += lineChars[i].width;\n }\n\n let lineX = 0;\n if (textAlign === 'center') {\n lineX = -lineWidth / 2;\n } else if (textAlign === 'right') {\n lineX = -lineWidth;\n }\n\n // Calculate selection boundaries on this line\n const lineSelStart = Math.max(minSel, firstCharIndex);\n const lineSelEnd = Math.min(maxSel, lastCharIndex + 1);\n\n // Measure width up to selection start using per-character widths\n let xBeforeSelection = 0;\n for (let i = 0; i < lineChars.length && lineChars[i].index < lineSelStart; i++) {\n const c = lineChars[i];\n const isLeadingSpace = i < leadingSpacesCount;\n const isTrailingSpace = i >= lineChars.length - trailingSpacesCount;\n const leadingHidden = !isParagraphStart && leadingSpacesCount > 0;\n const trailingHidden = !isParagraphEnd && trailingSpacesCount > 0;\n const isVisible = !((isLeadingSpace && leadingHidden) || (isTrailingSpace && trailingHidden));\n if (isVisible) {\n xBeforeSelection += c.width;\n }\n }\n\n // Measure width up to selection end using per-character widths\n let xBeforeSelectionEnd = 0;\n for (let i = 0; i < lineChars.length && lineChars[i].index < lineSelEnd; i++) {\n const c = lineChars[i];\n const isLeadingSpace = i < leadingSpacesCount;\n const isTrailingSpace = i >= lineChars.length - trailingSpacesCount;\n const leadingHidden = !isParagraphStart && leadingSpacesCount > 0;\n const trailingHidden = !isParagraphEnd && trailingSpacesCount > 0;\n const isVisible = !((isLeadingSpace && leadingHidden) || (isTrailingSpace && trailingHidden));\n if (isVisible) {\n xBeforeSelectionEnd += c.width;\n }\n }\n\n // Draw selection rectangle\n const selectionX = lineX + xBeforeSelection;\n const selectionWidth = xBeforeSelectionEnd - xBeforeSelection;\n ctx.fillRect(selectionX, selCurrentY, selectionWidth, lineBoxHeight);\n\n // Track handle positions (first occurrence becomes start, last becomes end)\n if (startHandlePos === null) {\n // First line with selection - start handle at top-left\n startHandlePos = { x: selectionX, y: selCurrentY };\n }\n // Always update end handle - last line with selection, at bottom-right\n endHandlePos = { x: selectionX + selectionWidth, y: selCurrentY + lineBoxHeight };\n\n ctx.restore();\n }\n }\n\n // Advance to next line\n if (lineIndex < wrappedLines.length - 1) {\n selCurrentY += lineSpacing;\n }\n });\n ctx.restore();\n\n // Re-render text ON TOP of selection so text isn't tinted\n // This ensures selection appears BEHIND the text characters\n if (editRichText) {\n ctx.save();\n // Render the text content again (it will draw on top of selection)\n const customData = textElement.transformType === 'custom' ? textElement.transformData as CustomTransformData : null;\n const maxWidth = customData?.width\n ? customData.width - HORIZONTAL_PADDING * 2\n : undefined;\n renderRichTextFillOnly(ctx, editRichText, {\n fontSize,\n fontFamily,\n color: textElement.color || '#000000',\n bold,\n italic,\n underline,\n strikethrough,\n textAlign,\n }, maxWidth);\n ctx.restore();\n }\n }\n\n // Render iOS-style selection handles for touch devices\n if (hasSelection && isTouchDevice && startHandlePos && endHandlePos) {\n // Type assertions needed because TypeScript doesn't track assignments across if blocks\n const startPos = startHandlePos as { x: number; y: number };\n const endPos = endHandlePos as { x: number; y: number };\n\n // ZOOM-INVARIANT sizing: divide by zoom to maintain constant screen-space size\n // Visual handle size - keep small and elegant\n const handleRadius = 6 / currentZoom; // ~6px on screen (small circle)\n const stemWidth = 2 / currentZoom; // ~2px on screen\n\n ctx.save();\n const accentColor = getThemeAccentColor();\n ctx.fillStyle = accentColor;\n ctx.strokeStyle = accentColor;\n ctx.lineWidth = stemWidth;\n ctx.lineCap = 'round';\n\n // Calculate handle center positions (where the circles are drawn)\n // Circle at top of start bookend (above the vertical line)\n const startHandleCenter = { x: startPos.x, y: startPos.y - handleRadius };\n // Circle at bottom of end bookend (below the vertical line)\n const endHandleCenter = { x: endPos.x, y: endPos.y + handleRadius };\n\n // Start handle (circle ABOVE selection, at top-left)\n // Vertical line spans full text height (top to bottom)\n ctx.beginPath();\n ctx.moveTo(startPos.x, startPos.y);\n ctx.lineTo(startPos.x, startPos.y + lineBoxHeight);\n ctx.stroke();\n // Circle at top of stem (with white border for visibility)\n ctx.beginPath();\n ctx.arc(startHandleCenter.x, startHandleCenter.y, handleRadius, 0, Math.PI * 2);\n ctx.fill();\n ctx.strokeStyle = 'white';\n ctx.lineWidth = 2 / currentZoom;\n ctx.stroke();\n\n // End handle (circle BELOW selection, at bottom-right)\n // Vertical line spans full text height (top to bottom)\n ctx.strokeStyle = accentColor;\n ctx.lineWidth = stemWidth;\n ctx.beginPath();\n ctx.moveTo(endPos.x, endPos.y - lineBoxHeight);\n ctx.lineTo(endPos.x, endPos.y);\n ctx.stroke();\n // Circle at bottom of stem (with white border for visibility)\n ctx.beginPath();\n ctx.arc(endHandleCenter.x, endHandleCenter.y, handleRadius, 0, Math.PI * 2);\n ctx.fill();\n ctx.strokeStyle = 'white';\n ctx.lineWidth = 2 / currentZoom;\n ctx.stroke();\n\n ctx.restore();\n\n // Store handle positions for hit testing (in element-local coordinates)\n // Includes both handle center (for hit testing) and text edge (for coordinate offset during drag)\n if (selectionHandlePositionsRef) {\n selectionHandlePositionsRef.current = {\n start: {\n center: startHandleCenter,\n textEdge: startPos, // Original selection edge (top-left of selection on first line)\n },\n end: {\n center: endHandleCenter,\n textEdge: endPos, // Original selection edge (bottom-right of selection on last line)\n },\n };\n }\n } else if (selectionHandlePositionsRef) {\n // Clear handle positions when no selection or not touch device\n selectionHandlePositionsRef.current = { start: null, end: null };\n }\n\n // Render cursor (blinking vertical line) - only if no selection\n // Use zoom-invariant line width so cursor appears same size at all zoom levels\n if (!hasSelection && cursorOpacity > 0) {\n ctx.save();\n ctx.globalAlpha = cursorOpacity;\n ctx.strokeStyle = getThemeAccentColor();\n ctx.lineWidth = 3 / currentZoom; // Zoom-invariant: always 3px on screen\n ctx.lineCap = 'round'; // Rounded ends for smoother appearance\n ctx.beginPath();\n ctx.moveTo(cursorX, cursorY);\n ctx.lineTo(cursorX, cursorY + cursorHeight);\n ctx.stroke();\n ctx.restore();\n }\n\n ctx.restore();\n }\n\n /**\n * Render edit mode features for transformed text (circle, wave, arch, etc.)\n * Renders cursor along the transform path\n */\n private static renderTransformEditModeLayer(\n ctx: CanvasRenderingContext2D,\n element: TextElement,\n editModeData: {\n cursorPosition: number;\n selectionStart: number;\n selectionEnd: number;\n editText: string;\n editRichText: RichText | null;\n cursorOpacity: number;\n },\n zoom: number = 1.0\n ): void {\n const { cursorPosition, cursorOpacity } = editModeData;\n const fontSize = element.fontSize || 24;\n const fontFamily = element.fontFamily || 'Arial';\n const bold = element.bold || false;\n const italic = element.italic || false;\n\n ctx.save();\n\n // Apply element's transform (position and rotation)\n ctx.translate(element.x, element.y);\n ctx.rotate((-element.rotation * Math.PI) / 180);\n\n // Set up font to measure characters\n const weight = bold ? 'bold' : 'normal';\n const style = italic ? 'italic' : 'normal';\n ctx.font = `${style} ${weight} ${fontSize}px ${fontFamily}`;\n\n // Get character positions along the transform path\n const chars = Array.from(element.text);\n const charWidths = chars.map((char) => ctx.measureText(char).width);\n const positions = HoverRenderer.calculateCharPositions(element, chars, charWidths);\n\n // Find cursor position\n if (cursorPosition >= 0 && cursorPosition <= chars.length && cursorOpacity > 0) {\n let cursorPos: { x: number; y: number; angle: number };\n\n if (cursorPosition === 0) {\n // Cursor before first character\n if (positions.length > 0) {\n const firstPos = positions[0];\n const charWidth = charWidths[0];\n // Position cursor half a character width before the first character\n cursorPos = {\n x: firstPos.x - Math.cos(firstPos.angle) * (charWidth / 2),\n y: firstPos.y - Math.sin(firstPos.angle) * (charWidth / 2),\n angle: firstPos.angle,\n };\n } else {\n // No characters, cursor at origin\n cursorPos = { x: 0, y: 0, angle: 0 };\n }\n } else if (cursorPosition >= positions.length) {\n // Cursor after last character\n const lastPos = positions[positions.length - 1];\n const lastCharWidth = charWidths[charWidths.length - 1];\n cursorPos = {\n x: lastPos.x + Math.cos(lastPos.angle) * (lastCharWidth / 2),\n y: lastPos.y + Math.sin(lastPos.angle) * (lastCharWidth / 2),\n angle: lastPos.angle,\n };\n } else {\n // Cursor between characters - use position of character at cursor\n const charPos = positions[cursorPosition];\n const charWidth = charWidths[cursorPosition];\n cursorPos = {\n x: charPos.x - Math.cos(charPos.angle) * (charWidth / 2),\n y: charPos.y - Math.sin(charPos.angle) * (charWidth / 2),\n angle: charPos.angle,\n };\n }\n\n // Draw cursor at calculated position with rotation\n // Use zoom-invariant line width so cursor appears same size at all zoom levels\n ctx.save();\n ctx.translate(cursorPos.x, cursorPos.y);\n ctx.rotate(cursorPos.angle);\n\n ctx.globalAlpha = cursorOpacity;\n ctx.strokeStyle = getThemeAccentColor();\n ctx.lineWidth = 2 / zoom; // Zoom-invariant: always 2px on screen\n\n const cursorHeight = fontSize * 1.2;\n ctx.beginPath();\n ctx.moveTo(0, -cursorHeight / 2);\n ctx.lineTo(0, cursorHeight / 2);\n ctx.stroke();\n\n ctx.restore();\n }\n\n ctx.restore();\n }\n\n /**\n * Render crop box layer (for images in crop mode)\n * Shows both image resize handles and crop handles\n */\n static renderCropBoxLayer(\n ctx: CanvasRenderingContext2D,\n selectedElement: BaseElement,\n transformHandles: TransformHandles,\n zoom: number = 1.0\n ): void {\n if (!(selectedElement instanceof ImageElement) || !selectedElement.isCropping) return;\n const imgElement = selectedElement as ImageElement;\n\n const cropBox = imgElement.getCropBoxBounds();\n if (!cropBox) return;\n\n // Crop handle style constants - divide by zoom to maintain consistent screen-space size\n // Since we apply ctx.scale(zoom) below, these need to be in world-space (larger when zoomed out)\n const EDGE_HANDLE_THICKNESS = 4 / zoom; // Thickness of edge rectangles\n const CROP_BOX_LINE_WIDTH = 2 / zoom; // Width of crop box outline\n const CORNER_HANDLE_RADIUS_SCALED = CORNER_HANDLE_VISUAL_RADIUS / zoom; // Circular corner radius (visual)\n const EDGE_HANDLE_LENGTH_SCALED = EDGE_HANDLE_VISUAL_LENGTH / zoom; // Edge handle length (visual)\n const GRID_LINE_WIDTH = 1 / zoom; // Grid line width\n\n ctx.save();\n\n // Transform to the visible area center (this.x, this.y), scaled by zoom\n ctx.translate(selectedElement.x * zoom, selectedElement.y * zoom);\n ctx.rotate(RotationUtils.toRadians(selectedElement.rotation));\n\n // Apply flip transformations AND zoom to match where the image is actually rendered\n // This is necessary so the dark overlay and handles align with the flipped image\n const flipH = imgElement.transformData.flipHorizontal ? -1 : 1;\n const flipV = imgElement.transformData.flipVertical ? -1 : 1;\n ctx.scale(flipH * zoom, flipV * zoom);\n\n // Calculate where the full image frame is relative to the visible crop center\n const cropWidth = imgElement.transformData.width * imgElement.transformData.cropWidth;\n const cropHeight = imgElement.transformData.height * imgElement.transformData.cropHeight;\n\n // Offset from crop center to frame center in local space\n const localOffsetX =\n imgElement.transformData.width / 2 -\n (imgElement.transformData.cropX * imgElement.transformData.width + cropWidth / 2);\n const localOffsetY =\n imgElement.transformData.height / 2 -\n (imgElement.transformData.cropY * imgElement.transformData.height + cropHeight / 2);\n\n // Image bounds in local coordinates (full frame)\n const halfWidth = imgElement.transformData.width / 2;\n const halfHeight = imgElement.transformData.height / 2;\n const imageBounds = {\n x: localOffsetX - halfWidth,\n y: localOffsetY - halfHeight,\n width: imgElement.transformData.width,\n height: imgElement.transformData.height,\n };\n\n // Darken area outside crop box\n ctx.fillStyle = 'rgba(0, 0, 0, 0.5)';\n\n // Top\n if (cropBox.y > imageBounds.y) {\n ctx.fillRect(imageBounds.x, imageBounds.y, imageBounds.width, cropBox.y - imageBounds.y);\n }\n\n // Bottom\n const cropBottom = cropBox.y + cropBox.height;\n const imageBottom = imageBounds.y + imageBounds.height;\n if (cropBottom < imageBottom) {\n ctx.fillRect(imageBounds.x, cropBottom, imageBounds.width, imageBottom - cropBottom);\n }\n\n // Left\n if (cropBox.x > imageBounds.x) {\n ctx.fillRect(imageBounds.x, cropBox.y, cropBox.x - imageBounds.x, cropBox.height);\n }\n\n // Right\n const cropRight = cropBox.x + cropBox.width;\n const imageRight = imageBounds.x + imageBounds.width;\n if (cropRight < imageRight) {\n ctx.fillRect(cropRight, cropBox.y, imageRight - cropRight, cropBox.height);\n }\n\n // Draw crop box outline with theme color\n ctx.strokeStyle = theme.canvas.selectionColor;\n ctx.lineWidth = CROP_BOX_LINE_WIDTH;\n ctx.strokeRect(cropBox.x, cropBox.y, cropBox.width, cropBox.height);\n\n // Draw grid lines (rule of thirds)\n ctx.strokeStyle = 'rgba(255, 255, 255, 0.5)';\n ctx.lineWidth = GRID_LINE_WIDTH;\n\n // Vertical lines\n const thirdWidth = cropBox.width / 3;\n ctx.beginPath();\n ctx.moveTo(cropBox.x + thirdWidth, cropBox.y);\n ctx.lineTo(cropBox.x + thirdWidth, cropBox.y + cropBox.height);\n ctx.moveTo(cropBox.x + 2 * thirdWidth, cropBox.y);\n ctx.lineTo(cropBox.x + 2 * thirdWidth, cropBox.y + cropBox.height);\n ctx.stroke();\n\n // Horizontal lines\n const thirdHeight = cropBox.height / 3;\n ctx.beginPath();\n ctx.moveTo(cropBox.x, cropBox.y + thirdHeight);\n ctx.lineTo(cropBox.x + cropBox.width, cropBox.y + thirdHeight);\n ctx.moveTo(cropBox.x, cropBox.y + 2 * thirdHeight);\n ctx.lineTo(cropBox.x + cropBox.width, cropBox.y + 2 * thirdHeight);\n ctx.stroke();\n\n // Draw corner and edge handles for crop box\n\n // Corner handles (circular with white fill and gray border)\n const corners = [\n { x: cropBox.x, y: cropBox.y }, // top-left\n { x: cropBox.x + cropBox.width, y: cropBox.y }, // top-right\n { x: cropBox.x + cropBox.width, y: cropBox.y + cropBox.height }, // bottom-right\n { x: cropBox.x, y: cropBox.y + cropBox.height }, // bottom-left\n ];\n\n corners.forEach((corner) => {\n // Draw gray border\n ctx.beginPath();\n ctx.arc(corner.x, corner.y, CORNER_HANDLE_RADIUS_SCALED + 1 / zoom, 0, Math.PI * 2);\n ctx.fillStyle = '#bbb';\n ctx.fill();\n\n // Draw white fill\n ctx.beginPath();\n ctx.arc(corner.x, corner.y, CORNER_HANDLE_RADIUS_SCALED, 0, Math.PI * 2);\n ctx.fillStyle = '#fff';\n ctx.fill();\n });\n\n // Edge handles (rectangles - wide for top/bottom, tall for left/right at crop box edges)\n const edges = [\n { x: cropBox.x + cropBox.width / 2, y: cropBox.y, orientation: 'horizontal' }, // top\n { x: cropBox.x + cropBox.width / 2, y: cropBox.y + cropBox.height, orientation: 'horizontal' }, // bottom\n { x: cropBox.x, y: cropBox.y + cropBox.height / 2, orientation: 'vertical' }, // left\n { x: cropBox.x + cropBox.width, y: cropBox.y + cropBox.height / 2, orientation: 'vertical' }, // right\n ];\n\n edges.forEach((edge) => {\n let width, height;\n if (edge.orientation === 'horizontal') {\n // Top/bottom: wide rectangles\n width = EDGE_HANDLE_LENGTH_SCALED;\n height = EDGE_HANDLE_THICKNESS;\n } else {\n // Left/right: tall rectangles\n width = EDGE_HANDLE_THICKNESS;\n height = EDGE_HANDLE_LENGTH_SCALED;\n }\n\n const x = edge.x - width / 2;\n const y = edge.y - height / 2;\n\n // Fill with white (sharp corners)\n ctx.fillStyle = '#fff';\n ctx.fillRect(x, y, width, height);\n\n // Stroke with gray border\n ctx.strokeStyle = '#bbb';\n ctx.lineWidth = GRID_LINE_WIDTH;\n ctx.strokeRect(x, y, width, height);\n });\n\n ctx.restore();\n\n // Render image resize handles (white circles) LAST in world coordinates\n // These are drawn last so they appear on top of everything\n // NOTE: We render these OUTSIDE the transformed context (after restore)\n // so we use world coordinates directly with zoom applied\n if (transformHandles && transformHandles.resizeHandles) {\n // Only render corner handles for images\n const cornerHandles = transformHandles.resizeHandles.filter(\n (h) =>\n h.anchor === 'top-left' ||\n h.anchor === 'top-right' ||\n h.anchor === 'bottom-left' ||\n h.anchor === 'bottom-right'\n );\n\n // Get crop box corners in world coordinates to check for overlap\n const cropCorners = imgElement.getCropBoxWorldCorners();\n\n // Match the exact style from TransformHandles.js\n const handleRadius = 6; // HANDLE_SIZE / 2 = 12 / 2 = 6\n const minDistance = 20; // Hide image handle if crop handle is within 20px\n\n cornerHandles.forEach((handle) => {\n // Check if any crop corner is too close to this image corner\n let tooClose = false;\n if (cropCorners) {\n for (const cropCorner of cropCorners) {\n const dx = handle.x - cropCorner.x;\n const dy = handle.y - cropCorner.y;\n const distance = Math.sqrt(dx * dx + dy * dy);\n if (distance < minDistance) {\n tooClose = true;\n break;\n }\n }\n }\n\n // Only render if not too close to a crop handle\n if (!tooClose) {\n ctx.save();\n // Ensure fully opaque rendering\n ctx.globalAlpha = 1.0;\n ctx.beginPath();\n // Apply zoom to convert world coordinates to screen coordinates\n ctx.arc(handle.x * zoom, handle.y * zoom, handleRadius, 0, 2 * Math.PI);\n // Match the exact style from TransformHandles - white fill with theme accent border\n ctx.fillStyle = '#fff';\n ctx.fill();\n ctx.strokeStyle = getThemeAccentColor(ctx.canvas);\n ctx.lineWidth = 2;\n ctx.stroke();\n ctx.restore();\n }\n });\n }\n }\n}\n","/**\n * CanvasRenderer - Layered canvas rendering system (facade)\n *\n * Main entry point for canvas rendering. Delegates to focused renderer modules:\n * - SelectionRenderer: Selection boxes, transform handles, resize info\n * - HoverRenderer: Hover outlines, ring effects, character position calculations\n * - InteractionFeedbackRenderer: Snap guides, spacing indicators, distance labels\n * - EditModeRenderer: Text cursor, selection highlighting, crop UI\n *\n * This file retains:\n * - Element layer rendering (knockout, clipping, overflow dimming)\n * - The main render() orchestration method\n * - All public static method signatures (delegating to sub-renderers)\n *\n * ============================================================================\n * IMPORTANT: THREE SEPARATE VISUAL FEEDBACK SYSTEMS (DO NOT CONFUSE!)\n * ============================================================================\n *\n * 1. **HOVER RING EFFECT** (HoverRenderer.ts)\n * - Colored ring/outline that appears when hovering over text elements\n * - Rendered by: HoverRenderer.renderHoverLayer()\n * - Uses: Offscreen canvas compositing with gap effect\n * - Example: Hover over \" Foo Bar\" text to see cyan/accent colored ring\n *\n * 2. **ELEMENT STROKE EFFECT** (StrokeRenderer.ts)\n * - Actual stroke property on elements (element.stroke.enabled = true)\n * - Rendered by: StrokeRenderer.renderTextStroke()\n * - Location: src/rendering/StrokeRenderer.ts\n * - Only renders when user explicitly enables stroke in effects panel\n * - Example: Text with a black outline configured in effects panel\n *\n * 3. **SELECTION BOX** (Transform classes)\n * - Dashed rectangle around selected/hovered elements\n * - Rendered by: element.render(ctx, isSelected, isHovered) in each transform class\n * - Location: CustomTransform.ts, CircleTransform.ts, etc.\n * - Shows bounding box of element\n * - Example: Dashed green rectangle when you select text\n *\n * These are COMPLETELY SEPARATE systems. During the \" Foo Bar\" bug fix,\n * we fixed #1 (hover ring effect), NOT #2 (element stroke).\n */\n\nimport {\n PREVIEW_ELEMENT_OPACITY,\n} from '../constants.js';\nimport type { BaseElement } from './BaseElement.js';\nimport type { TransformHandles } from './TransformHandles.js';\nimport type { InteractionStateMachine, ActiveChildContext } from './InteractionStateMachine.js';\nimport { isGroupElement, isImageElement } from '../types/guards.js';\nimport { RichText } from '../types/index.js';\nimport type { SnapGuide, SpacingIndicator, AnyElementConfig, ArtboardDistressTexture, CanvasError, ClipShape } from '../types/index.js';\nimport { renderWithCompositing } from '../rendering/CompositingRenderer.js';\nimport type { CompositeOp } from '../rendering/CompositingRenderer.js';\nimport { renderWithMasks } from '../rendering/MaskRenderer.js';\nimport { applyArtboardDistressTexture, applyElementDistressTexture } from '../rendering/DistressTextureRenderer.js';\nimport { applyArtboardImageMask } from '../rendering/MaskRenderer.js';\nimport { createLogger } from '../utils/logger.js';\n\n// Focused renderer modules\nimport { SelectionRenderer } from './SelectionRenderer.js';\nimport { HoverRenderer } from './HoverRenderer.js';\nimport { InteractionFeedbackRenderer } from './InteractionFeedbackRenderer.js';\nimport { EditModeRenderer } from './EditModeRenderer.js';\n\nconst renderLogger = createLogger('CanvasRenderer');\n\ninterface HoverState {\n type: 'element' | 'resize-handle' | 'rotation-handle' | null;\n data?: BaseElement | null;\n}\n\nexport class CanvasRenderer {\n // =========================================================================\n // Pooled Offscreen Canvases (avoid per-frame allocation)\n // =========================================================================\n\n /** Pooled offscreen canvas for clipping content rendering */\n private static _contentCanvas: HTMLCanvasElement | null = null;\n private static _contentCanvasSize: { width: number; height: number } = { width: 0, height: 0 };\n\n /** Pooled offscreen canvas for clipping mask rendering */\n private static _maskCanvas: HTMLCanvasElement | null = null;\n private static _maskCanvasSize: { width: number; height: number } = { width: 0, height: 0 };\n\n /**\n * Get a pooled offscreen canvas for clipping content, only recreating\n * when dimensions change. Eliminates per-frame canvas allocation.\n */\n private static _getContentCanvas(width: number, height: number): HTMLCanvasElement {\n if (\n !this._contentCanvas ||\n this._contentCanvasSize.width !== width ||\n this._contentCanvasSize.height !== height\n ) {\n this._contentCanvas = document.createElement('canvas');\n this._contentCanvas.width = width;\n this._contentCanvas.height = height;\n this._contentCanvasSize = { width, height };\n }\n return this._contentCanvas;\n }\n\n /**\n * Get a pooled offscreen canvas for clipping masks, only recreating\n * when dimensions change. Eliminates per-frame canvas allocation.\n */\n private static _getMaskCanvas(width: number, height: number): HTMLCanvasElement {\n if (\n !this._maskCanvas ||\n this._maskCanvasSize.width !== width ||\n this._maskCanvasSize.height !== height\n ) {\n this._maskCanvas = document.createElement('canvas');\n this._maskCanvas.width = width;\n this._maskCanvas.height = height;\n this._maskCanvasSize = { width, height };\n }\n return this._maskCanvas;\n }\n\n // =========================================================================\n // Per-frame allocation cache (avoid toJSON() / Map / Set on every frame)\n // =========================================================================\n\n /**\n * Cached element JSON configs keyed on the elements array reference.\n * toJSON() calls are expensive at 60fps with 20+ elements.\n * Safe to cache because knockout/mask metadata (id, blendMode, knockoutParts, masks)\n * only changes on React state updates, which always produce a new array reference.\n * Interactive operations (drag, resize) mutate element position in-place on the\n * same instances without changing the array reference.\n */\n private static _cachedElementsRef: BaseElement[] | null = null;\n private static _cachedElementConfigs: AnyElementConfig[] | null = null;\n private static _cachedElementMap: Map<string, BaseElement> | null = null;\n\n /** Reusable Set for tracking knockout-rendered IDs — avoids per-frame allocation. */\n private static readonly _knockoutRenderedIds: Set<string> = new Set<string>();\n /**\n * Optional callback for render errors. Set by SnowconeCanvas to forward\n * rendering errors to the onError prop. When set, individual element render\n * failures are caught and reported instead of crashing the entire canvas.\n */\n static onRenderError: ((error: CanvasError) => void) | null = null;\n\n /**\n * Safely render an element, catching errors so one element's failure\n * doesn't crash the entire canvas render loop.\n */\n private static safeRender(\n ctx: CanvasRenderingContext2D,\n element: BaseElement,\n isSelected: boolean,\n isHovered: boolean,\n ): void {\n try {\n element.render(ctx, isSelected, isHovered);\n } catch (error) {\n const err = error instanceof Error ? error : new Error(String(error));\n renderLogger.error(`Failed to render element ${element.id}:`, err);\n if (CanvasRenderer.onRenderError) {\n CanvasRenderer.onRenderError({\n category: 'render',\n message: `Failed to render element: ${err.message}`,\n originalError: err,\n elementId: element.id,\n recoverable: true,\n });\n }\n }\n }\n\n // =========================================================================\n // Element Layer Rendering (kept here - tightly coupled knockout/clipping)\n // =========================================================================\n\n /**\n * Helper function to render an element (using actual element instance, not config)\n * Used by knockout rendering system\n */\n private static renderElement(\n ctx: CanvasRenderingContext2D,\n element: BaseElement,\n isPreview: boolean = true\n ): void {\n // Apply subtle opacity for preview mode\n if (isPreview) {\n ctx.save();\n ctx.globalAlpha = PREVIEW_ELEMENT_OPACITY;\n }\n\n // Render the element (no selection/hover highlights for knockout rendering)\n element.render(ctx, false, false);\n\n if (isPreview) {\n ctx.restore();\n }\n }\n\n /**\n * Apply artboard clip path to the context, respecting clipShape.\n * After calling this, subsequent drawing will be clipped to the artboard shape.\n * Caller must call ctx.beginPath() before this if needed.\n */\n private static applyArtboardClipPath(\n ctx: CanvasRenderingContext2D,\n artboard: { x: number; y: number; width: number; height: number; borderRadius?: number; clipShape?: ClipShape }\n ): void {\n const { x, y, width, height, clipShape } = artboard;\n const borderRadius = artboard.borderRadius || 0;\n\n ctx.beginPath();\n\n if (!clipShape || clipShape === 'rectangle') {\n if (borderRadius > 0) {\n ctx.roundRect(x, y, width, height, borderRadius);\n } else {\n ctx.rect(x, y, width, height);\n }\n } else if (clipShape === 'circle') {\n const centerX = x + width / 2;\n const centerY = y + height / 2;\n const radius = Math.min(width, height) / 2;\n ctx.arc(centerX, centerY, radius, 0, Math.PI * 2);\n } else if (typeof clipShape === 'object' && clipShape.type === 'rounded') {\n const radius = Math.min(clipShape.radius, Math.min(width, height) / 2);\n ctx.roundRect(x, y, width, height, radius);\n } else if (typeof clipShape === 'object' && clipShape.type === 'path') {\n try {\n const path = new Path2D(clipShape.d);\n ctx.translate(x, y);\n ctx.clip(path);\n ctx.translate(-x, -y);\n return; // Path2D handles clip directly\n } catch (e) {\n // Invalid path - fall back to rectangle\n ctx.rect(x, y, width, height);\n }\n } else if (typeof clipShape === 'object' && clipShape.type === 'composite-path') {\n // ADR-0054 multi-piece spreads: union of piece-local boundary paths,\n // each translated (and optionally 90°/180°/270° rotated) into the\n // artboard frame. Path2D.addPath(path, DOMMatrix) composes; Canvas's\n // clip() respects the resulting compound region.\n try {\n const composite = new Path2D();\n for (const piece of clipShape.pieces) {\n const sub = new Path2D(piece.d);\n const rot = piece.rotation ?? 0;\n const matrix = new DOMMatrix();\n matrix.translateSelf(piece.x, piece.y);\n if (rot !== 0) {\n // Rotate around the piece's *unrotated* center so the\n // post-rotation bbox lands flush at (piece.x, piece.y).\n const cx = (piece.baseWidth ?? 0) / 2;\n const cy = (piece.baseHeight ?? 0) / 2;\n // After rotation, the piece's visual bbox top-left can move;\n // compensate so rotated piece sits at (piece.x, piece.y).\n const swap = rot === 90 || rot === 270;\n const visW = swap ? (piece.baseHeight ?? 0) : (piece.baseWidth ?? 0);\n const visH = swap ? (piece.baseWidth ?? 0) : (piece.baseHeight ?? 0);\n matrix.translateSelf(visW / 2, visH / 2);\n matrix.rotateSelf(rot);\n matrix.translateSelf(-cx, -cy);\n }\n composite.addPath(sub, matrix);\n }\n ctx.translate(x, y);\n ctx.clip(composite);\n ctx.translate(-x, -y);\n return;\n } catch (e) {\n ctx.rect(x, y, width, height);\n }\n }\n\n ctx.clip();\n }\n\n /**\n * Render an element with overflow dimming - parts outside the artboard render at 30% opacity\n * Uses two-pass rendering: first at 30% opacity (overflow), then clipped to artboard at 100% (inside)\n */\n private static renderElementWithOverflowDimming(\n ctx: CanvasRenderingContext2D,\n element: BaseElement,\n artboard: { x: number; y: number; width: number; height: number; borderRadius?: number; clipShape?: ClipShape },\n isSelected: boolean,\n isHovered: boolean,\n isPreview: boolean\n ): void {\n // Save the current transform for later restoration\n const savedTransform = ctx.getTransform();\n const borderRadius = artboard.borderRadius || 0;\n\n // Pass 1: Render at 30% opacity with blur ONLY in overflow area (outside artboard)\n // Use an inverted clip to render only outside the artboard bounds\n ctx.save();\n ctx.globalAlpha = 0.3 * (isPreview ? PREVIEW_ELEMENT_OPACITY : 1.0);\n // `blur(4px)` is intentionally unscaled by devicePixelRatio so it\n // matches PieceGuideRenderer's die-cut backdrop blur (also 4px,\n // unscaled) — the two passes should read as the same blur strength\n // on the same display. See PieceGuideRenderer.ts around `drawDieCut`\n // for the matching convention.\n ctx.filter = 'blur(4px)';\n\n // Create inverted clip: cover entire canvas, then subtract artboard\n // Using evenodd fill rule, the artboard \"hole\" will be excluded from the clip\n ctx.beginPath();\n // Outer rectangle must cover the entire VISIBLE world area (accounting for zoom/pan)\n // Get the inverse of the current transform to convert canvas coords to world coords\n // Note: Use actual canvas pixel dimensions - the transform already includes DPR scaling\n const transform = ctx.getTransform();\n const inverseTransform = transform.inverse();\n const screenWidth = ctx.canvas.width;\n const screenHeight = ctx.canvas.height;\n\n // Transform canvas corners to world coordinates\n const topLeft = new DOMPoint(0, 0).matrixTransform(inverseTransform);\n const bottomRight = new DOMPoint(screenWidth, screenHeight).matrixTransform(inverseTransform);\n\n // Add generous padding to ensure complete coverage even with slight transform errors\n const padding = Math.max(bottomRight.x - topLeft.x, bottomRight.y - topLeft.y);\n const worldMinX = topLeft.x - padding;\n const worldMinY = topLeft.y - padding;\n const worldMaxX = bottomRight.x + padding;\n const worldMaxY = bottomRight.y + padding;\n\n // Inner shape (will be \"cut out\" by evenodd) — what to *exclude*\n // from the dim halo. For ADR-0054 multi-piece spreads with\n // path-kind boundaries, this is the union of piece silhouettes\n // so the halo fills the whole viewport except inside silhouettes.\n // Without this, the area *between* silhouettes and the artboard's\n // bounding rect is left fully transparent, the parent's bg shows\n // through unmodified, and the user sees a sharp \"bright frame\"\n // around the silhouettes that contrasts with the dim halo region\n // (same parent bg + 30% artwork composite). The composite path\n // makes the whole \"outside silhouettes\" area read uniformly.\n //\n // For non-composite-path artboards, the artboard rect — rounded\n // by `borderRadius` for phone case corner wedges — is still the\n // right cutout. The historical comment chain on this block (sharp-\n // rect vs rounded) applies there.\n //\n // Build everything as a single Path2D and `ctx.clip(path,\n // 'evenodd')` so the outer rect + Path2D silhouettes can compose\n // (ctx.beginPath() + ctx.rect() + Path2D would not).\n const compositeShape =\n typeof artboard.clipShape === 'object' &&\n artboard.clipShape !== null &&\n artboard.clipShape.type === 'composite-path'\n ? artboard.clipShape\n : null;\n if (compositeShape) {\n const compoundPath = new Path2D();\n compoundPath.rect(worldMinX, worldMinY, worldMaxX - worldMinX, worldMaxY - worldMinY);\n for (const piece of compositeShape.pieces) {\n const sub = new Path2D(piece.d);\n const rot = piece.rotation ?? 0;\n const matrix = new DOMMatrix();\n matrix.translateSelf(artboard.x + piece.x, artboard.y + piece.y);\n if (rot !== 0) {\n const cx = (piece.baseWidth ?? 0) / 2;\n const cy = (piece.baseHeight ?? 0) / 2;\n const swap = rot === 90 || rot === 270;\n const visW = swap ? (piece.baseHeight ?? 0) : (piece.baseWidth ?? 0);\n const visH = swap ? (piece.baseWidth ?? 0) : (piece.baseHeight ?? 0);\n matrix.translateSelf(visW / 2, visH / 2);\n matrix.rotateSelf(rot);\n matrix.translateSelf(-cx, -cy);\n }\n compoundPath.addPath(sub, matrix);\n }\n ctx.clip(compoundPath, 'evenodd');\n } else {\n ctx.rect(worldMinX, worldMinY, worldMaxX - worldMinX, worldMaxY - worldMinY);\n if (borderRadius > 0) {\n ctx.roundRect(artboard.x, artboard.y, artboard.width, artboard.height, borderRadius);\n } else {\n ctx.rect(artboard.x, artboard.y, artboard.width, artboard.height);\n }\n ctx.clip('evenodd');\n }\n\n element.render(ctx, false, false); // Don't show selection/hover for the dimmed version\n ctx.restore();\n\n // Pass 2: Clip to artboard shape and render at 100% opacity\n ctx.save();\n this.applyArtboardClipPath(ctx, artboard);\n\n if (isPreview) {\n ctx.globalAlpha = PREVIEW_ELEMENT_OPACITY;\n }\n element.render(ctx, isSelected, isHovered);\n ctx.restore();\n\n // Restore transform (clip modifies it)\n ctx.setTransform(savedTransform);\n }\n\n /**\n * Render all elements layer\n * @param showOverflowDimmed When true, element parts outside the artboard render at 30% opacity\n * @param suppressOverflowDim When true, skip the 30% overflow pass even if `showOverflowDimmed`\n * is enabled. Used for piece-guide rendering (ADR-0054) where the boundary's custom path\n * clipShape is the visible design edge — overflow beyond the rectangular artboard reads as\n * a coloured halo rather than useful UX. Selected/hovered elements fall through to the\n * clipped-only branch which respects `clipShape` correctly.\n */\n static renderElementsLayer(\n ctx: CanvasRenderingContext2D,\n elements: BaseElement[],\n selectedId: string | null,\n hoverState?: HoverState,\n stateMachine?: InteractionStateMachine,\n artboardBackgroundColor?: string,\n artboard?: { x: number; y: number; width: number; height: number; borderRadius?: number; clipShape?: ClipShape },\n isPreview: boolean = true,\n showOverflowDimmed: boolean = false,\n suppressOverflowDim: boolean = false\n ): void {\n const isDragging = stateMachine != null && stateMachine.getMode() === 'drag';\n const activeChildContext = stateMachine?._activeChildContext;\n\n // Cache element JSON configs keyed on array reference to eliminate per-frame toJSON() calls.\n // Rebuilds only when the elements array reference changes (React state update).\n if (elements !== CanvasRenderer._cachedElementsRef) {\n CanvasRenderer._cachedElementConfigs = elements.map((e) => e.toJSON()) as AnyElementConfig[];\n CanvasRenderer._cachedElementMap = new Map(elements.map((el) => [el.id, el]));\n CanvasRenderer._cachedElementsRef = elements;\n }\n const allElementConfigs = CanvasRenderer._cachedElementConfigs!;\n const elementMap = CanvasRenderer._cachedElementMap!;\n\n // Reuse Set across frames to avoid per-frame allocation; clear before use.\n const knockoutRenderedIds = CanvasRenderer._knockoutRenderedIds;\n knockoutRenderedIds.clear();\n\n // First pass: render compositing elements (knockout and clip)\n elements.forEach((element, index) => {\n if (element.blendMode === 'knockout' || element.blendMode === 'clip') {\n const elementConfig = allElementConfigs[index];\n const compositeOp: CompositeOp = element.blendMode === 'knockout' ? 'destination-out' : 'destination-in';\n\n // Get affected elements using the same logic as CompositingRenderer\n const scope = elementConfig.knockoutParts?.scope || 'group';\n const compositingIndex = allElementConfigs.findIndex((el) => el.id === elementConfig.id);\n\n // Check if any compositing parts are actually enabled\n const hasCompositingParts = elementConfig.knockoutParts?.fill || elementConfig.knockoutParts?.stroke;\n\n // Get affected elements\n const affectedElements =\n scope === 'artboard' && compositingIndex !== -1 ? allElementConfigs.slice(0, compositingIndex) : [];\n\n // For artboard scope, use compositing even with 0 affected elements\n // This allows knockout to reveal the artboard background color\n const shouldUseCompositing = hasCompositingParts && (scope === 'artboard' || affectedElements.length > 0);\n\n if (shouldUseCompositing) {\n // Mark affected elements as rendered\n affectedElements.forEach((el) => el.id && knockoutRenderedIds.add(el.id));\n\n // Render with compositing using actual element instances\n renderWithCompositing(\n ctx,\n elementConfig as AnyElementConfig,\n allElementConfigs as AnyElementConfig[],\n (ctx, config) => {\n const actualElement = config.id && elementMap.get(config.id);\n if (actualElement) {\n this.renderElement(ctx as CanvasRenderingContext2D, actualElement, isPreview);\n }\n },\n artboardBackgroundColor,\n artboard,\n compositeOp\n );\n\n knockoutRenderedIds.add(element.id);\n }\n }\n });\n\n // Second pass: render normal (non-knockout) elements with clipping support\n // Check if any elements have clipping enabled\n const hasClipping = elements.some((el) => !knockoutRenderedIds.has(el.id) && el.isClipping);\n\n if (!hasClipping) {\n // No clipping - render normally\n elements.forEach((element) => {\n // Skip if already rendered by knockout\n if (knockoutRenderedIds.has(element.id)) return;\n\n // Skip invisible elements\n if (element.visible === false) return;\n\n const isSelected = element.id === selectedId;\n const isHovered = hoverState?.type === 'element' && hoverState?.data?.id === element.id;\n\n // Don't show group as selected when dragging a child within it (hides the group outline)\n const isDraggingChildInThisGroup =\n isDragging && activeChildContext && isGroupElement(element) && element.id === selectedId;\n const shouldShowAsSelected = isSelected && !isDraggingChildInThisGroup;\n\n // Check if element has custom texture distress effect\n const elementConfig = allElementConfigs[elements.indexOf(element)];\n const hasCustomDistress = elementConfig?.distressEffect?.enabled &&\n elementConfig.distressEffect.style === 'custom' &&\n elementConfig.distressEffect.textureUrl;\n\n // Render element with masks applied if present\n if (elementConfig && elementConfig.masks && elementConfig.masks.length > 0) {\n // Render with masks (overflow dimming not supported with masks for now)\n renderWithMasks(ctx, elementConfig as AnyElementConfig, (maskCtx) => {\n const renderContent = (renderCtx: CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D) => {\n if (isPreview) {\n renderCtx.save();\n (renderCtx as CanvasRenderingContext2D).globalAlpha = PREVIEW_ELEMENT_OPACITY;\n }\n this.safeRender(renderCtx as CanvasRenderingContext2D, element, shouldShowAsSelected, isHovered);\n if (isPreview) {\n (renderCtx as CanvasRenderingContext2D).restore();\n }\n };\n\n // Apply distress inside masks if element has both\n if (hasCustomDistress) {\n const bbox = element.getVisualBoundingBox();\n applyElementDistressTexture(maskCtx, elementConfig!.distressEffect!, bbox, renderContent);\n } else {\n renderContent(maskCtx);\n }\n });\n } else if (hasCustomDistress) {\n // Per-element custom texture distress\n // Use visual bounding box (actual rendered pixel extent) not math bounding box\n // (resize handles). Transforms like arch/circle/wave extend text beyond math bounds.\n const bbox = element.getVisualBoundingBox();\n applyElementDistressTexture(ctx, elementConfig!.distressEffect!, bbox, (offCtx) => {\n if (isPreview) {\n offCtx.save();\n (offCtx as CanvasRenderingContext2D).globalAlpha = PREVIEW_ELEMENT_OPACITY;\n }\n this.safeRender(offCtx as CanvasRenderingContext2D, element, shouldShowAsSelected, isHovered);\n if (isPreview) {\n offCtx.restore();\n }\n });\n } else if (showOverflowDimmed && !suppressOverflowDim && artboard && shouldShowAsSelected) {\n // Selected only: Render with overflow dimming - parts outside artboard at 30% opacity.\n // Hover used to trigger this too, but the halo on every mouseover read as noisy\n // distraction (artwork peeked past the piece edges any time the cursor moved over\n // a layer). The signal is reserved for explicit selection now — once the user has\n // committed via tap/click, they want to see how far their element extends.\n // Skipped when `suppressOverflowDim` is set (piece-guide contexts) so selected\n // elements fall through to the clipped-only branch and don't produce the 30%+blur\n // halo.\n this.renderElementWithOverflowDimming(ctx, element, artboard, shouldShowAsSelected, isHovered, isPreview);\n } else if (showOverflowDimmed && artboard) {\n // Not selected/hovered: Clip to artboard shape (hide overflow completely)\n ctx.save();\n this.applyArtboardClipPath(ctx, artboard);\n if (isPreview) {\n ctx.globalAlpha = PREVIEW_ELEMENT_OPACITY;\n }\n this.safeRender(ctx, element, shouldShowAsSelected, isHovered);\n ctx.restore();\n } else {\n // Normal rendering without masks or overflow handling\n if (isPreview) {\n ctx.save();\n ctx.globalAlpha = PREVIEW_ELEMENT_OPACITY;\n }\n this.safeRender(ctx, element, shouldShowAsSelected, isHovered);\n if (isPreview) {\n ctx.restore();\n }\n }\n });\n } else {\n // Has clipping - use offscreen canvas compositing\n this._renderWithClipping(\n ctx,\n elements,\n knockoutRenderedIds,\n selectedId,\n hoverState,\n isDragging,\n activeChildContext,\n allElementConfigs as AnyElementConfig[],\n isPreview\n );\n }\n }\n\n /**\n * Render elements with clipping mask support at artboard level\n * Elements with isClipping=true clip all elements below them\n */\n private static _renderWithClipping(\n ctx: CanvasRenderingContext2D,\n elements: BaseElement[],\n knockoutRenderedIds: Set<string>,\n selectedId: string | null,\n hoverState: HoverState | undefined,\n isDragging: boolean | undefined,\n activeChildContext: ActiveChildContext | undefined,\n allElementConfigs: AnyElementConfig[],\n isPreview: boolean = true\n ): void {\n const canvas = ctx.canvas;\n const width = canvas.width;\n const height = canvas.height;\n const transform = ctx.getTransform();\n\n // Group elements into clipping segments\n const segments: {\n content: BaseElement[];\n mask?: BaseElement;\n contentConfigs: AnyElementConfig[];\n maskConfig?: AnyElementConfig;\n }[] = [];\n let currentContent: BaseElement[] = [];\n let currentContentConfigs: AnyElementConfig[] = [];\n\n // Iterate through elements (bottom to top in visual order)\n for (let i = 0; i < elements.length; i++) {\n const element = elements[i];\n const elementConfig = allElementConfigs[i];\n\n // Skip if already rendered by knockout\n if (knockoutRenderedIds.has(element.id)) continue;\n\n // Skip invisible elements\n if (element.visible === false) continue;\n\n if (element.isClipping) {\n // This element clips everything we've collected so far\n if (currentContent.length > 0) {\n segments.push({\n content: currentContent,\n mask: element,\n contentConfigs: currentContentConfigs,\n maskConfig: elementConfig,\n });\n currentContent = [];\n currentContentConfigs = [];\n } else {\n // Clipping mask with no content below it - just render the mask normally\n segments.push({\n content: [element],\n contentConfigs: [elementConfig],\n });\n }\n } else {\n currentContent.push(element);\n currentContentConfigs.push(elementConfig);\n }\n }\n\n // Add remaining content without clipping\n if (currentContent.length > 0) {\n segments.push({\n content: currentContent,\n contentConfigs: currentContentConfigs,\n });\n }\n\n\n // Render each segment\n for (const segment of segments) {\n if (!segment.mask) {\n // No mask - render normally\n segment.content.forEach((element, idx) => {\n const isSelected = element.id === selectedId;\n const isHovered = hoverState?.type === 'element' && hoverState?.data?.id === element.id;\n const isDraggingChildInThisGroup =\n isDragging && activeChildContext && isGroupElement(element) && element.id === selectedId;\n const shouldShowAsSelected = isSelected && !isDraggingChildInThisGroup;\n\n const elementConfig = segment.contentConfigs[idx];\n if (elementConfig && elementConfig.masks && elementConfig.masks.length > 0) {\n renderWithMasks(ctx, elementConfig as AnyElementConfig, (maskCtx) => {\n if (isPreview) {\n maskCtx.save();\n maskCtx.globalAlpha = PREVIEW_ELEMENT_OPACITY;\n }\n element.render(maskCtx as CanvasRenderingContext2D, shouldShowAsSelected, isHovered);\n if (isPreview) {\n maskCtx.restore();\n }\n });\n } else {\n if (isPreview) {\n ctx.save();\n ctx.globalAlpha = PREVIEW_ELEMENT_OPACITY;\n }\n element.render(ctx, shouldShowAsSelected, isHovered);\n if (isPreview) {\n ctx.restore();\n }\n }\n });\n } else {\n // Render with clipping mask\n\n const contentCanvas = this._getContentCanvas(width, height);\n const contentCtx = contentCanvas.getContext('2d');\n if (!contentCtx) continue;\n\n // Clear the pooled canvas before use\n contentCtx.setTransform(1, 0, 0, 1, 0, 0);\n contentCtx.clearRect(0, 0, width, height);\n contentCtx.globalCompositeOperation = 'source-over';\n\n contentCtx.setTransform(transform);\n\n // Render content\n segment.content.forEach((element, idx) => {\n const isSelected = element.id === selectedId;\n const isHovered = hoverState?.type === 'element' && hoverState?.data?.id === element.id;\n const isDraggingChildInThisGroup =\n isDragging && activeChildContext && isGroupElement(element) && element.id === selectedId;\n const shouldShowAsSelected = isSelected && !isDraggingChildInThisGroup;\n\n\n const elementConfig = segment.contentConfigs[idx];\n if (elementConfig && elementConfig.masks && elementConfig.masks.length > 0) {\n renderWithMasks(contentCtx, elementConfig as AnyElementConfig, (maskCtx) => {\n if (isPreview) {\n maskCtx.save();\n maskCtx.globalAlpha = PREVIEW_ELEMENT_OPACITY;\n }\n element.render(maskCtx as CanvasRenderingContext2D, shouldShowAsSelected, isHovered);\n if (isPreview) {\n maskCtx.restore();\n }\n });\n } else {\n if (isPreview) {\n contentCtx.save();\n contentCtx.globalAlpha = PREVIEW_ELEMENT_OPACITY;\n }\n element.render(contentCtx, shouldShowAsSelected, isHovered);\n if (isPreview) {\n contentCtx.restore();\n }\n }\n });\n\n // Create mask (using pooled canvas)\n const maskCanvas = this._getMaskCanvas(width, height);\n const maskCtx = maskCanvas.getContext('2d');\n if (!maskCtx) continue;\n\n // Clear the pooled canvas before use\n maskCtx.setTransform(1, 0, 0, 1, 0, 0);\n maskCtx.clearRect(0, 0, width, height);\n maskCtx.globalCompositeOperation = 'source-over';\n\n maskCtx.setTransform(transform);\n\n const maskIsSelected = segment.mask.id === selectedId;\n const maskIsHovered = hoverState?.type === 'element' && hoverState?.data?.id === segment.mask.id;\n\n if (segment.maskConfig && segment.maskConfig.masks && segment.maskConfig.masks.length > 0) {\n renderWithMasks(maskCtx, segment.maskConfig as AnyElementConfig, (innerMaskCtx) => {\n if (isPreview) {\n innerMaskCtx.save();\n innerMaskCtx.globalAlpha = PREVIEW_ELEMENT_OPACITY;\n }\n segment.mask!.render(innerMaskCtx as CanvasRenderingContext2D, maskIsSelected, maskIsHovered);\n if (isPreview) {\n innerMaskCtx.restore();\n }\n });\n } else {\n if (isPreview) {\n maskCtx.save();\n maskCtx.globalAlpha = PREVIEW_ELEMENT_OPACITY;\n }\n segment.mask.render(maskCtx, maskIsSelected, maskIsHovered);\n if (isPreview) {\n maskCtx.restore();\n }\n }\n\n // Apply mask using destination-in\n contentCtx.globalCompositeOperation = 'destination-in';\n contentCtx.setTransform(1, 0, 0, 1, 0, 0);\n contentCtx.drawImage(maskCanvas, 0, 0);\n\n // Draw to main canvas\n ctx.save();\n ctx.setTransform(1, 0, 0, 1, 0, 0);\n ctx.drawImage(contentCanvas, 0, 0);\n ctx.restore();\n }\n }\n }\n\n // =========================================================================\n // Delegated Methods (preserve public API, delegate to focused renderers)\n // =========================================================================\n\n /**\n * Render snap guides layer\n * @see InteractionFeedbackRenderer.renderSnapGuidesLayer\n */\n static renderSnapGuidesLayer(ctx: CanvasRenderingContext2D, snapGuides: SnapGuide[] = []): void {\n InteractionFeedbackRenderer.renderSnapGuidesLayer(ctx, snapGuides);\n }\n\n /**\n * Render spacing indicators layer\n * @see InteractionFeedbackRenderer.renderSpacingIndicatorsLayer\n */\n static renderSpacingIndicatorsLayer(ctx: CanvasRenderingContext2D, spacingIndicators: SpacingIndicator[] = []): void {\n InteractionFeedbackRenderer.renderSpacingIndicatorsLayer(ctx, spacingIndicators);\n }\n\n /**\n * Render a distance label with background\n * @see InteractionFeedbackRenderer.renderDistanceLabel\n */\n static renderDistanceLabel(ctx: CanvasRenderingContext2D, x: number, y: number, distance: number): void {\n InteractionFeedbackRenderer.renderDistanceLabel(ctx, x, y, distance);\n }\n\n /**\n * Render selection box layer\n * @see SelectionRenderer.renderSelectionLayer\n */\n static renderSelectionLayer(\n ctx: CanvasRenderingContext2D,\n selectedElement: BaseElement | null,\n stateMachine: InteractionStateMachine,\n zoom: number = 1.0\n ): void {\n SelectionRenderer.renderSelectionLayer(ctx, selectedElement, stateMachine, zoom);\n }\n\n /**\n * Render position and size info below the selected element\n * @see SelectionRenderer.renderPositionSizeInfo\n */\n static renderPositionSizeInfo(\n ctx: CanvasRenderingContext2D,\n selectedElement: BaseElement | null,\n transformHandles: TransformHandles | null,\n stateMachine: InteractionStateMachine | null,\n zoom: number = 1.0\n ): void {\n SelectionRenderer.renderPositionSizeInfo(ctx, selectedElement, transformHandles, stateMachine, zoom);\n }\n\n /**\n * Render transform handles layer\n * @see SelectionRenderer.renderHandlesLayer\n */\n static renderHandlesLayer(\n ctx: CanvasRenderingContext2D,\n selectedElement: BaseElement | null,\n transformHandles: TransformHandles,\n currentRotation: number,\n isRotating: boolean,\n hoverState: HoverState,\n stateMachine: InteractionStateMachine,\n zoom: number = 1.0,\n showRotationHandle: boolean = true\n ): void {\n SelectionRenderer.renderHandlesLayer(\n ctx, selectedElement, transformHandles, currentRotation,\n isRotating, hoverState, stateMachine, zoom, showRotationHandle\n );\n }\n\n /**\n * Render hover highlights layer with fade-in animation\n * @see HoverRenderer.renderHoverLayer\n */\n static renderHoverLayer(\n ctx: CanvasRenderingContext2D,\n hoverState: HoverState,\n selectedId: string | null,\n _isAltKeyPressed: boolean = false,\n zoom: number = 1.0,\n artboardBackgroundColor?: string\n ): void {\n HoverRenderer.renderHoverLayer(ctx, hoverState, selectedId, _isAltKeyPressed, zoom, artboardBackgroundColor);\n }\n\n /**\n * Render crop box layer (for images in crop mode)\n * @see EditModeRenderer.renderCropBoxLayer\n */\n static renderCropBoxLayer(\n ctx: CanvasRenderingContext2D,\n selectedElement: BaseElement,\n transformHandles: TransformHandles,\n zoom: number = 1.0\n ): void {\n EditModeRenderer.renderCropBoxLayer(ctx, selectedElement, transformHandles, zoom);\n }\n\n // =========================================================================\n // Main Render Orchestration\n // =========================================================================\n\n /**\n * Complete rendering pipeline\n * Renders all layers in correct z-order\n */\n static render({\n ctx,\n elements,\n selectedId,\n selectedElement,\n // Chrome-related fields (transformHandles, currentRotation,\n // isRotating, hideHandles, isAltKeyPressed, showRotationHandle)\n // are accepted for backwards compatibility with the public type\n // signature exposed via `api/internals.ts`, but are no longer\n // consumed here — single-selection chrome is now drawn by\n // `renderInteractionChromeLayer` after piece guides. See that\n // method for the actual chrome rendering.\n hoverState,\n isEditing,\n stateMachine,\n snapGuides = [],\n spacingIndicators = [],\n artboardBackgroundColor,\n artboard,\n isPreview = true,\n zoom = 1.0,\n paddingOffset = { x: 0, y: 0 },\n showOverflowDimmed = false,\n suppressOverflowDim = false,\n distressTexture,\n imageMask,\n editModeData,\n }: {\n ctx: CanvasRenderingContext2D;\n elements: BaseElement[];\n selectedId: string | null;\n selectedElement: BaseElement | null;\n transformHandles: TransformHandles | null;\n currentRotation: number;\n isRotating: boolean;\n hoverState: HoverState;\n isEditing: boolean;\n stateMachine: InteractionStateMachine | null;\n snapGuides?: SnapGuide[];\n spacingIndicators?: SpacingIndicator[];\n hideHandles?: boolean;\n isAltKeyPressed?: boolean;\n artboardBackgroundColor?: string;\n artboard?: { x: number; y: number; width: number; height: number; borderRadius?: number; clipShape?: ClipShape };\n isPreview?: boolean;\n zoom?: number;\n paddingOffset?: { x: number; y: number };\n /** When true, element parts outside the artboard render at 30% opacity */\n showOverflowDimmed?: boolean;\n /**\n * When true, skip the 30% overflow-dim pass even if `showOverflowDimmed` is on.\n * Used by ADR-0054 piece-guide rendering: the boundary's custom path clipShape is\n * the visible design edge, so the rectangular-artboard overflow halo reads as\n * coloured noise rather than useful UX. Selected elements fall through to the\n * clipped-only branch, which respects `clipShape` correctly.\n */\n suppressOverflowDim?: boolean;\n /** Whether to show the rotation handle (defaults to true, set false for embedded mode) */\n showRotationHandle?: boolean;\n /** Artboard-level distress texture (applied after elements, before UI layers) */\n distressTexture?: ArtboardDistressTexture;\n /** Artboard-level image mask (applied after distress texture, before UI layers) */\n imageMask?: import('../types/index.js').ArtboardImageMask;\n editModeData?: {\n cursorPosition: number;\n selectionStart: number;\n selectionEnd: number;\n editText: string;\n editRichText: RichText | null;\n cursorOpacity: number;\n };\n }): void {\n // Layer 1: Elements (rendered with zoom applied)\n this.renderElementsLayer(\n ctx,\n elements,\n selectedId,\n hoverState,\n stateMachine ?? undefined,\n artboardBackgroundColor,\n artboard,\n isPreview,\n showOverflowDimmed,\n suppressOverflowDim\n );\n\n // Layer 1.25: Artboard-level distress texture (after elements, before UI)\n if (distressTexture?.enabled && artboard) {\n applyArtboardDistressTexture(ctx, distressTexture, artboard, artboardBackgroundColor);\n }\n\n // Layer 1.3: Artboard-level image mask (after distress, before UI)\n if (imageMask?.enabled && artboard) {\n applyArtboardImageMask(ctx, imageMask, artboard, artboardBackgroundColor);\n }\n\n // Layer 1.5: Edit mode cursor and selection (rendered with zoom applied, same as elements)\n if (isEditing && editModeData && selectedElement) {\n EditModeRenderer.renderEditModeLayer(ctx, selectedElement, editModeData, zoom);\n }\n\n // For UI elements (guides, handles, etc.), we need to render at native size\n // even when zoom is applied. We do this by:\n // 1. Saving the current transform (which has DPR + zoom)\n // 2. Resetting to DPR-only transform\n // 3. Scaling all UI positions by zoom to compensate\n // 4. Restoring the original transform\n if (zoom !== 1.0) {\n ctx.save();\n\n // Read the *effective* DPR from the current ctx transform —\n // matches what the render loop applied (which may be less than\n // `window.devicePixelRatio` when the buffer cap kicked in for\n // high-zoom). Using window.dpr here would drift the snap\n // guides relative to the elements by `dpr / effectiveDpr`.\n const transform = ctx.getTransform();\n const effectiveDpr = transform.a / zoom;\n\n // Reset transform to effective-DPR-only (removes zoom), but\n // preserve padding offset (in world coords, scaled to screen).\n const offsetX = paddingOffset.x * zoom * effectiveDpr;\n const offsetY = paddingOffset.y * zoom * effectiveDpr;\n ctx.setTransform(effectiveDpr, 0, 0, effectiveDpr, offsetX, offsetY);\n }\n\n // Transform snap guides positions by zoom\n const zoomedSnapGuides = snapGuides.map((guide) => ({\n ...guide,\n x: guide.x !== undefined ? guide.x * zoom : undefined,\n y: guide.y !== undefined ? guide.y * zoom : undefined,\n x1: guide.x1 !== undefined ? guide.x1 * zoom : undefined,\n y1: guide.y1 !== undefined ? guide.y1 * zoom : undefined,\n x2: guide.x2 !== undefined ? guide.x2 * zoom : undefined,\n y2: guide.y2 !== undefined ? guide.y2 * zoom : undefined,\n }));\n\n // Transform spacing indicators by zoom\n const zoomedSpacingIndicators = spacingIndicators.map((indicator) => ({\n ...indicator,\n x: indicator.x !== undefined ? indicator.x * zoom : undefined,\n y: indicator.y !== undefined ? indicator.y * zoom : undefined,\n x1: indicator.x1 !== undefined ? indicator.x1 * zoom : undefined,\n y1: indicator.y1 !== undefined ? indicator.y1 * zoom : undefined,\n x2: indicator.x2 !== undefined ? indicator.x2 * zoom : undefined,\n y2: indicator.y2 !== undefined ? indicator.y2 * zoom : undefined,\n labelX: indicator.labelX * zoom,\n labelY: indicator.labelY * zoom,\n }));\n\n // Layer 2: Snap guides (renders on top of elements)\n InteractionFeedbackRenderer.renderSnapGuidesLayer(ctx, zoomedSnapGuides);\n\n // Layer 2.5: Spacing indicators (renders after snap guides)\n InteractionFeedbackRenderer.renderSpacingIndicatorsLayer(ctx, zoomedSpacingIndicators);\n\n // Single-selection interaction chrome (selection bbox + handles +\n // position/size info + hover outline + crop-mode chrome) used to\n // render here as Layers 3–6. They've been hoisted out to\n // `renderInteractionChromeLayer`, which `useCanvasRenderLoop`\n // calls *after* `renderPieceGuides` so the partial die-cut\n // knockout (alpha 0.7, intentionally dims artwork to 30% inside\n // the cutout) doesn't also dim selection chrome that the user\n // needs at full opacity for resize/drag feedback.\n\n // Restore original transform (with zoom) if we modified it\n if (zoom !== 1.0) {\n ctx.restore();\n }\n }\n\n /**\n * Single-selection interaction chrome: bbox, handles, position/size\n * info, hover outline, and the crop-mode alt branch. Hoisted out of\n * `render()` so the master render loop can call it *after*\n * `renderPieceGuides`. Otherwise the piece-guide partial die-cut\n * knockout (`destination-out` at alpha 0.7) erases 70% of the\n * chrome's alpha along with the artwork it's intentionally dimming.\n *\n * Renders at native screen scale: identical transform manipulation\n * to the original Layer 2 / 3–6 block in `render()` so chrome stays\n * crisp regardless of canvas zoom.\n */\n static renderInteractionChromeLayer({\n ctx,\n selectedElement,\n transformHandles,\n stateMachine,\n currentRotation,\n isRotating,\n hoverState,\n selectedId,\n hideHandles = false,\n isEditing,\n isAltKeyPressed = false,\n artboardBackgroundColor,\n hoverClipArtboard,\n showRotationHandle = true,\n zoom = 1.0,\n paddingOffset = { x: 0, y: 0 },\n }: {\n ctx: CanvasRenderingContext2D;\n selectedElement: BaseElement | null;\n transformHandles: TransformHandles | null;\n stateMachine: InteractionStateMachine | null;\n currentRotation: number;\n isRotating: boolean;\n hoverState: HoverState;\n selectedId: string | null;\n hideHandles?: boolean;\n isEditing: boolean;\n isAltKeyPressed?: boolean;\n artboardBackgroundColor?: string;\n /**\n * Optional clip rect (in world coords) confining the hover outline\n * to the visible artboard / piece bounds. Selection chrome ignores\n * this — once the user commits to a selection they want to see the\n * full extent of the element. The hover outline though was reading\n * as noisy when the cursor moved over an element that extended past\n * the piece edge, since the hover ring was drawn into the overflow\n * region on top of the dimmed surrounding canvas.\n */\n hoverClipArtboard?: {\n x: number;\n y: number;\n width: number;\n height: number;\n borderRadius?: number;\n clipShape?: ClipShape;\n };\n showRotationHandle?: boolean;\n zoom?: number;\n paddingOffset?: { x: number; y: number };\n }): void {\n // Same transform manipulation as the parent render() does for\n // its UI layers: reset to DPR-only so chrome paints at native\n // screen size, then restore. Caller-supplied coordinates are\n // pre-multiplied by zoom inside the individual chrome renderers.\n //\n // We read the *effective* DPR from the current ctx transform\n // (which the render loop set as `effectiveDpr × zoom`). This\n // matters when the render loop has capped the canvas backing\n // buffer at a max dimension (so `effectiveDpr < window.dpr`):\n // using `window.devicePixelRatio` here would mismatch the\n // element-render scale and the chrome would drift away from\n // the element by `dpr / effectiveDpr` as zoom grows past the\n // cap threshold.\n if (zoom !== 1.0) {\n ctx.save();\n const transform = ctx.getTransform();\n const effectiveDpr = transform.a / zoom;\n const offsetX = paddingOffset.x * zoom * effectiveDpr;\n const offsetY = paddingOffset.y * zoom * effectiveDpr;\n ctx.setTransform(effectiveDpr, 0, 0, effectiveDpr, offsetX, offsetY);\n }\n\n const isCropping =\n selectedElement && isImageElement(selectedElement) && selectedElement.isCropping;\n\n if (!isCropping) {\n // Layer 3: Selection box (hidden while dragging or during keyboard nudging)\n if (!hideHandles && stateMachine) {\n SelectionRenderer.renderSelectionLayer(ctx, selectedElement, stateMachine, zoom);\n }\n\n // Layer 4: Position and size info (above rotation handle, only while resizing)\n if (transformHandles && stateMachine) {\n SelectionRenderer.renderPositionSizeInfo(ctx, selectedElement, transformHandles, stateMachine, zoom);\n }\n\n // Layer 5: Transform handles (hidden during keyboard nudging)\n if (!hideHandles && transformHandles && stateMachine) {\n SelectionRenderer.renderHandlesLayer(\n ctx,\n selectedElement,\n transformHandles,\n currentRotation,\n isRotating,\n hoverState,\n stateMachine,\n zoom,\n showRotationHandle\n );\n }\n\n // Layer 6: Hover highlights (only when not editing). Wrapped in\n // an artboard clip so the hover ring doesn't bleed into the\n // overflow region (outside the piece shape) — that was reading\n // as noisy on every mouseover, especially on piece-guide\n // products where the visible piece is smaller than the element's\n // bounding rect. Selection chrome above is intentionally NOT\n // clipped: once the user commits via tap/click, they want to\n // see how far the element extends.\n if (!isEditing) {\n if (hoverClipArtboard) {\n ctx.save();\n // Build the clip path manually here (rather than via the\n // private `applyArtboardClipPath` helper) so we don't leak\n // `clip()` calls into the parent transform space — the\n // chrome layer's transform is `effectiveDpr × identity`\n // (no zoom), so we multiply world coords by `zoom` to land\n // in physical pixels.\n const cb = hoverClipArtboard;\n const cx = cb.x * zoom;\n const cy = cb.y * zoom;\n const cw = cb.width * zoom;\n const ch = cb.height * zoom;\n const radius = (cb.borderRadius ?? 0) * zoom;\n ctx.beginPath();\n if (radius > 0) {\n ctx.roundRect(cx, cy, cw, ch, radius);\n } else {\n ctx.rect(cx, cy, cw, ch);\n }\n ctx.clip();\n }\n HoverRenderer.renderHoverLayer(ctx, hoverState, selectedId, isAltKeyPressed, zoom, artboardBackgroundColor);\n if (hoverClipArtboard) {\n ctx.restore();\n }\n }\n } else {\n // In crop mode: render crop box with both image and crop handles\n if (transformHandles) {\n EditModeRenderer.renderCropBoxLayer(ctx, selectedElement, transformHandles, zoom);\n }\n }\n\n if (zoom !== 1.0) {\n ctx.restore();\n }\n }\n}\n","/**\n * Element Serializer - Converts elements to worker-compatible format\n * Handles ImageBitmap registration with the worker for efficient caching.\n *\n * ARCHITECTURE (Worker-Based Caching):\n * The ImageBitmap cache lives in the web worker, not the main thread.\n * This reduces main thread memory by ~50% for image-heavy canvases.\n *\n * Flow:\n * 1. First export: Create ImageBitmap, transfer to worker, worker caches it\n * 2. Later exports: Send only JSON with cache keys, worker looks up cached bitmaps\n *\n * The main thread only tracks WHICH bitmaps have been registered (via registeredBitmapKeys).\n * Actual bitmap memory lives in the worker.\n */\n\nimport type { ArtboardElement } from '../core/ArtboardElement.js';\nimport type { BaseElement } from '../core/BaseElement.js';\nimport { ImageElement } from '../core/ImageElement.js';\nimport { ImageCache } from '../core/ImageCache.js';\nimport type { AnyElementConfig, ImageTransformData, ArtboardDistressTexture, ArtboardImageMask } from '../types/index.js';\nimport { createLogger } from '../utils/logger.js';\n\nconst logger = createLogger('element-serializer');\n\n// ============================================================================\n// Worker Bitmap Registration Tracking\n// ============================================================================\n\n/**\n * Default maximum dimension for image capping (in pixels)\n * Images larger than this on any dimension will be scaled down while preserving aspect ratio.\n * This prevents memory issues with very large images (e.g., 6000x6000 = 144MB per bitmap).\n */\nexport const DEFAULT_MAX_BITMAP_DIMENSION = 4000;\n\n/**\n * Track which bitmap cache keys have been registered with the worker.\n * This is just a Set of keys - the actual bitmaps live in the worker.\n */\nconst registeredBitmapKeys = new Set<string>();\n\n/**\n * Get cache key for an image element\n * Uses element ID and image src to create a unique key\n * Format: \"{elementId}:{srcHash}\"\n */\nexport function getImageCacheKey(elementId: string, imageSrc: string | undefined): string {\n // Use a hash of the src to keep keys manageable\n const srcHash = imageSrc ? hashString(imageSrc) : 'no-src';\n return `${elementId}:${srcHash}`;\n}\n\n/**\n * Simple string hash for cache keys\n */\nfunction hashString(str: string): string {\n let hash = 0;\n for (let i = 0; i < str.length; i++) {\n const char = str.charCodeAt(i);\n hash = ((hash << 5) - hash) + char;\n hash = hash & hash; // Convert to 32bit integer\n }\n return hash.toString(36);\n}\n\n/**\n * Clear all registered bitmap keys.\n * Call this when the worker cache is cleared (e.g., on editor exit).\n * The actual bitmap cleanup happens in the worker via 'clear-all-bitmaps' message.\n */\nexport function clearRegisteredBitmapKeys(): void {\n registeredBitmapKeys.clear();\n}\n\n/**\n * Remove a specific element's registration tracking.\n * Call this when an element is removed or its image source changes.\n * The actual bitmap cleanup happens in the worker via 'clear-bitmap' message.\n */\nexport function unregisterElementBitmaps(elementId: string): void {\n // Find and remove any registration entries for this element\n for (const key of registeredBitmapKeys) {\n if (key.startsWith(`${elementId}:`)) {\n registeredBitmapKeys.delete(key);\n }\n }\n}\n\n/**\n * Mark a bitmap as registered with the worker\n */\nexport function markBitmapRegistered(cacheKey: string): void {\n registeredBitmapKeys.add(cacheKey);\n}\n\n/**\n * Check if a bitmap is already registered with the worker\n */\nexport function isBitmapRegistered(cacheKey: string): boolean {\n return registeredBitmapKeys.has(cacheKey);\n}\n\n// ============================================================================\n// Dimension Capping\n// ============================================================================\n\n/**\n * Create an ImageBitmap with dimension capping.\n * If the source image exceeds maxDimension on any side, it will be scaled down\n * while preserving aspect ratio.\n *\n * @param source - HTMLImageElement to create bitmap from\n * @param maxDimension - Maximum allowed dimension (default: 4000px)\n * @returns Promise<ImageBitmap> - The (potentially scaled) ImageBitmap\n */\nexport async function createCappedImageBitmap(\n source: HTMLImageElement,\n maxDimension: number = DEFAULT_MAX_BITMAP_DIMENSION\n): Promise<ImageBitmap> {\n const { naturalWidth, naturalHeight } = source;\n\n // If within limits, create bitmap at full resolution\n if (naturalWidth <= maxDimension && naturalHeight <= maxDimension) {\n return createImageBitmap(source);\n }\n\n // Scale down maintaining aspect ratio\n const scale = maxDimension / Math.max(naturalWidth, naturalHeight);\n const targetWidth = Math.round(naturalWidth * scale);\n const targetHeight = Math.round(naturalHeight * scale);\n\n return createImageBitmap(source, {\n resizeWidth: targetWidth,\n resizeHeight: targetHeight,\n resizeQuality: 'high',\n });\n}\n\n// ============================================================================\n// Legacy API Compatibility\n// ============================================================================\n\n// Callback to clear worker cache - set by WorkerExportManager\nlet workerCacheClearCallback: (() => void) | null = null;\nlet workerElementClearCallback: ((elementId: string) => void) | null = null;\n\n/**\n * Register callbacks for worker cache clearing.\n * Called by WorkerExportManager to enable legacy API to clear worker cache.\n * @internal\n */\nexport function registerWorkerCacheCallbacks(\n clearAll: () => void,\n clearElement: (elementId: string) => void\n): void {\n workerCacheClearCallback = clearAll;\n workerElementClearCallback = clearElement;\n}\n\n/**\n * Unregister callbacks (e.g., when worker terminates).\n * @internal\n */\nexport function unregisterWorkerCacheCallbacks(): void {\n workerCacheClearCallback = null;\n workerElementClearCallback = null;\n}\n\n/**\n * Clear all ImageBitmap caches.\n * This clears both the main thread tracking AND the worker cache (if available).\n * Call this when exiting editor mode to free memory.\n */\nexport function clearImageBitmapCache(): void {\n // Clear main thread tracking\n clearRegisteredBitmapKeys();\n\n // Also clear worker cache if callback is registered\n if (workerCacheClearCallback) {\n workerCacheClearCallback();\n }\n}\n\n/**\n * Remove a specific element's cached bitmaps.\n * This clears both the main thread tracking AND the worker cache (if available).\n * Call this when an element is removed or its image source changes.\n */\nexport function removeFromImageBitmapCache(elementId: string): void {\n // Clear main thread tracking\n unregisterElementBitmaps(elementId);\n\n // Also clear worker cache if callback is registered\n if (workerElementClearCallback) {\n workerElementClearCallback(elementId);\n }\n}\n\n// ============================================================================\n// Types\n// ============================================================================\n\n/**\n * Serialized artboard data for export\n */\nexport interface SerializedArtboardData {\n id: string;\n name: string;\n width: number;\n height: number;\n backgroundColor: string;\n exportBackground: boolean;\n x: number;\n y: number;\n distressTexture?: ArtboardDistressTexture;\n imageMask?: ArtboardImageMask;\n}\n\n/**\n * Serialized export data sent to worker\n * Note: Images reference worker cache via bitmapCacheKey, not transferred inline\n */\nexport interface SerializedExportData {\n version: string;\n artboard: SerializedArtboardData;\n elements: AnyElementConfig[]; // Serialized element data\n fonts: string[]; // List of fonts used\n}\n\n/**\n * A new bitmap that needs to be registered with the worker\n */\nexport interface NewBitmapRegistration {\n cacheKey: string;\n bitmap: ImageBitmap;\n}\n\n/**\n * Result from serializeForWorkerExport\n */\nexport interface SerializationResult {\n /** Serialized data to send to worker for export */\n data: SerializedExportData;\n /** New bitmaps that need to be registered with worker before export */\n newBitmaps: NewBitmapRegistration[];\n}\n\nexport interface SerializedImageElement {\n id: string;\n type: 'image';\n x: number;\n y: number;\n width: number;\n height: number;\n rotation: number;\n /** Cache key for worker bitmap lookup in format \"{elementId}:{srcHash}\" */\n bitmapCacheKey: string;\n cropX?: number;\n cropY?: number;\n cropWidth?: number;\n cropHeight?: number;\n flipHorizontal?: boolean;\n flipVertical?: boolean;\n borderRadius?: number;\n opacity?: number;\n}\n\n// ============================================================================\n// Serialization Functions\n// ============================================================================\n\n/**\n * Recursively collect fonts from an element and its children.\n * Also checks rich text spans for per-character font families.\n */\nfunction collectFonts(elementJson: AnyElementConfig | Record<string, unknown>, fonts: Set<string>): void {\n // Collect font from this element\n const json = elementJson as Record<string, unknown>;\n if (typeof json.fontFamily === 'string') {\n fonts.add(json.fontFamily);\n }\n\n // Collect fonts from rich text spans (per-character font families)\n if (json.richText && typeof json.richText === 'object') {\n const richText = json.richText as Record<string, unknown>;\n if (richText.spans && Array.isArray(richText.spans)) {\n for (const span of richText.spans) {\n const spanObj = span as Record<string, unknown>;\n if (spanObj.style && typeof spanObj.style === 'object') {\n const style = spanObj.style as Record<string, unknown>;\n if (typeof style.fontFamily === 'string') {\n fonts.add(style.fontFamily);\n }\n }\n }\n }\n }\n\n // Recursively collect fonts from children (groups)\n if (json.children && Array.isArray(json.children)) {\n for (const child of json.children) {\n collectFonts(child as AnyElementConfig, fonts);\n }\n }\n\n // Recursively collect fonts from mask elements\n if (elementJson.masks && Array.isArray(elementJson.masks)) {\n for (const mask of elementJson.masks) {\n if (mask.maskElement) {\n collectFonts(mask.maskElement, fonts);\n }\n }\n }\n}\n\n/**\n * Resolve builtin-mask: URLs in mask elements to data URLs.\n * The ImageCache on the main thread has the generated data URLs for\n * builtin mask presets; replace the synthetic keys so the export worker\n * can fetch them via standard data: URLs.\n */\nfunction resolveMaskImageUrls(masks: unknown[]): unknown[] {\n if (typeof document === 'undefined') return masks; // Skip in worker/SSR\n const cache = ImageCache.getInstance();\n return masks.map((mask: any) => {\n if (!mask?.maskElement || mask.maskElement.transformType !== 'image') return mask;\n const imageUrl = mask.maskElement.imageUrl;\n if (!imageUrl || !imageUrl.startsWith('builtin-mask:')) return mask;\n\n // Resolve the synthetic URL to the actual data URL from ImageCache\n const img = cache.get(imageUrl);\n if (img?.src && img.src.startsWith('data:')) {\n return {\n ...mask,\n maskElement: {\n ...mask.maskElement,\n imageUrl: img.src, // Replace with data URL\n },\n };\n }\n return mask;\n });\n}\n\n/**\n * Serialize artboard and elements for worker export.\n *\n * ARCHITECTURE:\n * - Images are identified by bitmapCacheKey (format: \"{elementId}:{srcHash}\")\n * - If a bitmap is not yet registered with the worker, it's included in newBitmaps\n * - Caller should register newBitmaps with worker before sending export request\n * - Worker looks up bitmaps from its cache by bitmapCacheKey\n *\n * @param artboard - The artboard to export\n * @param elements - All elements in the canvas\n * @param maxBitmapDimension - Optional max dimension for image capping (default: 4000px)\n * @returns SerializationResult with serialized data and any new bitmaps to register\n */\nexport async function serializeForWorkerExport(\n artboard: ArtboardElement,\n elements: BaseElement[],\n maxBitmapDimension: number = DEFAULT_MAX_BITMAP_DIMENSION\n): Promise<SerializationResult> {\n // Filter elements that belong to this artboard\n const artboardElements = elements.filter((el) => artboard.hasElementId(el.id));\n\n const serializedElements: AnyElementConfig[] = [];\n const newBitmaps: NewBitmapRegistration[] = [];\n const fonts = new Set<string>();\n\n // Process each element\n for (const element of artboardElements) {\n // toJSON returns BaseElementConfig; cast to Record for flexible property access\n const json = element.toJSON();\n\n // Collect fonts from text elements (recursively for groups and masks)\n collectFonts(json as unknown as AnyElementConfig, fonts);\n\n // Handle image elements\n if (element instanceof ImageElement && !element.imageElement) {\n // Image hasn't loaded yet — skip it rather than serializing without a bitmap\n logger.warn(`[element-serializer] Skipping image ${element.id}: image not loaded (state: ${element.imageLoadState})`);\n continue;\n }\n if (element instanceof ImageElement && element.imageElement) {\n try {\n const cacheKey = getImageCacheKey(element.id, element.imageUrl);\n const isCached = isBitmapRegistered(cacheKey);\n // Check if bitmap is already registered with worker\n if (!isCached) {\n // Create new bitmap with dimension capping\n const bitmap = await createCappedImageBitmap(element.imageElement, maxBitmapDimension);\n\n // Add to new bitmaps list for registration\n newBitmaps.push({ cacheKey, bitmap });\n\n // Mark as registered (will be confirmed after worker receives it)\n markBitmapRegistered(cacheKey);\n }\n\n // Note: ImageElement stores dimensions in transformData\n const td = (element.transformData || {}) as ImageTransformData;\n const hasMasks = json.masks && (json.masks as unknown[]).length > 0;\n\n // For masked images, use the full frame dimensions — the mask handles\n // clipping, not the crop rectangle. For unmasked images, use visible\n // (cropped) dimensions so the worker draws at the correct on-screen size.\n const visibleWidth = hasMasks ? td.width : td.width * (td.cropWidth ?? 1);\n const visibleHeight = hasMasks ? td.height : td.height * (td.cropHeight ?? 1);\n\n const imageData: SerializedImageElement = {\n id: element.id,\n type: 'image',\n x: element.x,\n y: element.y,\n width: visibleWidth,\n height: visibleHeight,\n rotation: element.rotation || 0,\n bitmapCacheKey: cacheKey,\n };\n\n // Only include crop if it's actually cropped (not the full image)\n // and the element does NOT have masks (masks handle clipping instead).\n // transformData stores crop as fractions (0-1), but drawImage needs pixels\n // Default is cropX=0, cropY=0, cropWidth=1, cropHeight=1 (full image)\n const isCropped = !hasMasks && (td.cropX !== 0 || td.cropY !== 0 || td.cropWidth !== 1 || td.cropHeight !== 1);\n if (isCropped) {\n // We need to get bitmap dimensions for pixel conversion\n // For new bitmaps, we can use the one we just created\n // For cached bitmaps, we need to rely on the original image dimensions\n // Note: The worker will have the actual bitmap dimensions\n const bitmapWidth = element.imageElement.naturalWidth;\n const bitmapHeight = element.imageElement.naturalHeight;\n\n // Apply dimension capping to crop calculations\n let scale = 1;\n if (bitmapWidth > maxBitmapDimension || bitmapHeight > maxBitmapDimension) {\n scale = maxBitmapDimension / Math.max(bitmapWidth, bitmapHeight);\n }\n\n imageData.cropX = td.cropX * bitmapWidth * scale;\n imageData.cropY = td.cropY * bitmapHeight * scale;\n imageData.cropWidth = td.cropWidth * bitmapWidth * scale;\n imageData.cropHeight = td.cropHeight * bitmapHeight * scale;\n }\n\n // Flip and border radius\n if (td.flipHorizontal) imageData.flipHorizontal = td.flipHorizontal;\n if (td.flipVertical) imageData.flipVertical = td.flipVertical;\n if (td.borderRadius) imageData.borderRadius = td.borderRadius;\n if (element.opacity !== undefined) imageData.opacity = element.opacity;\n\n // Include effect properties so the worker can apply distress, masks, and knockout\n // to image elements (same as text elements get via toJSON() spread).\n // eslint-disable-next-line @typescript-eslint/no-explicit-any -- extending typed image data with dynamic effect properties for worker\n const serializedImage: Record<string, unknown> = imageData as any;\n if (element.distressEffect) serializedImage.distressEffect = { ...element.distressEffect };\n if (json.masks && (json.masks as unknown[]).length > 0) serializedImage.masks = resolveMaskImageUrls(json.masks as unknown[]);\n if (json.blendMode) serializedImage.blendMode = json.blendMode;\n if (json.knockoutParts) serializedImage.knockoutParts = json.knockoutParts;\n\n // Include bounding box for distress/mask positioning in the worker\n if ('getVisualBoundingBox' in element && typeof element.getVisualBoundingBox === 'function') {\n serializedImage._boundingBox = element.getVisualBoundingBox();\n } else if ('getBoundingBox' in element && typeof element.getBoundingBox === 'function') {\n serializedImage._boundingBox = element.getBoundingBox();\n }\n\n serializedElements.push(serializedImage as unknown as AnyElementConfig);\n } catch (error) {\n logger.error(`[element-serializer] Failed to create ImageBitmap for ${json.id}:`, error);\n // Skip this image element\n }\n } else {\n // Text, group, or other elements - serialize with type mapping\n // The worker expects 'type' but toJSON() produces 'transformType'\n const serialized: Record<string, unknown> = {\n ...json,\n type: json.transformType, // Map transformType to type for worker compatibility\n };\n\n // Resolve builtin-mask: URLs in masks to data URLs for the worker\n if (serialized.masks && Array.isArray(serialized.masks) && serialized.masks.length > 0) {\n serialized.masks = resolveMaskImageUrls(serialized.masks);\n }\n\n // Include bounding box for distress/mask rendering in the worker\n // The worker can't call getBoundingBox() so we pre-compute it.\n // Use getVisualBoundingBox() which returns actual rendered pixel extent,\n // not the math bounding box used for resize handles. Transforms like\n // arch/circle/wave extend text well beyond the math bounds.\n if ('getVisualBoundingBox' in element && typeof element.getVisualBoundingBox === 'function') {\n serialized._boundingBox = element.getVisualBoundingBox();\n } else if ('getBoundingBox' in element && typeof element.getBoundingBox === 'function') {\n serialized._boundingBox = element.getBoundingBox();\n }\n\n serializedElements.push(serialized as unknown as AnyElementConfig);\n }\n }\n\n const fontsList = Array.from(fonts);\n\n return {\n data: {\n version: '1.0.0',\n artboard: {\n id: artboard.id,\n name: artboard.name,\n width: artboard.width,\n height: artboard.height,\n backgroundColor: artboard.backgroundColor,\n exportBackground: artboard.exportBackground,\n x: artboard.x,\n y: artboard.y,\n ...(artboard.distressTexture && { distressTexture: { ...artboard.distressTexture } }),\n ...(artboard.imageMask && { imageMask: { ...artboard.imageMask } }),\n },\n elements: serializedElements,\n fonts: fontsList,\n },\n newBitmaps,\n };\n}\n","// AUTO-GENERATED by scripts/bundle-worker.js. Do not edit.\nexport default \"\\\"use strict\\\";\\n(() => {\\n var __create = Object.create;\\n var __defProp = Object.defineProperty;\\n var __getOwnPropDesc = Object.getOwnPropertyDescriptor;\\n var __getOwnPropNames = Object.getOwnPropertyNames;\\n var __getProtoOf = Object.getPrototypeOf;\\n var __hasOwnProp = Object.prototype.hasOwnProperty;\\n var __esm = (fn, res) => function __init() {\\n return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;\\n };\\n var __commonJS = (cb, mod) => function __require() {\\n return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;\\n };\\n var __export = (target, all) => {\\n for (var name in all)\\n __defProp(target, name, { get: all[name], enumerable: true });\\n };\\n var __copyProps = (to, from, except, desc) => {\\n if (from && typeof from === \\\"object\\\" || typeof from === \\\"function\\\") {\\n for (let key of __getOwnPropNames(from))\\n if (!__hasOwnProp.call(to, key) && key !== except)\\n __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });\\n }\\n return to;\\n };\\n var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(\\n // If the importer is in node compatibility mode or this is not an ESM\\n // file that has been converted to a CommonJS file using a Babel-\\n // compatible transform (i.e. \\\"__esModule\\\" has not been set), then set\\n // \\\"default\\\" to the CommonJS \\\"module.exports\\\" for node compatibility.\\n isNodeMode || !mod || !mod.__esModule ? __defProp(target, \\\"default\\\", { value: mod, enumerable: true }) : target,\\n mod\\n ));\\n\\n // ../../node_modules/.pnpm/restructure@3.0.2/node_modules/restructure/src/DecodeStream.js\\n var ENCODING_MAPPING, DecodeStream;\\n var init_DecodeStream = __esm({\\n \\\"../../node_modules/.pnpm/restructure@3.0.2/node_modules/restructure/src/DecodeStream.js\\\"() {\\n ENCODING_MAPPING = {\\n utf16le: \\\"utf-16le\\\",\\n ucs2: \\\"utf-16le\\\",\\n utf16be: \\\"utf-16be\\\"\\n };\\n DecodeStream = class {\\n constructor(buffer) {\\n this.buffer = buffer;\\n this.view = new DataView(buffer.buffer, buffer.byteOffset, buffer.byteLength);\\n this.pos = 0;\\n this.length = this.buffer.length;\\n }\\n readString(length, encoding = \\\"ascii\\\") {\\n encoding = ENCODING_MAPPING[encoding] || encoding;\\n let buf = this.readBuffer(length);\\n try {\\n let decoder = new TextDecoder(encoding);\\n return decoder.decode(buf);\\n } catch (err) {\\n return buf;\\n }\\n }\\n readBuffer(length) {\\n return this.buffer.slice(this.pos, this.pos += length);\\n }\\n readUInt24BE() {\\n return (this.readUInt16BE() << 8) + this.readUInt8();\\n }\\n readUInt24LE() {\\n return this.readUInt16LE() + (this.readUInt8() << 16);\\n }\\n readInt24BE() {\\n return (this.readInt16BE() << 8) + this.readUInt8();\\n }\\n readInt24LE() {\\n return this.readUInt16LE() + (this.readInt8() << 16);\\n }\\n };\\n DecodeStream.TYPES = {\\n UInt8: 1,\\n UInt16: 2,\\n UInt24: 3,\\n UInt32: 4,\\n Int8: 1,\\n Int16: 2,\\n Int24: 3,\\n Int32: 4,\\n Float: 4,\\n Double: 8\\n };\\n for (let key of Object.getOwnPropertyNames(DataView.prototype)) {\\n if (key.slice(0, 3) === \\\"get\\\") {\\n let type = key.slice(3).replace(\\\"Ui\\\", \\\"UI\\\");\\n if (type === \\\"Float32\\\") {\\n type = \\\"Float\\\";\\n } else if (type === \\\"Float64\\\") {\\n type = \\\"Double\\\";\\n }\\n let bytes = DecodeStream.TYPES[type];\\n DecodeStream.prototype[\\\"read\\\" + type + (bytes === 1 ? \\\"\\\" : \\\"BE\\\")] = function() {\\n const ret = this.view[key](this.pos, false);\\n this.pos += bytes;\\n return ret;\\n };\\n if (bytes !== 1) {\\n DecodeStream.prototype[\\\"read\\\" + type + \\\"LE\\\"] = function() {\\n const ret = this.view[key](this.pos, true);\\n this.pos += bytes;\\n return ret;\\n };\\n }\\n }\\n }\\n }\\n });\\n\\n // ../../node_modules/.pnpm/restructure@3.0.2/node_modules/restructure/src/EncodeStream.js\\n function stringToUtf16(string, swap) {\\n let buf = new Uint16Array(string.length);\\n for (let i = 0; i < string.length; i++) {\\n let code = string.charCodeAt(i);\\n if (swap) {\\n code = code >> 8 | (code & 255) << 8;\\n }\\n buf[i] = code;\\n }\\n return new Uint8Array(buf.buffer);\\n }\\n function stringToAscii(string) {\\n let buf = new Uint8Array(string.length);\\n for (let i = 0; i < string.length; i++) {\\n buf[i] = string.charCodeAt(i);\\n }\\n return buf;\\n }\\n var textEncoder, isBigEndian, EncodeStream;\\n var init_EncodeStream = __esm({\\n \\\"../../node_modules/.pnpm/restructure@3.0.2/node_modules/restructure/src/EncodeStream.js\\\"() {\\n init_DecodeStream();\\n textEncoder = new TextEncoder();\\n isBigEndian = new Uint8Array(new Uint16Array([4660]).buffer)[0] == 18;\\n EncodeStream = class {\\n constructor(buffer) {\\n this.buffer = buffer;\\n this.view = new DataView(this.buffer.buffer, this.buffer.byteOffset, this.buffer.byteLength);\\n this.pos = 0;\\n }\\n writeBuffer(buffer) {\\n this.buffer.set(buffer, this.pos);\\n this.pos += buffer.length;\\n }\\n writeString(string, encoding = \\\"ascii\\\") {\\n let buf;\\n switch (encoding) {\\n case \\\"utf16le\\\":\\n case \\\"utf16-le\\\":\\n case \\\"ucs2\\\":\\n buf = stringToUtf16(string, isBigEndian);\\n break;\\n case \\\"utf16be\\\":\\n case \\\"utf16-be\\\":\\n buf = stringToUtf16(string, !isBigEndian);\\n break;\\n case \\\"utf8\\\":\\n buf = textEncoder.encode(string);\\n break;\\n case \\\"ascii\\\":\\n buf = stringToAscii(string);\\n break;\\n default:\\n throw new Error(`Unsupported encoding: ${encoding}`);\\n }\\n this.writeBuffer(buf);\\n }\\n writeUInt24BE(val) {\\n this.buffer[this.pos++] = val >>> 16 & 255;\\n this.buffer[this.pos++] = val >>> 8 & 255;\\n this.buffer[this.pos++] = val & 255;\\n }\\n writeUInt24LE(val) {\\n this.buffer[this.pos++] = val & 255;\\n this.buffer[this.pos++] = val >>> 8 & 255;\\n this.buffer[this.pos++] = val >>> 16 & 255;\\n }\\n writeInt24BE(val) {\\n if (val >= 0) {\\n this.writeUInt24BE(val);\\n } else {\\n this.writeUInt24BE(val + 16777215 + 1);\\n }\\n }\\n writeInt24LE(val) {\\n if (val >= 0) {\\n this.writeUInt24LE(val);\\n } else {\\n this.writeUInt24LE(val + 16777215 + 1);\\n }\\n }\\n fill(val, length) {\\n if (length < this.buffer.length) {\\n this.buffer.fill(val, this.pos, this.pos + length);\\n this.pos += length;\\n } else {\\n const buf = new Uint8Array(length);\\n buf.fill(val);\\n this.writeBuffer(buf);\\n }\\n }\\n };\\n for (let key of Object.getOwnPropertyNames(DataView.prototype)) {\\n if (key.slice(0, 3) === \\\"set\\\") {\\n let type = key.slice(3).replace(\\\"Ui\\\", \\\"UI\\\");\\n if (type === \\\"Float32\\\") {\\n type = \\\"Float\\\";\\n } else if (type === \\\"Float64\\\") {\\n type = \\\"Double\\\";\\n }\\n let bytes = DecodeStream.TYPES[type];\\n EncodeStream.prototype[\\\"write\\\" + type + (bytes === 1 ? \\\"\\\" : \\\"BE\\\")] = function(value) {\\n this.view[key](this.pos, value, false);\\n this.pos += bytes;\\n };\\n if (bytes !== 1) {\\n EncodeStream.prototype[\\\"write\\\" + type + \\\"LE\\\"] = function(value) {\\n this.view[key](this.pos, value, true);\\n this.pos += bytes;\\n };\\n }\\n }\\n }\\n }\\n });\\n\\n // ../../node_modules/.pnpm/restructure@3.0.2/node_modules/restructure/src/Base.js\\n var Base;\\n var init_Base = __esm({\\n \\\"../../node_modules/.pnpm/restructure@3.0.2/node_modules/restructure/src/Base.js\\\"() {\\n init_DecodeStream();\\n init_EncodeStream();\\n Base = class {\\n fromBuffer(buffer) {\\n let stream = new DecodeStream(buffer);\\n return this.decode(stream);\\n }\\n toBuffer(value) {\\n let size = this.size(value);\\n let buffer = new Uint8Array(size);\\n let stream = new EncodeStream(buffer);\\n this.encode(stream, value);\\n return buffer;\\n }\\n };\\n }\\n });\\n\\n // ../../node_modules/.pnpm/restructure@3.0.2/node_modules/restructure/src/Number.js\\n var NumberT, uint8, uint16be, uint16, uint16le, uint24be, uint24, uint24le, uint32be, uint32, uint32le, int8, int16be, int16, int16le, int24be, int24le, int32be, int32, int32le, floatbe, floatle, doublebe, doublele, Fixed, fixed16be, fixed16, fixed16le, fixed32be, fixed32, fixed32le;\\n var init_Number = __esm({\\n \\\"../../node_modules/.pnpm/restructure@3.0.2/node_modules/restructure/src/Number.js\\\"() {\\n init_DecodeStream();\\n init_Base();\\n NumberT = class extends Base {\\n constructor(type, endian = \\\"BE\\\") {\\n super();\\n this.type = type;\\n this.endian = endian;\\n this.fn = this.type;\\n if (this.type[this.type.length - 1] !== \\\"8\\\") {\\n this.fn += this.endian;\\n }\\n }\\n size() {\\n return DecodeStream.TYPES[this.type];\\n }\\n decode(stream) {\\n return stream[`read${this.fn}`]();\\n }\\n encode(stream, val) {\\n return stream[`write${this.fn}`](val);\\n }\\n };\\n uint8 = new NumberT(\\\"UInt8\\\");\\n uint16be = new NumberT(\\\"UInt16\\\", \\\"BE\\\");\\n uint16 = uint16be;\\n uint16le = new NumberT(\\\"UInt16\\\", \\\"LE\\\");\\n uint24be = new NumberT(\\\"UInt24\\\", \\\"BE\\\");\\n uint24 = uint24be;\\n uint24le = new NumberT(\\\"UInt24\\\", \\\"LE\\\");\\n uint32be = new NumberT(\\\"UInt32\\\", \\\"BE\\\");\\n uint32 = uint32be;\\n uint32le = new NumberT(\\\"UInt32\\\", \\\"LE\\\");\\n int8 = new NumberT(\\\"Int8\\\");\\n int16be = new NumberT(\\\"Int16\\\", \\\"BE\\\");\\n int16 = int16be;\\n int16le = new NumberT(\\\"Int16\\\", \\\"LE\\\");\\n int24be = new NumberT(\\\"Int24\\\", \\\"BE\\\");\\n int24le = new NumberT(\\\"Int24\\\", \\\"LE\\\");\\n int32be = new NumberT(\\\"Int32\\\", \\\"BE\\\");\\n int32 = int32be;\\n int32le = new NumberT(\\\"Int32\\\", \\\"LE\\\");\\n floatbe = new NumberT(\\\"Float\\\", \\\"BE\\\");\\n floatle = new NumberT(\\\"Float\\\", \\\"LE\\\");\\n doublebe = new NumberT(\\\"Double\\\", \\\"BE\\\");\\n doublele = new NumberT(\\\"Double\\\", \\\"LE\\\");\\n Fixed = class extends NumberT {\\n constructor(size, endian, fracBits = size >> 1) {\\n super(`Int${size}`, endian);\\n this._point = 1 << fracBits;\\n }\\n decode(stream) {\\n return super.decode(stream) / this._point;\\n }\\n encode(stream, val) {\\n return super.encode(stream, val * this._point | 0);\\n }\\n };\\n fixed16be = new Fixed(16, \\\"BE\\\");\\n fixed16 = fixed16be;\\n fixed16le = new Fixed(16, \\\"LE\\\");\\n fixed32be = new Fixed(32, \\\"BE\\\");\\n fixed32 = fixed32be;\\n fixed32le = new Fixed(32, \\\"LE\\\");\\n }\\n });\\n\\n // ../../node_modules/.pnpm/restructure@3.0.2/node_modules/restructure/src/utils.js\\n function resolveLength(length, stream, parent) {\\n let res;\\n if (typeof length === \\\"number\\\") {\\n res = length;\\n } else if (typeof length === \\\"function\\\") {\\n res = length.call(parent, parent);\\n } else if (parent && typeof length === \\\"string\\\") {\\n res = parent[length];\\n } else if (stream && length instanceof NumberT) {\\n res = length.decode(stream);\\n }\\n if (isNaN(res)) {\\n throw new Error(\\\"Not a fixed size\\\");\\n }\\n return res;\\n }\\n var PropertyDescriptor;\\n var init_utils = __esm({\\n \\\"../../node_modules/.pnpm/restructure@3.0.2/node_modules/restructure/src/utils.js\\\"() {\\n init_Number();\\n PropertyDescriptor = class {\\n constructor(opts = {}) {\\n this.enumerable = true;\\n this.configurable = true;\\n for (let key in opts) {\\n const val = opts[key];\\n this[key] = val;\\n }\\n }\\n };\\n }\\n });\\n\\n // ../../node_modules/.pnpm/restructure@3.0.2/node_modules/restructure/src/Array.js\\n var ArrayT;\\n var init_Array = __esm({\\n \\\"../../node_modules/.pnpm/restructure@3.0.2/node_modules/restructure/src/Array.js\\\"() {\\n init_Base();\\n init_Number();\\n init_utils();\\n ArrayT = class extends Base {\\n constructor(type, length, lengthType = \\\"count\\\") {\\n super();\\n this.type = type;\\n this.length = length;\\n this.lengthType = lengthType;\\n }\\n decode(stream, parent) {\\n let length;\\n const { pos } = stream;\\n const res = [];\\n let ctx = parent;\\n if (this.length != null) {\\n length = resolveLength(this.length, stream, parent);\\n }\\n if (this.length instanceof NumberT) {\\n Object.defineProperties(res, {\\n parent: { value: parent },\\n _startOffset: { value: pos },\\n _currentOffset: { value: 0, writable: true },\\n _length: { value: length }\\n });\\n ctx = res;\\n }\\n if (length == null || this.lengthType === \\\"bytes\\\") {\\n const target = length != null ? stream.pos + length : (parent != null ? parent._length : void 0) ? parent._startOffset + parent._length : stream.length;\\n while (stream.pos < target) {\\n res.push(this.type.decode(stream, ctx));\\n }\\n } else {\\n for (let i = 0, end = length; i < end; i++) {\\n res.push(this.type.decode(stream, ctx));\\n }\\n }\\n return res;\\n }\\n size(array, ctx, includePointers = true) {\\n if (!array) {\\n return this.type.size(null, ctx) * resolveLength(this.length, null, ctx);\\n }\\n let size = 0;\\n if (this.length instanceof NumberT) {\\n size += this.length.size();\\n ctx = { parent: ctx, pointerSize: 0 };\\n }\\n for (let item of array) {\\n size += this.type.size(item, ctx);\\n }\\n if (ctx && includePointers && this.length instanceof NumberT) {\\n size += ctx.pointerSize;\\n }\\n return size;\\n }\\n encode(stream, array, parent) {\\n let ctx = parent;\\n if (this.length instanceof NumberT) {\\n ctx = {\\n pointers: [],\\n startOffset: stream.pos,\\n parent\\n };\\n ctx.pointerOffset = stream.pos + this.size(array, ctx, false);\\n this.length.encode(stream, array.length);\\n }\\n for (let item of array) {\\n this.type.encode(stream, item, ctx);\\n }\\n if (this.length instanceof NumberT) {\\n let i = 0;\\n while (i < ctx.pointers.length) {\\n const ptr = ctx.pointers[i++];\\n ptr.type.encode(stream, ptr.val, ptr.parent);\\n }\\n }\\n }\\n };\\n }\\n });\\n\\n // ../../node_modules/.pnpm/restructure@3.0.2/node_modules/restructure/src/LazyArray.js\\n var LazyArray, LazyArrayValue;\\n var init_LazyArray = __esm({\\n \\\"../../node_modules/.pnpm/restructure@3.0.2/node_modules/restructure/src/LazyArray.js\\\"() {\\n init_Array();\\n init_Number();\\n init_utils();\\n LazyArray = class extends ArrayT {\\n decode(stream, parent) {\\n const { pos } = stream;\\n const length = resolveLength(this.length, stream, parent);\\n if (this.length instanceof NumberT) {\\n parent = {\\n parent,\\n _startOffset: pos,\\n _currentOffset: 0,\\n _length: length\\n };\\n }\\n const res = new LazyArrayValue(this.type, length, stream, parent);\\n stream.pos += length * this.type.size(null, parent);\\n return res;\\n }\\n size(val, ctx) {\\n if (val instanceof LazyArrayValue) {\\n val = val.toArray();\\n }\\n return super.size(val, ctx);\\n }\\n encode(stream, val, ctx) {\\n if (val instanceof LazyArrayValue) {\\n val = val.toArray();\\n }\\n return super.encode(stream, val, ctx);\\n }\\n };\\n LazyArrayValue = class {\\n constructor(type, length, stream, ctx) {\\n this.type = type;\\n this.length = length;\\n this.stream = stream;\\n this.ctx = ctx;\\n this.base = this.stream.pos;\\n this.items = [];\\n }\\n get(index) {\\n if (index < 0 || index >= this.length) {\\n return void 0;\\n }\\n if (this.items[index] == null) {\\n const { pos } = this.stream;\\n this.stream.pos = this.base + this.type.size(null, this.ctx) * index;\\n this.items[index] = this.type.decode(this.stream, this.ctx);\\n this.stream.pos = pos;\\n }\\n return this.items[index];\\n }\\n toArray() {\\n const result = [];\\n for (let i = 0, end = this.length; i < end; i++) {\\n result.push(this.get(i));\\n }\\n return result;\\n }\\n };\\n }\\n });\\n\\n // ../../node_modules/.pnpm/restructure@3.0.2/node_modules/restructure/src/Bitfield.js\\n var Bitfield;\\n var init_Bitfield = __esm({\\n \\\"../../node_modules/.pnpm/restructure@3.0.2/node_modules/restructure/src/Bitfield.js\\\"() {\\n init_Base();\\n Bitfield = class extends Base {\\n constructor(type, flags = []) {\\n super();\\n this.type = type;\\n this.flags = flags;\\n }\\n decode(stream) {\\n const val = this.type.decode(stream);\\n const res = {};\\n for (let i = 0; i < this.flags.length; i++) {\\n const flag = this.flags[i];\\n if (flag != null) {\\n res[flag] = !!(val & 1 << i);\\n }\\n }\\n return res;\\n }\\n size() {\\n return this.type.size();\\n }\\n encode(stream, keys) {\\n let val = 0;\\n for (let i = 0; i < this.flags.length; i++) {\\n const flag = this.flags[i];\\n if (flag != null) {\\n if (keys[flag]) {\\n val |= 1 << i;\\n }\\n }\\n }\\n return this.type.encode(stream, val);\\n }\\n };\\n }\\n });\\n\\n // ../../node_modules/.pnpm/restructure@3.0.2/node_modules/restructure/src/Boolean.js\\n var init_Boolean = __esm({\\n \\\"../../node_modules/.pnpm/restructure@3.0.2/node_modules/restructure/src/Boolean.js\\\"() {\\n init_Base();\\n }\\n });\\n\\n // ../../node_modules/.pnpm/restructure@3.0.2/node_modules/restructure/src/Buffer.js\\n var BufferT;\\n var init_Buffer = __esm({\\n \\\"../../node_modules/.pnpm/restructure@3.0.2/node_modules/restructure/src/Buffer.js\\\"() {\\n init_Base();\\n init_Number();\\n init_utils();\\n BufferT = class extends Base {\\n constructor(length) {\\n super();\\n this.length = length;\\n }\\n decode(stream, parent) {\\n const length = resolveLength(this.length, stream, parent);\\n return stream.readBuffer(length);\\n }\\n size(val, parent) {\\n if (!val) {\\n return resolveLength(this.length, null, parent);\\n }\\n let len = val.length;\\n if (this.length instanceof NumberT) {\\n len += this.length.size();\\n }\\n return len;\\n }\\n encode(stream, buf, parent) {\\n if (this.length instanceof NumberT) {\\n this.length.encode(stream, buf.length);\\n }\\n return stream.writeBuffer(buf);\\n }\\n };\\n }\\n });\\n\\n // ../../node_modules/.pnpm/restructure@3.0.2/node_modules/restructure/src/Enum.js\\n var init_Enum = __esm({\\n \\\"../../node_modules/.pnpm/restructure@3.0.2/node_modules/restructure/src/Enum.js\\\"() {\\n init_Base();\\n }\\n });\\n\\n // ../../node_modules/.pnpm/restructure@3.0.2/node_modules/restructure/src/Optional.js\\n var Optional;\\n var init_Optional = __esm({\\n \\\"../../node_modules/.pnpm/restructure@3.0.2/node_modules/restructure/src/Optional.js\\\"() {\\n init_Base();\\n Optional = class extends Base {\\n constructor(type, condition = true) {\\n super();\\n this.type = type;\\n this.condition = condition;\\n }\\n decode(stream, parent) {\\n let { condition } = this;\\n if (typeof condition === \\\"function\\\") {\\n condition = condition.call(parent, parent);\\n }\\n if (condition) {\\n return this.type.decode(stream, parent);\\n }\\n }\\n size(val, parent) {\\n let { condition } = this;\\n if (typeof condition === \\\"function\\\") {\\n condition = condition.call(parent, parent);\\n }\\n if (condition) {\\n return this.type.size(val, parent);\\n } else {\\n return 0;\\n }\\n }\\n encode(stream, val, parent) {\\n let { condition } = this;\\n if (typeof condition === \\\"function\\\") {\\n condition = condition.call(parent, parent);\\n }\\n if (condition) {\\n return this.type.encode(stream, val, parent);\\n }\\n }\\n };\\n }\\n });\\n\\n // ../../node_modules/.pnpm/restructure@3.0.2/node_modules/restructure/src/Reserved.js\\n var Reserved;\\n var init_Reserved = __esm({\\n \\\"../../node_modules/.pnpm/restructure@3.0.2/node_modules/restructure/src/Reserved.js\\\"() {\\n init_Base();\\n init_utils();\\n Reserved = class extends Base {\\n constructor(type, count = 1) {\\n super();\\n this.type = type;\\n this.count = count;\\n }\\n decode(stream, parent) {\\n stream.pos += this.size(null, parent);\\n return void 0;\\n }\\n size(data, parent) {\\n const count = resolveLength(this.count, null, parent);\\n return this.type.size() * count;\\n }\\n encode(stream, val, parent) {\\n return stream.fill(0, this.size(val, parent));\\n }\\n };\\n }\\n });\\n\\n // ../../node_modules/.pnpm/restructure@3.0.2/node_modules/restructure/src/String.js\\n function encodingWidth(encoding) {\\n switch (encoding) {\\n case \\\"ascii\\\":\\n case \\\"utf8\\\":\\n return 1;\\n case \\\"utf16le\\\":\\n case \\\"utf16-le\\\":\\n case \\\"utf-16be\\\":\\n case \\\"utf-16le\\\":\\n case \\\"utf16be\\\":\\n case \\\"utf16-be\\\":\\n case \\\"ucs2\\\":\\n return 2;\\n default:\\n return 1;\\n }\\n }\\n function byteLength(string, encoding) {\\n switch (encoding) {\\n case \\\"ascii\\\":\\n return string.length;\\n case \\\"utf8\\\":\\n let len = 0;\\n for (let i = 0; i < string.length; i++) {\\n let c = string.charCodeAt(i);\\n if (c >= 55296 && c <= 56319 && i < string.length - 1) {\\n let c2 = string.charCodeAt(++i);\\n if ((c2 & 64512) === 56320) {\\n c = ((c & 1023) << 10) + (c2 & 1023) + 65536;\\n } else {\\n i--;\\n }\\n }\\n if ((c & 4294967168) === 0) {\\n len++;\\n } else if ((c & 4294965248) === 0) {\\n len += 2;\\n } else if ((c & 4294901760) === 0) {\\n len += 3;\\n } else if ((c & 4292870144) === 0) {\\n len += 4;\\n }\\n }\\n return len;\\n case \\\"utf16le\\\":\\n case \\\"utf16-le\\\":\\n case \\\"utf16be\\\":\\n case \\\"utf16-be\\\":\\n case \\\"ucs2\\\":\\n return string.length * 2;\\n default:\\n throw new Error(\\\"Unknown encoding \\\" + encoding);\\n }\\n }\\n var StringT;\\n var init_String = __esm({\\n \\\"../../node_modules/.pnpm/restructure@3.0.2/node_modules/restructure/src/String.js\\\"() {\\n init_Base();\\n init_Number();\\n init_utils();\\n StringT = class extends Base {\\n constructor(length, encoding = \\\"ascii\\\") {\\n super();\\n this.length = length;\\n this.encoding = encoding;\\n }\\n decode(stream, parent) {\\n let length, pos;\\n let { encoding } = this;\\n if (typeof encoding === \\\"function\\\") {\\n encoding = encoding.call(parent, parent) || \\\"ascii\\\";\\n }\\n let width = encodingWidth(encoding);\\n if (this.length != null) {\\n length = resolveLength(this.length, stream, parent);\\n } else {\\n let buffer;\\n ({ buffer, length, pos } = stream);\\n while (pos < length - width + 1 && (buffer[pos] !== 0 || width === 2 && buffer[pos + 1] !== 0)) {\\n pos += width;\\n }\\n length = pos - stream.pos;\\n }\\n const string = stream.readString(length, encoding);\\n if (this.length == null && stream.pos < stream.length) {\\n stream.pos += width;\\n }\\n return string;\\n }\\n size(val, parent) {\\n if (val === void 0 || val === null) {\\n return resolveLength(this.length, null, parent);\\n }\\n let { encoding } = this;\\n if (typeof encoding === \\\"function\\\") {\\n encoding = encoding.call(parent != null ? parent.val : void 0, parent != null ? parent.val : void 0) || \\\"ascii\\\";\\n }\\n if (encoding === \\\"utf16be\\\") {\\n encoding = \\\"utf16le\\\";\\n }\\n let size = byteLength(val, encoding);\\n if (this.length instanceof NumberT) {\\n size += this.length.size();\\n }\\n if (this.length == null) {\\n size += encodingWidth(encoding);\\n }\\n return size;\\n }\\n encode(stream, val, parent) {\\n let { encoding } = this;\\n if (typeof encoding === \\\"function\\\") {\\n encoding = encoding.call(parent != null ? parent.val : void 0, parent != null ? parent.val : void 0) || \\\"ascii\\\";\\n }\\n if (this.length instanceof NumberT) {\\n this.length.encode(stream, byteLength(val, encoding));\\n }\\n stream.writeString(val, encoding);\\n if (this.length == null) {\\n return encodingWidth(encoding) == 2 ? stream.writeUInt16LE(0) : stream.writeUInt8(0);\\n }\\n }\\n };\\n }\\n });\\n\\n // ../../node_modules/.pnpm/restructure@3.0.2/node_modules/restructure/src/Struct.js\\n var Struct;\\n var init_Struct = __esm({\\n \\\"../../node_modules/.pnpm/restructure@3.0.2/node_modules/restructure/src/Struct.js\\\"() {\\n init_Base();\\n init_utils();\\n Struct = class extends Base {\\n constructor(fields = {}) {\\n super();\\n this.fields = fields;\\n }\\n decode(stream, parent, length = 0) {\\n const res = this._setup(stream, parent, length);\\n this._parseFields(stream, res, this.fields);\\n if (this.process != null) {\\n this.process.call(res, stream);\\n }\\n return res;\\n }\\n _setup(stream, parent, length) {\\n const res = {};\\n Object.defineProperties(res, {\\n parent: { value: parent },\\n _startOffset: { value: stream.pos },\\n _currentOffset: { value: 0, writable: true },\\n _length: { value: length }\\n });\\n return res;\\n }\\n _parseFields(stream, res, fields) {\\n for (let key in fields) {\\n var val;\\n const type = fields[key];\\n if (typeof type === \\\"function\\\") {\\n val = type.call(res, res);\\n } else {\\n val = type.decode(stream, res);\\n }\\n if (val !== void 0) {\\n if (val instanceof PropertyDescriptor) {\\n Object.defineProperty(res, key, val);\\n } else {\\n res[key] = val;\\n }\\n }\\n res._currentOffset = stream.pos - res._startOffset;\\n }\\n }\\n size(val, parent, includePointers = true) {\\n if (val == null) {\\n val = {};\\n }\\n const ctx = {\\n parent,\\n val,\\n pointerSize: 0\\n };\\n if (this.preEncode != null) {\\n this.preEncode.call(val);\\n }\\n let size = 0;\\n for (let key in this.fields) {\\n const type = this.fields[key];\\n if (type.size != null) {\\n size += type.size(val[key], ctx);\\n }\\n }\\n if (includePointers) {\\n size += ctx.pointerSize;\\n }\\n return size;\\n }\\n encode(stream, val, parent) {\\n let type;\\n if (this.preEncode != null) {\\n this.preEncode.call(val, stream);\\n }\\n const ctx = {\\n pointers: [],\\n startOffset: stream.pos,\\n parent,\\n val,\\n pointerSize: 0\\n };\\n ctx.pointerOffset = stream.pos + this.size(val, ctx, false);\\n for (let key in this.fields) {\\n type = this.fields[key];\\n if (type.encode != null) {\\n type.encode(stream, val[key], ctx);\\n }\\n }\\n let i = 0;\\n while (i < ctx.pointers.length) {\\n const ptr = ctx.pointers[i++];\\n ptr.type.encode(stream, ptr.val, ptr.parent);\\n }\\n }\\n };\\n }\\n });\\n\\n // ../../node_modules/.pnpm/restructure@3.0.2/node_modules/restructure/src/VersionedStruct.js\\n var getPath, VersionedStruct;\\n var init_VersionedStruct = __esm({\\n \\\"../../node_modules/.pnpm/restructure@3.0.2/node_modules/restructure/src/VersionedStruct.js\\\"() {\\n init_Struct();\\n getPath = (object, pathArray) => {\\n return pathArray.reduce((prevObj, key) => prevObj && prevObj[key], object);\\n };\\n VersionedStruct = class _VersionedStruct extends Struct {\\n constructor(type, versions = {}) {\\n super();\\n this.type = type;\\n this.versions = versions;\\n if (typeof type === \\\"string\\\") {\\n this.versionPath = type.split(\\\".\\\");\\n }\\n }\\n decode(stream, parent, length = 0) {\\n const res = this._setup(stream, parent, length);\\n if (typeof this.type === \\\"string\\\") {\\n res.version = getPath(parent, this.versionPath);\\n } else {\\n res.version = this.type.decode(stream);\\n }\\n if (this.versions.header) {\\n this._parseFields(stream, res, this.versions.header);\\n }\\n const fields = this.versions[res.version];\\n if (fields == null) {\\n throw new Error(`Unknown version ${res.version}`);\\n }\\n if (fields instanceof _VersionedStruct) {\\n return fields.decode(stream, parent);\\n }\\n this._parseFields(stream, res, fields);\\n if (this.process != null) {\\n this.process.call(res, stream);\\n }\\n return res;\\n }\\n size(val, parent, includePointers = true) {\\n let key, type;\\n if (!val) {\\n throw new Error(\\\"Not a fixed size\\\");\\n }\\n if (this.preEncode != null) {\\n this.preEncode.call(val);\\n }\\n const ctx = {\\n parent,\\n val,\\n pointerSize: 0\\n };\\n let size = 0;\\n if (typeof this.type !== \\\"string\\\") {\\n size += this.type.size(val.version, ctx);\\n }\\n if (this.versions.header) {\\n for (key in this.versions.header) {\\n type = this.versions.header[key];\\n if (type.size != null) {\\n size += type.size(val[key], ctx);\\n }\\n }\\n }\\n const fields = this.versions[val.version];\\n if (fields == null) {\\n throw new Error(`Unknown version ${val.version}`);\\n }\\n for (key in fields) {\\n type = fields[key];\\n if (type.size != null) {\\n size += type.size(val[key], ctx);\\n }\\n }\\n if (includePointers) {\\n size += ctx.pointerSize;\\n }\\n return size;\\n }\\n encode(stream, val, parent) {\\n let key, type;\\n if (this.preEncode != null) {\\n this.preEncode.call(val, stream);\\n }\\n const ctx = {\\n pointers: [],\\n startOffset: stream.pos,\\n parent,\\n val,\\n pointerSize: 0\\n };\\n ctx.pointerOffset = stream.pos + this.size(val, ctx, false);\\n if (typeof this.type !== \\\"string\\\") {\\n this.type.encode(stream, val.version);\\n }\\n if (this.versions.header) {\\n for (key in this.versions.header) {\\n type = this.versions.header[key];\\n if (type.encode != null) {\\n type.encode(stream, val[key], ctx);\\n }\\n }\\n }\\n const fields = this.versions[val.version];\\n for (key in fields) {\\n type = fields[key];\\n if (type.encode != null) {\\n type.encode(stream, val[key], ctx);\\n }\\n }\\n let i = 0;\\n while (i < ctx.pointers.length) {\\n const ptr = ctx.pointers[i++];\\n ptr.type.encode(stream, ptr.val, ptr.parent);\\n }\\n }\\n };\\n }\\n });\\n\\n // ../../node_modules/.pnpm/restructure@3.0.2/node_modules/restructure/src/Pointer.js\\n var Pointer, VoidPointer;\\n var init_Pointer = __esm({\\n \\\"../../node_modules/.pnpm/restructure@3.0.2/node_modules/restructure/src/Pointer.js\\\"() {\\n init_utils();\\n init_Base();\\n Pointer = class extends Base {\\n constructor(offsetType, type, options = {}) {\\n super();\\n this.offsetType = offsetType;\\n this.type = type;\\n this.options = options;\\n if (this.type === \\\"void\\\") {\\n this.type = null;\\n }\\n if (this.options.type == null) {\\n this.options.type = \\\"local\\\";\\n }\\n if (this.options.allowNull == null) {\\n this.options.allowNull = true;\\n }\\n if (this.options.nullValue == null) {\\n this.options.nullValue = 0;\\n }\\n if (this.options.lazy == null) {\\n this.options.lazy = false;\\n }\\n if (this.options.relativeTo) {\\n if (typeof this.options.relativeTo !== \\\"function\\\") {\\n throw new Error(\\\"relativeTo option must be a function\\\");\\n }\\n this.relativeToGetter = options.relativeTo;\\n }\\n }\\n decode(stream, ctx) {\\n const offset = this.offsetType.decode(stream, ctx);\\n if (offset === this.options.nullValue && this.options.allowNull) {\\n return null;\\n }\\n let relative;\\n switch (this.options.type) {\\n case \\\"local\\\":\\n relative = ctx._startOffset;\\n break;\\n case \\\"immediate\\\":\\n relative = stream.pos - this.offsetType.size();\\n break;\\n case \\\"parent\\\":\\n relative = ctx.parent._startOffset;\\n break;\\n default:\\n var c = ctx;\\n while (c.parent) {\\n c = c.parent;\\n }\\n relative = c._startOffset || 0;\\n }\\n if (this.options.relativeTo) {\\n relative += this.relativeToGetter(ctx);\\n }\\n const ptr = offset + relative;\\n if (this.type != null) {\\n let val = null;\\n const decodeValue = () => {\\n if (val != null) {\\n return val;\\n }\\n const { pos } = stream;\\n stream.pos = ptr;\\n val = this.type.decode(stream, ctx);\\n stream.pos = pos;\\n return val;\\n };\\n if (this.options.lazy) {\\n return new PropertyDescriptor({\\n get: decodeValue\\n });\\n }\\n return decodeValue();\\n } else {\\n return ptr;\\n }\\n }\\n size(val, ctx) {\\n const parent = ctx;\\n switch (this.options.type) {\\n case \\\"local\\\":\\n case \\\"immediate\\\":\\n break;\\n case \\\"parent\\\":\\n ctx = ctx.parent;\\n break;\\n default:\\n while (ctx.parent) {\\n ctx = ctx.parent;\\n }\\n }\\n let { type } = this;\\n if (type == null) {\\n if (!(val instanceof VoidPointer)) {\\n throw new Error(\\\"Must be a VoidPointer\\\");\\n }\\n ({ type } = val);\\n val = val.value;\\n }\\n if (val && ctx) {\\n let size = type.size(val, parent);\\n ctx.pointerSize += size;\\n }\\n return this.offsetType.size();\\n }\\n encode(stream, val, ctx) {\\n let relative;\\n const parent = ctx;\\n if (val == null) {\\n this.offsetType.encode(stream, this.options.nullValue);\\n return;\\n }\\n switch (this.options.type) {\\n case \\\"local\\\":\\n relative = ctx.startOffset;\\n break;\\n case \\\"immediate\\\":\\n relative = stream.pos + this.offsetType.size(val, parent);\\n break;\\n case \\\"parent\\\":\\n ctx = ctx.parent;\\n relative = ctx.startOffset;\\n break;\\n default:\\n relative = 0;\\n while (ctx.parent) {\\n ctx = ctx.parent;\\n }\\n }\\n if (this.options.relativeTo) {\\n relative += this.relativeToGetter(parent.val);\\n }\\n this.offsetType.encode(stream, ctx.pointerOffset - relative);\\n let { type } = this;\\n if (type == null) {\\n if (!(val instanceof VoidPointer)) {\\n throw new Error(\\\"Must be a VoidPointer\\\");\\n }\\n ({ type } = val);\\n val = val.value;\\n }\\n ctx.pointers.push({\\n type,\\n val,\\n parent\\n });\\n return ctx.pointerOffset += type.size(val, parent);\\n }\\n };\\n VoidPointer = class {\\n constructor(type, value) {\\n this.type = type;\\n this.value = value;\\n }\\n };\\n }\\n });\\n\\n // ../../node_modules/.pnpm/restructure@3.0.2/node_modules/restructure/index.js\\n var init_restructure = __esm({\\n \\\"../../node_modules/.pnpm/restructure@3.0.2/node_modules/restructure/index.js\\\"() {\\n init_EncodeStream();\\n init_DecodeStream();\\n init_Array();\\n init_LazyArray();\\n init_Bitfield();\\n init_Boolean();\\n init_Buffer();\\n init_Enum();\\n init_Optional();\\n init_Reserved();\\n init_String();\\n init_Struct();\\n init_VersionedStruct();\\n init_utils();\\n init_Number();\\n init_Pointer();\\n }\\n });\\n\\n // ../../node_modules/.pnpm/@swc+helpers@0.5.21/node_modules/@swc/helpers/esm/_define_property.js\\n function _define_property(obj, key, value) {\\n if (key in obj) {\\n Object.defineProperty(obj, key, { value, enumerable: true, configurable: true, writable: true });\\n } else obj[key] = value;\\n return obj;\\n }\\n var init_define_property = __esm({\\n \\\"../../node_modules/.pnpm/@swc+helpers@0.5.21/node_modules/@swc/helpers/esm/_define_property.js\\\"() {\\n }\\n });\\n\\n // ../../node_modules/.pnpm/tslib@2.8.1/node_modules/tslib/tslib.es6.mjs\\n function __decorate(decorators, target, key, desc) {\\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\\n if (typeof Reflect === \\\"object\\\" && typeof Reflect.decorate === \\\"function\\\") r = Reflect.decorate(decorators, target, key, desc);\\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\\n return c > 3 && r && Object.defineProperty(target, key, r), r;\\n }\\n var init_tslib_es6 = __esm({\\n \\\"../../node_modules/.pnpm/tslib@2.8.1/node_modules/tslib/tslib.es6.mjs\\\"() {\\n }\\n });\\n\\n // ../../node_modules/.pnpm/@swc+helpers@0.5.21/node_modules/@swc/helpers/esm/_ts_decorate.js\\n var init_ts_decorate = __esm({\\n \\\"../../node_modules/.pnpm/@swc+helpers@0.5.21/node_modules/@swc/helpers/esm/_ts_decorate.js\\\"() {\\n init_tslib_es6();\\n }\\n });\\n\\n // ../../node_modules/.pnpm/fast-deep-equal@3.1.3/node_modules/fast-deep-equal/index.js\\n var require_fast_deep_equal = __commonJS({\\n \\\"../../node_modules/.pnpm/fast-deep-equal@3.1.3/node_modules/fast-deep-equal/index.js\\\"(exports, module) {\\n \\\"use strict\\\";\\n module.exports = function equal(a, b) {\\n if (a === b) return true;\\n if (a && b && typeof a == \\\"object\\\" && typeof b == \\\"object\\\") {\\n if (a.constructor !== b.constructor) return false;\\n var length, i, keys;\\n if (Array.isArray(a)) {\\n length = a.length;\\n if (length != b.length) return false;\\n for (i = length; i-- !== 0; )\\n if (!equal(a[i], b[i])) return false;\\n return true;\\n }\\n if (a.constructor === RegExp) return a.source === b.source && a.flags === b.flags;\\n if (a.valueOf !== Object.prototype.valueOf) return a.valueOf() === b.valueOf();\\n if (a.toString !== Object.prototype.toString) return a.toString() === b.toString();\\n keys = Object.keys(a);\\n length = keys.length;\\n if (length !== Object.keys(b).length) return false;\\n for (i = length; i-- !== 0; )\\n if (!Object.prototype.hasOwnProperty.call(b, keys[i])) return false;\\n for (i = length; i-- !== 0; ) {\\n var key = keys[i];\\n if (!equal(a[key], b[key])) return false;\\n }\\n return true;\\n }\\n return a !== a && b !== b;\\n };\\n }\\n });\\n\\n // ../../node_modules/.pnpm/base64-js@1.5.1/node_modules/base64-js/index.js\\n var require_base64_js = __commonJS({\\n \\\"../../node_modules/.pnpm/base64-js@1.5.1/node_modules/base64-js/index.js\\\"(exports) {\\n \\\"use strict\\\";\\n exports.byteLength = byteLength2;\\n exports.toByteArray = toByteArray;\\n exports.fromByteArray = fromByteArray;\\n var lookup = [];\\n var revLookup = [];\\n var Arr = typeof Uint8Array !== \\\"undefined\\\" ? Uint8Array : Array;\\n var code = \\\"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\\\";\\n for (i = 0, len = code.length; i < len; ++i) {\\n lookup[i] = code[i];\\n revLookup[code.charCodeAt(i)] = i;\\n }\\n var i;\\n var len;\\n revLookup[\\\"-\\\".charCodeAt(0)] = 62;\\n revLookup[\\\"_\\\".charCodeAt(0)] = 63;\\n function getLens(b64) {\\n var len2 = b64.length;\\n if (len2 % 4 > 0) {\\n throw new Error(\\\"Invalid string. Length must be a multiple of 4\\\");\\n }\\n var validLen = b64.indexOf(\\\"=\\\");\\n if (validLen === -1) validLen = len2;\\n var placeHoldersLen = validLen === len2 ? 0 : 4 - validLen % 4;\\n return [validLen, placeHoldersLen];\\n }\\n function byteLength2(b64) {\\n var lens = getLens(b64);\\n var validLen = lens[0];\\n var placeHoldersLen = lens[1];\\n return (validLen + placeHoldersLen) * 3 / 4 - placeHoldersLen;\\n }\\n function _byteLength(b64, validLen, placeHoldersLen) {\\n return (validLen + placeHoldersLen) * 3 / 4 - placeHoldersLen;\\n }\\n function toByteArray(b64) {\\n var tmp;\\n var lens = getLens(b64);\\n var validLen = lens[0];\\n var placeHoldersLen = lens[1];\\n var arr = new Arr(_byteLength(b64, validLen, placeHoldersLen));\\n var curByte = 0;\\n var len2 = placeHoldersLen > 0 ? validLen - 4 : validLen;\\n var i2;\\n for (i2 = 0; i2 < len2; i2 += 4) {\\n tmp = revLookup[b64.charCodeAt(i2)] << 18 | revLookup[b64.charCodeAt(i2 + 1)] << 12 | revLookup[b64.charCodeAt(i2 + 2)] << 6 | revLookup[b64.charCodeAt(i2 + 3)];\\n arr[curByte++] = tmp >> 16 & 255;\\n arr[curByte++] = tmp >> 8 & 255;\\n arr[curByte++] = tmp & 255;\\n }\\n if (placeHoldersLen === 2) {\\n tmp = revLookup[b64.charCodeAt(i2)] << 2 | revLookup[b64.charCodeAt(i2 + 1)] >> 4;\\n arr[curByte++] = tmp & 255;\\n }\\n if (placeHoldersLen === 1) {\\n tmp = revLookup[b64.charCodeAt(i2)] << 10 | revLookup[b64.charCodeAt(i2 + 1)] << 4 | revLookup[b64.charCodeAt(i2 + 2)] >> 2;\\n arr[curByte++] = tmp >> 8 & 255;\\n arr[curByte++] = tmp & 255;\\n }\\n return arr;\\n }\\n function tripletToBase64(num) {\\n return lookup[num >> 18 & 63] + lookup[num >> 12 & 63] + lookup[num >> 6 & 63] + lookup[num & 63];\\n }\\n function encodeChunk(uint82, start, end) {\\n var tmp;\\n var output = [];\\n for (var i2 = start; i2 < end; i2 += 3) {\\n tmp = (uint82[i2] << 16 & 16711680) + (uint82[i2 + 1] << 8 & 65280) + (uint82[i2 + 2] & 255);\\n output.push(tripletToBase64(tmp));\\n }\\n return output.join(\\\"\\\");\\n }\\n function fromByteArray(uint82) {\\n var tmp;\\n var len2 = uint82.length;\\n var extraBytes = len2 % 3;\\n var parts = [];\\n var maxChunkLength = 16383;\\n for (var i2 = 0, len22 = len2 - extraBytes; i2 < len22; i2 += maxChunkLength) {\\n parts.push(encodeChunk(uint82, i2, i2 + maxChunkLength > len22 ? len22 : i2 + maxChunkLength));\\n }\\n if (extraBytes === 1) {\\n tmp = uint82[len2 - 1];\\n parts.push(\\n lookup[tmp >> 2] + lookup[tmp << 4 & 63] + \\\"==\\\"\\n );\\n } else if (extraBytes === 2) {\\n tmp = (uint82[len2 - 2] << 8) + uint82[len2 - 1];\\n parts.push(\\n lookup[tmp >> 10] + lookup[tmp >> 4 & 63] + lookup[tmp << 2 & 63] + \\\"=\\\"\\n );\\n }\\n return parts.join(\\\"\\\");\\n }\\n }\\n });\\n\\n // ../../node_modules/.pnpm/tiny-inflate@1.0.3/node_modules/tiny-inflate/index.js\\n var require_tiny_inflate = __commonJS({\\n \\\"../../node_modules/.pnpm/tiny-inflate@1.0.3/node_modules/tiny-inflate/index.js\\\"(exports, module) {\\n var TINF_OK = 0;\\n var TINF_DATA_ERROR = -3;\\n function Tree() {\\n this.table = new Uint16Array(16);\\n this.trans = new Uint16Array(288);\\n }\\n function Data(source, dest) {\\n this.source = source;\\n this.sourceIndex = 0;\\n this.tag = 0;\\n this.bitcount = 0;\\n this.dest = dest;\\n this.destLen = 0;\\n this.ltree = new Tree();\\n this.dtree = new Tree();\\n }\\n var sltree = new Tree();\\n var sdtree = new Tree();\\n var length_bits = new Uint8Array(30);\\n var length_base = new Uint16Array(30);\\n var dist_bits = new Uint8Array(30);\\n var dist_base = new Uint16Array(30);\\n var clcidx = new Uint8Array([\\n 16,\\n 17,\\n 18,\\n 0,\\n 8,\\n 7,\\n 9,\\n 6,\\n 10,\\n 5,\\n 11,\\n 4,\\n 12,\\n 3,\\n 13,\\n 2,\\n 14,\\n 1,\\n 15\\n ]);\\n var code_tree = new Tree();\\n var lengths = new Uint8Array(288 + 32);\\n function tinf_build_bits_base(bits, base, delta, first) {\\n var i, sum;\\n for (i = 0; i < delta; ++i) bits[i] = 0;\\n for (i = 0; i < 30 - delta; ++i) bits[i + delta] = i / delta | 0;\\n for (sum = first, i = 0; i < 30; ++i) {\\n base[i] = sum;\\n sum += 1 << bits[i];\\n }\\n }\\n function tinf_build_fixed_trees(lt, dt) {\\n var i;\\n for (i = 0; i < 7; ++i) lt.table[i] = 0;\\n lt.table[7] = 24;\\n lt.table[8] = 152;\\n lt.table[9] = 112;\\n for (i = 0; i < 24; ++i) lt.trans[i] = 256 + i;\\n for (i = 0; i < 144; ++i) lt.trans[24 + i] = i;\\n for (i = 0; i < 8; ++i) lt.trans[24 + 144 + i] = 280 + i;\\n for (i = 0; i < 112; ++i) lt.trans[24 + 144 + 8 + i] = 144 + i;\\n for (i = 0; i < 5; ++i) dt.table[i] = 0;\\n dt.table[5] = 32;\\n for (i = 0; i < 32; ++i) dt.trans[i] = i;\\n }\\n var offs = new Uint16Array(16);\\n function tinf_build_tree(t, lengths2, off, num) {\\n var i, sum;\\n for (i = 0; i < 16; ++i) t.table[i] = 0;\\n for (i = 0; i < num; ++i) t.table[lengths2[off + i]]++;\\n t.table[0] = 0;\\n for (sum = 0, i = 0; i < 16; ++i) {\\n offs[i] = sum;\\n sum += t.table[i];\\n }\\n for (i = 0; i < num; ++i) {\\n if (lengths2[off + i]) t.trans[offs[lengths2[off + i]]++] = i;\\n }\\n }\\n function tinf_getbit(d) {\\n if (!d.bitcount--) {\\n d.tag = d.source[d.sourceIndex++];\\n d.bitcount = 7;\\n }\\n var bit = d.tag & 1;\\n d.tag >>>= 1;\\n return bit;\\n }\\n function tinf_read_bits(d, num, base) {\\n if (!num)\\n return base;\\n while (d.bitcount < 24) {\\n d.tag |= d.source[d.sourceIndex++] << d.bitcount;\\n d.bitcount += 8;\\n }\\n var val = d.tag & 65535 >>> 16 - num;\\n d.tag >>>= num;\\n d.bitcount -= num;\\n return val + base;\\n }\\n function tinf_decode_symbol(d, t) {\\n while (d.bitcount < 24) {\\n d.tag |= d.source[d.sourceIndex++] << d.bitcount;\\n d.bitcount += 8;\\n }\\n var sum = 0, cur = 0, len = 0;\\n var tag = d.tag;\\n do {\\n cur = 2 * cur + (tag & 1);\\n tag >>>= 1;\\n ++len;\\n sum += t.table[len];\\n cur -= t.table[len];\\n } while (cur >= 0);\\n d.tag = tag;\\n d.bitcount -= len;\\n return t.trans[sum + cur];\\n }\\n function tinf_decode_trees(d, lt, dt) {\\n var hlit, hdist, hclen;\\n var i, num, length;\\n hlit = tinf_read_bits(d, 5, 257);\\n hdist = tinf_read_bits(d, 5, 1);\\n hclen = tinf_read_bits(d, 4, 4);\\n for (i = 0; i < 19; ++i) lengths[i] = 0;\\n for (i = 0; i < hclen; ++i) {\\n var clen = tinf_read_bits(d, 3, 0);\\n lengths[clcidx[i]] = clen;\\n }\\n tinf_build_tree(code_tree, lengths, 0, 19);\\n for (num = 0; num < hlit + hdist; ) {\\n var sym = tinf_decode_symbol(d, code_tree);\\n switch (sym) {\\n case 16:\\n var prev = lengths[num - 1];\\n for (length = tinf_read_bits(d, 2, 3); length; --length) {\\n lengths[num++] = prev;\\n }\\n break;\\n case 17:\\n for (length = tinf_read_bits(d, 3, 3); length; --length) {\\n lengths[num++] = 0;\\n }\\n break;\\n case 18:\\n for (length = tinf_read_bits(d, 7, 11); length; --length) {\\n lengths[num++] = 0;\\n }\\n break;\\n default:\\n lengths[num++] = sym;\\n break;\\n }\\n }\\n tinf_build_tree(lt, lengths, 0, hlit);\\n tinf_build_tree(dt, lengths, hlit, hdist);\\n }\\n function tinf_inflate_block_data(d, lt, dt) {\\n while (1) {\\n var sym = tinf_decode_symbol(d, lt);\\n if (sym === 256) {\\n return TINF_OK;\\n }\\n if (sym < 256) {\\n d.dest[d.destLen++] = sym;\\n } else {\\n var length, dist, offs2;\\n var i;\\n sym -= 257;\\n length = tinf_read_bits(d, length_bits[sym], length_base[sym]);\\n dist = tinf_decode_symbol(d, dt);\\n offs2 = d.destLen - tinf_read_bits(d, dist_bits[dist], dist_base[dist]);\\n for (i = offs2; i < offs2 + length; ++i) {\\n d.dest[d.destLen++] = d.dest[i];\\n }\\n }\\n }\\n }\\n function tinf_inflate_uncompressed_block(d) {\\n var length, invlength;\\n var i;\\n while (d.bitcount > 8) {\\n d.sourceIndex--;\\n d.bitcount -= 8;\\n }\\n length = d.source[d.sourceIndex + 1];\\n length = 256 * length + d.source[d.sourceIndex];\\n invlength = d.source[d.sourceIndex + 3];\\n invlength = 256 * invlength + d.source[d.sourceIndex + 2];\\n if (length !== (~invlength & 65535))\\n return TINF_DATA_ERROR;\\n d.sourceIndex += 4;\\n for (i = length; i; --i)\\n d.dest[d.destLen++] = d.source[d.sourceIndex++];\\n d.bitcount = 0;\\n return TINF_OK;\\n }\\n function tinf_uncompress(source, dest) {\\n var d = new Data(source, dest);\\n var bfinal, btype, res;\\n do {\\n bfinal = tinf_getbit(d);\\n btype = tinf_read_bits(d, 2, 0);\\n switch (btype) {\\n case 0:\\n res = tinf_inflate_uncompressed_block(d);\\n break;\\n case 1:\\n res = tinf_inflate_block_data(d, sltree, sdtree);\\n break;\\n case 2:\\n tinf_decode_trees(d, d.ltree, d.dtree);\\n res = tinf_inflate_block_data(d, d.ltree, d.dtree);\\n break;\\n default:\\n res = TINF_DATA_ERROR;\\n }\\n if (res !== TINF_OK)\\n throw new Error(\\\"Data error\\\");\\n } while (!bfinal);\\n if (d.destLen < d.dest.length) {\\n if (typeof d.dest.slice === \\\"function\\\")\\n return d.dest.slice(0, d.destLen);\\n else\\n return d.dest.subarray(0, d.destLen);\\n }\\n return d.dest;\\n }\\n tinf_build_fixed_trees(sltree, sdtree);\\n tinf_build_bits_base(length_bits, length_base, 4, 3);\\n tinf_build_bits_base(dist_bits, dist_base, 2, 1);\\n length_bits[28] = 0;\\n length_base[28] = 258;\\n module.exports = tinf_uncompress;\\n }\\n });\\n\\n // ../../node_modules/.pnpm/unicode-trie@2.0.0/node_modules/unicode-trie/swap.js\\n var require_swap = __commonJS({\\n \\\"../../node_modules/.pnpm/unicode-trie@2.0.0/node_modules/unicode-trie/swap.js\\\"(exports, module) {\\n var isBigEndian2 = new Uint8Array(new Uint32Array([305419896]).buffer)[0] === 18;\\n var swap = (b, n, m) => {\\n let i = b[n];\\n b[n] = b[m];\\n b[m] = i;\\n };\\n var swap32 = (array) => {\\n const len = array.length;\\n for (let i = 0; i < len; i += 4) {\\n swap(array, i, i + 3);\\n swap(array, i + 1, i + 2);\\n }\\n };\\n var swap32LE = (array) => {\\n if (isBigEndian2) {\\n swap32(array);\\n }\\n };\\n module.exports = {\\n swap32LE\\n };\\n }\\n });\\n\\n // ../../node_modules/.pnpm/unicode-trie@2.0.0/node_modules/unicode-trie/index.js\\n var require_unicode_trie = __commonJS({\\n \\\"../../node_modules/.pnpm/unicode-trie@2.0.0/node_modules/unicode-trie/index.js\\\"(exports, module) {\\n var inflate = require_tiny_inflate();\\n var { swap32LE } = require_swap();\\n var SHIFT_1 = 6 + 5;\\n var SHIFT_2 = 5;\\n var SHIFT_1_2 = SHIFT_1 - SHIFT_2;\\n var OMITTED_BMP_INDEX_1_LENGTH = 65536 >> SHIFT_1;\\n var INDEX_2_BLOCK_LENGTH = 1 << SHIFT_1_2;\\n var INDEX_2_MASK = INDEX_2_BLOCK_LENGTH - 1;\\n var INDEX_SHIFT = 2;\\n var DATA_BLOCK_LENGTH = 1 << SHIFT_2;\\n var DATA_MASK = DATA_BLOCK_LENGTH - 1;\\n var LSCP_INDEX_2_OFFSET = 65536 >> SHIFT_2;\\n var LSCP_INDEX_2_LENGTH = 1024 >> SHIFT_2;\\n var INDEX_2_BMP_LENGTH = LSCP_INDEX_2_OFFSET + LSCP_INDEX_2_LENGTH;\\n var UTF8_2B_INDEX_2_OFFSET = INDEX_2_BMP_LENGTH;\\n var UTF8_2B_INDEX_2_LENGTH = 2048 >> 6;\\n var INDEX_1_OFFSET = UTF8_2B_INDEX_2_OFFSET + UTF8_2B_INDEX_2_LENGTH;\\n var DATA_GRANULARITY = 1 << INDEX_SHIFT;\\n var UnicodeTrie = class {\\n constructor(data) {\\n const isBuffer = typeof data.readUInt32BE === \\\"function\\\" && typeof data.slice === \\\"function\\\";\\n if (isBuffer || data instanceof Uint8Array) {\\n let uncompressedLength;\\n if (isBuffer) {\\n this.highStart = data.readUInt32LE(0);\\n this.errorValue = data.readUInt32LE(4);\\n uncompressedLength = data.readUInt32LE(8);\\n data = data.slice(12);\\n } else {\\n const view = new DataView(data.buffer);\\n this.highStart = view.getUint32(0, true);\\n this.errorValue = view.getUint32(4, true);\\n uncompressedLength = view.getUint32(8, true);\\n data = data.subarray(12);\\n }\\n data = inflate(data, new Uint8Array(uncompressedLength));\\n data = inflate(data, new Uint8Array(uncompressedLength));\\n swap32LE(data);\\n this.data = new Uint32Array(data.buffer);\\n } else {\\n ({ data: this.data, highStart: this.highStart, errorValue: this.errorValue } = data);\\n }\\n }\\n get(codePoint) {\\n let index;\\n if (codePoint < 0 || codePoint > 1114111) {\\n return this.errorValue;\\n }\\n if (codePoint < 55296 || codePoint > 56319 && codePoint <= 65535) {\\n index = (this.data[codePoint >> SHIFT_2] << INDEX_SHIFT) + (codePoint & DATA_MASK);\\n return this.data[index];\\n }\\n if (codePoint <= 65535) {\\n index = (this.data[LSCP_INDEX_2_OFFSET + (codePoint - 55296 >> SHIFT_2)] << INDEX_SHIFT) + (codePoint & DATA_MASK);\\n return this.data[index];\\n }\\n if (codePoint < this.highStart) {\\n index = this.data[INDEX_1_OFFSET - OMITTED_BMP_INDEX_1_LENGTH + (codePoint >> SHIFT_1)];\\n index = this.data[index + (codePoint >> SHIFT_2 & INDEX_2_MASK)];\\n index = (index << INDEX_SHIFT) + (codePoint & DATA_MASK);\\n return this.data[index];\\n }\\n return this.data[this.data.length - DATA_GRANULARITY];\\n }\\n };\\n module.exports = UnicodeTrie;\\n }\\n });\\n\\n // ../../node_modules/.pnpm/unicode-properties@1.4.1/node_modules/unicode-properties/dist/module.mjs\\n function $parcel$interopDefault(a) {\\n return a && a.__esModule ? a.default : a;\\n }\\n function $747425b437e121da$export$410364bbb673ddbc(codePoint) {\\n const val = $747425b437e121da$var$trie.get(codePoint);\\n return (0, /* @__PURE__ */ $parcel$interopDefault($f4087201da764553$exports)).categories[val >> $747425b437e121da$var$CATEGORY_SHIFT & $747425b437e121da$var$CATEGORY_MASK];\\n }\\n function $747425b437e121da$export$c03b919c6651ed55(codePoint) {\\n const val = $747425b437e121da$var$trie.get(codePoint);\\n return (0, /* @__PURE__ */ $parcel$interopDefault($f4087201da764553$exports)).combiningClasses[val >> $747425b437e121da$var$COMBINING_SHIFT & $747425b437e121da$var$COMBINING_MASK];\\n }\\n function $747425b437e121da$export$941569448d136665(codePoint) {\\n const val = $747425b437e121da$var$trie.get(codePoint);\\n return (0, /* @__PURE__ */ $parcel$interopDefault($f4087201da764553$exports)).scripts[val >> $747425b437e121da$var$SCRIPT_SHIFT & $747425b437e121da$var$SCRIPT_MASK];\\n }\\n function $747425b437e121da$export$727d9dbc4fbb948f(codePoint) {\\n return $747425b437e121da$export$410364bbb673ddbc(codePoint) === \\\"Nd\\\";\\n }\\n function $747425b437e121da$export$e33ad6871e762338(codePoint) {\\n const category = $747425b437e121da$export$410364bbb673ddbc(codePoint);\\n return category === \\\"Mn\\\" || category === \\\"Me\\\" || category === \\\"Mc\\\";\\n }\\n var import_base64_js, import_unicode_trie, $f4087201da764553$exports, $747425b437e121da$var$trie, $747425b437e121da$var$log2, $747425b437e121da$var$bits, $747425b437e121da$var$CATEGORY_BITS, $747425b437e121da$var$COMBINING_BITS, $747425b437e121da$var$SCRIPT_BITS, $747425b437e121da$var$EAW_BITS, $747425b437e121da$var$NUMBER_BITS, $747425b437e121da$var$CATEGORY_SHIFT, $747425b437e121da$var$COMBINING_SHIFT, $747425b437e121da$var$SCRIPT_SHIFT, $747425b437e121da$var$CATEGORY_MASK, $747425b437e121da$var$COMBINING_MASK, $747425b437e121da$var$SCRIPT_MASK, $747425b437e121da$var$EAW_MASK, $747425b437e121da$var$NUMBER_MASK;\\n var init_module = __esm({\\n \\\"../../node_modules/.pnpm/unicode-properties@1.4.1/node_modules/unicode-properties/dist/module.mjs\\\"() {\\n import_base64_js = __toESM(require_base64_js(), 1);\\n import_unicode_trie = __toESM(require_unicode_trie(), 1);\\n $f4087201da764553$exports = {};\\n $f4087201da764553$exports = JSON.parse('{\\\"categories\\\":[\\\"Cc\\\",\\\"Zs\\\",\\\"Po\\\",\\\"Sc\\\",\\\"Ps\\\",\\\"Pe\\\",\\\"Sm\\\",\\\"Pd\\\",\\\"Nd\\\",\\\"Lu\\\",\\\"Sk\\\",\\\"Pc\\\",\\\"Ll\\\",\\\"So\\\",\\\"Lo\\\",\\\"Pi\\\",\\\"Cf\\\",\\\"No\\\",\\\"Pf\\\",\\\"Lt\\\",\\\"Lm\\\",\\\"Mn\\\",\\\"Me\\\",\\\"Mc\\\",\\\"Nl\\\",\\\"Zl\\\",\\\"Zp\\\",\\\"Cs\\\",\\\"Co\\\"],\\\"combiningClasses\\\":[\\\"Not_Reordered\\\",\\\"Above\\\",\\\"Above_Right\\\",\\\"Below\\\",\\\"Attached_Above_Right\\\",\\\"Attached_Below\\\",\\\"Overlay\\\",\\\"Iota_Subscript\\\",\\\"Double_Below\\\",\\\"Double_Above\\\",\\\"Below_Right\\\",\\\"Above_Left\\\",\\\"CCC10\\\",\\\"CCC11\\\",\\\"CCC12\\\",\\\"CCC13\\\",\\\"CCC14\\\",\\\"CCC15\\\",\\\"CCC16\\\",\\\"CCC17\\\",\\\"CCC18\\\",\\\"CCC19\\\",\\\"CCC20\\\",\\\"CCC21\\\",\\\"CCC22\\\",\\\"CCC23\\\",\\\"CCC24\\\",\\\"CCC25\\\",\\\"CCC30\\\",\\\"CCC31\\\",\\\"CCC32\\\",\\\"CCC27\\\",\\\"CCC28\\\",\\\"CCC29\\\",\\\"CCC33\\\",\\\"CCC34\\\",\\\"CCC35\\\",\\\"CCC36\\\",\\\"Nukta\\\",\\\"Virama\\\",\\\"CCC84\\\",\\\"CCC91\\\",\\\"CCC103\\\",\\\"CCC107\\\",\\\"CCC118\\\",\\\"CCC122\\\",\\\"CCC129\\\",\\\"CCC130\\\",\\\"CCC132\\\",\\\"Attached_Above\\\",\\\"Below_Left\\\",\\\"Left\\\",\\\"Kana_Voicing\\\",\\\"CCC26\\\",\\\"Right\\\"],\\\"scripts\\\":[\\\"Common\\\",\\\"Latin\\\",\\\"Bopomofo\\\",\\\"Inherited\\\",\\\"Greek\\\",\\\"Coptic\\\",\\\"Cyrillic\\\",\\\"Armenian\\\",\\\"Hebrew\\\",\\\"Arabic\\\",\\\"Syriac\\\",\\\"Thaana\\\",\\\"Nko\\\",\\\"Samaritan\\\",\\\"Mandaic\\\",\\\"Devanagari\\\",\\\"Bengali\\\",\\\"Gurmukhi\\\",\\\"Gujarati\\\",\\\"Oriya\\\",\\\"Tamil\\\",\\\"Telugu\\\",\\\"Kannada\\\",\\\"Malayalam\\\",\\\"Sinhala\\\",\\\"Thai\\\",\\\"Lao\\\",\\\"Tibetan\\\",\\\"Myanmar\\\",\\\"Georgian\\\",\\\"Hangul\\\",\\\"Ethiopic\\\",\\\"Cherokee\\\",\\\"Canadian_Aboriginal\\\",\\\"Ogham\\\",\\\"Runic\\\",\\\"Tagalog\\\",\\\"Hanunoo\\\",\\\"Buhid\\\",\\\"Tagbanwa\\\",\\\"Khmer\\\",\\\"Mongolian\\\",\\\"Limbu\\\",\\\"Tai_Le\\\",\\\"New_Tai_Lue\\\",\\\"Buginese\\\",\\\"Tai_Tham\\\",\\\"Balinese\\\",\\\"Sundanese\\\",\\\"Batak\\\",\\\"Lepcha\\\",\\\"Ol_Chiki\\\",\\\"Braille\\\",\\\"Glagolitic\\\",\\\"Tifinagh\\\",\\\"Han\\\",\\\"Hiragana\\\",\\\"Katakana\\\",\\\"Yi\\\",\\\"Lisu\\\",\\\"Vai\\\",\\\"Bamum\\\",\\\"Syloti_Nagri\\\",\\\"Phags_Pa\\\",\\\"Saurashtra\\\",\\\"Kayah_Li\\\",\\\"Rejang\\\",\\\"Javanese\\\",\\\"Cham\\\",\\\"Tai_Viet\\\",\\\"Meetei_Mayek\\\",\\\"null\\\",\\\"Linear_B\\\",\\\"Lycian\\\",\\\"Carian\\\",\\\"Old_Italic\\\",\\\"Gothic\\\",\\\"Old_Permic\\\",\\\"Ugaritic\\\",\\\"Old_Persian\\\",\\\"Deseret\\\",\\\"Shavian\\\",\\\"Osmanya\\\",\\\"Osage\\\",\\\"Elbasan\\\",\\\"Caucasian_Albanian\\\",\\\"Linear_A\\\",\\\"Cypriot\\\",\\\"Imperial_Aramaic\\\",\\\"Palmyrene\\\",\\\"Nabataean\\\",\\\"Hatran\\\",\\\"Phoenician\\\",\\\"Lydian\\\",\\\"Meroitic_Hieroglyphs\\\",\\\"Meroitic_Cursive\\\",\\\"Kharoshthi\\\",\\\"Old_South_Arabian\\\",\\\"Old_North_Arabian\\\",\\\"Manichaean\\\",\\\"Avestan\\\",\\\"Inscriptional_Parthian\\\",\\\"Inscriptional_Pahlavi\\\",\\\"Psalter_Pahlavi\\\",\\\"Old_Turkic\\\",\\\"Old_Hungarian\\\",\\\"Hanifi_Rohingya\\\",\\\"Old_Sogdian\\\",\\\"Sogdian\\\",\\\"Elymaic\\\",\\\"Brahmi\\\",\\\"Kaithi\\\",\\\"Sora_Sompeng\\\",\\\"Chakma\\\",\\\"Mahajani\\\",\\\"Sharada\\\",\\\"Khojki\\\",\\\"Multani\\\",\\\"Khudawadi\\\",\\\"Grantha\\\",\\\"Newa\\\",\\\"Tirhuta\\\",\\\"Siddham\\\",\\\"Modi\\\",\\\"Takri\\\",\\\"Ahom\\\",\\\"Dogra\\\",\\\"Warang_Citi\\\",\\\"Nandinagari\\\",\\\"Zanabazar_Square\\\",\\\"Soyombo\\\",\\\"Pau_Cin_Hau\\\",\\\"Bhaiksuki\\\",\\\"Marchen\\\",\\\"Masaram_Gondi\\\",\\\"Gunjala_Gondi\\\",\\\"Makasar\\\",\\\"Cuneiform\\\",\\\"Egyptian_Hieroglyphs\\\",\\\"Anatolian_Hieroglyphs\\\",\\\"Mro\\\",\\\"Bassa_Vah\\\",\\\"Pahawh_Hmong\\\",\\\"Medefaidrin\\\",\\\"Miao\\\",\\\"Tangut\\\",\\\"Nushu\\\",\\\"Duployan\\\",\\\"SignWriting\\\",\\\"Nyiakeng_Puachue_Hmong\\\",\\\"Wancho\\\",\\\"Mende_Kikakui\\\",\\\"Adlam\\\"],\\\"eaw\\\":[\\\"N\\\",\\\"Na\\\",\\\"A\\\",\\\"W\\\",\\\"H\\\",\\\"F\\\"]}');\\n $747425b437e121da$var$trie = new (0, import_unicode_trie.default)((0, import_base64_js.default).toByteArray(\\\"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\\\"));\\n $747425b437e121da$var$log2 = Math.log2 || ((n) => Math.log(n) / Math.LN2);\\n $747425b437e121da$var$bits = (n) => $747425b437e121da$var$log2(n) + 1 | 0;\\n $747425b437e121da$var$CATEGORY_BITS = $747425b437e121da$var$bits((0, /* @__PURE__ */ $parcel$interopDefault($f4087201da764553$exports)).categories.length - 1);\\n $747425b437e121da$var$COMBINING_BITS = $747425b437e121da$var$bits((0, /* @__PURE__ */ $parcel$interopDefault($f4087201da764553$exports)).combiningClasses.length - 1);\\n $747425b437e121da$var$SCRIPT_BITS = $747425b437e121da$var$bits((0, /* @__PURE__ */ $parcel$interopDefault($f4087201da764553$exports)).scripts.length - 1);\\n $747425b437e121da$var$EAW_BITS = $747425b437e121da$var$bits((0, /* @__PURE__ */ $parcel$interopDefault($f4087201da764553$exports)).eaw.length - 1);\\n $747425b437e121da$var$NUMBER_BITS = 10;\\n $747425b437e121da$var$CATEGORY_SHIFT = $747425b437e121da$var$COMBINING_BITS + $747425b437e121da$var$SCRIPT_BITS + $747425b437e121da$var$EAW_BITS + $747425b437e121da$var$NUMBER_BITS;\\n $747425b437e121da$var$COMBINING_SHIFT = $747425b437e121da$var$SCRIPT_BITS + $747425b437e121da$var$EAW_BITS + $747425b437e121da$var$NUMBER_BITS;\\n $747425b437e121da$var$SCRIPT_SHIFT = $747425b437e121da$var$EAW_BITS + $747425b437e121da$var$NUMBER_BITS;\\n $747425b437e121da$var$CATEGORY_MASK = (1 << $747425b437e121da$var$CATEGORY_BITS) - 1;\\n $747425b437e121da$var$COMBINING_MASK = (1 << $747425b437e121da$var$COMBINING_BITS) - 1;\\n $747425b437e121da$var$SCRIPT_MASK = (1 << $747425b437e121da$var$SCRIPT_BITS) - 1;\\n $747425b437e121da$var$EAW_MASK = (1 << $747425b437e121da$var$EAW_BITS) - 1;\\n $747425b437e121da$var$NUMBER_MASK = (1 << $747425b437e121da$var$NUMBER_BITS) - 1;\\n }\\n });\\n\\n // ../../node_modules/.pnpm/dfa@1.2.0/node_modules/dfa/index.js\\n var require_dfa = __commonJS({\\n \\\"../../node_modules/.pnpm/dfa@1.2.0/node_modules/dfa/index.js\\\"(exports, module) {\\n \\\"use strict\\\";\\n var INITIAL_STATE = 1;\\n var FAIL_STATE = 0;\\n var StateMachine = class {\\n constructor(dfa) {\\n this.stateTable = dfa.stateTable;\\n this.accepting = dfa.accepting;\\n this.tags = dfa.tags;\\n }\\n /**\\n * Returns an iterable object that yields pattern matches over the input sequence.\\n * Matches are of the form [startIndex, endIndex, tags].\\n */\\n match(str) {\\n var self2 = this;\\n return {\\n *[Symbol.iterator]() {\\n var state = INITIAL_STATE;\\n var startRun = null;\\n var lastAccepting = null;\\n var lastState = null;\\n for (var p = 0; p < str.length; p++) {\\n var c = str[p];\\n lastState = state;\\n state = self2.stateTable[state][c];\\n if (state === FAIL_STATE) {\\n if (startRun != null && lastAccepting != null && lastAccepting >= startRun) {\\n yield [startRun, lastAccepting, self2.tags[lastState]];\\n }\\n state = self2.stateTable[INITIAL_STATE][c];\\n startRun = null;\\n }\\n if (state !== FAIL_STATE && startRun == null) {\\n startRun = p;\\n }\\n if (self2.accepting[state]) {\\n lastAccepting = p;\\n }\\n if (state === FAIL_STATE) {\\n state = INITIAL_STATE;\\n }\\n }\\n if (startRun != null && lastAccepting != null && lastAccepting >= startRun) {\\n yield [startRun, lastAccepting, self2.tags[state]];\\n }\\n }\\n };\\n }\\n /**\\n * For each match over the input sequence, action functions matching\\n * the tag definitions in the input pattern are called with the startIndex,\\n * endIndex, and sub-match sequence.\\n */\\n apply(str, actions) {\\n for (var [start, end, tags] of this.match(str)) {\\n for (var tag of tags) {\\n if (typeof actions[tag] === \\\"function\\\") {\\n actions[tag](start, end, str.slice(start, end + 1));\\n }\\n }\\n }\\n }\\n };\\n module.exports = StateMachine;\\n }\\n });\\n\\n // ../../node_modules/.pnpm/clone@2.1.2/node_modules/clone/clone.js\\n var require_clone = __commonJS({\\n \\\"../../node_modules/.pnpm/clone@2.1.2/node_modules/clone/clone.js\\\"(exports, module) {\\n var clone = function() {\\n \\\"use strict\\\";\\n function _instanceof(obj, type) {\\n return type != null && obj instanceof type;\\n }\\n var nativeMap;\\n try {\\n nativeMap = Map;\\n } catch (_) {\\n nativeMap = function() {\\n };\\n }\\n var nativeSet;\\n try {\\n nativeSet = Set;\\n } catch (_) {\\n nativeSet = function() {\\n };\\n }\\n var nativePromise;\\n try {\\n nativePromise = Promise;\\n } catch (_) {\\n nativePromise = function() {\\n };\\n }\\n function clone2(parent, circular, depth, prototype, includeNonEnumerable) {\\n if (typeof circular === \\\"object\\\") {\\n depth = circular.depth;\\n prototype = circular.prototype;\\n includeNonEnumerable = circular.includeNonEnumerable;\\n circular = circular.circular;\\n }\\n var allParents = [];\\n var allChildren = [];\\n var useBuffer = typeof Buffer != \\\"undefined\\\";\\n if (typeof circular == \\\"undefined\\\")\\n circular = true;\\n if (typeof depth == \\\"undefined\\\")\\n depth = Infinity;\\n function _clone(parent2, depth2) {\\n if (parent2 === null)\\n return null;\\n if (depth2 === 0)\\n return parent2;\\n var child;\\n var proto;\\n if (typeof parent2 != \\\"object\\\") {\\n return parent2;\\n }\\n if (_instanceof(parent2, nativeMap)) {\\n child = new nativeMap();\\n } else if (_instanceof(parent2, nativeSet)) {\\n child = new nativeSet();\\n } else if (_instanceof(parent2, nativePromise)) {\\n child = new nativePromise(function(resolve, reject) {\\n parent2.then(function(value) {\\n resolve(_clone(value, depth2 - 1));\\n }, function(err) {\\n reject(_clone(err, depth2 - 1));\\n });\\n });\\n } else if (clone2.__isArray(parent2)) {\\n child = [];\\n } else if (clone2.__isRegExp(parent2)) {\\n child = new RegExp(parent2.source, __getRegExpFlags(parent2));\\n if (parent2.lastIndex) child.lastIndex = parent2.lastIndex;\\n } else if (clone2.__isDate(parent2)) {\\n child = new Date(parent2.getTime());\\n } else if (useBuffer && Buffer.isBuffer(parent2)) {\\n if (Buffer.allocUnsafe) {\\n child = Buffer.allocUnsafe(parent2.length);\\n } else {\\n child = new Buffer(parent2.length);\\n }\\n parent2.copy(child);\\n return child;\\n } else if (_instanceof(parent2, Error)) {\\n child = Object.create(parent2);\\n } else {\\n if (typeof prototype == \\\"undefined\\\") {\\n proto = Object.getPrototypeOf(parent2);\\n child = Object.create(proto);\\n } else {\\n child = Object.create(prototype);\\n proto = prototype;\\n }\\n }\\n if (circular) {\\n var index = allParents.indexOf(parent2);\\n if (index != -1) {\\n return allChildren[index];\\n }\\n allParents.push(parent2);\\n allChildren.push(child);\\n }\\n if (_instanceof(parent2, nativeMap)) {\\n parent2.forEach(function(value, key) {\\n var keyChild = _clone(key, depth2 - 1);\\n var valueChild = _clone(value, depth2 - 1);\\n child.set(keyChild, valueChild);\\n });\\n }\\n if (_instanceof(parent2, nativeSet)) {\\n parent2.forEach(function(value) {\\n var entryChild = _clone(value, depth2 - 1);\\n child.add(entryChild);\\n });\\n }\\n for (var i in parent2) {\\n var attrs;\\n if (proto) {\\n attrs = Object.getOwnPropertyDescriptor(proto, i);\\n }\\n if (attrs && attrs.set == null) {\\n continue;\\n }\\n child[i] = _clone(parent2[i], depth2 - 1);\\n }\\n if (Object.getOwnPropertySymbols) {\\n var symbols = Object.getOwnPropertySymbols(parent2);\\n for (var i = 0; i < symbols.length; i++) {\\n var symbol = symbols[i];\\n var descriptor = Object.getOwnPropertyDescriptor(parent2, symbol);\\n if (descriptor && !descriptor.enumerable && !includeNonEnumerable) {\\n continue;\\n }\\n child[symbol] = _clone(parent2[symbol], depth2 - 1);\\n if (!descriptor.enumerable) {\\n Object.defineProperty(child, symbol, {\\n enumerable: false\\n });\\n }\\n }\\n }\\n if (includeNonEnumerable) {\\n var allPropertyNames = Object.getOwnPropertyNames(parent2);\\n for (var i = 0; i < allPropertyNames.length; i++) {\\n var propertyName = allPropertyNames[i];\\n var descriptor = Object.getOwnPropertyDescriptor(parent2, propertyName);\\n if (descriptor && descriptor.enumerable) {\\n continue;\\n }\\n child[propertyName] = _clone(parent2[propertyName], depth2 - 1);\\n Object.defineProperty(child, propertyName, {\\n enumerable: false\\n });\\n }\\n }\\n return child;\\n }\\n return _clone(parent, depth);\\n }\\n clone2.clonePrototype = function clonePrototype(parent) {\\n if (parent === null)\\n return null;\\n var c = function() {\\n };\\n c.prototype = parent;\\n return new c();\\n };\\n function __objToStr(o) {\\n return Object.prototype.toString.call(o);\\n }\\n clone2.__objToStr = __objToStr;\\n function __isDate(o) {\\n return typeof o === \\\"object\\\" && __objToStr(o) === \\\"[object Date]\\\";\\n }\\n clone2.__isDate = __isDate;\\n function __isArray(o) {\\n return typeof o === \\\"object\\\" && __objToStr(o) === \\\"[object Array]\\\";\\n }\\n clone2.__isArray = __isArray;\\n function __isRegExp(o) {\\n return typeof o === \\\"object\\\" && __objToStr(o) === \\\"[object RegExp]\\\";\\n }\\n clone2.__isRegExp = __isRegExp;\\n function __getRegExpFlags(re) {\\n var flags = \\\"\\\";\\n if (re.global) flags += \\\"g\\\";\\n if (re.ignoreCase) flags += \\\"i\\\";\\n if (re.multiline) flags += \\\"m\\\";\\n return flags;\\n }\\n clone2.__getRegExpFlags = __getRegExpFlags;\\n return clone2;\\n }();\\n if (typeof module === \\\"object\\\" && module.exports) {\\n module.exports = clone;\\n }\\n }\\n });\\n\\n // ../../node_modules/.pnpm/brotli@1.3.3/node_modules/brotli/dec/streams.js\\n var require_streams = __commonJS({\\n \\\"../../node_modules/.pnpm/brotli@1.3.3/node_modules/brotli/dec/streams.js\\\"(exports) {\\n function BrotliInput(buffer) {\\n this.buffer = buffer;\\n this.pos = 0;\\n }\\n BrotliInput.prototype.read = function(buf, i, count) {\\n if (this.pos + count > this.buffer.length) {\\n count = this.buffer.length - this.pos;\\n }\\n for (var p = 0; p < count; p++)\\n buf[i + p] = this.buffer[this.pos + p];\\n this.pos += count;\\n return count;\\n };\\n exports.BrotliInput = BrotliInput;\\n function BrotliOutput(buf) {\\n this.buffer = buf;\\n this.pos = 0;\\n }\\n BrotliOutput.prototype.write = function(buf, count) {\\n if (this.pos + count > this.buffer.length)\\n throw new Error(\\\"Output buffer is not large enough\\\");\\n this.buffer.set(buf.subarray(0, count), this.pos);\\n this.pos += count;\\n return count;\\n };\\n exports.BrotliOutput = BrotliOutput;\\n }\\n });\\n\\n // ../../node_modules/.pnpm/brotli@1.3.3/node_modules/brotli/dec/bit_reader.js\\n var require_bit_reader = __commonJS({\\n \\\"../../node_modules/.pnpm/brotli@1.3.3/node_modules/brotli/dec/bit_reader.js\\\"(exports, module) {\\n var BROTLI_READ_SIZE = 4096;\\n var BROTLI_IBUF_SIZE = 2 * BROTLI_READ_SIZE + 32;\\n var BROTLI_IBUF_MASK = 2 * BROTLI_READ_SIZE - 1;\\n var kBitMask = new Uint32Array([\\n 0,\\n 1,\\n 3,\\n 7,\\n 15,\\n 31,\\n 63,\\n 127,\\n 255,\\n 511,\\n 1023,\\n 2047,\\n 4095,\\n 8191,\\n 16383,\\n 32767,\\n 65535,\\n 131071,\\n 262143,\\n 524287,\\n 1048575,\\n 2097151,\\n 4194303,\\n 8388607,\\n 16777215\\n ]);\\n function BrotliBitReader(input) {\\n this.buf_ = new Uint8Array(BROTLI_IBUF_SIZE);\\n this.input_ = input;\\n this.reset();\\n }\\n BrotliBitReader.READ_SIZE = BROTLI_READ_SIZE;\\n BrotliBitReader.IBUF_MASK = BROTLI_IBUF_MASK;\\n BrotliBitReader.prototype.reset = function() {\\n this.buf_ptr_ = 0;\\n this.val_ = 0;\\n this.pos_ = 0;\\n this.bit_pos_ = 0;\\n this.bit_end_pos_ = 0;\\n this.eos_ = 0;\\n this.readMoreInput();\\n for (var i = 0; i < 4; i++) {\\n this.val_ |= this.buf_[this.pos_] << 8 * i;\\n ++this.pos_;\\n }\\n return this.bit_end_pos_ > 0;\\n };\\n BrotliBitReader.prototype.readMoreInput = function() {\\n if (this.bit_end_pos_ > 256) {\\n return;\\n } else if (this.eos_) {\\n if (this.bit_pos_ > this.bit_end_pos_)\\n throw new Error(\\\"Unexpected end of input \\\" + this.bit_pos_ + \\\" \\\" + this.bit_end_pos_);\\n } else {\\n var dst = this.buf_ptr_;\\n var bytes_read = this.input_.read(this.buf_, dst, BROTLI_READ_SIZE);\\n if (bytes_read < 0) {\\n throw new Error(\\\"Unexpected end of input\\\");\\n }\\n if (bytes_read < BROTLI_READ_SIZE) {\\n this.eos_ = 1;\\n for (var p = 0; p < 32; p++)\\n this.buf_[dst + bytes_read + p] = 0;\\n }\\n if (dst === 0) {\\n for (var p = 0; p < 32; p++)\\n this.buf_[(BROTLI_READ_SIZE << 1) + p] = this.buf_[p];\\n this.buf_ptr_ = BROTLI_READ_SIZE;\\n } else {\\n this.buf_ptr_ = 0;\\n }\\n this.bit_end_pos_ += bytes_read << 3;\\n }\\n };\\n BrotliBitReader.prototype.fillBitWindow = function() {\\n while (this.bit_pos_ >= 8) {\\n this.val_ >>>= 8;\\n this.val_ |= this.buf_[this.pos_ & BROTLI_IBUF_MASK] << 24;\\n ++this.pos_;\\n this.bit_pos_ = this.bit_pos_ - 8 >>> 0;\\n this.bit_end_pos_ = this.bit_end_pos_ - 8 >>> 0;\\n }\\n };\\n BrotliBitReader.prototype.readBits = function(n_bits) {\\n if (32 - this.bit_pos_ < n_bits) {\\n this.fillBitWindow();\\n }\\n var val = this.val_ >>> this.bit_pos_ & kBitMask[n_bits];\\n this.bit_pos_ += n_bits;\\n return val;\\n };\\n module.exports = BrotliBitReader;\\n }\\n });\\n\\n // ../../node_modules/.pnpm/brotli@1.3.3/node_modules/brotli/dec/dictionary.bin.js\\n var require_dictionary_bin = __commonJS({\\n \\\"../../node_modules/.pnpm/brotli@1.3.3/node_modules/brotli/dec/dictionary.bin.js\\\"(exports, module) {\\n module.exports = \\\"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\\\";\\n }\\n });\\n\\n // ../../node_modules/.pnpm/brotli@1.3.3/node_modules/brotli/dec/dictionary-browser.js\\n var require_dictionary_browser = __commonJS({\\n \\\"../../node_modules/.pnpm/brotli@1.3.3/node_modules/brotli/dec/dictionary-browser.js\\\"(exports) {\\n var base64 = require_base64_js();\\n exports.init = function() {\\n var BrotliDecompressBuffer = require_decode().BrotliDecompressBuffer;\\n var compressed = base64.toByteArray(require_dictionary_bin());\\n return BrotliDecompressBuffer(compressed);\\n };\\n }\\n });\\n\\n // ../../node_modules/.pnpm/brotli@1.3.3/node_modules/brotli/dec/dictionary.js\\n var require_dictionary = __commonJS({\\n \\\"../../node_modules/.pnpm/brotli@1.3.3/node_modules/brotli/dec/dictionary.js\\\"(exports) {\\n var data = require_dictionary_browser();\\n exports.init = function() {\\n exports.dictionary = data.init();\\n };\\n exports.offsetsByLength = new Uint32Array([\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 4096,\\n 9216,\\n 21504,\\n 35840,\\n 44032,\\n 53248,\\n 63488,\\n 74752,\\n 87040,\\n 93696,\\n 100864,\\n 104704,\\n 106752,\\n 108928,\\n 113536,\\n 115968,\\n 118528,\\n 119872,\\n 121280,\\n 122016\\n ]);\\n exports.sizeBitsByLength = new Uint8Array([\\n 0,\\n 0,\\n 0,\\n 0,\\n 10,\\n 10,\\n 11,\\n 11,\\n 10,\\n 10,\\n 10,\\n 10,\\n 10,\\n 9,\\n 9,\\n 8,\\n 7,\\n 7,\\n 8,\\n 7,\\n 7,\\n 6,\\n 6,\\n 5,\\n 5\\n ]);\\n exports.minDictionaryWordLength = 4;\\n exports.maxDictionaryWordLength = 24;\\n }\\n });\\n\\n // ../../node_modules/.pnpm/brotli@1.3.3/node_modules/brotli/dec/huffman.js\\n var require_huffman = __commonJS({\\n \\\"../../node_modules/.pnpm/brotli@1.3.3/node_modules/brotli/dec/huffman.js\\\"(exports) {\\n function HuffmanCode(bits, value) {\\n this.bits = bits;\\n this.value = value;\\n }\\n exports.HuffmanCode = HuffmanCode;\\n var MAX_LENGTH = 15;\\n function GetNextKey(key, len) {\\n var step = 1 << len - 1;\\n while (key & step) {\\n step >>= 1;\\n }\\n return (key & step - 1) + step;\\n }\\n function ReplicateValue(table, i, step, end, code) {\\n do {\\n end -= step;\\n table[i + end] = new HuffmanCode(code.bits, code.value);\\n } while (end > 0);\\n }\\n function NextTableBitSize(count, len, root_bits) {\\n var left = 1 << len - root_bits;\\n while (len < MAX_LENGTH) {\\n left -= count[len];\\n if (left <= 0) break;\\n ++len;\\n left <<= 1;\\n }\\n return len - root_bits;\\n }\\n exports.BrotliBuildHuffmanTable = function(root_table, table, root_bits, code_lengths, code_lengths_size) {\\n var start_table = table;\\n var code;\\n var len;\\n var symbol;\\n var key;\\n var step;\\n var low;\\n var mask;\\n var table_bits;\\n var table_size;\\n var total_size;\\n var sorted;\\n var count = new Int32Array(MAX_LENGTH + 1);\\n var offset = new Int32Array(MAX_LENGTH + 1);\\n sorted = new Int32Array(code_lengths_size);\\n for (symbol = 0; symbol < code_lengths_size; symbol++) {\\n count[code_lengths[symbol]]++;\\n }\\n offset[1] = 0;\\n for (len = 1; len < MAX_LENGTH; len++) {\\n offset[len + 1] = offset[len] + count[len];\\n }\\n for (symbol = 0; symbol < code_lengths_size; symbol++) {\\n if (code_lengths[symbol] !== 0) {\\n sorted[offset[code_lengths[symbol]]++] = symbol;\\n }\\n }\\n table_bits = root_bits;\\n table_size = 1 << table_bits;\\n total_size = table_size;\\n if (offset[MAX_LENGTH] === 1) {\\n for (key = 0; key < total_size; ++key) {\\n root_table[table + key] = new HuffmanCode(0, sorted[0] & 65535);\\n }\\n return total_size;\\n }\\n key = 0;\\n symbol = 0;\\n for (len = 1, step = 2; len <= root_bits; ++len, step <<= 1) {\\n for (; count[len] > 0; --count[len]) {\\n code = new HuffmanCode(len & 255, sorted[symbol++] & 65535);\\n ReplicateValue(root_table, table + key, step, table_size, code);\\n key = GetNextKey(key, len);\\n }\\n }\\n mask = total_size - 1;\\n low = -1;\\n for (len = root_bits + 1, step = 2; len <= MAX_LENGTH; ++len, step <<= 1) {\\n for (; count[len] > 0; --count[len]) {\\n if ((key & mask) !== low) {\\n table += table_size;\\n table_bits = NextTableBitSize(count, len, root_bits);\\n table_size = 1 << table_bits;\\n total_size += table_size;\\n low = key & mask;\\n root_table[start_table + low] = new HuffmanCode(table_bits + root_bits & 255, table - start_table - low & 65535);\\n }\\n code = new HuffmanCode(len - root_bits & 255, sorted[symbol++] & 65535);\\n ReplicateValue(root_table, table + (key >> root_bits), step, table_size, code);\\n key = GetNextKey(key, len);\\n }\\n }\\n return total_size;\\n };\\n }\\n });\\n\\n // ../../node_modules/.pnpm/brotli@1.3.3/node_modules/brotli/dec/context.js\\n var require_context = __commonJS({\\n \\\"../../node_modules/.pnpm/brotli@1.3.3/node_modules/brotli/dec/context.js\\\"(exports) {\\n exports.lookup = new Uint8Array([\\n /* CONTEXT_UTF8, last byte. */\\n /* ASCII range. */\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 4,\\n 4,\\n 0,\\n 0,\\n 4,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 8,\\n 12,\\n 16,\\n 12,\\n 12,\\n 20,\\n 12,\\n 16,\\n 24,\\n 28,\\n 12,\\n 12,\\n 32,\\n 12,\\n 36,\\n 12,\\n 44,\\n 44,\\n 44,\\n 44,\\n 44,\\n 44,\\n 44,\\n 44,\\n 44,\\n 44,\\n 32,\\n 32,\\n 24,\\n 40,\\n 28,\\n 12,\\n 12,\\n 48,\\n 52,\\n 52,\\n 52,\\n 48,\\n 52,\\n 52,\\n 52,\\n 48,\\n 52,\\n 52,\\n 52,\\n 52,\\n 52,\\n 48,\\n 52,\\n 52,\\n 52,\\n 52,\\n 52,\\n 48,\\n 52,\\n 52,\\n 52,\\n 52,\\n 52,\\n 24,\\n 12,\\n 28,\\n 12,\\n 12,\\n 12,\\n 56,\\n 60,\\n 60,\\n 60,\\n 56,\\n 60,\\n 60,\\n 60,\\n 56,\\n 60,\\n 60,\\n 60,\\n 60,\\n 60,\\n 56,\\n 60,\\n 60,\\n 60,\\n 60,\\n 60,\\n 56,\\n 60,\\n 60,\\n 60,\\n 60,\\n 60,\\n 24,\\n 12,\\n 28,\\n 12,\\n 0,\\n /* UTF8 continuation byte range. */\\n 0,\\n 1,\\n 0,\\n 1,\\n 0,\\n 1,\\n 0,\\n 1,\\n 0,\\n 1,\\n 0,\\n 1,\\n 0,\\n 1,\\n 0,\\n 1,\\n 0,\\n 1,\\n 0,\\n 1,\\n 0,\\n 1,\\n 0,\\n 1,\\n 0,\\n 1,\\n 0,\\n 1,\\n 0,\\n 1,\\n 0,\\n 1,\\n 0,\\n 1,\\n 0,\\n 1,\\n 0,\\n 1,\\n 0,\\n 1,\\n 0,\\n 1,\\n 0,\\n 1,\\n 0,\\n 1,\\n 0,\\n 1,\\n 0,\\n 1,\\n 0,\\n 1,\\n 0,\\n 1,\\n 0,\\n 1,\\n 0,\\n 1,\\n 0,\\n 1,\\n 0,\\n 1,\\n 0,\\n 1,\\n /* UTF8 lead byte range. */\\n 2,\\n 3,\\n 2,\\n 3,\\n 2,\\n 3,\\n 2,\\n 3,\\n 2,\\n 3,\\n 2,\\n 3,\\n 2,\\n 3,\\n 2,\\n 3,\\n 2,\\n 3,\\n 2,\\n 3,\\n 2,\\n 3,\\n 2,\\n 3,\\n 2,\\n 3,\\n 2,\\n 3,\\n 2,\\n 3,\\n 2,\\n 3,\\n 2,\\n 3,\\n 2,\\n 3,\\n 2,\\n 3,\\n 2,\\n 3,\\n 2,\\n 3,\\n 2,\\n 3,\\n 2,\\n 3,\\n 2,\\n 3,\\n 2,\\n 3,\\n 2,\\n 3,\\n 2,\\n 3,\\n 2,\\n 3,\\n 2,\\n 3,\\n 2,\\n 3,\\n 2,\\n 3,\\n 2,\\n 3,\\n /* CONTEXT_UTF8 second last byte. */\\n /* ASCII range. */\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 1,\\n 1,\\n 1,\\n 1,\\n 1,\\n 1,\\n 1,\\n 1,\\n 1,\\n 1,\\n 1,\\n 1,\\n 1,\\n 1,\\n 1,\\n 2,\\n 2,\\n 2,\\n 2,\\n 2,\\n 2,\\n 2,\\n 2,\\n 2,\\n 2,\\n 1,\\n 1,\\n 1,\\n 1,\\n 1,\\n 1,\\n 1,\\n 2,\\n 2,\\n 2,\\n 2,\\n 2,\\n 2,\\n 2,\\n 2,\\n 2,\\n 2,\\n 2,\\n 2,\\n 2,\\n 2,\\n 2,\\n 2,\\n 2,\\n 2,\\n 2,\\n 2,\\n 2,\\n 2,\\n 2,\\n 2,\\n 2,\\n 2,\\n 1,\\n 1,\\n 1,\\n 1,\\n 1,\\n 1,\\n 3,\\n 3,\\n 3,\\n 3,\\n 3,\\n 3,\\n 3,\\n 3,\\n 3,\\n 3,\\n 3,\\n 3,\\n 3,\\n 3,\\n 3,\\n 3,\\n 3,\\n 3,\\n 3,\\n 3,\\n 3,\\n 3,\\n 3,\\n 3,\\n 3,\\n 3,\\n 1,\\n 1,\\n 1,\\n 1,\\n 0,\\n /* UTF8 continuation byte range. */\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n /* UTF8 lead byte range. */\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 2,\\n 2,\\n 2,\\n 2,\\n 2,\\n 2,\\n 2,\\n 2,\\n 2,\\n 2,\\n 2,\\n 2,\\n 2,\\n 2,\\n 2,\\n 2,\\n 2,\\n 2,\\n 2,\\n 2,\\n 2,\\n 2,\\n 2,\\n 2,\\n 2,\\n 2,\\n 2,\\n 2,\\n 2,\\n 2,\\n 2,\\n 2,\\n /* CONTEXT_SIGNED, second last byte. */\\n 0,\\n 1,\\n 1,\\n 1,\\n 1,\\n 1,\\n 1,\\n 1,\\n 1,\\n 1,\\n 1,\\n 1,\\n 1,\\n 1,\\n 1,\\n 1,\\n 2,\\n 2,\\n 2,\\n 2,\\n 2,\\n 2,\\n 2,\\n 2,\\n 2,\\n 2,\\n 2,\\n 2,\\n 2,\\n 2,\\n 2,\\n 2,\\n 2,\\n 2,\\n 2,\\n 2,\\n 2,\\n 2,\\n 2,\\n 2,\\n 2,\\n 2,\\n 2,\\n 2,\\n 2,\\n 2,\\n 2,\\n 2,\\n 2,\\n 2,\\n 2,\\n 2,\\n 2,\\n 2,\\n 2,\\n 2,\\n 2,\\n 2,\\n 2,\\n 2,\\n 2,\\n 2,\\n 2,\\n 2,\\n 3,\\n 3,\\n 3,\\n 3,\\n 3,\\n 3,\\n 3,\\n 3,\\n 3,\\n 3,\\n 3,\\n 3,\\n 3,\\n 3,\\n 3,\\n 3,\\n 3,\\n 3,\\n 3,\\n 3,\\n 3,\\n 3,\\n 3,\\n 3,\\n 3,\\n 3,\\n 3,\\n 3,\\n 3,\\n 3,\\n 3,\\n 3,\\n 3,\\n 3,\\n 3,\\n 3,\\n 3,\\n 3,\\n 3,\\n 3,\\n 3,\\n 3,\\n 3,\\n 3,\\n 3,\\n 3,\\n 3,\\n 3,\\n 3,\\n 3,\\n 3,\\n 3,\\n 3,\\n 3,\\n 3,\\n 3,\\n 3,\\n 3,\\n 3,\\n 3,\\n 3,\\n 3,\\n 3,\\n 3,\\n 4,\\n 4,\\n 4,\\n 4,\\n 4,\\n 4,\\n 4,\\n 4,\\n 4,\\n 4,\\n 4,\\n 4,\\n 4,\\n 4,\\n 4,\\n 4,\\n 4,\\n 4,\\n 4,\\n 4,\\n 4,\\n 4,\\n 4,\\n 4,\\n 4,\\n 4,\\n 4,\\n 4,\\n 4,\\n 4,\\n 4,\\n 4,\\n 4,\\n 4,\\n 4,\\n 4,\\n 4,\\n 4,\\n 4,\\n 4,\\n 4,\\n 4,\\n 4,\\n 4,\\n 4,\\n 4,\\n 4,\\n 4,\\n 4,\\n 4,\\n 4,\\n 4,\\n 4,\\n 4,\\n 4,\\n 4,\\n 4,\\n 4,\\n 4,\\n 4,\\n 4,\\n 4,\\n 4,\\n 4,\\n 5,\\n 5,\\n 5,\\n 5,\\n 5,\\n 5,\\n 5,\\n 5,\\n 5,\\n 5,\\n 5,\\n 5,\\n 5,\\n 5,\\n 5,\\n 5,\\n 5,\\n 5,\\n 5,\\n 5,\\n 5,\\n 5,\\n 5,\\n 5,\\n 5,\\n 5,\\n 5,\\n 5,\\n 5,\\n 5,\\n 5,\\n 5,\\n 5,\\n 5,\\n 5,\\n 5,\\n 5,\\n 5,\\n 5,\\n 5,\\n 5,\\n 5,\\n 5,\\n 5,\\n 5,\\n 5,\\n 5,\\n 5,\\n 6,\\n 6,\\n 6,\\n 6,\\n 6,\\n 6,\\n 6,\\n 6,\\n 6,\\n 6,\\n 6,\\n 6,\\n 6,\\n 6,\\n 6,\\n 7,\\n /* CONTEXT_SIGNED, last byte, same as the above values shifted by 3 bits. */\\n 0,\\n 8,\\n 8,\\n 8,\\n 8,\\n 8,\\n 8,\\n 8,\\n 8,\\n 8,\\n 8,\\n 8,\\n 8,\\n 8,\\n 8,\\n 8,\\n 16,\\n 16,\\n 16,\\n 16,\\n 16,\\n 16,\\n 16,\\n 16,\\n 16,\\n 16,\\n 16,\\n 16,\\n 16,\\n 16,\\n 16,\\n 16,\\n 16,\\n 16,\\n 16,\\n 16,\\n 16,\\n 16,\\n 16,\\n 16,\\n 16,\\n 16,\\n 16,\\n 16,\\n 16,\\n 16,\\n 16,\\n 16,\\n 16,\\n 16,\\n 16,\\n 16,\\n 16,\\n 16,\\n 16,\\n 16,\\n 16,\\n 16,\\n 16,\\n 16,\\n 16,\\n 16,\\n 16,\\n 16,\\n 24,\\n 24,\\n 24,\\n 24,\\n 24,\\n 24,\\n 24,\\n 24,\\n 24,\\n 24,\\n 24,\\n 24,\\n 24,\\n 24,\\n 24,\\n 24,\\n 24,\\n 24,\\n 24,\\n 24,\\n 24,\\n 24,\\n 24,\\n 24,\\n 24,\\n 24,\\n 24,\\n 24,\\n 24,\\n 24,\\n 24,\\n 24,\\n 24,\\n 24,\\n 24,\\n 24,\\n 24,\\n 24,\\n 24,\\n 24,\\n 24,\\n 24,\\n 24,\\n 24,\\n 24,\\n 24,\\n 24,\\n 24,\\n 24,\\n 24,\\n 24,\\n 24,\\n 24,\\n 24,\\n 24,\\n 24,\\n 24,\\n 24,\\n 24,\\n 24,\\n 24,\\n 24,\\n 24,\\n 24,\\n 32,\\n 32,\\n 32,\\n 32,\\n 32,\\n 32,\\n 32,\\n 32,\\n 32,\\n 32,\\n 32,\\n 32,\\n 32,\\n 32,\\n 32,\\n 32,\\n 32,\\n 32,\\n 32,\\n 32,\\n 32,\\n 32,\\n 32,\\n 32,\\n 32,\\n 32,\\n 32,\\n 32,\\n 32,\\n 32,\\n 32,\\n 32,\\n 32,\\n 32,\\n 32,\\n 32,\\n 32,\\n 32,\\n 32,\\n 32,\\n 32,\\n 32,\\n 32,\\n 32,\\n 32,\\n 32,\\n 32,\\n 32,\\n 32,\\n 32,\\n 32,\\n 32,\\n 32,\\n 32,\\n 32,\\n 32,\\n 32,\\n 32,\\n 32,\\n 32,\\n 32,\\n 32,\\n 32,\\n 32,\\n 40,\\n 40,\\n 40,\\n 40,\\n 40,\\n 40,\\n 40,\\n 40,\\n 40,\\n 40,\\n 40,\\n 40,\\n 40,\\n 40,\\n 40,\\n 40,\\n 40,\\n 40,\\n 40,\\n 40,\\n 40,\\n 40,\\n 40,\\n 40,\\n 40,\\n 40,\\n 40,\\n 40,\\n 40,\\n 40,\\n 40,\\n 40,\\n 40,\\n 40,\\n 40,\\n 40,\\n 40,\\n 40,\\n 40,\\n 40,\\n 40,\\n 40,\\n 40,\\n 40,\\n 40,\\n 40,\\n 40,\\n 40,\\n 48,\\n 48,\\n 48,\\n 48,\\n 48,\\n 48,\\n 48,\\n 48,\\n 48,\\n 48,\\n 48,\\n 48,\\n 48,\\n 48,\\n 48,\\n 56,\\n /* CONTEXT_LSB6, last byte. */\\n 0,\\n 1,\\n 2,\\n 3,\\n 4,\\n 5,\\n 6,\\n 7,\\n 8,\\n 9,\\n 10,\\n 11,\\n 12,\\n 13,\\n 14,\\n 15,\\n 16,\\n 17,\\n 18,\\n 19,\\n 20,\\n 21,\\n 22,\\n 23,\\n 24,\\n 25,\\n 26,\\n 27,\\n 28,\\n 29,\\n 30,\\n 31,\\n 32,\\n 33,\\n 34,\\n 35,\\n 36,\\n 37,\\n 38,\\n 39,\\n 40,\\n 41,\\n 42,\\n 43,\\n 44,\\n 45,\\n 46,\\n 47,\\n 48,\\n 49,\\n 50,\\n 51,\\n 52,\\n 53,\\n 54,\\n 55,\\n 56,\\n 57,\\n 58,\\n 59,\\n 60,\\n 61,\\n 62,\\n 63,\\n 0,\\n 1,\\n 2,\\n 3,\\n 4,\\n 5,\\n 6,\\n 7,\\n 8,\\n 9,\\n 10,\\n 11,\\n 12,\\n 13,\\n 14,\\n 15,\\n 16,\\n 17,\\n 18,\\n 19,\\n 20,\\n 21,\\n 22,\\n 23,\\n 24,\\n 25,\\n 26,\\n 27,\\n 28,\\n 29,\\n 30,\\n 31,\\n 32,\\n 33,\\n 34,\\n 35,\\n 36,\\n 37,\\n 38,\\n 39,\\n 40,\\n 41,\\n 42,\\n 43,\\n 44,\\n 45,\\n 46,\\n 47,\\n 48,\\n 49,\\n 50,\\n 51,\\n 52,\\n 53,\\n 54,\\n 55,\\n 56,\\n 57,\\n 58,\\n 59,\\n 60,\\n 61,\\n 62,\\n 63,\\n 0,\\n 1,\\n 2,\\n 3,\\n 4,\\n 5,\\n 6,\\n 7,\\n 8,\\n 9,\\n 10,\\n 11,\\n 12,\\n 13,\\n 14,\\n 15,\\n 16,\\n 17,\\n 18,\\n 19,\\n 20,\\n 21,\\n 22,\\n 23,\\n 24,\\n 25,\\n 26,\\n 27,\\n 28,\\n 29,\\n 30,\\n 31,\\n 32,\\n 33,\\n 34,\\n 35,\\n 36,\\n 37,\\n 38,\\n 39,\\n 40,\\n 41,\\n 42,\\n 43,\\n 44,\\n 45,\\n 46,\\n 47,\\n 48,\\n 49,\\n 50,\\n 51,\\n 52,\\n 53,\\n 54,\\n 55,\\n 56,\\n 57,\\n 58,\\n 59,\\n 60,\\n 61,\\n 62,\\n 63,\\n 0,\\n 1,\\n 2,\\n 3,\\n 4,\\n 5,\\n 6,\\n 7,\\n 8,\\n 9,\\n 10,\\n 11,\\n 12,\\n 13,\\n 14,\\n 15,\\n 16,\\n 17,\\n 18,\\n 19,\\n 20,\\n 21,\\n 22,\\n 23,\\n 24,\\n 25,\\n 26,\\n 27,\\n 28,\\n 29,\\n 30,\\n 31,\\n 32,\\n 33,\\n 34,\\n 35,\\n 36,\\n 37,\\n 38,\\n 39,\\n 40,\\n 41,\\n 42,\\n 43,\\n 44,\\n 45,\\n 46,\\n 47,\\n 48,\\n 49,\\n 50,\\n 51,\\n 52,\\n 53,\\n 54,\\n 55,\\n 56,\\n 57,\\n 58,\\n 59,\\n 60,\\n 61,\\n 62,\\n 63,\\n /* CONTEXT_MSB6, last byte. */\\n 0,\\n 0,\\n 0,\\n 0,\\n 1,\\n 1,\\n 1,\\n 1,\\n 2,\\n 2,\\n 2,\\n 2,\\n 3,\\n 3,\\n 3,\\n 3,\\n 4,\\n 4,\\n 4,\\n 4,\\n 5,\\n 5,\\n 5,\\n 5,\\n 6,\\n 6,\\n 6,\\n 6,\\n 7,\\n 7,\\n 7,\\n 7,\\n 8,\\n 8,\\n 8,\\n 8,\\n 9,\\n 9,\\n 9,\\n 9,\\n 10,\\n 10,\\n 10,\\n 10,\\n 11,\\n 11,\\n 11,\\n 11,\\n 12,\\n 12,\\n 12,\\n 12,\\n 13,\\n 13,\\n 13,\\n 13,\\n 14,\\n 14,\\n 14,\\n 14,\\n 15,\\n 15,\\n 15,\\n 15,\\n 16,\\n 16,\\n 16,\\n 16,\\n 17,\\n 17,\\n 17,\\n 17,\\n 18,\\n 18,\\n 18,\\n 18,\\n 19,\\n 19,\\n 19,\\n 19,\\n 20,\\n 20,\\n 20,\\n 20,\\n 21,\\n 21,\\n 21,\\n 21,\\n 22,\\n 22,\\n 22,\\n 22,\\n 23,\\n 23,\\n 23,\\n 23,\\n 24,\\n 24,\\n 24,\\n 24,\\n 25,\\n 25,\\n 25,\\n 25,\\n 26,\\n 26,\\n 26,\\n 26,\\n 27,\\n 27,\\n 27,\\n 27,\\n 28,\\n 28,\\n 28,\\n 28,\\n 29,\\n 29,\\n 29,\\n 29,\\n 30,\\n 30,\\n 30,\\n 30,\\n 31,\\n 31,\\n 31,\\n 31,\\n 32,\\n 32,\\n 32,\\n 32,\\n 33,\\n 33,\\n 33,\\n 33,\\n 34,\\n 34,\\n 34,\\n 34,\\n 35,\\n 35,\\n 35,\\n 35,\\n 36,\\n 36,\\n 36,\\n 36,\\n 37,\\n 37,\\n 37,\\n 37,\\n 38,\\n 38,\\n 38,\\n 38,\\n 39,\\n 39,\\n 39,\\n 39,\\n 40,\\n 40,\\n 40,\\n 40,\\n 41,\\n 41,\\n 41,\\n 41,\\n 42,\\n 42,\\n 42,\\n 42,\\n 43,\\n 43,\\n 43,\\n 43,\\n 44,\\n 44,\\n 44,\\n 44,\\n 45,\\n 45,\\n 45,\\n 45,\\n 46,\\n 46,\\n 46,\\n 46,\\n 47,\\n 47,\\n 47,\\n 47,\\n 48,\\n 48,\\n 48,\\n 48,\\n 49,\\n 49,\\n 49,\\n 49,\\n 50,\\n 50,\\n 50,\\n 50,\\n 51,\\n 51,\\n 51,\\n 51,\\n 52,\\n 52,\\n 52,\\n 52,\\n 53,\\n 53,\\n 53,\\n 53,\\n 54,\\n 54,\\n 54,\\n 54,\\n 55,\\n 55,\\n 55,\\n 55,\\n 56,\\n 56,\\n 56,\\n 56,\\n 57,\\n 57,\\n 57,\\n 57,\\n 58,\\n 58,\\n 58,\\n 58,\\n 59,\\n 59,\\n 59,\\n 59,\\n 60,\\n 60,\\n 60,\\n 60,\\n 61,\\n 61,\\n 61,\\n 61,\\n 62,\\n 62,\\n 62,\\n 62,\\n 63,\\n 63,\\n 63,\\n 63,\\n /* CONTEXT_{M,L}SB6, second last byte, */\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0,\\n 0\\n ]);\\n exports.lookupOffsets = new Uint16Array([\\n /* CONTEXT_LSB6 */\\n 1024,\\n 1536,\\n /* CONTEXT_MSB6 */\\n 1280,\\n 1536,\\n /* CONTEXT_UTF8 */\\n 0,\\n 256,\\n /* CONTEXT_SIGNED */\\n 768,\\n 512\\n ]);\\n }\\n });\\n\\n // ../../node_modules/.pnpm/brotli@1.3.3/node_modules/brotli/dec/prefix.js\\n var require_prefix = __commonJS({\\n \\\"../../node_modules/.pnpm/brotli@1.3.3/node_modules/brotli/dec/prefix.js\\\"(exports) {\\n function PrefixCodeRange(offset, nbits) {\\n this.offset = offset;\\n this.nbits = nbits;\\n }\\n exports.kBlockLengthPrefixCode = [\\n new PrefixCodeRange(1, 2),\\n new PrefixCodeRange(5, 2),\\n new PrefixCodeRange(9, 2),\\n new PrefixCodeRange(13, 2),\\n new PrefixCodeRange(17, 3),\\n new PrefixCodeRange(25, 3),\\n new PrefixCodeRange(33, 3),\\n new PrefixCodeRange(41, 3),\\n new PrefixCodeRange(49, 4),\\n new PrefixCodeRange(65, 4),\\n new PrefixCodeRange(81, 4),\\n new PrefixCodeRange(97, 4),\\n new PrefixCodeRange(113, 5),\\n new PrefixCodeRange(145, 5),\\n new PrefixCodeRange(177, 5),\\n new PrefixCodeRange(209, 5),\\n new PrefixCodeRange(241, 6),\\n new PrefixCodeRange(305, 6),\\n new PrefixCodeRange(369, 7),\\n new PrefixCodeRange(497, 8),\\n new PrefixCodeRange(753, 9),\\n new PrefixCodeRange(1265, 10),\\n new PrefixCodeRange(2289, 11),\\n new PrefixCodeRange(4337, 12),\\n new PrefixCodeRange(8433, 13),\\n new PrefixCodeRange(16625, 24)\\n ];\\n exports.kInsertLengthPrefixCode = [\\n new PrefixCodeRange(0, 0),\\n new PrefixCodeRange(1, 0),\\n new PrefixCodeRange(2, 0),\\n new PrefixCodeRange(3, 0),\\n new PrefixCodeRange(4, 0),\\n new PrefixCodeRange(5, 0),\\n new PrefixCodeRange(6, 1),\\n new PrefixCodeRange(8, 1),\\n new PrefixCodeRange(10, 2),\\n new PrefixCodeRange(14, 2),\\n new PrefixCodeRange(18, 3),\\n new PrefixCodeRange(26, 3),\\n new PrefixCodeRange(34, 4),\\n new PrefixCodeRange(50, 4),\\n new PrefixCodeRange(66, 5),\\n new PrefixCodeRange(98, 5),\\n new PrefixCodeRange(130, 6),\\n new PrefixCodeRange(194, 7),\\n new PrefixCodeRange(322, 8),\\n new PrefixCodeRange(578, 9),\\n new PrefixCodeRange(1090, 10),\\n new PrefixCodeRange(2114, 12),\\n new PrefixCodeRange(6210, 14),\\n new PrefixCodeRange(22594, 24)\\n ];\\n exports.kCopyLengthPrefixCode = [\\n new PrefixCodeRange(2, 0),\\n new PrefixCodeRange(3, 0),\\n new PrefixCodeRange(4, 0),\\n new PrefixCodeRange(5, 0),\\n new PrefixCodeRange(6, 0),\\n new PrefixCodeRange(7, 0),\\n new PrefixCodeRange(8, 0),\\n new PrefixCodeRange(9, 0),\\n new PrefixCodeRange(10, 1),\\n new PrefixCodeRange(12, 1),\\n new PrefixCodeRange(14, 2),\\n new PrefixCodeRange(18, 2),\\n new PrefixCodeRange(22, 3),\\n new PrefixCodeRange(30, 3),\\n new PrefixCodeRange(38, 4),\\n new PrefixCodeRange(54, 4),\\n new PrefixCodeRange(70, 5),\\n new PrefixCodeRange(102, 5),\\n new PrefixCodeRange(134, 6),\\n new PrefixCodeRange(198, 7),\\n new PrefixCodeRange(326, 8),\\n new PrefixCodeRange(582, 9),\\n new PrefixCodeRange(1094, 10),\\n new PrefixCodeRange(2118, 24)\\n ];\\n exports.kInsertRangeLut = [\\n 0,\\n 0,\\n 8,\\n 8,\\n 0,\\n 16,\\n 8,\\n 16,\\n 16\\n ];\\n exports.kCopyRangeLut = [\\n 0,\\n 8,\\n 0,\\n 8,\\n 16,\\n 0,\\n 16,\\n 8,\\n 16\\n ];\\n }\\n });\\n\\n // ../../node_modules/.pnpm/brotli@1.3.3/node_modules/brotli/dec/transform.js\\n var require_transform = __commonJS({\\n \\\"../../node_modules/.pnpm/brotli@1.3.3/node_modules/brotli/dec/transform.js\\\"(exports) {\\n var BrotliDictionary = require_dictionary();\\n var kIdentity = 0;\\n var kOmitLast1 = 1;\\n var kOmitLast2 = 2;\\n var kOmitLast3 = 3;\\n var kOmitLast4 = 4;\\n var kOmitLast5 = 5;\\n var kOmitLast6 = 6;\\n var kOmitLast7 = 7;\\n var kOmitLast8 = 8;\\n var kOmitLast9 = 9;\\n var kUppercaseFirst = 10;\\n var kUppercaseAll = 11;\\n var kOmitFirst1 = 12;\\n var kOmitFirst2 = 13;\\n var kOmitFirst3 = 14;\\n var kOmitFirst4 = 15;\\n var kOmitFirst5 = 16;\\n var kOmitFirst6 = 17;\\n var kOmitFirst7 = 18;\\n var kOmitFirst9 = 20;\\n function Transform(prefix, transform, suffix) {\\n this.prefix = new Uint8Array(prefix.length);\\n this.transform = transform;\\n this.suffix = new Uint8Array(suffix.length);\\n for (var i = 0; i < prefix.length; i++)\\n this.prefix[i] = prefix.charCodeAt(i);\\n for (var i = 0; i < suffix.length; i++)\\n this.suffix[i] = suffix.charCodeAt(i);\\n }\\n var kTransforms = [\\n new Transform(\\\"\\\", kIdentity, \\\"\\\"),\\n new Transform(\\\"\\\", kIdentity, \\\" \\\"),\\n new Transform(\\\" \\\", kIdentity, \\\" \\\"),\\n new Transform(\\\"\\\", kOmitFirst1, \\\"\\\"),\\n new Transform(\\\"\\\", kUppercaseFirst, \\\" \\\"),\\n new Transform(\\\"\\\", kIdentity, \\\" the \\\"),\\n new Transform(\\\" \\\", kIdentity, \\\"\\\"),\\n new Transform(\\\"s \\\", kIdentity, \\\" \\\"),\\n new Transform(\\\"\\\", kIdentity, \\\" of \\\"),\\n new Transform(\\\"\\\", kUppercaseFirst, \\\"\\\"),\\n new Transform(\\\"\\\", kIdentity, \\\" and \\\"),\\n new Transform(\\\"\\\", kOmitFirst2, \\\"\\\"),\\n new Transform(\\\"\\\", kOmitLast1, \\\"\\\"),\\n new Transform(\\\", \\\", kIdentity, \\\" \\\"),\\n new Transform(\\\"\\\", kIdentity, \\\", \\\"),\\n new Transform(\\\" \\\", kUppercaseFirst, \\\" \\\"),\\n new Transform(\\\"\\\", kIdentity, \\\" in \\\"),\\n new Transform(\\\"\\\", kIdentity, \\\" to \\\"),\\n new Transform(\\\"e \\\", kIdentity, \\\" \\\"),\\n new Transform(\\\"\\\", kIdentity, '\\\"'),\\n new Transform(\\\"\\\", kIdentity, \\\".\\\"),\\n new Transform(\\\"\\\", kIdentity, '\\\">'),\\n new Transform(\\\"\\\", kIdentity, \\\"\\\\n\\\"),\\n new Transform(\\\"\\\", kOmitLast3, \\\"\\\"),\\n new Transform(\\\"\\\", kIdentity, \\\"]\\\"),\\n new Transform(\\\"\\\", kIdentity, \\\" for \\\"),\\n new Transform(\\\"\\\", kOmitFirst3, \\\"\\\"),\\n new Transform(\\\"\\\", kOmitLast2, \\\"\\\"),\\n new Transform(\\\"\\\", kIdentity, \\\" a \\\"),\\n new Transform(\\\"\\\", kIdentity, \\\" that \\\"),\\n new Transform(\\\" \\\", kUppercaseFirst, \\\"\\\"),\\n new Transform(\\\"\\\", kIdentity, \\\". \\\"),\\n new Transform(\\\".\\\", kIdentity, \\\"\\\"),\\n new Transform(\\\" \\\", kIdentity, \\\", \\\"),\\n new Transform(\\\"\\\", kOmitFirst4, \\\"\\\"),\\n new Transform(\\\"\\\", kIdentity, \\\" with \\\"),\\n new Transform(\\\"\\\", kIdentity, \\\"'\\\"),\\n new Transform(\\\"\\\", kIdentity, \\\" from \\\"),\\n new Transform(\\\"\\\", kIdentity, \\\" by \\\"),\\n new Transform(\\\"\\\", kOmitFirst5, \\\"\\\"),\\n new Transform(\\\"\\\", kOmitFirst6, \\\"\\\"),\\n new Transform(\\\" the \\\", kIdentity, \\\"\\\"),\\n new Transform(\\\"\\\", kOmitLast4, \\\"\\\"),\\n new Transform(\\\"\\\", kIdentity, \\\". The \\\"),\\n new Transform(\\\"\\\", kUppercaseAll, \\\"\\\"),\\n new Transform(\\\"\\\", kIdentity, \\\" on \\\"),\\n new Transform(\\\"\\\", kIdentity, \\\" as \\\"),\\n new Transform(\\\"\\\", kIdentity, \\\" is \\\"),\\n new Transform(\\\"\\\", kOmitLast7, \\\"\\\"),\\n new Transform(\\\"\\\", kOmitLast1, \\\"ing \\\"),\\n new Transform(\\\"\\\", kIdentity, \\\"\\\\n\\t\\\"),\\n new Transform(\\\"\\\", kIdentity, \\\":\\\"),\\n new Transform(\\\" \\\", kIdentity, \\\". \\\"),\\n new Transform(\\\"\\\", kIdentity, \\\"ed \\\"),\\n new Transform(\\\"\\\", kOmitFirst9, \\\"\\\"),\\n new Transform(\\\"\\\", kOmitFirst7, \\\"\\\"),\\n new Transform(\\\"\\\", kOmitLast6, \\\"\\\"),\\n new Transform(\\\"\\\", kIdentity, \\\"(\\\"),\\n new Transform(\\\"\\\", kUppercaseFirst, \\\", \\\"),\\n new Transform(\\\"\\\", kOmitLast8, \\\"\\\"),\\n new Transform(\\\"\\\", kIdentity, \\\" at \\\"),\\n new Transform(\\\"\\\", kIdentity, \\\"ly \\\"),\\n new Transform(\\\" the \\\", kIdentity, \\\" of \\\"),\\n new Transform(\\\"\\\", kOmitLast5, \\\"\\\"),\\n new Transform(\\\"\\\", kOmitLast9, \\\"\\\"),\\n new Transform(\\\" \\\", kUppercaseFirst, \\\", \\\"),\\n new Transform(\\\"\\\", kUppercaseFirst, '\\\"'),\\n new Transform(\\\".\\\", kIdentity, \\\"(\\\"),\\n new Transform(\\\"\\\", kUppercaseAll, \\\" \\\"),\\n new Transform(\\\"\\\", kUppercaseFirst, '\\\">'),\\n new Transform(\\\"\\\", kIdentity, '=\\\"'),\\n new Transform(\\\" \\\", kIdentity, \\\".\\\"),\\n new Transform(\\\".com/\\\", kIdentity, \\\"\\\"),\\n new Transform(\\\" the \\\", kIdentity, \\\" of the \\\"),\\n new Transform(\\\"\\\", kUppercaseFirst, \\\"'\\\"),\\n new Transform(\\\"\\\", kIdentity, \\\". This \\\"),\\n new Transform(\\\"\\\", kIdentity, \\\",\\\"),\\n new Transform(\\\".\\\", kIdentity, \\\" \\\"),\\n new Transform(\\\"\\\", kUppercaseFirst, \\\"(\\\"),\\n new Transform(\\\"\\\", kUppercaseFirst, \\\".\\\"),\\n new Transform(\\\"\\\", kIdentity, \\\" not \\\"),\\n new Transform(\\\" \\\", kIdentity, '=\\\"'),\\n new Transform(\\\"\\\", kIdentity, \\\"er \\\"),\\n new Transform(\\\" \\\", kUppercaseAll, \\\" \\\"),\\n new Transform(\\\"\\\", kIdentity, \\\"al \\\"),\\n new Transform(\\\" \\\", kUppercaseAll, \\\"\\\"),\\n new Transform(\\\"\\\", kIdentity, \\\"='\\\"),\\n new Transform(\\\"\\\", kUppercaseAll, '\\\"'),\\n new Transform(\\\"\\\", kUppercaseFirst, \\\". \\\"),\\n new Transform(\\\" \\\", kIdentity, \\\"(\\\"),\\n new Transform(\\\"\\\", kIdentity, \\\"ful \\\"),\\n new Transform(\\\" \\\", kUppercaseFirst, \\\". \\\"),\\n new Transform(\\\"\\\", kIdentity, \\\"ive \\\"),\\n new Transform(\\\"\\\", kIdentity, \\\"less \\\"),\\n new Transform(\\\"\\\", kUppercaseAll, \\\"'\\\"),\\n new Transform(\\\"\\\", kIdentity, \\\"est \\\"),\\n new Transform(\\\" \\\", kUppercaseFirst, \\\".\\\"),\\n new Transform(\\\"\\\", kUppercaseAll, '\\\">'),\\n new Transform(\\\" \\\", kIdentity, \\\"='\\\"),\\n new Transform(\\\"\\\", kUppercaseFirst, \\\",\\\"),\\n new Transform(\\\"\\\", kIdentity, \\\"ize \\\"),\\n new Transform(\\\"\\\", kUppercaseAll, \\\".\\\"),\\n new Transform(\\\"\\\\xC2\\\\xA0\\\", kIdentity, \\\"\\\"),\\n new Transform(\\\" \\\", kIdentity, \\\",\\\"),\\n new Transform(\\\"\\\", kUppercaseFirst, '=\\\"'),\\n new Transform(\\\"\\\", kUppercaseAll, '=\\\"'),\\n new Transform(\\\"\\\", kIdentity, \\\"ous \\\"),\\n new Transform(\\\"\\\", kUppercaseAll, \\\", \\\"),\\n new Transform(\\\"\\\", kUppercaseFirst, \\\"='\\\"),\\n new Transform(\\\" \\\", kUppercaseFirst, \\\",\\\"),\\n new Transform(\\\" \\\", kUppercaseAll, '=\\\"'),\\n new Transform(\\\" \\\", kUppercaseAll, \\\", \\\"),\\n new Transform(\\\"\\\", kUppercaseAll, \\\",\\\"),\\n new Transform(\\\"\\\", kUppercaseAll, \\\"(\\\"),\\n new Transform(\\\"\\\", kUppercaseAll, \\\". \\\"),\\n new Transform(\\\" \\\", kUppercaseAll, \\\".\\\"),\\n new Transform(\\\"\\\", kUppercaseAll, \\\"='\\\"),\\n new Transform(\\\" \\\", kUppercaseAll, \\\". \\\"),\\n new Transform(\\\" \\\", kUppercaseFirst, '=\\\"'),\\n new Transform(\\\" \\\", kUppercaseAll, \\\"='\\\"),\\n new Transform(\\\" \\\", kUppercaseFirst, \\\"='\\\")\\n ];\\n exports.kTransforms = kTransforms;\\n exports.kNumTransforms = kTransforms.length;\\n function ToUpperCase(p, i) {\\n if (p[i] < 192) {\\n if (p[i] >= 97 && p[i] <= 122) {\\n p[i] ^= 32;\\n }\\n return 1;\\n }\\n if (p[i] < 224) {\\n p[i + 1] ^= 32;\\n return 2;\\n }\\n p[i + 2] ^= 5;\\n return 3;\\n }\\n exports.transformDictionaryWord = function(dst, idx, word, len, transform) {\\n var prefix = kTransforms[transform].prefix;\\n var suffix = kTransforms[transform].suffix;\\n var t = kTransforms[transform].transform;\\n var skip = t < kOmitFirst1 ? 0 : t - (kOmitFirst1 - 1);\\n var i = 0;\\n var start_idx = idx;\\n var uppercase;\\n if (skip > len) {\\n skip = len;\\n }\\n var prefix_pos = 0;\\n while (prefix_pos < prefix.length) {\\n dst[idx++] = prefix[prefix_pos++];\\n }\\n word += skip;\\n len -= skip;\\n if (t <= kOmitLast9) {\\n len -= t;\\n }\\n for (i = 0; i < len; i++) {\\n dst[idx++] = BrotliDictionary.dictionary[word + i];\\n }\\n uppercase = idx - len;\\n if (t === kUppercaseFirst) {\\n ToUpperCase(dst, uppercase);\\n } else if (t === kUppercaseAll) {\\n while (len > 0) {\\n var step = ToUpperCase(dst, uppercase);\\n uppercase += step;\\n len -= step;\\n }\\n }\\n var suffix_pos = 0;\\n while (suffix_pos < suffix.length) {\\n dst[idx++] = suffix[suffix_pos++];\\n }\\n return idx - start_idx;\\n };\\n }\\n });\\n\\n // ../../node_modules/.pnpm/brotli@1.3.3/node_modules/brotli/dec/decode.js\\n var require_decode = __commonJS({\\n \\\"../../node_modules/.pnpm/brotli@1.3.3/node_modules/brotli/dec/decode.js\\\"(exports) {\\n var BrotliInput = require_streams().BrotliInput;\\n var BrotliOutput = require_streams().BrotliOutput;\\n var BrotliBitReader = require_bit_reader();\\n var BrotliDictionary = require_dictionary();\\n var HuffmanCode = require_huffman().HuffmanCode;\\n var BrotliBuildHuffmanTable = require_huffman().BrotliBuildHuffmanTable;\\n var Context = require_context();\\n var Prefix = require_prefix();\\n var Transform = require_transform();\\n var kDefaultCodeLength = 8;\\n var kCodeLengthRepeatCode = 16;\\n var kNumLiteralCodes = 256;\\n var kNumInsertAndCopyCodes = 704;\\n var kNumBlockLengthCodes = 26;\\n var kLiteralContextBits = 6;\\n var kDistanceContextBits = 2;\\n var HUFFMAN_TABLE_BITS = 8;\\n var HUFFMAN_TABLE_MASK = 255;\\n var HUFFMAN_MAX_TABLE_SIZE = 1080;\\n var CODE_LENGTH_CODES = 18;\\n var kCodeLengthCodeOrder = new Uint8Array([\\n 1,\\n 2,\\n 3,\\n 4,\\n 0,\\n 5,\\n 17,\\n 6,\\n 16,\\n 7,\\n 8,\\n 9,\\n 10,\\n 11,\\n 12,\\n 13,\\n 14,\\n 15\\n ]);\\n var NUM_DISTANCE_SHORT_CODES = 16;\\n var kDistanceShortCodeIndexOffset = new Uint8Array([\\n 3,\\n 2,\\n 1,\\n 0,\\n 3,\\n 3,\\n 3,\\n 3,\\n 3,\\n 3,\\n 2,\\n 2,\\n 2,\\n 2,\\n 2,\\n 2\\n ]);\\n var kDistanceShortCodeValueOffset = new Int8Array([\\n 0,\\n 0,\\n 0,\\n 0,\\n -1,\\n 1,\\n -2,\\n 2,\\n -3,\\n 3,\\n -1,\\n 1,\\n -2,\\n 2,\\n -3,\\n 3\\n ]);\\n var kMaxHuffmanTableSize = new Uint16Array([\\n 256,\\n 402,\\n 436,\\n 468,\\n 500,\\n 534,\\n 566,\\n 598,\\n 630,\\n 662,\\n 694,\\n 726,\\n 758,\\n 790,\\n 822,\\n 854,\\n 886,\\n 920,\\n 952,\\n 984,\\n 1016,\\n 1048,\\n 1080\\n ]);\\n function DecodeWindowBits(br) {\\n var n;\\n if (br.readBits(1) === 0) {\\n return 16;\\n }\\n n = br.readBits(3);\\n if (n > 0) {\\n return 17 + n;\\n }\\n n = br.readBits(3);\\n if (n > 0) {\\n return 8 + n;\\n }\\n return 17;\\n }\\n function DecodeVarLenUint8(br) {\\n if (br.readBits(1)) {\\n var nbits = br.readBits(3);\\n if (nbits === 0) {\\n return 1;\\n } else {\\n return br.readBits(nbits) + (1 << nbits);\\n }\\n }\\n return 0;\\n }\\n function MetaBlockLength() {\\n this.meta_block_length = 0;\\n this.input_end = 0;\\n this.is_uncompressed = 0;\\n this.is_metadata = false;\\n }\\n function DecodeMetaBlockLength(br) {\\n var out = new MetaBlockLength();\\n var size_nibbles;\\n var size_bytes;\\n var i;\\n out.input_end = br.readBits(1);\\n if (out.input_end && br.readBits(1)) {\\n return out;\\n }\\n size_nibbles = br.readBits(2) + 4;\\n if (size_nibbles === 7) {\\n out.is_metadata = true;\\n if (br.readBits(1) !== 0)\\n throw new Error(\\\"Invalid reserved bit\\\");\\n size_bytes = br.readBits(2);\\n if (size_bytes === 0)\\n return out;\\n for (i = 0; i < size_bytes; i++) {\\n var next_byte = br.readBits(8);\\n if (i + 1 === size_bytes && size_bytes > 1 && next_byte === 0)\\n throw new Error(\\\"Invalid size byte\\\");\\n out.meta_block_length |= next_byte << i * 8;\\n }\\n } else {\\n for (i = 0; i < size_nibbles; ++i) {\\n var next_nibble = br.readBits(4);\\n if (i + 1 === size_nibbles && size_nibbles > 4 && next_nibble === 0)\\n throw new Error(\\\"Invalid size nibble\\\");\\n out.meta_block_length |= next_nibble << i * 4;\\n }\\n }\\n ++out.meta_block_length;\\n if (!out.input_end && !out.is_metadata) {\\n out.is_uncompressed = br.readBits(1);\\n }\\n return out;\\n }\\n function ReadSymbol(table, index, br) {\\n var start_index = index;\\n var nbits;\\n br.fillBitWindow();\\n index += br.val_ >>> br.bit_pos_ & HUFFMAN_TABLE_MASK;\\n nbits = table[index].bits - HUFFMAN_TABLE_BITS;\\n if (nbits > 0) {\\n br.bit_pos_ += HUFFMAN_TABLE_BITS;\\n index += table[index].value;\\n index += br.val_ >>> br.bit_pos_ & (1 << nbits) - 1;\\n }\\n br.bit_pos_ += table[index].bits;\\n return table[index].value;\\n }\\n function ReadHuffmanCodeLengths(code_length_code_lengths, num_symbols, code_lengths, br) {\\n var symbol = 0;\\n var prev_code_len = kDefaultCodeLength;\\n var repeat = 0;\\n var repeat_code_len = 0;\\n var space = 32768;\\n var table = [];\\n for (var i = 0; i < 32; i++)\\n table.push(new HuffmanCode(0, 0));\\n BrotliBuildHuffmanTable(table, 0, 5, code_length_code_lengths, CODE_LENGTH_CODES);\\n while (symbol < num_symbols && space > 0) {\\n var p = 0;\\n var code_len;\\n br.readMoreInput();\\n br.fillBitWindow();\\n p += br.val_ >>> br.bit_pos_ & 31;\\n br.bit_pos_ += table[p].bits;\\n code_len = table[p].value & 255;\\n if (code_len < kCodeLengthRepeatCode) {\\n repeat = 0;\\n code_lengths[symbol++] = code_len;\\n if (code_len !== 0) {\\n prev_code_len = code_len;\\n space -= 32768 >> code_len;\\n }\\n } else {\\n var extra_bits = code_len - 14;\\n var old_repeat;\\n var repeat_delta;\\n var new_len = 0;\\n if (code_len === kCodeLengthRepeatCode) {\\n new_len = prev_code_len;\\n }\\n if (repeat_code_len !== new_len) {\\n repeat = 0;\\n repeat_code_len = new_len;\\n }\\n old_repeat = repeat;\\n if (repeat > 0) {\\n repeat -= 2;\\n repeat <<= extra_bits;\\n }\\n repeat += br.readBits(extra_bits) + 3;\\n repeat_delta = repeat - old_repeat;\\n if (symbol + repeat_delta > num_symbols) {\\n throw new Error(\\\"[ReadHuffmanCodeLengths] symbol + repeat_delta > num_symbols\\\");\\n }\\n for (var x = 0; x < repeat_delta; x++)\\n code_lengths[symbol + x] = repeat_code_len;\\n symbol += repeat_delta;\\n if (repeat_code_len !== 0) {\\n space -= repeat_delta << 15 - repeat_code_len;\\n }\\n }\\n }\\n if (space !== 0) {\\n throw new Error(\\\"[ReadHuffmanCodeLengths] space = \\\" + space);\\n }\\n for (; symbol < num_symbols; symbol++)\\n code_lengths[symbol] = 0;\\n }\\n function ReadHuffmanCode(alphabet_size, tables, table, br) {\\n var table_size = 0;\\n var simple_code_or_skip;\\n var code_lengths = new Uint8Array(alphabet_size);\\n br.readMoreInput();\\n simple_code_or_skip = br.readBits(2);\\n if (simple_code_or_skip === 1) {\\n var i;\\n var max_bits_counter = alphabet_size - 1;\\n var max_bits = 0;\\n var symbols = new Int32Array(4);\\n var num_symbols = br.readBits(2) + 1;\\n while (max_bits_counter) {\\n max_bits_counter >>= 1;\\n ++max_bits;\\n }\\n for (i = 0; i < num_symbols; ++i) {\\n symbols[i] = br.readBits(max_bits) % alphabet_size;\\n code_lengths[symbols[i]] = 2;\\n }\\n code_lengths[symbols[0]] = 1;\\n switch (num_symbols) {\\n case 1:\\n break;\\n case 3:\\n if (symbols[0] === symbols[1] || symbols[0] === symbols[2] || symbols[1] === symbols[2]) {\\n throw new Error(\\\"[ReadHuffmanCode] invalid symbols\\\");\\n }\\n break;\\n case 2:\\n if (symbols[0] === symbols[1]) {\\n throw new Error(\\\"[ReadHuffmanCode] invalid symbols\\\");\\n }\\n code_lengths[symbols[1]] = 1;\\n break;\\n case 4:\\n if (symbols[0] === symbols[1] || symbols[0] === symbols[2] || symbols[0] === symbols[3] || symbols[1] === symbols[2] || symbols[1] === symbols[3] || symbols[2] === symbols[3]) {\\n throw new Error(\\\"[ReadHuffmanCode] invalid symbols\\\");\\n }\\n if (br.readBits(1)) {\\n code_lengths[symbols[2]] = 3;\\n code_lengths[symbols[3]] = 3;\\n } else {\\n code_lengths[symbols[0]] = 2;\\n }\\n break;\\n }\\n } else {\\n var i;\\n var code_length_code_lengths = new Uint8Array(CODE_LENGTH_CODES);\\n var space = 32;\\n var num_codes = 0;\\n var huff = [\\n new HuffmanCode(2, 0),\\n new HuffmanCode(2, 4),\\n new HuffmanCode(2, 3),\\n new HuffmanCode(3, 2),\\n new HuffmanCode(2, 0),\\n new HuffmanCode(2, 4),\\n new HuffmanCode(2, 3),\\n new HuffmanCode(4, 1),\\n new HuffmanCode(2, 0),\\n new HuffmanCode(2, 4),\\n new HuffmanCode(2, 3),\\n new HuffmanCode(3, 2),\\n new HuffmanCode(2, 0),\\n new HuffmanCode(2, 4),\\n new HuffmanCode(2, 3),\\n new HuffmanCode(4, 5)\\n ];\\n for (i = simple_code_or_skip; i < CODE_LENGTH_CODES && space > 0; ++i) {\\n var code_len_idx = kCodeLengthCodeOrder[i];\\n var p = 0;\\n var v;\\n br.fillBitWindow();\\n p += br.val_ >>> br.bit_pos_ & 15;\\n br.bit_pos_ += huff[p].bits;\\n v = huff[p].value;\\n code_length_code_lengths[code_len_idx] = v;\\n if (v !== 0) {\\n space -= 32 >> v;\\n ++num_codes;\\n }\\n }\\n if (!(num_codes === 1 || space === 0))\\n throw new Error(\\\"[ReadHuffmanCode] invalid num_codes or space\\\");\\n ReadHuffmanCodeLengths(code_length_code_lengths, alphabet_size, code_lengths, br);\\n }\\n table_size = BrotliBuildHuffmanTable(tables, table, HUFFMAN_TABLE_BITS, code_lengths, alphabet_size);\\n if (table_size === 0) {\\n throw new Error(\\\"[ReadHuffmanCode] BuildHuffmanTable failed: \\\");\\n }\\n return table_size;\\n }\\n function ReadBlockLength(table, index, br) {\\n var code;\\n var nbits;\\n code = ReadSymbol(table, index, br);\\n nbits = Prefix.kBlockLengthPrefixCode[code].nbits;\\n return Prefix.kBlockLengthPrefixCode[code].offset + br.readBits(nbits);\\n }\\n function TranslateShortCodes(code, ringbuffer, index) {\\n var val;\\n if (code < NUM_DISTANCE_SHORT_CODES) {\\n index += kDistanceShortCodeIndexOffset[code];\\n index &= 3;\\n val = ringbuffer[index] + kDistanceShortCodeValueOffset[code];\\n } else {\\n val = code - NUM_DISTANCE_SHORT_CODES + 1;\\n }\\n return val;\\n }\\n function MoveToFront(v, index) {\\n var value = v[index];\\n var i = index;\\n for (; i; --i) v[i] = v[i - 1];\\n v[0] = value;\\n }\\n function InverseMoveToFrontTransform(v, v_len) {\\n var mtf = new Uint8Array(256);\\n var i;\\n for (i = 0; i < 256; ++i) {\\n mtf[i] = i;\\n }\\n for (i = 0; i < v_len; ++i) {\\n var index = v[i];\\n v[i] = mtf[index];\\n if (index) MoveToFront(mtf, index);\\n }\\n }\\n function HuffmanTreeGroup(alphabet_size, num_htrees) {\\n this.alphabet_size = alphabet_size;\\n this.num_htrees = num_htrees;\\n this.codes = new Array(num_htrees + num_htrees * kMaxHuffmanTableSize[alphabet_size + 31 >>> 5]);\\n this.htrees = new Uint32Array(num_htrees);\\n }\\n HuffmanTreeGroup.prototype.decode = function(br) {\\n var i;\\n var table_size;\\n var next = 0;\\n for (i = 0; i < this.num_htrees; ++i) {\\n this.htrees[i] = next;\\n table_size = ReadHuffmanCode(this.alphabet_size, this.codes, next, br);\\n next += table_size;\\n }\\n };\\n function DecodeContextMap(context_map_size, br) {\\n var out = { num_htrees: null, context_map: null };\\n var use_rle_for_zeros;\\n var max_run_length_prefix = 0;\\n var table;\\n var i;\\n br.readMoreInput();\\n var num_htrees = out.num_htrees = DecodeVarLenUint8(br) + 1;\\n var context_map = out.context_map = new Uint8Array(context_map_size);\\n if (num_htrees <= 1) {\\n return out;\\n }\\n use_rle_for_zeros = br.readBits(1);\\n if (use_rle_for_zeros) {\\n max_run_length_prefix = br.readBits(4) + 1;\\n }\\n table = [];\\n for (i = 0; i < HUFFMAN_MAX_TABLE_SIZE; i++) {\\n table[i] = new HuffmanCode(0, 0);\\n }\\n ReadHuffmanCode(num_htrees + max_run_length_prefix, table, 0, br);\\n for (i = 0; i < context_map_size; ) {\\n var code;\\n br.readMoreInput();\\n code = ReadSymbol(table, 0, br);\\n if (code === 0) {\\n context_map[i] = 0;\\n ++i;\\n } else if (code <= max_run_length_prefix) {\\n var reps = 1 + (1 << code) + br.readBits(code);\\n while (--reps) {\\n if (i >= context_map_size) {\\n throw new Error(\\\"[DecodeContextMap] i >= context_map_size\\\");\\n }\\n context_map[i] = 0;\\n ++i;\\n }\\n } else {\\n context_map[i] = code - max_run_length_prefix;\\n ++i;\\n }\\n }\\n if (br.readBits(1)) {\\n InverseMoveToFrontTransform(context_map, context_map_size);\\n }\\n return out;\\n }\\n function DecodeBlockType(max_block_type, trees, tree_type, block_types, ringbuffers, indexes, br) {\\n var ringbuffer = tree_type * 2;\\n var index = tree_type;\\n var type_code = ReadSymbol(trees, tree_type * HUFFMAN_MAX_TABLE_SIZE, br);\\n var block_type;\\n if (type_code === 0) {\\n block_type = ringbuffers[ringbuffer + (indexes[index] & 1)];\\n } else if (type_code === 1) {\\n block_type = ringbuffers[ringbuffer + (indexes[index] - 1 & 1)] + 1;\\n } else {\\n block_type = type_code - 2;\\n }\\n if (block_type >= max_block_type) {\\n block_type -= max_block_type;\\n }\\n block_types[tree_type] = block_type;\\n ringbuffers[ringbuffer + (indexes[index] & 1)] = block_type;\\n ++indexes[index];\\n }\\n function CopyUncompressedBlockToOutput(output, len, pos, ringbuffer, ringbuffer_mask, br) {\\n var rb_size = ringbuffer_mask + 1;\\n var rb_pos = pos & ringbuffer_mask;\\n var br_pos = br.pos_ & BrotliBitReader.IBUF_MASK;\\n var nbytes;\\n if (len < 8 || br.bit_pos_ + (len << 3) < br.bit_end_pos_) {\\n while (len-- > 0) {\\n br.readMoreInput();\\n ringbuffer[rb_pos++] = br.readBits(8);\\n if (rb_pos === rb_size) {\\n output.write(ringbuffer, rb_size);\\n rb_pos = 0;\\n }\\n }\\n return;\\n }\\n if (br.bit_end_pos_ < 32) {\\n throw new Error(\\\"[CopyUncompressedBlockToOutput] br.bit_end_pos_ < 32\\\");\\n }\\n while (br.bit_pos_ < 32) {\\n ringbuffer[rb_pos] = br.val_ >>> br.bit_pos_;\\n br.bit_pos_ += 8;\\n ++rb_pos;\\n --len;\\n }\\n nbytes = br.bit_end_pos_ - br.bit_pos_ >> 3;\\n if (br_pos + nbytes > BrotliBitReader.IBUF_MASK) {\\n var tail = BrotliBitReader.IBUF_MASK + 1 - br_pos;\\n for (var x = 0; x < tail; x++)\\n ringbuffer[rb_pos + x] = br.buf_[br_pos + x];\\n nbytes -= tail;\\n rb_pos += tail;\\n len -= tail;\\n br_pos = 0;\\n }\\n for (var x = 0; x < nbytes; x++)\\n ringbuffer[rb_pos + x] = br.buf_[br_pos + x];\\n rb_pos += nbytes;\\n len -= nbytes;\\n if (rb_pos >= rb_size) {\\n output.write(ringbuffer, rb_size);\\n rb_pos -= rb_size;\\n for (var x = 0; x < rb_pos; x++)\\n ringbuffer[x] = ringbuffer[rb_size + x];\\n }\\n while (rb_pos + len >= rb_size) {\\n nbytes = rb_size - rb_pos;\\n if (br.input_.read(ringbuffer, rb_pos, nbytes) < nbytes) {\\n throw new Error(\\\"[CopyUncompressedBlockToOutput] not enough bytes\\\");\\n }\\n output.write(ringbuffer, rb_size);\\n len -= nbytes;\\n rb_pos = 0;\\n }\\n if (br.input_.read(ringbuffer, rb_pos, len) < len) {\\n throw new Error(\\\"[CopyUncompressedBlockToOutput] not enough bytes\\\");\\n }\\n br.reset();\\n }\\n function JumpToByteBoundary(br) {\\n var new_bit_pos = br.bit_pos_ + 7 & ~7;\\n var pad_bits = br.readBits(new_bit_pos - br.bit_pos_);\\n return pad_bits == 0;\\n }\\n function BrotliDecompressedSize(buffer) {\\n var input = new BrotliInput(buffer);\\n var br = new BrotliBitReader(input);\\n DecodeWindowBits(br);\\n var out = DecodeMetaBlockLength(br);\\n return out.meta_block_length;\\n }\\n exports.BrotliDecompressedSize = BrotliDecompressedSize;\\n function BrotliDecompressBuffer(buffer, output_size) {\\n var input = new BrotliInput(buffer);\\n if (output_size == null) {\\n output_size = BrotliDecompressedSize(buffer);\\n }\\n var output_buffer = new Uint8Array(output_size);\\n var output = new BrotliOutput(output_buffer);\\n BrotliDecompress(input, output);\\n if (output.pos < output.buffer.length) {\\n output.buffer = output.buffer.subarray(0, output.pos);\\n }\\n return output.buffer;\\n }\\n exports.BrotliDecompressBuffer = BrotliDecompressBuffer;\\n function BrotliDecompress(input, output) {\\n var i;\\n var pos = 0;\\n var input_end = 0;\\n var window_bits = 0;\\n var max_backward_distance;\\n var max_distance = 0;\\n var ringbuffer_size;\\n var ringbuffer_mask;\\n var ringbuffer;\\n var ringbuffer_end;\\n var dist_rb = [16, 15, 11, 4];\\n var dist_rb_idx = 0;\\n var prev_byte1 = 0;\\n var prev_byte2 = 0;\\n var hgroup = [new HuffmanTreeGroup(0, 0), new HuffmanTreeGroup(0, 0), new HuffmanTreeGroup(0, 0)];\\n var block_type_trees;\\n var block_len_trees;\\n var br;\\n var kRingBufferWriteAheadSlack = 128 + BrotliBitReader.READ_SIZE;\\n br = new BrotliBitReader(input);\\n window_bits = DecodeWindowBits(br);\\n max_backward_distance = (1 << window_bits) - 16;\\n ringbuffer_size = 1 << window_bits;\\n ringbuffer_mask = ringbuffer_size - 1;\\n ringbuffer = new Uint8Array(ringbuffer_size + kRingBufferWriteAheadSlack + BrotliDictionary.maxDictionaryWordLength);\\n ringbuffer_end = ringbuffer_size;\\n block_type_trees = [];\\n block_len_trees = [];\\n for (var x = 0; x < 3 * HUFFMAN_MAX_TABLE_SIZE; x++) {\\n block_type_trees[x] = new HuffmanCode(0, 0);\\n block_len_trees[x] = new HuffmanCode(0, 0);\\n }\\n while (!input_end) {\\n var meta_block_remaining_len = 0;\\n var is_uncompressed;\\n var block_length = [1 << 28, 1 << 28, 1 << 28];\\n var block_type = [0];\\n var num_block_types = [1, 1, 1];\\n var block_type_rb = [0, 1, 0, 1, 0, 1];\\n var block_type_rb_index = [0];\\n var distance_postfix_bits;\\n var num_direct_distance_codes;\\n var distance_postfix_mask;\\n var num_distance_codes;\\n var context_map = null;\\n var context_modes = null;\\n var num_literal_htrees;\\n var dist_context_map = null;\\n var num_dist_htrees;\\n var context_offset = 0;\\n var context_map_slice = null;\\n var literal_htree_index = 0;\\n var dist_context_offset = 0;\\n var dist_context_map_slice = null;\\n var dist_htree_index = 0;\\n var context_lookup_offset1 = 0;\\n var context_lookup_offset2 = 0;\\n var context_mode;\\n var htree_command;\\n for (i = 0; i < 3; ++i) {\\n hgroup[i].codes = null;\\n hgroup[i].htrees = null;\\n }\\n br.readMoreInput();\\n var _out = DecodeMetaBlockLength(br);\\n meta_block_remaining_len = _out.meta_block_length;\\n if (pos + meta_block_remaining_len > output.buffer.length) {\\n var tmp = new Uint8Array(pos + meta_block_remaining_len);\\n tmp.set(output.buffer);\\n output.buffer = tmp;\\n }\\n input_end = _out.input_end;\\n is_uncompressed = _out.is_uncompressed;\\n if (_out.is_metadata) {\\n JumpToByteBoundary(br);\\n for (; meta_block_remaining_len > 0; --meta_block_remaining_len) {\\n br.readMoreInput();\\n br.readBits(8);\\n }\\n continue;\\n }\\n if (meta_block_remaining_len === 0) {\\n continue;\\n }\\n if (is_uncompressed) {\\n br.bit_pos_ = br.bit_pos_ + 7 & ~7;\\n CopyUncompressedBlockToOutput(\\n output,\\n meta_block_remaining_len,\\n pos,\\n ringbuffer,\\n ringbuffer_mask,\\n br\\n );\\n pos += meta_block_remaining_len;\\n continue;\\n }\\n for (i = 0; i < 3; ++i) {\\n num_block_types[i] = DecodeVarLenUint8(br) + 1;\\n if (num_block_types[i] >= 2) {\\n ReadHuffmanCode(num_block_types[i] + 2, block_type_trees, i * HUFFMAN_MAX_TABLE_SIZE, br);\\n ReadHuffmanCode(kNumBlockLengthCodes, block_len_trees, i * HUFFMAN_MAX_TABLE_SIZE, br);\\n block_length[i] = ReadBlockLength(block_len_trees, i * HUFFMAN_MAX_TABLE_SIZE, br);\\n block_type_rb_index[i] = 1;\\n }\\n }\\n br.readMoreInput();\\n distance_postfix_bits = br.readBits(2);\\n num_direct_distance_codes = NUM_DISTANCE_SHORT_CODES + (br.readBits(4) << distance_postfix_bits);\\n distance_postfix_mask = (1 << distance_postfix_bits) - 1;\\n num_distance_codes = num_direct_distance_codes + (48 << distance_postfix_bits);\\n context_modes = new Uint8Array(num_block_types[0]);\\n for (i = 0; i < num_block_types[0]; ++i) {\\n br.readMoreInput();\\n context_modes[i] = br.readBits(2) << 1;\\n }\\n var _o1 = DecodeContextMap(num_block_types[0] << kLiteralContextBits, br);\\n num_literal_htrees = _o1.num_htrees;\\n context_map = _o1.context_map;\\n var _o2 = DecodeContextMap(num_block_types[2] << kDistanceContextBits, br);\\n num_dist_htrees = _o2.num_htrees;\\n dist_context_map = _o2.context_map;\\n hgroup[0] = new HuffmanTreeGroup(kNumLiteralCodes, num_literal_htrees);\\n hgroup[1] = new HuffmanTreeGroup(kNumInsertAndCopyCodes, num_block_types[1]);\\n hgroup[2] = new HuffmanTreeGroup(num_distance_codes, num_dist_htrees);\\n for (i = 0; i < 3; ++i) {\\n hgroup[i].decode(br);\\n }\\n context_map_slice = 0;\\n dist_context_map_slice = 0;\\n context_mode = context_modes[block_type[0]];\\n context_lookup_offset1 = Context.lookupOffsets[context_mode];\\n context_lookup_offset2 = Context.lookupOffsets[context_mode + 1];\\n htree_command = hgroup[1].htrees[0];\\n while (meta_block_remaining_len > 0) {\\n var cmd_code;\\n var range_idx;\\n var insert_code;\\n var copy_code;\\n var insert_length;\\n var copy_length;\\n var distance_code;\\n var distance;\\n var context;\\n var j;\\n var copy_dst;\\n br.readMoreInput();\\n if (block_length[1] === 0) {\\n DecodeBlockType(\\n num_block_types[1],\\n block_type_trees,\\n 1,\\n block_type,\\n block_type_rb,\\n block_type_rb_index,\\n br\\n );\\n block_length[1] = ReadBlockLength(block_len_trees, HUFFMAN_MAX_TABLE_SIZE, br);\\n htree_command = hgroup[1].htrees[block_type[1]];\\n }\\n --block_length[1];\\n cmd_code = ReadSymbol(hgroup[1].codes, htree_command, br);\\n range_idx = cmd_code >> 6;\\n if (range_idx >= 2) {\\n range_idx -= 2;\\n distance_code = -1;\\n } else {\\n distance_code = 0;\\n }\\n insert_code = Prefix.kInsertRangeLut[range_idx] + (cmd_code >> 3 & 7);\\n copy_code = Prefix.kCopyRangeLut[range_idx] + (cmd_code & 7);\\n insert_length = Prefix.kInsertLengthPrefixCode[insert_code].offset + br.readBits(Prefix.kInsertLengthPrefixCode[insert_code].nbits);\\n copy_length = Prefix.kCopyLengthPrefixCode[copy_code].offset + br.readBits(Prefix.kCopyLengthPrefixCode[copy_code].nbits);\\n prev_byte1 = ringbuffer[pos - 1 & ringbuffer_mask];\\n prev_byte2 = ringbuffer[pos - 2 & ringbuffer_mask];\\n for (j = 0; j < insert_length; ++j) {\\n br.readMoreInput();\\n if (block_length[0] === 0) {\\n DecodeBlockType(\\n num_block_types[0],\\n block_type_trees,\\n 0,\\n block_type,\\n block_type_rb,\\n block_type_rb_index,\\n br\\n );\\n block_length[0] = ReadBlockLength(block_len_trees, 0, br);\\n context_offset = block_type[0] << kLiteralContextBits;\\n context_map_slice = context_offset;\\n context_mode = context_modes[block_type[0]];\\n context_lookup_offset1 = Context.lookupOffsets[context_mode];\\n context_lookup_offset2 = Context.lookupOffsets[context_mode + 1];\\n }\\n context = Context.lookup[context_lookup_offset1 + prev_byte1] | Context.lookup[context_lookup_offset2 + prev_byte2];\\n literal_htree_index = context_map[context_map_slice + context];\\n --block_length[0];\\n prev_byte2 = prev_byte1;\\n prev_byte1 = ReadSymbol(hgroup[0].codes, hgroup[0].htrees[literal_htree_index], br);\\n ringbuffer[pos & ringbuffer_mask] = prev_byte1;\\n if ((pos & ringbuffer_mask) === ringbuffer_mask) {\\n output.write(ringbuffer, ringbuffer_size);\\n }\\n ++pos;\\n }\\n meta_block_remaining_len -= insert_length;\\n if (meta_block_remaining_len <= 0) break;\\n if (distance_code < 0) {\\n var context;\\n br.readMoreInput();\\n if (block_length[2] === 0) {\\n DecodeBlockType(\\n num_block_types[2],\\n block_type_trees,\\n 2,\\n block_type,\\n block_type_rb,\\n block_type_rb_index,\\n br\\n );\\n block_length[2] = ReadBlockLength(block_len_trees, 2 * HUFFMAN_MAX_TABLE_SIZE, br);\\n dist_context_offset = block_type[2] << kDistanceContextBits;\\n dist_context_map_slice = dist_context_offset;\\n }\\n --block_length[2];\\n context = (copy_length > 4 ? 3 : copy_length - 2) & 255;\\n dist_htree_index = dist_context_map[dist_context_map_slice + context];\\n distance_code = ReadSymbol(hgroup[2].codes, hgroup[2].htrees[dist_htree_index], br);\\n if (distance_code >= num_direct_distance_codes) {\\n var nbits;\\n var postfix;\\n var offset;\\n distance_code -= num_direct_distance_codes;\\n postfix = distance_code & distance_postfix_mask;\\n distance_code >>= distance_postfix_bits;\\n nbits = (distance_code >> 1) + 1;\\n offset = (2 + (distance_code & 1) << nbits) - 4;\\n distance_code = num_direct_distance_codes + (offset + br.readBits(nbits) << distance_postfix_bits) + postfix;\\n }\\n }\\n distance = TranslateShortCodes(distance_code, dist_rb, dist_rb_idx);\\n if (distance < 0) {\\n throw new Error(\\\"[BrotliDecompress] invalid distance\\\");\\n }\\n if (pos < max_backward_distance && max_distance !== max_backward_distance) {\\n max_distance = pos;\\n } else {\\n max_distance = max_backward_distance;\\n }\\n copy_dst = pos & ringbuffer_mask;\\n if (distance > max_distance) {\\n if (copy_length >= BrotliDictionary.minDictionaryWordLength && copy_length <= BrotliDictionary.maxDictionaryWordLength) {\\n var offset = BrotliDictionary.offsetsByLength[copy_length];\\n var word_id = distance - max_distance - 1;\\n var shift = BrotliDictionary.sizeBitsByLength[copy_length];\\n var mask = (1 << shift) - 1;\\n var word_idx = word_id & mask;\\n var transform_idx = word_id >> shift;\\n offset += word_idx * copy_length;\\n if (transform_idx < Transform.kNumTransforms) {\\n var len = Transform.transformDictionaryWord(ringbuffer, copy_dst, offset, copy_length, transform_idx);\\n copy_dst += len;\\n pos += len;\\n meta_block_remaining_len -= len;\\n if (copy_dst >= ringbuffer_end) {\\n output.write(ringbuffer, ringbuffer_size);\\n for (var _x = 0; _x < copy_dst - ringbuffer_end; _x++)\\n ringbuffer[_x] = ringbuffer[ringbuffer_end + _x];\\n }\\n } else {\\n throw new Error(\\\"Invalid backward reference. pos: \\\" + pos + \\\" distance: \\\" + distance + \\\" len: \\\" + copy_length + \\\" bytes left: \\\" + meta_block_remaining_len);\\n }\\n } else {\\n throw new Error(\\\"Invalid backward reference. pos: \\\" + pos + \\\" distance: \\\" + distance + \\\" len: \\\" + copy_length + \\\" bytes left: \\\" + meta_block_remaining_len);\\n }\\n } else {\\n if (distance_code > 0) {\\n dist_rb[dist_rb_idx & 3] = distance;\\n ++dist_rb_idx;\\n }\\n if (copy_length > meta_block_remaining_len) {\\n throw new Error(\\\"Invalid backward reference. pos: \\\" + pos + \\\" distance: \\\" + distance + \\\" len: \\\" + copy_length + \\\" bytes left: \\\" + meta_block_remaining_len);\\n }\\n for (j = 0; j < copy_length; ++j) {\\n ringbuffer[pos & ringbuffer_mask] = ringbuffer[pos - distance & ringbuffer_mask];\\n if ((pos & ringbuffer_mask) === ringbuffer_mask) {\\n output.write(ringbuffer, ringbuffer_size);\\n }\\n ++pos;\\n --meta_block_remaining_len;\\n }\\n }\\n prev_byte1 = ringbuffer[pos - 1 & ringbuffer_mask];\\n prev_byte2 = ringbuffer[pos - 2 & ringbuffer_mask];\\n }\\n pos &= 1073741823;\\n }\\n output.write(ringbuffer, pos & ringbuffer_mask);\\n }\\n exports.BrotliDecompress = BrotliDecompress;\\n BrotliDictionary.init();\\n }\\n });\\n\\n // ../../node_modules/.pnpm/brotli@1.3.3/node_modules/brotli/decompress.js\\n var require_decompress = __commonJS({\\n \\\"../../node_modules/.pnpm/brotli@1.3.3/node_modules/brotli/decompress.js\\\"(exports, module) {\\n module.exports = require_decode().BrotliDecompressBuffer;\\n }\\n });\\n\\n // ../../node_modules/.pnpm/fontkit@2.0.4/node_modules/fontkit/dist/browser-module.mjs\\n var browser_module_exports = {};\\n __export(browser_module_exports, {\\n create: () => $d636bc798e7178db$export$185802fd694ee1f5,\\n defaultLanguage: () => $d636bc798e7178db$export$42940898df819940,\\n logErrors: () => $d636bc798e7178db$export$bd5c5d8b8dcafd78,\\n registerFormat: () => $d636bc798e7178db$export$36b2f24e97d43be,\\n setDefaultLanguage: () => $d636bc798e7178db$export$5157e7780d44cc36\\n });\\n function $parcel$export(e, n, v, s) {\\n Object.defineProperty(e, n, { get: v, set: s, enumerable: true, configurable: true });\\n }\\n function $parcel$interopDefault2(a) {\\n return a && a.__esModule ? a.default : a;\\n }\\n function $d636bc798e7178db$export$36b2f24e97d43be(format) {\\n $d636bc798e7178db$var$formats.push(format);\\n }\\n function $d636bc798e7178db$export$185802fd694ee1f5(buffer, postscriptName) {\\n for (let i = 0; i < $d636bc798e7178db$var$formats.length; i++) {\\n let format = $d636bc798e7178db$var$formats[i];\\n if (format.probe(buffer)) {\\n let font = new format(new (0, DecodeStream)(buffer));\\n if (postscriptName) return font.getFont(postscriptName);\\n return font;\\n }\\n }\\n throw new Error(\\\"Unknown font format\\\");\\n }\\n function $d636bc798e7178db$export$5157e7780d44cc36(lang = \\\"en\\\") {\\n $d636bc798e7178db$export$42940898df819940 = lang;\\n }\\n function $e71565f2ce09cb6b$export$69a3209f1a06c04d(target, key, descriptor) {\\n if (descriptor.get) {\\n let get = descriptor.get;\\n descriptor.get = function() {\\n let value = get.call(this);\\n Object.defineProperty(this, key, {\\n value\\n });\\n return value;\\n };\\n } else if (typeof descriptor.value === \\\"function\\\") {\\n let fn = descriptor.value;\\n return {\\n get() {\\n let cache2 = /* @__PURE__ */ new Map();\\n function memoized(...args) {\\n let key2 = args.length > 0 ? args[0] : \\\"value\\\";\\n if (cache2.has(key2)) return cache2.get(key2);\\n let result = fn.apply(this, args);\\n cache2.set(key2, result);\\n return result;\\n }\\n Object.defineProperty(this, key, {\\n value: memoized\\n });\\n return memoized;\\n }\\n };\\n }\\n }\\n function $e449ad78d50845fe$export$badc544e0651b6b1(platformID, encodingID, languageID = 0) {\\n if (platformID === 1 && $e449ad78d50845fe$export$479e671907f486d1[languageID]) return $e449ad78d50845fe$export$479e671907f486d1[languageID];\\n return $e449ad78d50845fe$export$6fef87b7618bdf0b[platformID][encodingID];\\n }\\n function $e449ad78d50845fe$export$1dceb3c14ed68bee(encoding) {\\n let cached = $e449ad78d50845fe$var$encodingCache.get(encoding);\\n if (cached) return cached;\\n let mapping = $e449ad78d50845fe$var$MAC_ENCODINGS[encoding];\\n if (mapping) {\\n let res = /* @__PURE__ */ new Map();\\n for (let i = 0; i < mapping.length; i++) res.set(mapping.charCodeAt(i), 128 + i);\\n $e449ad78d50845fe$var$encodingCache.set(encoding, res);\\n return res;\\n }\\n if ($e449ad78d50845fe$var$SINGLE_BYTE_ENCODINGS.has(encoding)) {\\n let decoder = new TextDecoder(encoding);\\n let mapping2 = new Uint8Array(128);\\n for (let i = 0; i < 128; i++) mapping2[i] = 128 + i;\\n let res = /* @__PURE__ */ new Map();\\n let s = decoder.decode(mapping2);\\n for (let i = 0; i < 128; i++) res.set(s.charCodeAt(i), 128 + i);\\n $e449ad78d50845fe$var$encodingCache.set(encoding, res);\\n return res;\\n }\\n }\\n function $7cbbe4e24ef3cb75$export$df0008c6ff2da22a(SubTable) {\\n let Lookup = new Struct({\\n lookupType: uint16,\\n flags: $7cbbe4e24ef3cb75$var$LookupFlags,\\n subTableCount: uint16,\\n subTables: new ArrayT(new Pointer(uint16, SubTable), \\\"subTableCount\\\"),\\n markFilteringSet: new Optional(uint16, (t) => t.flags.flags.useMarkFilteringSet)\\n });\\n return new LazyArray(new Pointer(uint16, Lookup), uint16);\\n }\\n function $6cb7dd5f47d82580$export$79f7d93d790934ba(entryData = {}, lookupType = uint16) {\\n let entry = Object.assign({\\n newState: uint16,\\n flags: uint16\\n }, entryData);\\n let Entry = new Struct(entry);\\n let StateArray = new $6cb7dd5f47d82580$export$c5af1eebc882e39a(new ArrayT(uint16, (t) => t.nClasses));\\n let StateHeader = new Struct({\\n nClasses: uint32,\\n classTable: new Pointer(uint32, new $6cb7dd5f47d82580$export$8351f8c2ae2f103c(lookupType)),\\n stateArray: new Pointer(uint32, StateArray),\\n entryTable: new Pointer(uint32, new $6cb7dd5f47d82580$export$c5af1eebc882e39a(Entry))\\n });\\n return StateHeader;\\n }\\n function $6cb7dd5f47d82580$export$105027425199cc51(entryData = {}, lookupType = uint16) {\\n let ClassLookupTable = new Struct({\\n version() {\\n return 8;\\n },\\n firstGlyph: uint16,\\n values: new ArrayT(uint8, uint16)\\n });\\n let entry = Object.assign({\\n newStateOffset: uint16,\\n // convert offset to stateArray index\\n newState: (t) => (t.newStateOffset - (t.parent.stateArray.base - t.parent._startOffset)) / t.parent.nClasses,\\n flags: uint16\\n }, entryData);\\n let Entry = new Struct(entry);\\n let StateArray = new $6cb7dd5f47d82580$export$c5af1eebc882e39a(new ArrayT(uint8, (t) => t.nClasses));\\n let StateHeader1 = new Struct({\\n nClasses: uint16,\\n classTable: new Pointer(uint16, ClassLookupTable),\\n stateArray: new Pointer(uint16, StateArray),\\n entryTable: new Pointer(uint16, new $6cb7dd5f47d82580$export$c5af1eebc882e39a(Entry))\\n });\\n return StateHeader1;\\n }\\n function $12727730ddfc8bfe$export$2e0ae67339d5f1ac(arr, cmp) {\\n let min = 0;\\n let max = arr.length - 1;\\n while (min <= max) {\\n let mid = min + max >> 1;\\n let res = cmp(arr[mid]);\\n if (res < 0) max = mid - 1;\\n else if (res > 0) min = mid + 1;\\n else return mid;\\n }\\n return -1;\\n }\\n function $12727730ddfc8bfe$export$d02631cccf789723(index, end) {\\n let range = [];\\n while (index < end) range.push(index++);\\n return range;\\n }\\n function $12727730ddfc8bfe$export$94fdf11bafc8de6b(base64) {\\n let bufferLength = base64.length * 0.75;\\n if (base64[base64.length - 1] === \\\"=\\\") {\\n bufferLength--;\\n if (base64[base64.length - 2] === \\\"=\\\") bufferLength--;\\n }\\n let bytes = new Uint8Array(bufferLength);\\n let p = 0;\\n for (let i = 0, len = base64.length; i < len; i += 4) {\\n let encoded1 = $12727730ddfc8bfe$var$LOOKUP[base64.charCodeAt(i)];\\n let encoded2 = $12727730ddfc8bfe$var$LOOKUP[base64.charCodeAt(i + 1)];\\n let encoded3 = $12727730ddfc8bfe$var$LOOKUP[base64.charCodeAt(i + 2)];\\n let encoded4 = $12727730ddfc8bfe$var$LOOKUP[base64.charCodeAt(i + 3)];\\n bytes[p++] = encoded1 << 2 | encoded2 >> 4;\\n bytes[p++] = (encoded2 & 15) << 4 | encoded3 >> 2;\\n bytes[p++] = (encoded3 & 3) << 6 | encoded4 & 63;\\n }\\n return bytes;\\n }\\n function $130d1a642ebcd2b7$export$ce50e82f12a827a4(tag) {\\n return $130d1a642ebcd2b7$var$OPENTYPE_SCRIPTS[tag];\\n }\\n function $130d1a642ebcd2b7$export$e5cb25e204fb8450(string) {\\n let len = string.length;\\n let idx = 0;\\n while (idx < len) {\\n let code = string.charCodeAt(idx++);\\n if (55296 <= code && code <= 56319 && idx < len) {\\n let next = string.charCodeAt(idx);\\n if (56320 <= next && next <= 57343) {\\n idx++;\\n code = ((code & 1023) << 10) + (next & 1023) + 65536;\\n }\\n }\\n let script = (0, $747425b437e121da$export$941569448d136665)(code);\\n if (script !== \\\"Common\\\" && script !== \\\"Inherited\\\" && script !== \\\"Unknown\\\") return $130d1a642ebcd2b7$var$UNICODE_SCRIPTS[script];\\n }\\n return $130d1a642ebcd2b7$var$UNICODE_SCRIPTS.Unknown;\\n }\\n function $130d1a642ebcd2b7$export$16fab0757cfc223d(codePoints) {\\n for (let i = 0; i < codePoints.length; i++) {\\n let codePoint = codePoints[i];\\n let script = (0, $747425b437e121da$export$941569448d136665)(codePoint);\\n if (script !== \\\"Common\\\" && script !== \\\"Inherited\\\" && script !== \\\"Unknown\\\") return $130d1a642ebcd2b7$var$UNICODE_SCRIPTS[script];\\n }\\n return $130d1a642ebcd2b7$var$UNICODE_SCRIPTS.Unknown;\\n }\\n function $130d1a642ebcd2b7$export$9fddb9d0dd7d8a54(script) {\\n if ($130d1a642ebcd2b7$var$RTL[script]) return \\\"rtl\\\";\\n return \\\"ltr\\\";\\n }\\n function $3b6302b64eccc32c$export$b813f7d2a1677c16(features) {\\n let res = {};\\n for (let k in features) {\\n let r;\\n if (r = $3b6302b64eccc32c$var$OTMapping[k]) {\\n if (res[r[0]] == null) res[r[0]] = {};\\n res[r[0]][r[1]] = features[k];\\n }\\n }\\n return res;\\n }\\n function $3b6302b64eccc32c$var$mapFeatureStrings(f) {\\n let [type, setting] = f;\\n if (isNaN(type)) var typeCode = $3b6302b64eccc32c$var$features[type] && $3b6302b64eccc32c$var$features[type].code;\\n else var typeCode = type;\\n if (isNaN(setting)) var settingCode = $3b6302b64eccc32c$var$features[type] && $3b6302b64eccc32c$var$features[type][setting];\\n else var settingCode = setting;\\n return [\\n typeCode,\\n settingCode\\n ];\\n }\\n function $3b6302b64eccc32c$export$bd6df347a4f391c4(features) {\\n let res = {};\\n if (Array.isArray(features)) for (let k = 0; k < features.length; k++) {\\n let r;\\n let f = $3b6302b64eccc32c$var$mapFeatureStrings(features[k]);\\n if (r = $3b6302b64eccc32c$var$AATMapping[f[0]] && $3b6302b64eccc32c$var$AATMapping[f[0]][f[1]]) res[r] = true;\\n }\\n else if (typeof features === \\\"object\\\") for (let type in features) {\\n let feature = features[type];\\n for (let setting in feature) {\\n let r;\\n let f = $3b6302b64eccc32c$var$mapFeatureStrings([\\n type,\\n setting\\n ]);\\n if (feature[setting] && (r = $3b6302b64eccc32c$var$AATMapping[f[0]] && $3b6302b64eccc32c$var$AATMapping[f[0]][f[1]])) res[r] = true;\\n }\\n }\\n return Object.keys(res);\\n }\\n function $55f71433a605c87d$var$swap(glyphs, rangeA, rangeB, reverseA = false, reverseB = false) {\\n let end = glyphs.splice(rangeB[0] - (rangeB[1] - 1), rangeB[1]);\\n if (reverseB) end.reverse();\\n let start = glyphs.splice(rangeA[0], rangeA[1], ...end);\\n if (reverseA) start.reverse();\\n glyphs.splice(rangeB[0] - (rangeA[1] - 1), 0, ...start);\\n return glyphs;\\n }\\n function $55f71433a605c87d$var$reorderGlyphs(glyphs, verb, firstGlyph, lastGlyph) {\\n let length = lastGlyph - firstGlyph + 1;\\n switch (verb) {\\n case 0:\\n return glyphs;\\n case 1:\\n return $55f71433a605c87d$var$swap(glyphs, [\\n firstGlyph,\\n 1\\n ], [\\n lastGlyph,\\n 0\\n ]);\\n case 2:\\n return $55f71433a605c87d$var$swap(glyphs, [\\n firstGlyph,\\n 0\\n ], [\\n lastGlyph,\\n 1\\n ]);\\n case 3:\\n return $55f71433a605c87d$var$swap(glyphs, [\\n firstGlyph,\\n 1\\n ], [\\n lastGlyph,\\n 1\\n ]);\\n case 4:\\n return $55f71433a605c87d$var$swap(glyphs, [\\n firstGlyph,\\n 2\\n ], [\\n lastGlyph,\\n 0\\n ]);\\n case 5:\\n return $55f71433a605c87d$var$swap(glyphs, [\\n firstGlyph,\\n 2\\n ], [\\n lastGlyph,\\n 0\\n ], true, false);\\n case 6:\\n return $55f71433a605c87d$var$swap(glyphs, [\\n firstGlyph,\\n 0\\n ], [\\n lastGlyph,\\n 2\\n ]);\\n case 7:\\n return $55f71433a605c87d$var$swap(glyphs, [\\n firstGlyph,\\n 0\\n ], [\\n lastGlyph,\\n 2\\n ], false, true);\\n case 8:\\n return $55f71433a605c87d$var$swap(glyphs, [\\n firstGlyph,\\n 1\\n ], [\\n lastGlyph,\\n 2\\n ]);\\n case 9:\\n return $55f71433a605c87d$var$swap(glyphs, [\\n firstGlyph,\\n 1\\n ], [\\n lastGlyph,\\n 2\\n ], false, true);\\n case 10:\\n return $55f71433a605c87d$var$swap(glyphs, [\\n firstGlyph,\\n 2\\n ], [\\n lastGlyph,\\n 1\\n ]);\\n case 11:\\n return $55f71433a605c87d$var$swap(glyphs, [\\n firstGlyph,\\n 2\\n ], [\\n lastGlyph,\\n 1\\n ], true, false);\\n case 12:\\n return $55f71433a605c87d$var$swap(glyphs, [\\n firstGlyph,\\n 2\\n ], [\\n lastGlyph,\\n 2\\n ]);\\n case 13:\\n return $55f71433a605c87d$var$swap(glyphs, [\\n firstGlyph,\\n 2\\n ], [\\n lastGlyph,\\n 2\\n ], true, false);\\n case 14:\\n return $55f71433a605c87d$var$swap(glyphs, [\\n firstGlyph,\\n 2\\n ], [\\n lastGlyph,\\n 2\\n ], false, true);\\n case 15:\\n return $55f71433a605c87d$var$swap(glyphs, [\\n firstGlyph,\\n 2\\n ], [\\n lastGlyph,\\n 2\\n ], true, true);\\n default:\\n throw new Error(`Unknown verb: ${verb}`);\\n }\\n }\\n function $764eb544bbe1ccf0$var$getShapingClass(codePoint) {\\n let res = $764eb544bbe1ccf0$var$trie.get(codePoint);\\n if (res) return res - 1;\\n let category = (0, $747425b437e121da$export$410364bbb673ddbc)(codePoint);\\n if (category === \\\"Mn\\\" || category === \\\"Me\\\" || category === \\\"Cf\\\") return $764eb544bbe1ccf0$var$ShapingClasses.Transparent;\\n return $764eb544bbe1ccf0$var$ShapingClasses.Non_Joining;\\n }\\n function $e1c6bbc8cb416f8c$var$getType(code) {\\n if ($e1c6bbc8cb416f8c$var$isL(code)) return $e1c6bbc8cb416f8c$var$L;\\n if ($e1c6bbc8cb416f8c$var$isV(code)) return $e1c6bbc8cb416f8c$var$V;\\n if ($e1c6bbc8cb416f8c$var$isT(code)) return $e1c6bbc8cb416f8c$var$T;\\n if ($e1c6bbc8cb416f8c$var$isLV(code)) return $e1c6bbc8cb416f8c$var$LV;\\n if ($e1c6bbc8cb416f8c$var$isLVT(code)) return $e1c6bbc8cb416f8c$var$LVT;\\n if ($e1c6bbc8cb416f8c$var$isTone(code)) return $e1c6bbc8cb416f8c$var$M;\\n return $e1c6bbc8cb416f8c$var$X;\\n }\\n function $e1c6bbc8cb416f8c$var$getGlyph(font, code, features) {\\n return new (0, $10e7b257e1a9a756$export$2e2bcd8739ae039)(font, font.glyphForCodePoint(code).id, [\\n code\\n ], features);\\n }\\n function $e1c6bbc8cb416f8c$var$decompose(glyphs, i, font) {\\n let glyph = glyphs[i];\\n let code = glyph.codePoints[0];\\n let s = code - $e1c6bbc8cb416f8c$var$HANGUL_BASE;\\n let t = $e1c6bbc8cb416f8c$var$T_BASE + s % $e1c6bbc8cb416f8c$var$T_COUNT;\\n s = s / $e1c6bbc8cb416f8c$var$T_COUNT | 0;\\n let l = $e1c6bbc8cb416f8c$var$L_BASE + s / $e1c6bbc8cb416f8c$var$V_COUNT | 0;\\n let v = $e1c6bbc8cb416f8c$var$V_BASE + s % $e1c6bbc8cb416f8c$var$V_COUNT;\\n if (!font.hasGlyphForCodePoint(l) || !font.hasGlyphForCodePoint(v) || t !== $e1c6bbc8cb416f8c$var$T_BASE && !font.hasGlyphForCodePoint(t)) return i;\\n let ljmo = $e1c6bbc8cb416f8c$var$getGlyph(font, l, glyph.features);\\n ljmo.features.ljmo = true;\\n let vjmo = $e1c6bbc8cb416f8c$var$getGlyph(font, v, glyph.features);\\n vjmo.features.vjmo = true;\\n let insert = [\\n ljmo,\\n vjmo\\n ];\\n if (t > $e1c6bbc8cb416f8c$var$T_BASE) {\\n let tjmo = $e1c6bbc8cb416f8c$var$getGlyph(font, t, glyph.features);\\n tjmo.features.tjmo = true;\\n insert.push(tjmo);\\n }\\n glyphs.splice(i, 1, ...insert);\\n return i + insert.length - 1;\\n }\\n function $e1c6bbc8cb416f8c$var$compose(glyphs, i, font) {\\n let glyph = glyphs[i];\\n let code = glyphs[i].codePoints[0];\\n let type = $e1c6bbc8cb416f8c$var$getType(code);\\n let prev = glyphs[i - 1].codePoints[0];\\n let prevType = $e1c6bbc8cb416f8c$var$getType(prev);\\n let lv, ljmo, vjmo, tjmo;\\n if (prevType === $e1c6bbc8cb416f8c$var$LV && type === $e1c6bbc8cb416f8c$var$T) {\\n lv = prev;\\n tjmo = glyph;\\n } else {\\n if (type === $e1c6bbc8cb416f8c$var$V) {\\n ljmo = glyphs[i - 1];\\n vjmo = glyph;\\n } else {\\n ljmo = glyphs[i - 2];\\n vjmo = glyphs[i - 1];\\n tjmo = glyph;\\n }\\n let l = ljmo.codePoints[0];\\n let v = vjmo.codePoints[0];\\n if ($e1c6bbc8cb416f8c$var$isCombiningL(l) && $e1c6bbc8cb416f8c$var$isCombiningV(v)) lv = $e1c6bbc8cb416f8c$var$HANGUL_BASE + ((l - $e1c6bbc8cb416f8c$var$L_BASE) * $e1c6bbc8cb416f8c$var$V_COUNT + (v - $e1c6bbc8cb416f8c$var$V_BASE)) * $e1c6bbc8cb416f8c$var$T_COUNT;\\n }\\n let t = tjmo && tjmo.codePoints[0] || $e1c6bbc8cb416f8c$var$T_BASE;\\n if (lv != null && (t === $e1c6bbc8cb416f8c$var$T_BASE || $e1c6bbc8cb416f8c$var$isCombiningT(t))) {\\n let s = lv + (t - $e1c6bbc8cb416f8c$var$T_BASE);\\n if (font.hasGlyphForCodePoint(s)) {\\n let del = prevType === $e1c6bbc8cb416f8c$var$V ? 3 : 2;\\n glyphs.splice(i - del + 1, del, $e1c6bbc8cb416f8c$var$getGlyph(font, s, glyph.features));\\n return i - del + 1;\\n }\\n }\\n if (ljmo) ljmo.features.ljmo = true;\\n if (vjmo) vjmo.features.vjmo = true;\\n if (tjmo) tjmo.features.tjmo = true;\\n if (prevType === $e1c6bbc8cb416f8c$var$LV) {\\n $e1c6bbc8cb416f8c$var$decompose(glyphs, i - 1, font);\\n return i + 1;\\n }\\n return i;\\n }\\n function $e1c6bbc8cb416f8c$var$getLength(code) {\\n switch ($e1c6bbc8cb416f8c$var$getType(code)) {\\n case $e1c6bbc8cb416f8c$var$LV:\\n case $e1c6bbc8cb416f8c$var$LVT:\\n return 1;\\n case $e1c6bbc8cb416f8c$var$V:\\n return 2;\\n case $e1c6bbc8cb416f8c$var$T:\\n return 3;\\n }\\n }\\n function $e1c6bbc8cb416f8c$var$reorderToneMark(glyphs, i, font) {\\n let glyph = glyphs[i];\\n let code = glyphs[i].codePoints[0];\\n if (font.glyphForCodePoint(code).advanceWidth === 0) return;\\n let prev = glyphs[i - 1].codePoints[0];\\n let len = $e1c6bbc8cb416f8c$var$getLength(prev);\\n glyphs.splice(i, 1);\\n return glyphs.splice(i - len, 0, glyph);\\n }\\n function $e1c6bbc8cb416f8c$var$insertDottedCircle(glyphs, i, font) {\\n let glyph = glyphs[i];\\n let code = glyphs[i].codePoints[0];\\n if (font.hasGlyphForCodePoint($e1c6bbc8cb416f8c$var$DOTTED_CIRCLE)) {\\n let dottedCircle = $e1c6bbc8cb416f8c$var$getGlyph(font, $e1c6bbc8cb416f8c$var$DOTTED_CIRCLE, glyph.features);\\n let idx = font.glyphForCodePoint(code).advanceWidth === 0 ? i : i + 1;\\n glyphs.splice(idx, 0, dottedCircle);\\n i++;\\n }\\n return i;\\n }\\n function $7826f90f6f0cecc9$var$indicCategory(glyph) {\\n return $7826f90f6f0cecc9$var$trie.get(glyph.codePoints[0]) >> 8;\\n }\\n function $7826f90f6f0cecc9$var$indicPosition(glyph) {\\n return 1 << ($7826f90f6f0cecc9$var$trie.get(glyph.codePoints[0]) & 255);\\n }\\n function $7826f90f6f0cecc9$var$setupSyllables(font, glyphs) {\\n let syllable = 0;\\n let last = 0;\\n for (let [start, end, tags] of $7826f90f6f0cecc9$var$stateMachine.match(glyphs.map($7826f90f6f0cecc9$var$indicCategory))) {\\n if (start > last) {\\n ++syllable;\\n for (let i = last; i < start; i++) glyphs[i].shaperInfo = new $7826f90f6f0cecc9$var$IndicInfo((0, $90a9d3398ee54fe5$export$a513ea61a7bee91c).X, (0, $90a9d3398ee54fe5$export$1a1f61c9c4dd9df0).End, \\\"non_indic_cluster\\\", syllable);\\n }\\n ++syllable;\\n for (let i = start; i <= end; i++) glyphs[i].shaperInfo = new $7826f90f6f0cecc9$var$IndicInfo(1 << $7826f90f6f0cecc9$var$indicCategory(glyphs[i]), $7826f90f6f0cecc9$var$indicPosition(glyphs[i]), tags[0], syllable);\\n last = end + 1;\\n }\\n if (last < glyphs.length) {\\n ++syllable;\\n for (let i = last; i < glyphs.length; i++) glyphs[i].shaperInfo = new $7826f90f6f0cecc9$var$IndicInfo((0, $90a9d3398ee54fe5$export$a513ea61a7bee91c).X, (0, $90a9d3398ee54fe5$export$1a1f61c9c4dd9df0).End, \\\"non_indic_cluster\\\", syllable);\\n }\\n }\\n function $7826f90f6f0cecc9$var$isConsonant(glyph) {\\n return glyph.shaperInfo.category & (0, $90a9d3398ee54fe5$export$8519deaa7de2b07);\\n }\\n function $7826f90f6f0cecc9$var$isJoiner(glyph) {\\n return glyph.shaperInfo.category & (0, $90a9d3398ee54fe5$export$bbcd928767338e0d);\\n }\\n function $7826f90f6f0cecc9$var$isHalantOrCoeng(glyph) {\\n return glyph.shaperInfo.category & (0, $90a9d3398ee54fe5$export$ca9599b2a300afc);\\n }\\n function $7826f90f6f0cecc9$var$wouldSubstitute(glyphs, feature) {\\n for (let glyph of glyphs) glyph.features = {\\n [feature]: true\\n };\\n let GSUB = glyphs[0]._font._layoutEngine.engine.GSUBProcessor;\\n GSUB.applyFeatures([\\n feature\\n ], glyphs);\\n return glyphs.length === 1;\\n }\\n function $7826f90f6f0cecc9$var$consonantPosition(font, consonant, virama) {\\n let glyphs = [\\n virama,\\n consonant,\\n virama\\n ];\\n if ($7826f90f6f0cecc9$var$wouldSubstitute(glyphs.slice(0, 2), \\\"blwf\\\") || $7826f90f6f0cecc9$var$wouldSubstitute(glyphs.slice(1, 3), \\\"blwf\\\")) return (0, $90a9d3398ee54fe5$export$1a1f61c9c4dd9df0).Below_C;\\n else if ($7826f90f6f0cecc9$var$wouldSubstitute(glyphs.slice(0, 2), \\\"pstf\\\") || $7826f90f6f0cecc9$var$wouldSubstitute(glyphs.slice(1, 3), \\\"pstf\\\")) return (0, $90a9d3398ee54fe5$export$1a1f61c9c4dd9df0).Post_C;\\n else if ($7826f90f6f0cecc9$var$wouldSubstitute(glyphs.slice(0, 2), \\\"pref\\\") || $7826f90f6f0cecc9$var$wouldSubstitute(glyphs.slice(1, 3), \\\"pref\\\")) return (0, $90a9d3398ee54fe5$export$1a1f61c9c4dd9df0).Post_C;\\n return (0, $90a9d3398ee54fe5$export$1a1f61c9c4dd9df0).Base_C;\\n }\\n function $7826f90f6f0cecc9$var$initialReordering(font, glyphs, plan) {\\n let indicConfig = plan.indicConfig;\\n let features = font._layoutEngine.engine.GSUBProcessor.features;\\n let dottedCircle = font.glyphForCodePoint(9676).id;\\n let virama = font.glyphForCodePoint(indicConfig.virama).id;\\n if (virama) {\\n let info = new (0, $10e7b257e1a9a756$export$2e2bcd8739ae039)(font, virama, [\\n indicConfig.virama\\n ]);\\n for (let i = 0; i < glyphs.length; i++) if (glyphs[i].shaperInfo.position === (0, $90a9d3398ee54fe5$export$1a1f61c9c4dd9df0).Base_C) glyphs[i].shaperInfo.position = $7826f90f6f0cecc9$var$consonantPosition(font, glyphs[i].copy(), info);\\n }\\n for (let start = 0, end = $7826f90f6f0cecc9$var$nextSyllable(glyphs, 0); start < glyphs.length; start = end, end = $7826f90f6f0cecc9$var$nextSyllable(glyphs, start)) {\\n let { category, syllableType } = glyphs[start].shaperInfo;\\n if (syllableType === \\\"symbol_cluster\\\" || syllableType === \\\"non_indic_cluster\\\") continue;\\n if (syllableType === \\\"broken_cluster\\\" && dottedCircle) {\\n let g = new (0, $10e7b257e1a9a756$export$2e2bcd8739ae039)(font, dottedCircle, [\\n 9676\\n ]);\\n g.shaperInfo = new $7826f90f6f0cecc9$var$IndicInfo(1 << $7826f90f6f0cecc9$var$indicCategory(g), $7826f90f6f0cecc9$var$indicPosition(g), glyphs[start].shaperInfo.syllableType, glyphs[start].shaperInfo.syllable);\\n let i = start;\\n while (i < end && glyphs[i].shaperInfo.category === (0, $90a9d3398ee54fe5$export$a513ea61a7bee91c).Repha) i++;\\n glyphs.splice(i++, 0, g);\\n end++;\\n }\\n let base = end;\\n let limit = start;\\n let hasReph = false;\\n if (indicConfig.rephPos !== (0, $90a9d3398ee54fe5$export$1a1f61c9c4dd9df0).Ra_To_Become_Reph && features.rphf && start + 3 <= end && (indicConfig.rephMode === \\\"Implicit\\\" && !$7826f90f6f0cecc9$var$isJoiner(glyphs[start + 2]) || indicConfig.rephMode === \\\"Explicit\\\" && glyphs[start + 2].shaperInfo.category === (0, $90a9d3398ee54fe5$export$a513ea61a7bee91c).ZWJ)) {\\n let g = [\\n glyphs[start].copy(),\\n glyphs[start + 1].copy(),\\n glyphs[start + 2].copy()\\n ];\\n if ($7826f90f6f0cecc9$var$wouldSubstitute(g.slice(0, 2), \\\"rphf\\\") || indicConfig.rephMode === \\\"Explicit\\\" && $7826f90f6f0cecc9$var$wouldSubstitute(g, \\\"rphf\\\")) {\\n limit += 2;\\n while (limit < end && $7826f90f6f0cecc9$var$isJoiner(glyphs[limit])) limit++;\\n base = start;\\n hasReph = true;\\n }\\n } else if (indicConfig.rephMode === \\\"Log_Repha\\\" && glyphs[start].shaperInfo.category === (0, $90a9d3398ee54fe5$export$a513ea61a7bee91c).Repha) {\\n limit++;\\n while (limit < end && $7826f90f6f0cecc9$var$isJoiner(glyphs[limit])) limit++;\\n base = start;\\n hasReph = true;\\n }\\n switch (indicConfig.basePos) {\\n case \\\"Last\\\": {\\n let i = end;\\n let seenBelow = false;\\n do {\\n let info = glyphs[--i].shaperInfo;\\n if ($7826f90f6f0cecc9$var$isConsonant(glyphs[i])) {\\n if (info.position !== (0, $90a9d3398ee54fe5$export$1a1f61c9c4dd9df0).Below_C && (info.position !== (0, $90a9d3398ee54fe5$export$1a1f61c9c4dd9df0).Post_C || seenBelow)) {\\n base = i;\\n break;\\n }\\n if (info.position === (0, $90a9d3398ee54fe5$export$1a1f61c9c4dd9df0).Below_C) seenBelow = true;\\n base = i;\\n } else if (start < i && info.category === (0, $90a9d3398ee54fe5$export$a513ea61a7bee91c).ZWJ && glyphs[i - 1].shaperInfo.category === (0, $90a9d3398ee54fe5$export$a513ea61a7bee91c).H) break;\\n } while (i > limit);\\n break;\\n }\\n case \\\"First\\\":\\n base = start;\\n for (let i = base + 1; i < end; i++) if ($7826f90f6f0cecc9$var$isConsonant(glyphs[i])) glyphs[i].shaperInfo.position = (0, $90a9d3398ee54fe5$export$1a1f61c9c4dd9df0).Below_C;\\n }\\n if (hasReph && base === start && limit - base <= 2) hasReph = false;\\n for (let i = start; i < base; i++) {\\n let info = glyphs[i].shaperInfo;\\n info.position = Math.min((0, $90a9d3398ee54fe5$export$1a1f61c9c4dd9df0).Pre_C, info.position);\\n }\\n if (base < end) glyphs[base].shaperInfo.position = (0, $90a9d3398ee54fe5$export$1a1f61c9c4dd9df0).Base_C;\\n for (let i = base + 1; i < end; i++) if (glyphs[i].shaperInfo.category === (0, $90a9d3398ee54fe5$export$a513ea61a7bee91c).M) {\\n for (let j = i + 1; j < end; j++) if ($7826f90f6f0cecc9$var$isConsonant(glyphs[j])) {\\n glyphs[j].shaperInfo.position = (0, $90a9d3398ee54fe5$export$1a1f61c9c4dd9df0).Final_C;\\n break;\\n }\\n break;\\n }\\n if (hasReph) glyphs[start].shaperInfo.position = (0, $90a9d3398ee54fe5$export$1a1f61c9c4dd9df0).Ra_To_Become_Reph;\\n if (plan.isOldSpec) {\\n let disallowDoubleHalants = plan.unicodeScript !== \\\"Malayalam\\\";\\n for (let i = base + 1; i < end; i++) if (glyphs[i].shaperInfo.category === (0, $90a9d3398ee54fe5$export$a513ea61a7bee91c).H) {\\n let j;\\n for (j = end - 1; j > i; j--) {\\n if ($7826f90f6f0cecc9$var$isConsonant(glyphs[j]) || disallowDoubleHalants && glyphs[j].shaperInfo.category === (0, $90a9d3398ee54fe5$export$a513ea61a7bee91c).H) break;\\n }\\n if (glyphs[j].shaperInfo.category !== (0, $90a9d3398ee54fe5$export$a513ea61a7bee91c).H && j > i) {\\n let t = glyphs[i];\\n glyphs.splice(i, 0, ...glyphs.splice(i + 1, j - i));\\n glyphs[j] = t;\\n }\\n break;\\n }\\n }\\n let lastPos = (0, $90a9d3398ee54fe5$export$1a1f61c9c4dd9df0).Start;\\n for (let i = start; i < end; i++) {\\n let info = glyphs[i].shaperInfo;\\n if (info.category & ((0, $90a9d3398ee54fe5$export$bbcd928767338e0d) | (0, $90a9d3398ee54fe5$export$a513ea61a7bee91c).N | (0, $90a9d3398ee54fe5$export$a513ea61a7bee91c).RS | (0, $90a9d3398ee54fe5$export$a513ea61a7bee91c).CM | (0, $90a9d3398ee54fe5$export$ca9599b2a300afc) & info.category)) {\\n info.position = lastPos;\\n if (info.category === (0, $90a9d3398ee54fe5$export$a513ea61a7bee91c).H && info.position === (0, $90a9d3398ee54fe5$export$1a1f61c9c4dd9df0).Pre_M) {\\n for (let j = i; j > start; j--) if (glyphs[j - 1].shaperInfo.position !== (0, $90a9d3398ee54fe5$export$1a1f61c9c4dd9df0).Pre_M) {\\n info.position = glyphs[j - 1].shaperInfo.position;\\n break;\\n }\\n }\\n } else if (info.position !== (0, $90a9d3398ee54fe5$export$1a1f61c9c4dd9df0).SMVD) lastPos = info.position;\\n }\\n let last = base;\\n for (let i = base + 1; i < end; i++) {\\n if ($7826f90f6f0cecc9$var$isConsonant(glyphs[i])) {\\n for (let j = last + 1; j < i; j++) if (glyphs[j].shaperInfo.position < (0, $90a9d3398ee54fe5$export$1a1f61c9c4dd9df0).SMVD) glyphs[j].shaperInfo.position = glyphs[i].shaperInfo.position;\\n last = i;\\n } else if (glyphs[i].shaperInfo.category === (0, $90a9d3398ee54fe5$export$a513ea61a7bee91c).M) last = i;\\n }\\n let arr = glyphs.slice(start, end);\\n arr.sort((a, b) => a.shaperInfo.position - b.shaperInfo.position);\\n glyphs.splice(start, arr.length, ...arr);\\n for (let i = start; i < end; i++) if (glyphs[i].shaperInfo.position === (0, $90a9d3398ee54fe5$export$1a1f61c9c4dd9df0).Base_C) {\\n base = i;\\n break;\\n }\\n for (let i = start; i < end && glyphs[i].shaperInfo.position === (0, $90a9d3398ee54fe5$export$1a1f61c9c4dd9df0).Ra_To_Become_Reph; i++) glyphs[i].features.rphf = true;\\n let blwf = !plan.isOldSpec && indicConfig.blwfMode === \\\"Pre_And_Post\\\";\\n for (let i = start; i < base; i++) {\\n glyphs[i].features.half = true;\\n if (blwf) glyphs[i].features.blwf = true;\\n }\\n for (let i = base + 1; i < end; i++) {\\n glyphs[i].features.abvf = true;\\n glyphs[i].features.pstf = true;\\n glyphs[i].features.blwf = true;\\n }\\n if (plan.isOldSpec && plan.unicodeScript === \\\"Devanagari\\\") {\\n for (let i = start; i + 1 < base; i++) if (glyphs[i].shaperInfo.category === (0, $90a9d3398ee54fe5$export$a513ea61a7bee91c).Ra && glyphs[i + 1].shaperInfo.category === (0, $90a9d3398ee54fe5$export$a513ea61a7bee91c).H && (i + 1 === base || glyphs[i + 2].shaperInfo.category === (0, $90a9d3398ee54fe5$export$a513ea61a7bee91c).ZWJ)) {\\n glyphs[i].features.blwf = true;\\n glyphs[i + 1].features.blwf = true;\\n }\\n }\\n let prefLen = 2;\\n if (features.pref && base + prefLen < end)\\n for (let i = base + 1; i + prefLen - 1 < end; i++) {\\n let g = [\\n glyphs[i].copy(),\\n glyphs[i + 1].copy()\\n ];\\n if ($7826f90f6f0cecc9$var$wouldSubstitute(g, \\\"pref\\\")) {\\n for (let j = 0; j < prefLen; j++) glyphs[i++].features.pref = true;\\n if (features.cfar) for (; i < end; i++) glyphs[i].features.cfar = true;\\n break;\\n }\\n }\\n for (let i = start + 1; i < end; i++) if ($7826f90f6f0cecc9$var$isJoiner(glyphs[i])) {\\n let nonJoiner = glyphs[i].shaperInfo.category === (0, $90a9d3398ee54fe5$export$a513ea61a7bee91c).ZWNJ;\\n let j = i;\\n do {\\n j--;\\n if (nonJoiner) delete glyphs[j].features.half;\\n } while (j > start && !$7826f90f6f0cecc9$var$isConsonant(glyphs[j]));\\n }\\n }\\n }\\n function $7826f90f6f0cecc9$var$finalReordering(font, glyphs, plan) {\\n let indicConfig = plan.indicConfig;\\n let features = font._layoutEngine.engine.GSUBProcessor.features;\\n for (let start = 0, end = $7826f90f6f0cecc9$var$nextSyllable(glyphs, 0); start < glyphs.length; start = end, end = $7826f90f6f0cecc9$var$nextSyllable(glyphs, start)) {\\n let tryPref = !!features.pref;\\n let base = start;\\n for (; base < end; base++) if (glyphs[base].shaperInfo.position >= (0, $90a9d3398ee54fe5$export$1a1f61c9c4dd9df0).Base_C) {\\n if (tryPref && base + 1 < end) {\\n for (let i = base + 1; i < end; i++) if (glyphs[i].features.pref) {\\n if (!(glyphs[i].substituted && glyphs[i].isLigated && !glyphs[i].isMultiplied)) {\\n base = i;\\n while (base < end && $7826f90f6f0cecc9$var$isHalantOrCoeng(glyphs[base])) base++;\\n glyphs[base].shaperInfo.position = (0, $90a9d3398ee54fe5$export$1a1f61c9c4dd9df0).BASE_C;\\n tryPref = false;\\n }\\n break;\\n }\\n }\\n if (plan.unicodeScript === \\\"Malayalam\\\") for (let i = base + 1; i < end; i++) {\\n while (i < end && $7826f90f6f0cecc9$var$isJoiner(glyphs[i])) i++;\\n if (i === end || !$7826f90f6f0cecc9$var$isHalantOrCoeng(glyphs[i])) break;\\n i++;\\n while (i < end && $7826f90f6f0cecc9$var$isJoiner(glyphs[i])) i++;\\n if (i < end && $7826f90f6f0cecc9$var$isConsonant(glyphs[i]) && glyphs[i].shaperInfo.position === (0, $90a9d3398ee54fe5$export$1a1f61c9c4dd9df0).Below_C) {\\n base = i;\\n glyphs[base].shaperInfo.position = (0, $90a9d3398ee54fe5$export$1a1f61c9c4dd9df0).Base_C;\\n }\\n }\\n if (start < base && glyphs[base].shaperInfo.position > (0, $90a9d3398ee54fe5$export$1a1f61c9c4dd9df0).Base_C) base--;\\n break;\\n }\\n if (base === end && start < base && glyphs[base - 1].shaperInfo.category === (0, $90a9d3398ee54fe5$export$a513ea61a7bee91c).ZWJ) base--;\\n if (base < end) while (start < base && glyphs[base].shaperInfo.category & ((0, $90a9d3398ee54fe5$export$a513ea61a7bee91c).N | (0, $90a9d3398ee54fe5$export$ca9599b2a300afc))) base--;\\n if (start + 1 < end && start < base) {\\n let newPos = base === end ? base - 2 : base - 1;\\n if (plan.unicodeScript !== \\\"Malayalam\\\" && plan.unicodeScript !== \\\"Tamil\\\") {\\n while (newPos > start && !(glyphs[newPos].shaperInfo.category & ((0, $90a9d3398ee54fe5$export$a513ea61a7bee91c).M | (0, $90a9d3398ee54fe5$export$ca9599b2a300afc)))) newPos--;\\n if ($7826f90f6f0cecc9$var$isHalantOrCoeng(glyphs[newPos]) && glyphs[newPos].shaperInfo.position !== (0, $90a9d3398ee54fe5$export$1a1f61c9c4dd9df0).Pre_M) {\\n if (newPos + 1 < end && $7826f90f6f0cecc9$var$isJoiner(glyphs[newPos + 1])) newPos++;\\n } else newPos = start;\\n }\\n if (start < newPos && glyphs[newPos].shaperInfo.position !== (0, $90a9d3398ee54fe5$export$1a1f61c9c4dd9df0).Pre_M) {\\n for (let i = newPos; i > start; i--) if (glyphs[i - 1].shaperInfo.position === (0, $90a9d3398ee54fe5$export$1a1f61c9c4dd9df0).Pre_M) {\\n let oldPos = i - 1;\\n if (oldPos < base && base <= newPos) base--;\\n let tmp = glyphs[oldPos];\\n glyphs.splice(oldPos, 0, ...glyphs.splice(oldPos + 1, newPos - oldPos));\\n glyphs[newPos] = tmp;\\n newPos--;\\n }\\n }\\n }\\n if (start + 1 < end && glyphs[start].shaperInfo.position === (0, $90a9d3398ee54fe5$export$1a1f61c9c4dd9df0).Ra_To_Become_Reph && glyphs[start].shaperInfo.category === (0, $90a9d3398ee54fe5$export$a513ea61a7bee91c).Repha !== (glyphs[start].isLigated && !glyphs[start].isMultiplied)) {\\n let newRephPos;\\n let rephPos = indicConfig.rephPos;\\n let found = false;\\n if (rephPos !== (0, $90a9d3398ee54fe5$export$1a1f61c9c4dd9df0).After_Post) {\\n newRephPos = start + 1;\\n while (newRephPos < base && !$7826f90f6f0cecc9$var$isHalantOrCoeng(glyphs[newRephPos])) newRephPos++;\\n if (newRephPos < base && $7826f90f6f0cecc9$var$isHalantOrCoeng(glyphs[newRephPos])) {\\n if (newRephPos + 1 < base && $7826f90f6f0cecc9$var$isJoiner(glyphs[newRephPos + 1])) newRephPos++;\\n found = true;\\n }\\n if (!found && rephPos === (0, $90a9d3398ee54fe5$export$1a1f61c9c4dd9df0).After_Main) {\\n newRephPos = base;\\n while (newRephPos + 1 < end && glyphs[newRephPos + 1].shaperInfo.position <= (0, $90a9d3398ee54fe5$export$1a1f61c9c4dd9df0).After_Main) newRephPos++;\\n found = newRephPos < end;\\n }\\n if (!found && rephPos === (0, $90a9d3398ee54fe5$export$1a1f61c9c4dd9df0).After_Sub) {\\n newRephPos = base;\\n while (newRephPos + 1 < end && !(glyphs[newRephPos + 1].shaperInfo.position & ((0, $90a9d3398ee54fe5$export$1a1f61c9c4dd9df0).Post_C | (0, $90a9d3398ee54fe5$export$1a1f61c9c4dd9df0).After_Post | (0, $90a9d3398ee54fe5$export$1a1f61c9c4dd9df0).SMVD))) newRephPos++;\\n found = newRephPos < end;\\n }\\n }\\n if (!found) {\\n newRephPos = start + 1;\\n while (newRephPos < base && !$7826f90f6f0cecc9$var$isHalantOrCoeng(glyphs[newRephPos])) newRephPos++;\\n if (newRephPos < base && $7826f90f6f0cecc9$var$isHalantOrCoeng(glyphs[newRephPos])) {\\n if (newRephPos + 1 < base && $7826f90f6f0cecc9$var$isJoiner(glyphs[newRephPos + 1])) newRephPos++;\\n found = true;\\n }\\n }\\n if (!found) {\\n newRephPos = end - 1;\\n while (newRephPos > start && glyphs[newRephPos].shaperInfo.position === (0, $90a9d3398ee54fe5$export$1a1f61c9c4dd9df0).SMVD) newRephPos--;\\n if ($7826f90f6f0cecc9$var$isHalantOrCoeng(glyphs[newRephPos])) {\\n for (let i = base + 1; i < newRephPos; i++) if (glyphs[i].shaperInfo.category === (0, $90a9d3398ee54fe5$export$a513ea61a7bee91c).M) newRephPos--;\\n }\\n }\\n let reph = glyphs[start];\\n glyphs.splice(start, 0, ...glyphs.splice(start + 1, newRephPos - start));\\n glyphs[newRephPos] = reph;\\n if (start < base && base <= newRephPos) base--;\\n }\\n if (tryPref && base + 1 < end) {\\n for (let i = base + 1; i < end; i++) if (glyphs[i].features.pref) {\\n if (glyphs[i].isLigated && !glyphs[i].isMultiplied) {\\n let newPos = base;\\n if (plan.unicodeScript !== \\\"Malayalam\\\" && plan.unicodeScript !== \\\"Tamil\\\") {\\n while (newPos > start && !(glyphs[newPos - 1].shaperInfo.category & ((0, $90a9d3398ee54fe5$export$a513ea61a7bee91c).M | (0, $90a9d3398ee54fe5$export$ca9599b2a300afc)))) newPos--;\\n if (newPos > start && glyphs[newPos - 1].shaperInfo.category === (0, $90a9d3398ee54fe5$export$a513ea61a7bee91c).M) {\\n let oldPos2 = i;\\n for (let j = base + 1; j < oldPos2; j++) if (glyphs[j].shaperInfo.category === (0, $90a9d3398ee54fe5$export$a513ea61a7bee91c).M) {\\n newPos--;\\n break;\\n }\\n }\\n }\\n if (newPos > start && $7826f90f6f0cecc9$var$isHalantOrCoeng(glyphs[newPos - 1])) {\\n if (newPos < end && $7826f90f6f0cecc9$var$isJoiner(glyphs[newPos])) newPos++;\\n }\\n let oldPos = i;\\n let tmp = glyphs[oldPos];\\n glyphs.splice(newPos + 1, 0, ...glyphs.splice(newPos, oldPos - newPos));\\n glyphs[newPos] = tmp;\\n if (newPos <= base && base < oldPos) base++;\\n }\\n break;\\n }\\n }\\n if (glyphs[start].shaperInfo.position === (0, $90a9d3398ee54fe5$export$1a1f61c9c4dd9df0).Pre_M && (!start || !/Cf|Mn/.test((0, $747425b437e121da$export$410364bbb673ddbc)(glyphs[start - 1].codePoints[0])))) glyphs[start].features.init = true;\\n }\\n }\\n function $7826f90f6f0cecc9$var$nextSyllable(glyphs, start) {\\n if (start >= glyphs.length) return start;\\n let syllable = glyphs[start].shaperInfo.syllable;\\n while (++start < glyphs.length && glyphs[start].shaperInfo.syllable === syllable) ;\\n return start;\\n }\\n function $7ab494fe977143c6$var$useCategory(glyph) {\\n return $7ab494fe977143c6$var$trie.get(glyph.codePoints[0]);\\n }\\n function $7ab494fe977143c6$var$setupSyllables(font, glyphs) {\\n let syllable = 0;\\n for (let [start, end, tags] of $7ab494fe977143c6$var$stateMachine.match(glyphs.map($7ab494fe977143c6$var$useCategory))) {\\n ++syllable;\\n for (let i = start; i <= end; i++) glyphs[i].shaperInfo = new $7ab494fe977143c6$var$USEInfo($7ab494fe977143c6$var$categories[$7ab494fe977143c6$var$useCategory(glyphs[i])], tags[0], syllable);\\n let limit = glyphs[start].shaperInfo.category === \\\"R\\\" ? 1 : Math.min(3, end - start);\\n for (let i = start; i < start + limit; i++) glyphs[i].features.rphf = true;\\n }\\n }\\n function $7ab494fe977143c6$var$clearSubstitutionFlags(font, glyphs) {\\n for (let glyph of glyphs) glyph.substituted = false;\\n }\\n function $7ab494fe977143c6$var$recordRphf(font, glyphs) {\\n for (let glyph of glyphs) if (glyph.substituted && glyph.features.rphf)\\n glyph.shaperInfo.category = \\\"R\\\";\\n }\\n function $7ab494fe977143c6$var$recordPref(font, glyphs) {\\n for (let glyph of glyphs) if (glyph.substituted)\\n glyph.shaperInfo.category = \\\"VPre\\\";\\n }\\n function $7ab494fe977143c6$var$reorder(font, glyphs) {\\n let dottedCircle = font.glyphForCodePoint(9676).id;\\n for (let start = 0, end = $7ab494fe977143c6$var$nextSyllable(glyphs, 0); start < glyphs.length; start = end, end = $7ab494fe977143c6$var$nextSyllable(glyphs, start)) {\\n let i, j;\\n let info = glyphs[start].shaperInfo;\\n let type = info.syllableType;\\n if (type !== \\\"virama_terminated_cluster\\\" && type !== \\\"standard_cluster\\\" && type !== \\\"broken_cluster\\\") continue;\\n if (type === \\\"broken_cluster\\\" && dottedCircle) {\\n let g = new (0, $10e7b257e1a9a756$export$2e2bcd8739ae039)(font, dottedCircle, [\\n 9676\\n ]);\\n g.shaperInfo = info;\\n for (i = start; i < end && glyphs[i].shaperInfo.category === \\\"R\\\"; i++) ;\\n glyphs.splice(++i, 0, g);\\n end++;\\n }\\n if (info.category === \\\"R\\\" && end - start > 1)\\n for (i = start + 1; i < end; i++) {\\n info = glyphs[i].shaperInfo;\\n if ($7ab494fe977143c6$var$isBase(info) || $7ab494fe977143c6$var$isHalant(glyphs[i])) {\\n if ($7ab494fe977143c6$var$isHalant(glyphs[i])) i--;\\n glyphs.splice(start, 0, ...glyphs.splice(start + 1, i - start), glyphs[i]);\\n break;\\n }\\n }\\n for (i = start, j = end; i < end; i++) {\\n info = glyphs[i].shaperInfo;\\n if ($7ab494fe977143c6$var$isBase(info) || $7ab494fe977143c6$var$isHalant(glyphs[i]))\\n j = $7ab494fe977143c6$var$isHalant(glyphs[i]) ? i + 1 : i;\\n else if ((info.category === \\\"VPre\\\" || info.category === \\\"VMPre\\\") && j < i) glyphs.splice(j, 1, glyphs[i], ...glyphs.splice(j, i - j));\\n }\\n }\\n }\\n function $7ab494fe977143c6$var$nextSyllable(glyphs, start) {\\n if (start >= glyphs.length) return start;\\n let syllable = glyphs[start].shaperInfo.syllable;\\n while (++start < glyphs.length && glyphs[start].shaperInfo.syllable === syllable) ;\\n return start;\\n }\\n function $7ab494fe977143c6$var$isHalant(glyph) {\\n return glyph.shaperInfo.category === \\\"H\\\" && !glyph.isLigated;\\n }\\n function $7ab494fe977143c6$var$isBase(info) {\\n return info.category === \\\"B\\\" || info.category === \\\"GB\\\";\\n }\\n function $102b6fe50f1d50b4$export$7877a478dd30fd3d(script) {\\n if (!Array.isArray(script)) script = [\\n script\\n ];\\n for (let s of script) {\\n let shaper = $102b6fe50f1d50b4$var$SHAPERS[s];\\n if (shaper) return shaper;\\n }\\n return 0, $649970d87335b30f$export$2e2bcd8739ae039;\\n }\\n function $21ee218f84ac7f32$var$read255UInt16(stream) {\\n let code = stream.readUInt8();\\n if (code === $21ee218f84ac7f32$var$WORD_CODE) return stream.readUInt16BE();\\n if (code === $21ee218f84ac7f32$var$ONE_MORE_BYTE_CODE1) return stream.readUInt8() + $21ee218f84ac7f32$var$LOWEST_U_CODE;\\n if (code === $21ee218f84ac7f32$var$ONE_MORE_BYTE_CODE2) return stream.readUInt8() + $21ee218f84ac7f32$var$LOWEST_U_CODE * 2;\\n return code;\\n }\\n function $21ee218f84ac7f32$var$withSign(flag, baseval) {\\n return flag & 1 ? baseval : -baseval;\\n }\\n function $21ee218f84ac7f32$var$decodeTriplet(flags, glyphs, nPoints) {\\n let y;\\n let x = y = 0;\\n let res = [];\\n for (let i = 0; i < nPoints; i++) {\\n let dx = 0, dy = 0;\\n let flag = flags.readUInt8();\\n let onCurve = !(flag >> 7);\\n flag &= 127;\\n if (flag < 10) {\\n dx = 0;\\n dy = $21ee218f84ac7f32$var$withSign(flag, ((flag & 14) << 7) + glyphs.readUInt8());\\n } else if (flag < 20) {\\n dx = $21ee218f84ac7f32$var$withSign(flag, ((flag - 10 & 14) << 7) + glyphs.readUInt8());\\n dy = 0;\\n } else if (flag < 84) {\\n var b0 = flag - 20;\\n var b1 = glyphs.readUInt8();\\n dx = $21ee218f84ac7f32$var$withSign(flag, 1 + (b0 & 48) + (b1 >> 4));\\n dy = $21ee218f84ac7f32$var$withSign(flag >> 1, 1 + ((b0 & 12) << 2) + (b1 & 15));\\n } else if (flag < 120) {\\n var b0 = flag - 84;\\n dx = $21ee218f84ac7f32$var$withSign(flag, 1 + (b0 / 12 << 8) + glyphs.readUInt8());\\n dy = $21ee218f84ac7f32$var$withSign(flag >> 1, 1 + (b0 % 12 >> 2 << 8) + glyphs.readUInt8());\\n } else if (flag < 124) {\\n var b1 = glyphs.readUInt8();\\n let b2 = glyphs.readUInt8();\\n dx = $21ee218f84ac7f32$var$withSign(flag, (b1 << 4) + (b2 >> 4));\\n dy = $21ee218f84ac7f32$var$withSign(flag >> 1, ((b2 & 15) << 8) + glyphs.readUInt8());\\n } else {\\n dx = $21ee218f84ac7f32$var$withSign(flag, glyphs.readUInt16BE());\\n dy = $21ee218f84ac7f32$var$withSign(flag >> 1, glyphs.readUInt16BE());\\n }\\n x += dx;\\n y += dy;\\n res.push(new (0, $69aac16029968692$export$baf26146a414f24a)(onCurve, false, x, y));\\n }\\n return res;\\n }\\n var import_fast_deep_equal, import_unicode_trie2, import_dfa, import_clone, import_tiny_inflate, import_decompress, $d636bc798e7178db$exports, $d636bc798e7178db$export$bd5c5d8b8dcafd78, $d636bc798e7178db$var$formats, $d636bc798e7178db$export$42940898df819940, $26a62205ad06574e$var$SubHeader, $26a62205ad06574e$var$CmapGroup, $26a62205ad06574e$var$UnicodeValueRange, $26a62205ad06574e$var$UVSMapping, $26a62205ad06574e$var$DefaultUVS, $26a62205ad06574e$var$NonDefaultUVS, $26a62205ad06574e$var$VarSelectorRecord, $26a62205ad06574e$var$CmapSubtable, $26a62205ad06574e$var$CmapEntry, $26a62205ad06574e$export$2e2bcd8739ae039, $f2612a29f92ac062$export$2e2bcd8739ae039, $2c179dd593583073$export$2e2bcd8739ae039, $bdc9060542264b85$var$HmtxEntry, $bdc9060542264b85$export$2e2bcd8739ae039, $dbf51cb3d3fe409d$export$2e2bcd8739ae039, $e449ad78d50845fe$var$SINGLE_BYTE_ENCODINGS, $e449ad78d50845fe$var$MAC_ENCODINGS, $e449ad78d50845fe$var$encodingCache, $e449ad78d50845fe$export$6fef87b7618bdf0b, $e449ad78d50845fe$export$479e671907f486d1, $e449ad78d50845fe$export$2092376fd002e13, $2bcf221753ec8e32$var$NameRecord, $2bcf221753ec8e32$var$LangTagRecord, $2bcf221753ec8e32$var$NameTable, $2bcf221753ec8e32$export$2e2bcd8739ae039, $2bcf221753ec8e32$var$NAMES, $84b272aa31b70606$var$OS2, $84b272aa31b70606$var$versions, $84b272aa31b70606$export$2e2bcd8739ae039, $32d9e2eb9565d93c$export$2e2bcd8739ae039, $5202bd9d9ad8eaac$export$2e2bcd8739ae039, $5c0f37ca5ffb1850$export$2e2bcd8739ae039, $2b2b260902b1c57e$var$loca, $2b2b260902b1c57e$export$2e2bcd8739ae039, $7afb878c7bea4f66$export$2e2bcd8739ae039, $6c92b6371bce8bd9$export$2e2bcd8739ae039, $43e9821ef3717eec$export$2e2bcd8739ae039, $c2d28e92708f99da$var$FLOAT_EOF, $c2d28e92708f99da$var$FLOAT_LOOKUP, $c2d28e92708f99da$var$FLOAT_ENCODE_LOOKUP, $c2d28e92708f99da$export$2e2bcd8739ae039, $61aa549f16d58b9b$export$2e2bcd8739ae039, $0e34a43d05bde82c$export$2e2bcd8739ae039, $0e34a43d05bde82c$var$Ptr, $6d59db2e29cc77b3$var$CFFBlendOp, $6d59db2e29cc77b3$export$2e2bcd8739ae039, $229224aec43783c5$export$2e2bcd8739ae039, $bc0433d9b7e41f5f$export$dee0027060fa13bd, $bc0433d9b7e41f5f$export$4f58f497e14a53c3, $ef658f5c9a1488b2$export$c33b50336c234f16, $ef658f5c9a1488b2$export$3ed0f9e1fee8d489, $ef658f5c9a1488b2$export$dc28be11139d4120, $7cbbe4e24ef3cb75$var$LangSysTable, $7cbbe4e24ef3cb75$var$LangSysRecord, $7cbbe4e24ef3cb75$var$Script, $7cbbe4e24ef3cb75$var$ScriptRecord, $7cbbe4e24ef3cb75$export$3e15fc05ce864229, $7cbbe4e24ef3cb75$var$FeatureParams, $7cbbe4e24ef3cb75$export$6e91cf7616333d5, $7cbbe4e24ef3cb75$var$FeatureRecord, $7cbbe4e24ef3cb75$export$aa18130def4b6cb4, $7cbbe4e24ef3cb75$var$LookupFlags, $7cbbe4e24ef3cb75$var$RangeRecord, $7cbbe4e24ef3cb75$export$17608c3f81a6111, $7cbbe4e24ef3cb75$var$ClassRangeRecord, $7cbbe4e24ef3cb75$export$843d551fbbafef71, $7cbbe4e24ef3cb75$export$8215d14a63d9fb10, $7cbbe4e24ef3cb75$var$LookupRecord, $7cbbe4e24ef3cb75$var$Rule, $7cbbe4e24ef3cb75$var$RuleSet, $7cbbe4e24ef3cb75$var$ClassRule, $7cbbe4e24ef3cb75$var$ClassSet, $7cbbe4e24ef3cb75$export$841858b892ce1f4c, $7cbbe4e24ef3cb75$var$ChainRule, $7cbbe4e24ef3cb75$var$ChainRuleSet, $7cbbe4e24ef3cb75$export$5e6d09e6861162f6, $1a47b0c45c1c22fe$var$F2DOT14, $1a47b0c45c1c22fe$var$RegionAxisCoordinates, $1a47b0c45c1c22fe$var$VariationRegionList, $1a47b0c45c1c22fe$var$DeltaSet, $1a47b0c45c1c22fe$var$ItemVariationData, $1a47b0c45c1c22fe$export$fe1b122a2710f241, $1a47b0c45c1c22fe$var$ConditionTable, $1a47b0c45c1c22fe$var$ConditionSet, $1a47b0c45c1c22fe$var$FeatureTableSubstitutionRecord, $1a47b0c45c1c22fe$var$FeatureTableSubstitution, $1a47b0c45c1c22fe$var$FeatureVariationRecord, $1a47b0c45c1c22fe$export$441b70b7971dd419, $b84fd3dd9d8eddb2$var$PredefinedOp, $b84fd3dd9d8eddb2$var$CFFEncodingVersion, $b84fd3dd9d8eddb2$var$Range1, $b84fd3dd9d8eddb2$var$Range2, $b84fd3dd9d8eddb2$var$CFFCustomEncoding, $b84fd3dd9d8eddb2$var$CFFEncoding, $b84fd3dd9d8eddb2$var$RangeArray, $b84fd3dd9d8eddb2$var$CFFCustomCharset, $b84fd3dd9d8eddb2$var$CFFCharset, $b84fd3dd9d8eddb2$var$FDRange3, $b84fd3dd9d8eddb2$var$FDRange4, $b84fd3dd9d8eddb2$var$FDSelect, $b84fd3dd9d8eddb2$var$ptr, $b84fd3dd9d8eddb2$var$CFFPrivateOp, $b84fd3dd9d8eddb2$var$FontDict, $b84fd3dd9d8eddb2$var$CFFTopDict, $b84fd3dd9d8eddb2$var$VariationStore, $b84fd3dd9d8eddb2$var$CFF2TopDict, $b84fd3dd9d8eddb2$var$CFFTop, $b84fd3dd9d8eddb2$export$2e2bcd8739ae039, $822ac0d589e4e237$var$CFFFont, $822ac0d589e4e237$export$2e2bcd8739ae039, $2bbf2bc1ce37cd8f$var$VerticalOrigin, $2bbf2bc1ce37cd8f$export$2e2bcd8739ae039, $0941618dc22a946d$export$16b227cb15d716a0, $0941618dc22a946d$export$62c53e75f69bfe12, $0941618dc22a946d$var$EBDTComponent, $0941618dc22a946d$var$ByteAligned, $0941618dc22a946d$var$BitAligned, $0941618dc22a946d$export$f1f5ddeb20d14f, $9911c4c7201c13de$var$SBitLineMetrics, $9911c4c7201c13de$var$CodeOffsetPair, $9911c4c7201c13de$var$IndexSubtable, $9911c4c7201c13de$var$IndexSubtableArray, $9911c4c7201c13de$var$BitmapSizeTable, $9911c4c7201c13de$export$2e2bcd8739ae039, $abb847051efd51b1$var$ImageTable, $abb847051efd51b1$export$2e2bcd8739ae039, $eb629188f3dfefdd$var$LayerRecord, $eb629188f3dfefdd$var$BaseGlyphRecord, $eb629188f3dfefdd$export$2e2bcd8739ae039, $08734b8e7dc64587$var$ColorRecord, $08734b8e7dc64587$export$2e2bcd8739ae039, $497cef411d884e34$var$BaseCoord, $497cef411d884e34$var$BaseValues, $497cef411d884e34$var$FeatMinMaxRecord, $497cef411d884e34$var$MinMax, $497cef411d884e34$var$BaseLangSysRecord, $497cef411d884e34$var$BaseScript, $497cef411d884e34$var$BaseScriptRecord, $497cef411d884e34$var$BaseScriptList, $497cef411d884e34$var$BaseTagList, $497cef411d884e34$var$Axis, $497cef411d884e34$export$2e2bcd8739ae039, $cf5f33c63ef209e6$var$AttachPoint, $cf5f33c63ef209e6$var$AttachList, $cf5f33c63ef209e6$var$CaretValue, $cf5f33c63ef209e6$var$LigGlyph, $cf5f33c63ef209e6$var$LigCaretList, $cf5f33c63ef209e6$var$MarkGlyphSetsDef, $cf5f33c63ef209e6$export$2e2bcd8739ae039, $47e0e8ef515d9903$var$ValueFormat, $47e0e8ef515d9903$var$types, $47e0e8ef515d9903$var$ValueRecord, $47e0e8ef515d9903$var$PairValueRecord, $47e0e8ef515d9903$var$PairSet, $47e0e8ef515d9903$var$Class2Record, $47e0e8ef515d9903$var$Anchor, $47e0e8ef515d9903$var$EntryExitRecord, $47e0e8ef515d9903$var$MarkRecord, $47e0e8ef515d9903$var$MarkArray, $47e0e8ef515d9903$var$BaseRecord, $47e0e8ef515d9903$var$BaseArray, $47e0e8ef515d9903$var$ComponentRecord, $47e0e8ef515d9903$var$LigatureAttach, $47e0e8ef515d9903$var$LigatureArray, $47e0e8ef515d9903$export$73a8cfb19cd43a0f, $47e0e8ef515d9903$export$2e2bcd8739ae039, $d3f442064af66e06$var$Sequence, $d3f442064af66e06$var$AlternateSet, $d3f442064af66e06$var$Ligature, $d3f442064af66e06$var$LigatureSet, $d3f442064af66e06$var$GSUBLookup, $d3f442064af66e06$export$2e2bcd8739ae039, $71cfb3c4767fbd0c$var$JstfGSUBModList, $71cfb3c4767fbd0c$var$JstfPriority, $71cfb3c4767fbd0c$var$JstfLangSys, $71cfb3c4767fbd0c$var$JstfLangSysRecord, $71cfb3c4767fbd0c$var$JstfScript, $71cfb3c4767fbd0c$var$JstfScriptRecord, $71cfb3c4767fbd0c$export$2e2bcd8739ae039, $d059a6bd2d3b5b63$var$VariableSizeNumber, $d059a6bd2d3b5b63$var$MapDataEntry, $d059a6bd2d3b5b63$var$DeltaSetIndexMap, $d059a6bd2d3b5b63$export$2e2bcd8739ae039, $dceeca3e1977ce30$var$Signature, $dceeca3e1977ce30$var$SignatureBlock, $dceeca3e1977ce30$export$2e2bcd8739ae039, $8acd740a9435aad0$var$GaspRange, $8acd740a9435aad0$export$2e2bcd8739ae039, $b5f380243c34d6a0$var$DeviceRecord, $b5f380243c34d6a0$export$2e2bcd8739ae039, $ca2df1256966e313$var$KernPair, $ca2df1256966e313$var$ClassTable, $ca2df1256966e313$var$Kern2Array, $ca2df1256966e313$var$KernSubtable, $ca2df1256966e313$var$KernTable, $ca2df1256966e313$export$2e2bcd8739ae039, $7a9f92b0c46ebe33$export$2e2bcd8739ae039, $2b2ccc419d152631$export$2e2bcd8739ae039, $ca5b40b9bcda9c9b$var$Ratio, $ca5b40b9bcda9c9b$var$vTable, $ca5b40b9bcda9c9b$var$VdmxGroup, $ca5b40b9bcda9c9b$export$2e2bcd8739ae039, $69530a3c40755af0$export$2e2bcd8739ae039, $344073dd270f0e62$var$VmtxEntry, $344073dd270f0e62$export$2e2bcd8739ae039, $3793b781918cfced$var$shortFrac, $3793b781918cfced$var$Correspondence, $3793b781918cfced$var$Segment, $3793b781918cfced$export$2e2bcd8739ae039, $6cb7dd5f47d82580$var$UnboundedArrayAccessor, $6cb7dd5f47d82580$export$c5af1eebc882e39a, $6cb7dd5f47d82580$export$8351f8c2ae2f103c, $6a3746e8c708f5a3$var$BslnSubtable, $6a3746e8c708f5a3$export$2e2bcd8739ae039, $d0c76fac617b308a$var$Setting, $d0c76fac617b308a$var$FeatureName, $d0c76fac617b308a$export$2e2bcd8739ae039, $e83fd065f00fcd01$var$Axis, $e83fd065f00fcd01$var$Instance, $e83fd065f00fcd01$export$2e2bcd8739ae039, $dbe33c8d3a7f131c$var$shortFrac, $dbe33c8d3a7f131c$var$Offset, $dbe33c8d3a7f131c$var$gvar, $dbe33c8d3a7f131c$export$2e2bcd8739ae039, $05b01887df96c4ee$var$ClassTable, $05b01887df96c4ee$var$WidthDeltaRecord, $05b01887df96c4ee$var$WidthDeltaCluster, $05b01887df96c4ee$var$ActionData, $05b01887df96c4ee$var$Action, $05b01887df96c4ee$var$PostcompensationAction, $05b01887df96c4ee$var$PostCompensationTable, $05b01887df96c4ee$var$JustificationTable, $05b01887df96c4ee$export$2e2bcd8739ae039, $03ee6ebd54db1053$var$LigatureData, $03ee6ebd54db1053$var$ContextualData, $03ee6ebd54db1053$var$InsertionData, $03ee6ebd54db1053$var$SubstitutionTable, $03ee6ebd54db1053$var$SubtableData, $03ee6ebd54db1053$var$Subtable, $03ee6ebd54db1053$var$FeatureEntry, $03ee6ebd54db1053$var$MorxChain, $03ee6ebd54db1053$export$2e2bcd8739ae039, $b7492a80b0d1a056$var$OpticalBounds, $b7492a80b0d1a056$export$2e2bcd8739ae039, $c3395722bea751e2$var$tables, $c3395722bea751e2$export$2e2bcd8739ae039, $816c07a04b6dba87$var$TableEntry, $816c07a04b6dba87$var$Directory, $816c07a04b6dba87$export$2e2bcd8739ae039, $12727730ddfc8bfe$export$3d28c1996ced1f14, $12727730ddfc8bfe$var$CHARS, $12727730ddfc8bfe$var$LOOKUP, $f08dd41ef10b694c$export$2e2bcd8739ae039, $0bba3a9db57637f3$export$2e2bcd8739ae039, $0a4bdfeb6dfd6f5e$export$2e2bcd8739ae039, $f34600ab9d7f70d8$export$2e2bcd8739ae039, $130d1a642ebcd2b7$var$UNICODE_SCRIPTS, $130d1a642ebcd2b7$var$OPENTYPE_SCRIPTS, $130d1a642ebcd2b7$var$RTL, $be07b3e97a42687a$export$2e2bcd8739ae039, $1ac75d9a55b67f01$export$2e2bcd8739ae039, $3b6302b64eccc32c$var$features, $3b6302b64eccc32c$var$feature, $3b6302b64eccc32c$var$OTMapping, $3b6302b64eccc32c$var$AATMapping, $ff5ce077dae0f144$export$2e2bcd8739ae039, $50c7aac9316f2948$var$START_OF_TEXT_STATE, $50c7aac9316f2948$var$END_OF_TEXT_CLASS, $50c7aac9316f2948$var$OUT_OF_BOUNDS_CLASS, $50c7aac9316f2948$var$DELETED_GLYPH_CLASS, $50c7aac9316f2948$var$DONT_ADVANCE, $50c7aac9316f2948$export$2e2bcd8739ae039, $55f71433a605c87d$var$MARK_FIRST, $55f71433a605c87d$var$MARK_LAST, $55f71433a605c87d$var$VERB, $55f71433a605c87d$var$SET_MARK, $55f71433a605c87d$var$SET_COMPONENT, $55f71433a605c87d$var$PERFORM_ACTION, $55f71433a605c87d$var$LAST_MASK, $55f71433a605c87d$var$STORE_MASK, $55f71433a605c87d$var$OFFSET_MASK, $55f71433a605c87d$var$REVERSE_DIRECTION, $55f71433a605c87d$var$CURRENT_INSERT_BEFORE, $55f71433a605c87d$var$MARKED_INSERT_BEFORE, $55f71433a605c87d$var$CURRENT_INSERT_COUNT, $55f71433a605c87d$var$MARKED_INSERT_COUNT, $55f71433a605c87d$export$2e2bcd8739ae039, $ba6dd74203be8728$export$2e2bcd8739ae039, $94d7a73bd2edfc9a$export$2e2bcd8739ae039, $649970d87335b30f$var$VARIATION_FEATURES, $649970d87335b30f$var$COMMON_FEATURES, $649970d87335b30f$var$FRACTIONAL_FEATURES, $649970d87335b30f$var$HORIZONTAL_FEATURES, $649970d87335b30f$var$DIRECTIONAL_FEATURES, $649970d87335b30f$export$2e2bcd8739ae039, $764eb544bbe1ccf0$var$trie, $764eb544bbe1ccf0$var$FEATURES, $764eb544bbe1ccf0$var$ShapingClasses, $764eb544bbe1ccf0$var$ISOL, $764eb544bbe1ccf0$var$FINA, $764eb544bbe1ccf0$var$FIN2, $764eb544bbe1ccf0$var$FIN3, $764eb544bbe1ccf0$var$MEDI, $764eb544bbe1ccf0$var$MED2, $764eb544bbe1ccf0$var$INIT, $764eb544bbe1ccf0$var$NONE, $764eb544bbe1ccf0$var$STATE_TABLE, $764eb544bbe1ccf0$export$2e2bcd8739ae039, $85d408632270248b$export$2e2bcd8739ae039, $a83b9c36aaa94fd3$var$DEFAULT_SCRIPTS, $a83b9c36aaa94fd3$export$2e2bcd8739ae039, $10e7b257e1a9a756$export$2e2bcd8739ae039, $e1c6bbc8cb416f8c$export$2e2bcd8739ae039, $e1c6bbc8cb416f8c$var$HANGUL_BASE, $e1c6bbc8cb416f8c$var$HANGUL_END, $e1c6bbc8cb416f8c$var$HANGUL_COUNT, $e1c6bbc8cb416f8c$var$L_BASE, $e1c6bbc8cb416f8c$var$V_BASE, $e1c6bbc8cb416f8c$var$T_BASE, $e1c6bbc8cb416f8c$var$L_COUNT, $e1c6bbc8cb416f8c$var$V_COUNT, $e1c6bbc8cb416f8c$var$T_COUNT, $e1c6bbc8cb416f8c$var$L_END, $e1c6bbc8cb416f8c$var$V_END, $e1c6bbc8cb416f8c$var$T_END, $e1c6bbc8cb416f8c$var$DOTTED_CIRCLE, $e1c6bbc8cb416f8c$var$isL, $e1c6bbc8cb416f8c$var$isV, $e1c6bbc8cb416f8c$var$isT, $e1c6bbc8cb416f8c$var$isTone, $e1c6bbc8cb416f8c$var$isLVT, $e1c6bbc8cb416f8c$var$isLV, $e1c6bbc8cb416f8c$var$isCombiningL, $e1c6bbc8cb416f8c$var$isCombiningV, $e1c6bbc8cb416f8c$var$isCombiningT, $e1c6bbc8cb416f8c$var$X, $e1c6bbc8cb416f8c$var$L, $e1c6bbc8cb416f8c$var$V, $e1c6bbc8cb416f8c$var$T, $e1c6bbc8cb416f8c$var$LV, $e1c6bbc8cb416f8c$var$LVT, $e1c6bbc8cb416f8c$var$M, $e1c6bbc8cb416f8c$var$NO_ACTION, $e1c6bbc8cb416f8c$var$DECOMPOSE, $e1c6bbc8cb416f8c$var$COMPOSE, $e1c6bbc8cb416f8c$var$TONE_MARK, $e1c6bbc8cb416f8c$var$INVALID, $e1c6bbc8cb416f8c$var$STATE_TABLE, $4b0735ca6c692ea5$exports, $aa333a9607471296$exports, $90a9d3398ee54fe5$export$a513ea61a7bee91c, $90a9d3398ee54fe5$export$1a1f61c9c4dd9df0, $90a9d3398ee54fe5$export$8519deaa7de2b07, $90a9d3398ee54fe5$export$bbcd928767338e0d, $90a9d3398ee54fe5$export$ca9599b2a300afc, $90a9d3398ee54fe5$export$e99d119da76a0fc5, $90a9d3398ee54fe5$export$f647c9cfdd77d95a, $7826f90f6f0cecc9$var$decompositions, $7826f90f6f0cecc9$var$trie, $7826f90f6f0cecc9$var$stateMachine, $7826f90f6f0cecc9$export$2e2bcd8739ae039, $7826f90f6f0cecc9$var$IndicInfo, $7ab494fe977143c6$var$categories, $7ab494fe977143c6$var$decompositions, $7ab494fe977143c6$var$trie, $7ab494fe977143c6$var$stateMachine, $7ab494fe977143c6$export$2e2bcd8739ae039, $7ab494fe977143c6$var$USEInfo, $102b6fe50f1d50b4$var$SHAPERS, $0a876c45f1f7c41c$export$2e2bcd8739ae039, $c96c93587d49c14d$export$2e2bcd8739ae039, $a62492810de27e3d$export$2e2bcd8739ae039, $4c0a7fa5df7a9ab1$export$2e2bcd8739ae039, $f43aec954cdfdf21$var$SVG_COMMANDS, $f43aec954cdfdf21$export$2e2bcd8739ae039, $7713b9b7b438dff8$export$2e2bcd8739ae039, $f92906be28e61769$export$2e2bcd8739ae039, $69aac16029968692$var$GlyfHeader, $69aac16029968692$var$ON_CURVE, $69aac16029968692$var$X_SHORT_VECTOR, $69aac16029968692$var$Y_SHORT_VECTOR, $69aac16029968692$var$REPEAT, $69aac16029968692$var$SAME_X, $69aac16029968692$var$SAME_Y, $69aac16029968692$var$ARG_1_AND_2_ARE_WORDS, $69aac16029968692$var$WE_HAVE_A_SCALE, $69aac16029968692$var$MORE_COMPONENTS, $69aac16029968692$var$WE_HAVE_AN_X_AND_Y_SCALE, $69aac16029968692$var$WE_HAVE_A_TWO_BY_TWO, $69aac16029968692$var$WE_HAVE_INSTRUCTIONS, $69aac16029968692$export$baf26146a414f24a, $69aac16029968692$var$Component, $69aac16029968692$export$2e2bcd8739ae039, $62cc5109c6101893$export$2e2bcd8739ae039, $25d8f049c222084c$var$SBIXImage, $25d8f049c222084c$export$2e2bcd8739ae039, $0d411f0165859681$var$COLRLayer, $0d411f0165859681$export$2e2bcd8739ae039, $0bb840cac04e911b$var$TUPLES_SHARE_POINT_NUMBERS, $0bb840cac04e911b$var$TUPLE_COUNT_MASK, $0bb840cac04e911b$var$EMBEDDED_TUPLE_COORD, $0bb840cac04e911b$var$INTERMEDIATE_TUPLE, $0bb840cac04e911b$var$PRIVATE_POINT_NUMBERS, $0bb840cac04e911b$var$TUPLE_INDEX_MASK, $0bb840cac04e911b$var$POINTS_ARE_WORDS, $0bb840cac04e911b$var$POINT_RUN_COUNT_MASK, $0bb840cac04e911b$var$DELTAS_ARE_ZERO, $0bb840cac04e911b$var$DELTAS_ARE_WORDS, $0bb840cac04e911b$var$DELTA_RUN_COUNT_MASK, $0bb840cac04e911b$export$2e2bcd8739ae039, $5cc7476da92df375$var$resolved, $5cc7476da92df375$export$2e2bcd8739ae039, $807e58506be70005$var$ON_CURVE, $807e58506be70005$var$X_SHORT_VECTOR, $807e58506be70005$var$Y_SHORT_VECTOR, $807e58506be70005$var$REPEAT, $807e58506be70005$var$SAME_X, $807e58506be70005$var$SAME_Y, $807e58506be70005$var$Point, $807e58506be70005$var$Glyf, $807e58506be70005$export$2e2bcd8739ae039, $4abbb6a5dbdc441a$export$2e2bcd8739ae039, $001d739428a71d5a$export$2e2bcd8739ae039, $4c1709dee528ea76$export$2e2bcd8739ae039, $c1726355ecc5b889$var$WOFFDirectoryEntry, $c1726355ecc5b889$var$WOFFDirectory, $c1726355ecc5b889$export$2e2bcd8739ae039, $760785214b9fc52c$export$2e2bcd8739ae039, $8046190c9f1ad19e$export$2e2bcd8739ae039, $c28ec7bbb3b8de3a$var$Base128, $c28ec7bbb3b8de3a$var$knownTags, $c28ec7bbb3b8de3a$var$WOFF2DirectoryEntry, $c28ec7bbb3b8de3a$var$WOFF2Directory, $c28ec7bbb3b8de3a$export$2e2bcd8739ae039, $21ee218f84ac7f32$export$2e2bcd8739ae039, $21ee218f84ac7f32$var$Substream, $21ee218f84ac7f32$var$GlyfTable, $21ee218f84ac7f32$var$WORD_CODE, $21ee218f84ac7f32$var$ONE_MORE_BYTE_CODE2, $21ee218f84ac7f32$var$ONE_MORE_BYTE_CODE1, $21ee218f84ac7f32$var$LOWEST_U_CODE, $cd5853a56c68fec7$var$TTCHeader, $cd5853a56c68fec7$export$2e2bcd8739ae039, $05f49f930186144e$var$DFontName, $05f49f930186144e$var$DFontData, $05f49f930186144e$var$Ref, $05f49f930186144e$var$Type, $05f49f930186144e$var$TypeList, $05f49f930186144e$var$DFontMap, $05f49f930186144e$var$DFontHeader, $05f49f930186144e$export$2e2bcd8739ae039;\\n var init_browser_module = __esm({\\n \\\"../../node_modules/.pnpm/fontkit@2.0.4/node_modules/fontkit/dist/browser-module.mjs\\\"() {\\n init_restructure();\\n init_define_property();\\n init_ts_decorate();\\n import_fast_deep_equal = __toESM(require_fast_deep_equal(), 1);\\n init_module();\\n import_unicode_trie2 = __toESM(require_unicode_trie(), 1);\\n import_dfa = __toESM(require_dfa(), 1);\\n import_clone = __toESM(require_clone(), 1);\\n import_tiny_inflate = __toESM(require_tiny_inflate(), 1);\\n import_decompress = __toESM(require_decompress(), 1);\\n $d636bc798e7178db$exports = {};\\n $parcel$export($d636bc798e7178db$exports, \\\"logErrors\\\", () => $d636bc798e7178db$export$bd5c5d8b8dcafd78);\\n $parcel$export($d636bc798e7178db$exports, \\\"registerFormat\\\", () => $d636bc798e7178db$export$36b2f24e97d43be);\\n $parcel$export($d636bc798e7178db$exports, \\\"create\\\", () => $d636bc798e7178db$export$185802fd694ee1f5);\\n $parcel$export($d636bc798e7178db$exports, \\\"defaultLanguage\\\", () => $d636bc798e7178db$export$42940898df819940);\\n $parcel$export($d636bc798e7178db$exports, \\\"setDefaultLanguage\\\", () => $d636bc798e7178db$export$5157e7780d44cc36);\\n $d636bc798e7178db$export$bd5c5d8b8dcafd78 = false;\\n $d636bc798e7178db$var$formats = [];\\n $d636bc798e7178db$export$42940898df819940 = \\\"en\\\";\\n $26a62205ad06574e$var$SubHeader = new Struct({\\n firstCode: uint16,\\n entryCount: uint16,\\n idDelta: int16,\\n idRangeOffset: uint16\\n });\\n $26a62205ad06574e$var$CmapGroup = new Struct({\\n startCharCode: uint32,\\n endCharCode: uint32,\\n glyphID: uint32\\n });\\n $26a62205ad06574e$var$UnicodeValueRange = new Struct({\\n startUnicodeValue: uint24,\\n additionalCount: uint8\\n });\\n $26a62205ad06574e$var$UVSMapping = new Struct({\\n unicodeValue: uint24,\\n glyphID: uint16\\n });\\n $26a62205ad06574e$var$DefaultUVS = new ArrayT($26a62205ad06574e$var$UnicodeValueRange, uint32);\\n $26a62205ad06574e$var$NonDefaultUVS = new ArrayT($26a62205ad06574e$var$UVSMapping, uint32);\\n $26a62205ad06574e$var$VarSelectorRecord = new Struct({\\n varSelector: uint24,\\n defaultUVS: new Pointer(uint32, $26a62205ad06574e$var$DefaultUVS, {\\n type: \\\"parent\\\"\\n }),\\n nonDefaultUVS: new Pointer(uint32, $26a62205ad06574e$var$NonDefaultUVS, {\\n type: \\\"parent\\\"\\n })\\n });\\n $26a62205ad06574e$var$CmapSubtable = new VersionedStruct(uint16, {\\n 0: {\\n length: uint16,\\n language: uint16,\\n codeMap: new LazyArray(uint8, 256)\\n },\\n 2: {\\n length: uint16,\\n language: uint16,\\n subHeaderKeys: new ArrayT(uint16, 256),\\n subHeaderCount: (t) => Math.max.apply(Math, t.subHeaderKeys),\\n subHeaders: new LazyArray($26a62205ad06574e$var$SubHeader, \\\"subHeaderCount\\\"),\\n glyphIndexArray: new LazyArray(uint16, \\\"subHeaderCount\\\")\\n },\\n 4: {\\n length: uint16,\\n language: uint16,\\n segCountX2: uint16,\\n segCount: (t) => t.segCountX2 >> 1,\\n searchRange: uint16,\\n entrySelector: uint16,\\n rangeShift: uint16,\\n endCode: new LazyArray(uint16, \\\"segCount\\\"),\\n reservedPad: new Reserved(uint16),\\n startCode: new LazyArray(uint16, \\\"segCount\\\"),\\n idDelta: new LazyArray(int16, \\\"segCount\\\"),\\n idRangeOffset: new LazyArray(uint16, \\\"segCount\\\"),\\n glyphIndexArray: new LazyArray(uint16, (t) => (t.length - t._currentOffset) / 2)\\n },\\n 6: {\\n length: uint16,\\n language: uint16,\\n firstCode: uint16,\\n entryCount: uint16,\\n glyphIndices: new LazyArray(uint16, \\\"entryCount\\\")\\n },\\n 8: {\\n reserved: new Reserved(uint16),\\n length: uint32,\\n language: uint16,\\n is32: new LazyArray(uint8, 8192),\\n nGroups: uint32,\\n groups: new LazyArray($26a62205ad06574e$var$CmapGroup, \\\"nGroups\\\")\\n },\\n 10: {\\n reserved: new Reserved(uint16),\\n length: uint32,\\n language: uint32,\\n firstCode: uint32,\\n entryCount: uint32,\\n glyphIndices: new LazyArray(uint16, \\\"numChars\\\")\\n },\\n 12: {\\n reserved: new Reserved(uint16),\\n length: uint32,\\n language: uint32,\\n nGroups: uint32,\\n groups: new LazyArray($26a62205ad06574e$var$CmapGroup, \\\"nGroups\\\")\\n },\\n 13: {\\n reserved: new Reserved(uint16),\\n length: uint32,\\n language: uint32,\\n nGroups: uint32,\\n groups: new LazyArray($26a62205ad06574e$var$CmapGroup, \\\"nGroups\\\")\\n },\\n 14: {\\n length: uint32,\\n numRecords: uint32,\\n varSelectors: new LazyArray($26a62205ad06574e$var$VarSelectorRecord, \\\"numRecords\\\")\\n }\\n });\\n $26a62205ad06574e$var$CmapEntry = new Struct({\\n platformID: uint16,\\n encodingID: uint16,\\n table: new Pointer(uint32, $26a62205ad06574e$var$CmapSubtable, {\\n type: \\\"parent\\\",\\n lazy: true\\n })\\n });\\n $26a62205ad06574e$export$2e2bcd8739ae039 = new Struct({\\n version: uint16,\\n numSubtables: uint16,\\n tables: new ArrayT($26a62205ad06574e$var$CmapEntry, \\\"numSubtables\\\")\\n });\\n $f2612a29f92ac062$export$2e2bcd8739ae039 = new Struct({\\n version: int32,\\n revision: int32,\\n checkSumAdjustment: uint32,\\n magicNumber: uint32,\\n flags: uint16,\\n unitsPerEm: uint16,\\n created: new ArrayT(int32, 2),\\n modified: new ArrayT(int32, 2),\\n xMin: int16,\\n yMin: int16,\\n xMax: int16,\\n yMax: int16,\\n macStyle: new Bitfield(uint16, [\\n \\\"bold\\\",\\n \\\"italic\\\",\\n \\\"underline\\\",\\n \\\"outline\\\",\\n \\\"shadow\\\",\\n \\\"condensed\\\",\\n \\\"extended\\\"\\n ]),\\n lowestRecPPEM: uint16,\\n fontDirectionHint: int16,\\n indexToLocFormat: int16,\\n glyphDataFormat: int16\\n // 0 for current format\\n });\\n $2c179dd593583073$export$2e2bcd8739ae039 = new Struct({\\n version: int32,\\n ascent: int16,\\n descent: int16,\\n lineGap: int16,\\n advanceWidthMax: uint16,\\n minLeftSideBearing: int16,\\n minRightSideBearing: int16,\\n xMaxExtent: int16,\\n caretSlopeRise: int16,\\n caretSlopeRun: int16,\\n caretOffset: int16,\\n reserved: new Reserved(int16, 4),\\n metricDataFormat: int16,\\n numberOfMetrics: uint16\\n // Number of advance widths in 'hmtx' table\\n });\\n $bdc9060542264b85$var$HmtxEntry = new Struct({\\n advance: uint16,\\n bearing: int16\\n });\\n $bdc9060542264b85$export$2e2bcd8739ae039 = new Struct({\\n metrics: new LazyArray($bdc9060542264b85$var$HmtxEntry, (t) => t.parent.hhea.numberOfMetrics),\\n bearings: new LazyArray(int16, (t) => t.parent.maxp.numGlyphs - t.parent.hhea.numberOfMetrics)\\n });\\n $dbf51cb3d3fe409d$export$2e2bcd8739ae039 = new Struct({\\n version: int32,\\n numGlyphs: uint16,\\n maxPoints: uint16,\\n maxContours: uint16,\\n maxComponentPoints: uint16,\\n maxComponentContours: uint16,\\n maxZones: uint16,\\n maxTwilightPoints: uint16,\\n maxStorage: uint16,\\n maxFunctionDefs: uint16,\\n maxInstructionDefs: uint16,\\n maxStackElements: uint16,\\n maxSizeOfInstructions: uint16,\\n maxComponentElements: uint16,\\n maxComponentDepth: uint16\\n // Maximum levels of recursion; 1 for simple components\\n });\\n $e449ad78d50845fe$var$SINGLE_BYTE_ENCODINGS = /* @__PURE__ */ new Set([\\n \\\"x-mac-roman\\\",\\n \\\"x-mac-cyrillic\\\",\\n \\\"iso-8859-6\\\",\\n \\\"iso-8859-8\\\"\\n ]);\\n $e449ad78d50845fe$var$MAC_ENCODINGS = {\\n \\\"x-mac-croatian\\\": \\\"\\\\xC4\\\\xC5\\\\xC7\\\\xC9\\\\xD1\\\\xD6\\\\xDC\\\\xE1\\\\xE0\\\\xE2\\\\xE4\\\\xE3\\\\xE5\\\\xE7\\\\xE9\\\\xE8\\\\xEA\\\\xEB\\\\xED\\\\xEC\\\\xEE\\\\xEF\\\\xF1\\\\xF3\\\\xF2\\\\xF4\\\\xF6\\\\xF5\\\\xFA\\\\xF9\\\\xFB\\\\xFC\\\\u2020\\\\xB0\\\\xA2\\\\xA3\\\\xA7\\\\u2022\\\\xB6\\\\xDF\\\\xAE\\\\u0160\\\\u2122\\\\xB4\\\\xA8\\\\u2260\\\\u017D\\\\xD8\\\\u221E\\\\xB1\\\\u2264\\\\u2265\\\\u2206\\\\xB5\\\\u2202\\\\u2211\\\\u220F\\\\u0161\\\\u222B\\\\xAA\\\\xBA\\\\u03A9\\\\u017E\\\\xF8\\\\xBF\\\\xA1\\\\xAC\\\\u221A\\\\u0192\\\\u2248\\\\u0106\\\\xAB\\\\u010C\\\\u2026 \\\\xC0\\\\xC3\\\\xD5\\\\u0152\\\\u0153\\\\u0110\\\\u2014\\\\u201C\\\\u201D\\\\u2018\\\\u2019\\\\xF7\\\\u25CA\\\\uF8FF\\\\xA9\\\\u2044\\\\u20AC\\\\u2039\\\\u203A\\\\xC6\\\\xBB\\\\u2013\\\\xB7\\\\u201A\\\\u201E\\\\u2030\\\\xC2\\\\u0107\\\\xC1\\\\u010D\\\\xC8\\\\xCD\\\\xCE\\\\xCF\\\\xCC\\\\xD3\\\\xD4\\\\u0111\\\\xD2\\\\xDA\\\\xDB\\\\xD9\\\\u0131\\\\u02C6\\\\u02DC\\\\xAF\\\\u03C0\\\\xCB\\\\u02DA\\\\xB8\\\\xCA\\\\xE6\\\\u02C7\\\",\\n \\\"x-mac-gaelic\\\": \\\"\\\\xC4\\\\xC5\\\\xC7\\\\xC9\\\\xD1\\\\xD6\\\\xDC\\\\xE1\\\\xE0\\\\xE2\\\\xE4\\\\xE3\\\\xE5\\\\xE7\\\\xE9\\\\xE8\\\\xEA\\\\xEB\\\\xED\\\\xEC\\\\xEE\\\\xEF\\\\xF1\\\\xF3\\\\xF2\\\\xF4\\\\xF6\\\\xF5\\\\xFA\\\\xF9\\\\xFB\\\\xFC\\\\u2020\\\\xB0\\\\xA2\\\\xA3\\\\xA7\\\\u2022\\\\xB6\\\\xDF\\\\xAE\\\\xA9\\\\u2122\\\\xB4\\\\xA8\\\\u2260\\\\xC6\\\\xD8\\\\u1E02\\\\xB1\\\\u2264\\\\u2265\\\\u1E03\\\\u010A\\\\u010B\\\\u1E0A\\\\u1E0B\\\\u1E1E\\\\u1E1F\\\\u0120\\\\u0121\\\\u1E40\\\\xE6\\\\xF8\\\\u1E41\\\\u1E56\\\\u1E57\\\\u027C\\\\u0192\\\\u017F\\\\u1E60\\\\xAB\\\\xBB\\\\u2026 \\\\xC0\\\\xC3\\\\xD5\\\\u0152\\\\u0153\\\\u2013\\\\u2014\\\\u201C\\\\u201D\\\\u2018\\\\u2019\\\\u1E61\\\\u1E9B\\\\xFF\\\\u0178\\\\u1E6A\\\\u20AC\\\\u2039\\\\u203A\\\\u0176\\\\u0177\\\\u1E6B\\\\xB7\\\\u1EF2\\\\u1EF3\\\\u204A\\\\xC2\\\\xCA\\\\xC1\\\\xCB\\\\xC8\\\\xCD\\\\xCE\\\\xCF\\\\xCC\\\\xD3\\\\xD4\\\\u2663\\\\xD2\\\\xDA\\\\xDB\\\\xD9\\\\u0131\\\\xDD\\\\xFD\\\\u0174\\\\u0175\\\\u1E84\\\\u1E85\\\\u1E80\\\\u1E81\\\\u1E82\\\\u1E83\\\",\\n \\\"x-mac-greek\\\": \\\"\\\\xC4\\\\xB9\\\\xB2\\\\xC9\\\\xB3\\\\xD6\\\\xDC\\\\u0385\\\\xE0\\\\xE2\\\\xE4\\\\u0384\\\\xA8\\\\xE7\\\\xE9\\\\xE8\\\\xEA\\\\xEB\\\\xA3\\\\u2122\\\\xEE\\\\xEF\\\\u2022\\\\xBD\\\\u2030\\\\xF4\\\\xF6\\\\xA6\\\\u20AC\\\\xF9\\\\xFB\\\\xFC\\\\u2020\\\\u0393\\\\u0394\\\\u0398\\\\u039B\\\\u039E\\\\u03A0\\\\xDF\\\\xAE\\\\xA9\\\\u03A3\\\\u03AA\\\\xA7\\\\u2260\\\\xB0\\\\xB7\\\\u0391\\\\xB1\\\\u2264\\\\u2265\\\\xA5\\\\u0392\\\\u0395\\\\u0396\\\\u0397\\\\u0399\\\\u039A\\\\u039C\\\\u03A6\\\\u03AB\\\\u03A8\\\\u03A9\\\\u03AC\\\\u039D\\\\xAC\\\\u039F\\\\u03A1\\\\u2248\\\\u03A4\\\\xAB\\\\xBB\\\\u2026 \\\\u03A5\\\\u03A7\\\\u0386\\\\u0388\\\\u0153\\\\u2013\\\\u2015\\\\u201C\\\\u201D\\\\u2018\\\\u2019\\\\xF7\\\\u0389\\\\u038A\\\\u038C\\\\u038E\\\\u03AD\\\\u03AE\\\\u03AF\\\\u03CC\\\\u038F\\\\u03CD\\\\u03B1\\\\u03B2\\\\u03C8\\\\u03B4\\\\u03B5\\\\u03C6\\\\u03B3\\\\u03B7\\\\u03B9\\\\u03BE\\\\u03BA\\\\u03BB\\\\u03BC\\\\u03BD\\\\u03BF\\\\u03C0\\\\u03CE\\\\u03C1\\\\u03C3\\\\u03C4\\\\u03B8\\\\u03C9\\\\u03C2\\\\u03C7\\\\u03C5\\\\u03B6\\\\u03CA\\\\u03CB\\\\u0390\\\\u03B0\\\\xAD\\\",\\n \\\"x-mac-icelandic\\\": \\\"\\\\xC4\\\\xC5\\\\xC7\\\\xC9\\\\xD1\\\\xD6\\\\xDC\\\\xE1\\\\xE0\\\\xE2\\\\xE4\\\\xE3\\\\xE5\\\\xE7\\\\xE9\\\\xE8\\\\xEA\\\\xEB\\\\xED\\\\xEC\\\\xEE\\\\xEF\\\\xF1\\\\xF3\\\\xF2\\\\xF4\\\\xF6\\\\xF5\\\\xFA\\\\xF9\\\\xFB\\\\xFC\\\\xDD\\\\xB0\\\\xA2\\\\xA3\\\\xA7\\\\u2022\\\\xB6\\\\xDF\\\\xAE\\\\xA9\\\\u2122\\\\xB4\\\\xA8\\\\u2260\\\\xC6\\\\xD8\\\\u221E\\\\xB1\\\\u2264\\\\u2265\\\\xA5\\\\xB5\\\\u2202\\\\u2211\\\\u220F\\\\u03C0\\\\u222B\\\\xAA\\\\xBA\\\\u03A9\\\\xE6\\\\xF8\\\\xBF\\\\xA1\\\\xAC\\\\u221A\\\\u0192\\\\u2248\\\\u2206\\\\xAB\\\\xBB\\\\u2026 \\\\xC0\\\\xC3\\\\xD5\\\\u0152\\\\u0153\\\\u2013\\\\u2014\\\\u201C\\\\u201D\\\\u2018\\\\u2019\\\\xF7\\\\u25CA\\\\xFF\\\\u0178\\\\u2044\\\\u20AC\\\\xD0\\\\xF0\\\\xDE\\\\xFE\\\\xFD\\\\xB7\\\\u201A\\\\u201E\\\\u2030\\\\xC2\\\\xCA\\\\xC1\\\\xCB\\\\xC8\\\\xCD\\\\xCE\\\\xCF\\\\xCC\\\\xD3\\\\xD4\\\\uF8FF\\\\xD2\\\\xDA\\\\xDB\\\\xD9\\\\u0131\\\\u02C6\\\\u02DC\\\\xAF\\\\u02D8\\\\u02D9\\\\u02DA\\\\xB8\\\\u02DD\\\\u02DB\\\\u02C7\\\",\\n \\\"x-mac-inuit\\\": \\\"\\\\u1403\\\\u1404\\\\u1405\\\\u1406\\\\u140A\\\\u140B\\\\u1431\\\\u1432\\\\u1433\\\\u1434\\\\u1438\\\\u1439\\\\u1449\\\\u144E\\\\u144F\\\\u1450\\\\u1451\\\\u1455\\\\u1456\\\\u1466\\\\u146D\\\\u146E\\\\u146F\\\\u1470\\\\u1472\\\\u1473\\\\u1483\\\\u148B\\\\u148C\\\\u148D\\\\u148E\\\\u1490\\\\u1491\\\\xB0\\\\u14A1\\\\u14A5\\\\u14A6\\\\u2022\\\\xB6\\\\u14A7\\\\xAE\\\\xA9\\\\u2122\\\\u14A8\\\\u14AA\\\\u14AB\\\\u14BB\\\\u14C2\\\\u14C3\\\\u14C4\\\\u14C5\\\\u14C7\\\\u14C8\\\\u14D0\\\\u14EF\\\\u14F0\\\\u14F1\\\\u14F2\\\\u14F4\\\\u14F5\\\\u1505\\\\u14D5\\\\u14D6\\\\u14D7\\\\u14D8\\\\u14DA\\\\u14DB\\\\u14EA\\\\u1528\\\\u1529\\\\u152A\\\\u152B\\\\u152D\\\\u2026 \\\\u152E\\\\u153E\\\\u1555\\\\u1556\\\\u1557\\\\u2013\\\\u2014\\\\u201C\\\\u201D\\\\u2018\\\\u2019\\\\u1558\\\\u1559\\\\u155A\\\\u155D\\\\u1546\\\\u1547\\\\u1548\\\\u1549\\\\u154B\\\\u154C\\\\u1550\\\\u157F\\\\u1580\\\\u1581\\\\u1582\\\\u1583\\\\u1584\\\\u1585\\\\u158F\\\\u1590\\\\u1591\\\\u1592\\\\u1593\\\\u1594\\\\u1595\\\\u1671\\\\u1672\\\\u1673\\\\u1674\\\\u1675\\\\u1676\\\\u1596\\\\u15A0\\\\u15A1\\\\u15A2\\\\u15A3\\\\u15A4\\\\u15A5\\\\u15A6\\\\u157C\\\\u0141\\\\u0142\\\",\\n \\\"x-mac-ce\\\": \\\"\\\\xC4\\\\u0100\\\\u0101\\\\xC9\\\\u0104\\\\xD6\\\\xDC\\\\xE1\\\\u0105\\\\u010C\\\\xE4\\\\u010D\\\\u0106\\\\u0107\\\\xE9\\\\u0179\\\\u017A\\\\u010E\\\\xED\\\\u010F\\\\u0112\\\\u0113\\\\u0116\\\\xF3\\\\u0117\\\\xF4\\\\xF6\\\\xF5\\\\xFA\\\\u011A\\\\u011B\\\\xFC\\\\u2020\\\\xB0\\\\u0118\\\\xA3\\\\xA7\\\\u2022\\\\xB6\\\\xDF\\\\xAE\\\\xA9\\\\u2122\\\\u0119\\\\xA8\\\\u2260\\\\u0123\\\\u012E\\\\u012F\\\\u012A\\\\u2264\\\\u2265\\\\u012B\\\\u0136\\\\u2202\\\\u2211\\\\u0142\\\\u013B\\\\u013C\\\\u013D\\\\u013E\\\\u0139\\\\u013A\\\\u0145\\\\u0146\\\\u0143\\\\xAC\\\\u221A\\\\u0144\\\\u0147\\\\u2206\\\\xAB\\\\xBB\\\\u2026 \\\\u0148\\\\u0150\\\\xD5\\\\u0151\\\\u014C\\\\u2013\\\\u2014\\\\u201C\\\\u201D\\\\u2018\\\\u2019\\\\xF7\\\\u25CA\\\\u014D\\\\u0154\\\\u0155\\\\u0158\\\\u2039\\\\u203A\\\\u0159\\\\u0156\\\\u0157\\\\u0160\\\\u201A\\\\u201E\\\\u0161\\\\u015A\\\\u015B\\\\xC1\\\\u0164\\\\u0165\\\\xCD\\\\u017D\\\\u017E\\\\u016A\\\\xD3\\\\xD4\\\\u016B\\\\u016E\\\\xDA\\\\u016F\\\\u0170\\\\u0171\\\\u0172\\\\u0173\\\\xDD\\\\xFD\\\\u0137\\\\u017B\\\\u0141\\\\u017C\\\\u0122\\\\u02C7\\\",\\n \\\"x-mac-romanian\\\": \\\"\\\\xC4\\\\xC5\\\\xC7\\\\xC9\\\\xD1\\\\xD6\\\\xDC\\\\xE1\\\\xE0\\\\xE2\\\\xE4\\\\xE3\\\\xE5\\\\xE7\\\\xE9\\\\xE8\\\\xEA\\\\xEB\\\\xED\\\\xEC\\\\xEE\\\\xEF\\\\xF1\\\\xF3\\\\xF2\\\\xF4\\\\xF6\\\\xF5\\\\xFA\\\\xF9\\\\xFB\\\\xFC\\\\u2020\\\\xB0\\\\xA2\\\\xA3\\\\xA7\\\\u2022\\\\xB6\\\\xDF\\\\xAE\\\\xA9\\\\u2122\\\\xB4\\\\xA8\\\\u2260\\\\u0102\\\\u0218\\\\u221E\\\\xB1\\\\u2264\\\\u2265\\\\xA5\\\\xB5\\\\u2202\\\\u2211\\\\u220F\\\\u03C0\\\\u222B\\\\xAA\\\\xBA\\\\u03A9\\\\u0103\\\\u0219\\\\xBF\\\\xA1\\\\xAC\\\\u221A\\\\u0192\\\\u2248\\\\u2206\\\\xAB\\\\xBB\\\\u2026 \\\\xC0\\\\xC3\\\\xD5\\\\u0152\\\\u0153\\\\u2013\\\\u2014\\\\u201C\\\\u201D\\\\u2018\\\\u2019\\\\xF7\\\\u25CA\\\\xFF\\\\u0178\\\\u2044\\\\u20AC\\\\u2039\\\\u203A\\\\u021A\\\\u021B\\\\u2021\\\\xB7\\\\u201A\\\\u201E\\\\u2030\\\\xC2\\\\xCA\\\\xC1\\\\xCB\\\\xC8\\\\xCD\\\\xCE\\\\xCF\\\\xCC\\\\xD3\\\\xD4\\\\uF8FF\\\\xD2\\\\xDA\\\\xDB\\\\xD9\\\\u0131\\\\u02C6\\\\u02DC\\\\xAF\\\\u02D8\\\\u02D9\\\\u02DA\\\\xB8\\\\u02DD\\\\u02DB\\\\u02C7\\\",\\n \\\"x-mac-turkish\\\": \\\"\\\\xC4\\\\xC5\\\\xC7\\\\xC9\\\\xD1\\\\xD6\\\\xDC\\\\xE1\\\\xE0\\\\xE2\\\\xE4\\\\xE3\\\\xE5\\\\xE7\\\\xE9\\\\xE8\\\\xEA\\\\xEB\\\\xED\\\\xEC\\\\xEE\\\\xEF\\\\xF1\\\\xF3\\\\xF2\\\\xF4\\\\xF6\\\\xF5\\\\xFA\\\\xF9\\\\xFB\\\\xFC\\\\u2020\\\\xB0\\\\xA2\\\\xA3\\\\xA7\\\\u2022\\\\xB6\\\\xDF\\\\xAE\\\\xA9\\\\u2122\\\\xB4\\\\xA8\\\\u2260\\\\xC6\\\\xD8\\\\u221E\\\\xB1\\\\u2264\\\\u2265\\\\xA5\\\\xB5\\\\u2202\\\\u2211\\\\u220F\\\\u03C0\\\\u222B\\\\xAA\\\\xBA\\\\u03A9\\\\xE6\\\\xF8\\\\xBF\\\\xA1\\\\xAC\\\\u221A\\\\u0192\\\\u2248\\\\u2206\\\\xAB\\\\xBB\\\\u2026 \\\\xC0\\\\xC3\\\\xD5\\\\u0152\\\\u0153\\\\u2013\\\\u2014\\\\u201C\\\\u201D\\\\u2018\\\\u2019\\\\xF7\\\\u25CA\\\\xFF\\\\u0178\\\\u011E\\\\u011F\\\\u0130\\\\u0131\\\\u015E\\\\u015F\\\\u2021\\\\xB7\\\\u201A\\\\u201E\\\\u2030\\\\xC2\\\\xCA\\\\xC1\\\\xCB\\\\xC8\\\\xCD\\\\xCE\\\\xCF\\\\xCC\\\\xD3\\\\xD4\\\\uF8FF\\\\xD2\\\\xDA\\\\xDB\\\\xD9\\\\uF8A0\\\\u02C6\\\\u02DC\\\\xAF\\\\u02D8\\\\u02D9\\\\u02DA\\\\xB8\\\\u02DD\\\\u02DB\\\\u02C7\\\"\\n };\\n $e449ad78d50845fe$var$encodingCache = /* @__PURE__ */ new Map();\\n $e449ad78d50845fe$export$6fef87b7618bdf0b = [\\n // unicode\\n [\\n \\\"utf-16be\\\",\\n \\\"utf-16be\\\",\\n \\\"utf-16be\\\",\\n \\\"utf-16be\\\",\\n \\\"utf-16be\\\",\\n \\\"utf-16be\\\",\\n \\\"utf-16be\\\"\\n ],\\n // macintosh\\n // Mappings available at http://unicode.org/Public/MAPPINGS/VENDORS/APPLE/\\n // 0\\tRoman 17\\tMalayalam\\n // 1\\tJapanese\\t 18\\tSinhalese\\n // 2\\tTraditional Chinese\\t 19\\tBurmese\\n // 3\\tKorean\\t 20\\tKhmer\\n // 4\\tArabic\\t 21\\tThai\\n // 5\\tHebrew\\t 22\\tLaotian\\n // 6\\tGreek\\t 23\\tGeorgian\\n // 7\\tRussian\\t 24\\tArmenian\\n // 8\\tRSymbol\\t 25\\tSimplified Chinese\\n // 9\\tDevanagari\\t 26\\tTibetan\\n // 10\\tGurmukhi\\t 27\\tMongolian\\n // 11\\tGujarati\\t 28\\tGeez\\n // 12\\tOriya\\t 29\\tSlavic\\n // 13\\tBengali\\t 30\\tVietnamese\\n // 14\\tTamil\\t 31\\tSindhi\\n // 15\\tTelugu\\t 32\\t(Uninterpreted)\\n // 16\\tKannada\\n [\\n \\\"x-mac-roman\\\",\\n \\\"shift-jis\\\",\\n \\\"big5\\\",\\n \\\"euc-kr\\\",\\n \\\"iso-8859-6\\\",\\n \\\"iso-8859-8\\\",\\n \\\"x-mac-greek\\\",\\n \\\"x-mac-cyrillic\\\",\\n \\\"x-mac-symbol\\\",\\n \\\"x-mac-devanagari\\\",\\n \\\"x-mac-gurmukhi\\\",\\n \\\"x-mac-gujarati\\\",\\n \\\"Oriya\\\",\\n \\\"Bengali\\\",\\n \\\"Tamil\\\",\\n \\\"Telugu\\\",\\n \\\"Kannada\\\",\\n \\\"Malayalam\\\",\\n \\\"Sinhalese\\\",\\n \\\"Burmese\\\",\\n \\\"Khmer\\\",\\n \\\"iso-8859-11\\\",\\n \\\"Laotian\\\",\\n \\\"Georgian\\\",\\n \\\"Armenian\\\",\\n \\\"gbk\\\",\\n \\\"Tibetan\\\",\\n \\\"Mongolian\\\",\\n \\\"Geez\\\",\\n \\\"x-mac-ce\\\",\\n \\\"Vietnamese\\\",\\n \\\"Sindhi\\\"\\n ],\\n // ISO (deprecated)\\n [\\n \\\"ascii\\\",\\n null,\\n \\\"iso-8859-1\\\"\\n ],\\n // windows\\n // Docs here: http://msdn.microsoft.com/en-us/library/system.text.encoding(v=vs.110).aspx\\n [\\n \\\"symbol\\\",\\n \\\"utf-16be\\\",\\n \\\"shift-jis\\\",\\n \\\"gb18030\\\",\\n \\\"big5\\\",\\n \\\"euc-kr\\\",\\n \\\"johab\\\",\\n null,\\n null,\\n null,\\n \\\"utf-16be\\\"\\n ]\\n ];\\n $e449ad78d50845fe$export$479e671907f486d1 = {\\n 15: \\\"x-mac-icelandic\\\",\\n 17: \\\"x-mac-turkish\\\",\\n 18: \\\"x-mac-croatian\\\",\\n 24: \\\"x-mac-ce\\\",\\n 25: \\\"x-mac-ce\\\",\\n 26: \\\"x-mac-ce\\\",\\n 27: \\\"x-mac-ce\\\",\\n 28: \\\"x-mac-ce\\\",\\n 30: \\\"x-mac-icelandic\\\",\\n 37: \\\"x-mac-romanian\\\",\\n 38: \\\"x-mac-ce\\\",\\n 39: \\\"x-mac-ce\\\",\\n 40: \\\"x-mac-ce\\\",\\n 143: \\\"x-mac-inuit\\\",\\n 146: \\\"x-mac-gaelic\\\"\\n };\\n $e449ad78d50845fe$export$2092376fd002e13 = [\\n // unicode\\n [],\\n {\\n 0: \\\"en\\\",\\n 30: \\\"fo\\\",\\n 60: \\\"ks\\\",\\n 90: \\\"rw\\\",\\n 1: \\\"fr\\\",\\n 31: \\\"fa\\\",\\n 61: \\\"ku\\\",\\n 91: \\\"rn\\\",\\n 2: \\\"de\\\",\\n 32: \\\"ru\\\",\\n 62: \\\"sd\\\",\\n 92: \\\"ny\\\",\\n 3: \\\"it\\\",\\n 33: \\\"zh\\\",\\n 63: \\\"bo\\\",\\n 93: \\\"mg\\\",\\n 4: \\\"nl\\\",\\n 34: \\\"nl-BE\\\",\\n 64: \\\"ne\\\",\\n 94: \\\"eo\\\",\\n 5: \\\"sv\\\",\\n 35: \\\"ga\\\",\\n 65: \\\"sa\\\",\\n 128: \\\"cy\\\",\\n 6: \\\"es\\\",\\n 36: \\\"sq\\\",\\n 66: \\\"mr\\\",\\n 129: \\\"eu\\\",\\n 7: \\\"da\\\",\\n 37: \\\"ro\\\",\\n 67: \\\"bn\\\",\\n 130: \\\"ca\\\",\\n 8: \\\"pt\\\",\\n 38: \\\"cz\\\",\\n 68: \\\"as\\\",\\n 131: \\\"la\\\",\\n 9: \\\"no\\\",\\n 39: \\\"sk\\\",\\n 69: \\\"gu\\\",\\n 132: \\\"qu\\\",\\n 10: \\\"he\\\",\\n 40: \\\"si\\\",\\n 70: \\\"pa\\\",\\n 133: \\\"gn\\\",\\n 11: \\\"ja\\\",\\n 41: \\\"yi\\\",\\n 71: \\\"or\\\",\\n 134: \\\"ay\\\",\\n 12: \\\"ar\\\",\\n 42: \\\"sr\\\",\\n 72: \\\"ml\\\",\\n 135: \\\"tt\\\",\\n 13: \\\"fi\\\",\\n 43: \\\"mk\\\",\\n 73: \\\"kn\\\",\\n 136: \\\"ug\\\",\\n 14: \\\"el\\\",\\n 44: \\\"bg\\\",\\n 74: \\\"ta\\\",\\n 137: \\\"dz\\\",\\n 15: \\\"is\\\",\\n 45: \\\"uk\\\",\\n 75: \\\"te\\\",\\n 138: \\\"jv\\\",\\n 16: \\\"mt\\\",\\n 46: \\\"be\\\",\\n 76: \\\"si\\\",\\n 139: \\\"su\\\",\\n 17: \\\"tr\\\",\\n 47: \\\"uz\\\",\\n 77: \\\"my\\\",\\n 140: \\\"gl\\\",\\n 18: \\\"hr\\\",\\n 48: \\\"kk\\\",\\n 78: \\\"km\\\",\\n 141: \\\"af\\\",\\n 19: \\\"zh-Hant\\\",\\n 49: \\\"az-Cyrl\\\",\\n 79: \\\"lo\\\",\\n 142: \\\"br\\\",\\n 20: \\\"ur\\\",\\n 50: \\\"az-Arab\\\",\\n 80: \\\"vi\\\",\\n 143: \\\"iu\\\",\\n 21: \\\"hi\\\",\\n 51: \\\"hy\\\",\\n 81: \\\"id\\\",\\n 144: \\\"gd\\\",\\n 22: \\\"th\\\",\\n 52: \\\"ka\\\",\\n 82: \\\"tl\\\",\\n 145: \\\"gv\\\",\\n 23: \\\"ko\\\",\\n 53: \\\"mo\\\",\\n 83: \\\"ms\\\",\\n 146: \\\"ga\\\",\\n 24: \\\"lt\\\",\\n 54: \\\"ky\\\",\\n 84: \\\"ms-Arab\\\",\\n 147: \\\"to\\\",\\n 25: \\\"pl\\\",\\n 55: \\\"tg\\\",\\n 85: \\\"am\\\",\\n 148: \\\"el-polyton\\\",\\n 26: \\\"hu\\\",\\n 56: \\\"tk\\\",\\n 86: \\\"ti\\\",\\n 149: \\\"kl\\\",\\n 27: \\\"es\\\",\\n 57: \\\"mn-CN\\\",\\n 87: \\\"om\\\",\\n 150: \\\"az\\\",\\n 28: \\\"lv\\\",\\n 58: \\\"mn\\\",\\n 88: \\\"so\\\",\\n 151: \\\"nn\\\",\\n 29: \\\"se\\\",\\n 59: \\\"ps\\\",\\n 89: \\\"sw\\\"\\n },\\n // ISO (deprecated)\\n [],\\n {\\n 1078: \\\"af\\\",\\n 16393: \\\"en-IN\\\",\\n 1159: \\\"rw\\\",\\n 1074: \\\"tn\\\",\\n 1052: \\\"sq\\\",\\n 6153: \\\"en-IE\\\",\\n 1089: \\\"sw\\\",\\n 1115: \\\"si\\\",\\n 1156: \\\"gsw\\\",\\n 8201: \\\"en-JM\\\",\\n 1111: \\\"kok\\\",\\n 1051: \\\"sk\\\",\\n 1118: \\\"am\\\",\\n 17417: \\\"en-MY\\\",\\n 1042: \\\"ko\\\",\\n 1060: \\\"sl\\\",\\n 5121: \\\"ar-DZ\\\",\\n 5129: \\\"en-NZ\\\",\\n 1088: \\\"ky\\\",\\n 11274: \\\"es-AR\\\",\\n 15361: \\\"ar-BH\\\",\\n 13321: \\\"en-PH\\\",\\n 1108: \\\"lo\\\",\\n 16394: \\\"es-BO\\\",\\n 3073: \\\"ar\\\",\\n 18441: \\\"en-SG\\\",\\n 1062: \\\"lv\\\",\\n 13322: \\\"es-CL\\\",\\n 2049: \\\"ar-IQ\\\",\\n 7177: \\\"en-ZA\\\",\\n 1063: \\\"lt\\\",\\n 9226: \\\"es-CO\\\",\\n 11265: \\\"ar-JO\\\",\\n 11273: \\\"en-TT\\\",\\n 2094: \\\"dsb\\\",\\n 5130: \\\"es-CR\\\",\\n 13313: \\\"ar-KW\\\",\\n 2057: \\\"en-GB\\\",\\n 1134: \\\"lb\\\",\\n 7178: \\\"es-DO\\\",\\n 12289: \\\"ar-LB\\\",\\n 1033: \\\"en\\\",\\n 1071: \\\"mk\\\",\\n 12298: \\\"es-EC\\\",\\n 4097: \\\"ar-LY\\\",\\n 12297: \\\"en-ZW\\\",\\n 2110: \\\"ms-BN\\\",\\n 17418: \\\"es-SV\\\",\\n 6145: \\\"ary\\\",\\n 1061: \\\"et\\\",\\n 1086: \\\"ms\\\",\\n 4106: \\\"es-GT\\\",\\n 8193: \\\"ar-OM\\\",\\n 1080: \\\"fo\\\",\\n 1100: \\\"ml\\\",\\n 18442: \\\"es-HN\\\",\\n 16385: \\\"ar-QA\\\",\\n 1124: \\\"fil\\\",\\n 1082: \\\"mt\\\",\\n 2058: \\\"es-MX\\\",\\n 1025: \\\"ar-SA\\\",\\n 1035: \\\"fi\\\",\\n 1153: \\\"mi\\\",\\n 19466: \\\"es-NI\\\",\\n 10241: \\\"ar-SY\\\",\\n 2060: \\\"fr-BE\\\",\\n 1146: \\\"arn\\\",\\n 6154: \\\"es-PA\\\",\\n 7169: \\\"aeb\\\",\\n 3084: \\\"fr-CA\\\",\\n 1102: \\\"mr\\\",\\n 15370: \\\"es-PY\\\",\\n 14337: \\\"ar-AE\\\",\\n 1036: \\\"fr\\\",\\n 1148: \\\"moh\\\",\\n 10250: \\\"es-PE\\\",\\n 9217: \\\"ar-YE\\\",\\n 5132: \\\"fr-LU\\\",\\n 1104: \\\"mn\\\",\\n 20490: \\\"es-PR\\\",\\n 1067: \\\"hy\\\",\\n 6156: \\\"fr-MC\\\",\\n 2128: \\\"mn-CN\\\",\\n 3082: \\\"es\\\",\\n 1101: \\\"as\\\",\\n 4108: \\\"fr-CH\\\",\\n 1121: \\\"ne\\\",\\n 1034: \\\"es\\\",\\n 2092: \\\"az-Cyrl\\\",\\n 1122: \\\"fy\\\",\\n 1044: \\\"nb\\\",\\n 21514: \\\"es-US\\\",\\n 1068: \\\"az\\\",\\n 1110: \\\"gl\\\",\\n 2068: \\\"nn\\\",\\n 14346: \\\"es-UY\\\",\\n 1133: \\\"ba\\\",\\n 1079: \\\"ka\\\",\\n 1154: \\\"oc\\\",\\n 8202: \\\"es-VE\\\",\\n 1069: \\\"eu\\\",\\n 3079: \\\"de-AT\\\",\\n 1096: \\\"or\\\",\\n 2077: \\\"sv-FI\\\",\\n 1059: \\\"be\\\",\\n 1031: \\\"de\\\",\\n 1123: \\\"ps\\\",\\n 1053: \\\"sv\\\",\\n 2117: \\\"bn\\\",\\n 5127: \\\"de-LI\\\",\\n 1045: \\\"pl\\\",\\n 1114: \\\"syr\\\",\\n 1093: \\\"bn-IN\\\",\\n 4103: \\\"de-LU\\\",\\n 1046: \\\"pt\\\",\\n 1064: \\\"tg\\\",\\n 8218: \\\"bs-Cyrl\\\",\\n 2055: \\\"de-CH\\\",\\n 2070: \\\"pt-PT\\\",\\n 2143: \\\"tzm\\\",\\n 5146: \\\"bs\\\",\\n 1032: \\\"el\\\",\\n 1094: \\\"pa\\\",\\n 1097: \\\"ta\\\",\\n 1150: \\\"br\\\",\\n 1135: \\\"kl\\\",\\n 1131: \\\"qu-BO\\\",\\n 1092: \\\"tt\\\",\\n 1026: \\\"bg\\\",\\n 1095: \\\"gu\\\",\\n 2155: \\\"qu-EC\\\",\\n 1098: \\\"te\\\",\\n 1027: \\\"ca\\\",\\n 1128: \\\"ha\\\",\\n 3179: \\\"qu\\\",\\n 1054: \\\"th\\\",\\n 3076: \\\"zh-HK\\\",\\n 1037: \\\"he\\\",\\n 1048: \\\"ro\\\",\\n 1105: \\\"bo\\\",\\n 5124: \\\"zh-MO\\\",\\n 1081: \\\"hi\\\",\\n 1047: \\\"rm\\\",\\n 1055: \\\"tr\\\",\\n 2052: \\\"zh\\\",\\n 1038: \\\"hu\\\",\\n 1049: \\\"ru\\\",\\n 1090: \\\"tk\\\",\\n 4100: \\\"zh-SG\\\",\\n 1039: \\\"is\\\",\\n 9275: \\\"smn\\\",\\n 1152: \\\"ug\\\",\\n 1028: \\\"zh-TW\\\",\\n 1136: \\\"ig\\\",\\n 4155: \\\"smj-NO\\\",\\n 1058: \\\"uk\\\",\\n 1155: \\\"co\\\",\\n 1057: \\\"id\\\",\\n 5179: \\\"smj\\\",\\n 1070: \\\"hsb\\\",\\n 1050: \\\"hr\\\",\\n 1117: \\\"iu\\\",\\n 3131: \\\"se-FI\\\",\\n 1056: \\\"ur\\\",\\n 4122: \\\"hr-BA\\\",\\n 2141: \\\"iu-Latn\\\",\\n 1083: \\\"se\\\",\\n 2115: \\\"uz-Cyrl\\\",\\n 1029: \\\"cs\\\",\\n 2108: \\\"ga\\\",\\n 2107: \\\"se-SE\\\",\\n 1091: \\\"uz\\\",\\n 1030: \\\"da\\\",\\n 1076: \\\"xh\\\",\\n 8251: \\\"sms\\\",\\n 1066: \\\"vi\\\",\\n 1164: \\\"prs\\\",\\n 1077: \\\"zu\\\",\\n 6203: \\\"sma-NO\\\",\\n 1106: \\\"cy\\\",\\n 1125: \\\"dv\\\",\\n 1040: \\\"it\\\",\\n 7227: \\\"sms\\\",\\n 1160: \\\"wo\\\",\\n 2067: \\\"nl-BE\\\",\\n 2064: \\\"it-CH\\\",\\n 1103: \\\"sa\\\",\\n 1157: \\\"sah\\\",\\n 1043: \\\"nl\\\",\\n 1041: \\\"ja\\\",\\n 7194: \\\"sr-Cyrl-BA\\\",\\n 1144: \\\"ii\\\",\\n 3081: \\\"en-AU\\\",\\n 1099: \\\"kn\\\",\\n 3098: \\\"sr\\\",\\n 1130: \\\"yo\\\",\\n 10249: \\\"en-BZ\\\",\\n 1087: \\\"kk\\\",\\n 6170: \\\"sr-Latn-BA\\\",\\n 4105: \\\"en-CA\\\",\\n 1107: \\\"km\\\",\\n 2074: \\\"sr-Latn\\\",\\n 9225: \\\"en-029\\\",\\n 1158: \\\"quc\\\",\\n 1132: \\\"nso\\\"\\n }\\n ];\\n $2bcf221753ec8e32$var$NameRecord = new Struct({\\n platformID: uint16,\\n encodingID: uint16,\\n languageID: uint16,\\n nameID: uint16,\\n length: uint16,\\n string: new Pointer(uint16, new StringT(\\\"length\\\", (t) => (0, $e449ad78d50845fe$export$badc544e0651b6b1)(t.platformID, t.encodingID, t.languageID)), {\\n type: \\\"parent\\\",\\n relativeTo: (ctx) => ctx.parent.stringOffset,\\n allowNull: false\\n })\\n });\\n $2bcf221753ec8e32$var$LangTagRecord = new Struct({\\n length: uint16,\\n tag: new Pointer(uint16, new StringT(\\\"length\\\", \\\"utf16be\\\"), {\\n type: \\\"parent\\\",\\n relativeTo: (ctx) => ctx.stringOffset\\n })\\n });\\n $2bcf221753ec8e32$var$NameTable = new VersionedStruct(uint16, {\\n 0: {\\n count: uint16,\\n stringOffset: uint16,\\n records: new ArrayT($2bcf221753ec8e32$var$NameRecord, \\\"count\\\")\\n },\\n 1: {\\n count: uint16,\\n stringOffset: uint16,\\n records: new ArrayT($2bcf221753ec8e32$var$NameRecord, \\\"count\\\"),\\n langTagCount: uint16,\\n langTags: new ArrayT($2bcf221753ec8e32$var$LangTagRecord, \\\"langTagCount\\\")\\n }\\n });\\n $2bcf221753ec8e32$export$2e2bcd8739ae039 = $2bcf221753ec8e32$var$NameTable;\\n $2bcf221753ec8e32$var$NAMES = [\\n \\\"copyright\\\",\\n \\\"fontFamily\\\",\\n \\\"fontSubfamily\\\",\\n \\\"uniqueSubfamily\\\",\\n \\\"fullName\\\",\\n \\\"version\\\",\\n \\\"postscriptName\\\",\\n \\\"trademark\\\",\\n \\\"manufacturer\\\",\\n \\\"designer\\\",\\n \\\"description\\\",\\n \\\"vendorURL\\\",\\n \\\"designerURL\\\",\\n \\\"license\\\",\\n \\\"licenseURL\\\",\\n null,\\n \\\"preferredFamily\\\",\\n \\\"preferredSubfamily\\\",\\n \\\"compatibleFull\\\",\\n \\\"sampleText\\\",\\n \\\"postscriptCIDFontName\\\",\\n \\\"wwsFamilyName\\\",\\n \\\"wwsSubfamilyName\\\"\\n ];\\n $2bcf221753ec8e32$var$NameTable.process = function(stream) {\\n var records = {};\\n for (let record of this.records) {\\n let language = (0, $e449ad78d50845fe$export$2092376fd002e13)[record.platformID][record.languageID];\\n if (language == null && this.langTags != null && record.languageID >= 32768) language = this.langTags[record.languageID - 32768].tag;\\n if (language == null) language = record.platformID + \\\"-\\\" + record.languageID;\\n let key = record.nameID >= 256 ? \\\"fontFeatures\\\" : $2bcf221753ec8e32$var$NAMES[record.nameID] || record.nameID;\\n if (records[key] == null) records[key] = {};\\n let obj = records[key];\\n if (record.nameID >= 256) obj = obj[record.nameID] || (obj[record.nameID] = {});\\n if (typeof record.string === \\\"string\\\" || typeof obj[language] !== \\\"string\\\") obj[language] = record.string;\\n }\\n this.records = records;\\n };\\n $2bcf221753ec8e32$var$NameTable.preEncode = function() {\\n if (Array.isArray(this.records)) return;\\n this.version = 0;\\n let records = [];\\n for (let key in this.records) {\\n let val = this.records[key];\\n if (key === \\\"fontFeatures\\\") continue;\\n records.push({\\n platformID: 3,\\n encodingID: 1,\\n languageID: 1033,\\n nameID: $2bcf221753ec8e32$var$NAMES.indexOf(key),\\n length: val.en.length * 2,\\n string: val.en\\n });\\n if (key === \\\"postscriptName\\\") records.push({\\n platformID: 1,\\n encodingID: 0,\\n languageID: 0,\\n nameID: $2bcf221753ec8e32$var$NAMES.indexOf(key),\\n length: val.en.length,\\n string: val.en\\n });\\n }\\n this.records = records;\\n this.count = records.length;\\n this.stringOffset = $2bcf221753ec8e32$var$NameTable.size(this, null, false);\\n };\\n $84b272aa31b70606$var$OS2 = new VersionedStruct(uint16, {\\n header: {\\n xAvgCharWidth: int16,\\n usWeightClass: uint16,\\n usWidthClass: uint16,\\n fsType: new Bitfield(uint16, [\\n null,\\n \\\"noEmbedding\\\",\\n \\\"viewOnly\\\",\\n \\\"editable\\\",\\n null,\\n null,\\n null,\\n null,\\n \\\"noSubsetting\\\",\\n \\\"bitmapOnly\\\"\\n ]),\\n ySubscriptXSize: int16,\\n ySubscriptYSize: int16,\\n ySubscriptXOffset: int16,\\n ySubscriptYOffset: int16,\\n ySuperscriptXSize: int16,\\n ySuperscriptYSize: int16,\\n ySuperscriptXOffset: int16,\\n ySuperscriptYOffset: int16,\\n yStrikeoutSize: int16,\\n yStrikeoutPosition: int16,\\n sFamilyClass: int16,\\n panose: new ArrayT(uint8, 10),\\n ulCharRange: new ArrayT(uint32, 4),\\n vendorID: new StringT(4),\\n fsSelection: new Bitfield(uint16, [\\n \\\"italic\\\",\\n \\\"underscore\\\",\\n \\\"negative\\\",\\n \\\"outlined\\\",\\n \\\"strikeout\\\",\\n \\\"bold\\\",\\n \\\"regular\\\",\\n \\\"useTypoMetrics\\\",\\n \\\"wws\\\",\\n \\\"oblique\\\"\\n ]),\\n usFirstCharIndex: uint16,\\n usLastCharIndex: uint16\\n // The maximum Unicode index in this font\\n },\\n // The Apple version of this table ends here, but the Microsoft one continues on...\\n 0: {},\\n 1: {\\n typoAscender: int16,\\n typoDescender: int16,\\n typoLineGap: int16,\\n winAscent: uint16,\\n winDescent: uint16,\\n codePageRange: new ArrayT(uint32, 2)\\n },\\n 2: {\\n // these should be common with version 1 somehow\\n typoAscender: int16,\\n typoDescender: int16,\\n typoLineGap: int16,\\n winAscent: uint16,\\n winDescent: uint16,\\n codePageRange: new ArrayT(uint32, 2),\\n xHeight: int16,\\n capHeight: int16,\\n defaultChar: uint16,\\n breakChar: uint16,\\n maxContent: uint16\\n },\\n 5: {\\n typoAscender: int16,\\n typoDescender: int16,\\n typoLineGap: int16,\\n winAscent: uint16,\\n winDescent: uint16,\\n codePageRange: new ArrayT(uint32, 2),\\n xHeight: int16,\\n capHeight: int16,\\n defaultChar: uint16,\\n breakChar: uint16,\\n maxContent: uint16,\\n usLowerOpticalPointSize: uint16,\\n usUpperOpticalPointSize: uint16\\n }\\n });\\n $84b272aa31b70606$var$versions = $84b272aa31b70606$var$OS2.versions;\\n $84b272aa31b70606$var$versions[3] = $84b272aa31b70606$var$versions[4] = $84b272aa31b70606$var$versions[2];\\n $84b272aa31b70606$export$2e2bcd8739ae039 = $84b272aa31b70606$var$OS2;\\n $32d9e2eb9565d93c$export$2e2bcd8739ae039 = new VersionedStruct(fixed32, {\\n header: {\\n italicAngle: fixed32,\\n underlinePosition: int16,\\n underlineThickness: int16,\\n isFixedPitch: uint32,\\n minMemType42: uint32,\\n maxMemType42: uint32,\\n minMemType1: uint32,\\n maxMemType1: uint32\\n // Maximum memory usage when a TrueType font is downloaded as a Type 1 font\\n },\\n 1: {},\\n 2: {\\n numberOfGlyphs: uint16,\\n glyphNameIndex: new ArrayT(uint16, \\\"numberOfGlyphs\\\"),\\n names: new ArrayT(new StringT(uint8))\\n },\\n 2.5: {\\n numberOfGlyphs: uint16,\\n offsets: new ArrayT(uint8, \\\"numberOfGlyphs\\\")\\n },\\n 3: {},\\n 4: {\\n map: new ArrayT(uint32, (t) => t.parent.maxp.numGlyphs)\\n }\\n });\\n $5202bd9d9ad8eaac$export$2e2bcd8739ae039 = new Struct({\\n controlValues: new ArrayT(int16)\\n });\\n $5c0f37ca5ffb1850$export$2e2bcd8739ae039 = new Struct({\\n instructions: new ArrayT(uint8)\\n });\\n $2b2b260902b1c57e$var$loca = new VersionedStruct(\\\"head.indexToLocFormat\\\", {\\n 0: {\\n offsets: new ArrayT(uint16)\\n },\\n 1: {\\n offsets: new ArrayT(uint32)\\n }\\n });\\n $2b2b260902b1c57e$var$loca.process = function() {\\n if (this.version === 0 && !this._processed) {\\n for (let i = 0; i < this.offsets.length; i++) this.offsets[i] <<= 1;\\n this._processed = true;\\n }\\n };\\n $2b2b260902b1c57e$var$loca.preEncode = function() {\\n if (this.version === 0 && this._processed !== false) {\\n for (let i = 0; i < this.offsets.length; i++) this.offsets[i] >>>= 1;\\n this._processed = false;\\n }\\n };\\n $2b2b260902b1c57e$export$2e2bcd8739ae039 = $2b2b260902b1c57e$var$loca;\\n $7afb878c7bea4f66$export$2e2bcd8739ae039 = new Struct({\\n controlValueProgram: new ArrayT(uint8)\\n });\\n $6c92b6371bce8bd9$export$2e2bcd8739ae039 = new ArrayT(new BufferT());\\n $43e9821ef3717eec$export$2e2bcd8739ae039 = class {\\n getCFFVersion(ctx) {\\n while (ctx && !ctx.hdrSize) ctx = ctx.parent;\\n return ctx ? ctx.version : -1;\\n }\\n decode(stream, parent) {\\n let version = this.getCFFVersion(parent);\\n let count = version >= 2 ? stream.readUInt32BE() : stream.readUInt16BE();\\n if (count === 0) return [];\\n let offSize = stream.readUInt8();\\n let offsetType;\\n if (offSize === 1) offsetType = uint8;\\n else if (offSize === 2) offsetType = uint16;\\n else if (offSize === 3) offsetType = uint24;\\n else if (offSize === 4) offsetType = uint32;\\n else throw new Error(`Bad offset size in CFFIndex: ${offSize} ${stream.pos}`);\\n let ret = [];\\n let startPos = stream.pos + (count + 1) * offSize - 1;\\n let start = offsetType.decode(stream);\\n for (let i = 0; i < count; i++) {\\n let end = offsetType.decode(stream);\\n if (this.type != null) {\\n let pos = stream.pos;\\n stream.pos = startPos + start;\\n parent.length = end - start;\\n ret.push(this.type.decode(stream, parent));\\n stream.pos = pos;\\n } else ret.push({\\n offset: startPos + start,\\n length: end - start\\n });\\n start = end;\\n }\\n stream.pos = startPos + start;\\n return ret;\\n }\\n size(arr, parent) {\\n let size = 2;\\n if (arr.length === 0) return size;\\n let type = this.type || new BufferT();\\n let offset = 1;\\n for (let i = 0; i < arr.length; i++) {\\n let item = arr[i];\\n offset += type.size(item, parent);\\n }\\n let offsetType;\\n if (offset <= 255) offsetType = uint8;\\n else if (offset <= 65535) offsetType = uint16;\\n else if (offset <= 16777215) offsetType = uint24;\\n else if (offset <= 4294967295) offsetType = uint32;\\n else throw new Error(\\\"Bad offset in CFFIndex\\\");\\n size += 1 + offsetType.size() * (arr.length + 1);\\n size += offset - 1;\\n return size;\\n }\\n encode(stream, arr, parent) {\\n stream.writeUInt16BE(arr.length);\\n if (arr.length === 0) return;\\n let type = this.type || new BufferT();\\n let sizes = [];\\n let offset = 1;\\n for (let item of arr) {\\n let s = type.size(item, parent);\\n sizes.push(s);\\n offset += s;\\n }\\n let offsetType;\\n if (offset <= 255) offsetType = uint8;\\n else if (offset <= 65535) offsetType = uint16;\\n else if (offset <= 16777215) offsetType = uint24;\\n else if (offset <= 4294967295) offsetType = uint32;\\n else throw new Error(\\\"Bad offset in CFFIndex\\\");\\n stream.writeUInt8(offsetType.size());\\n offset = 1;\\n offsetType.encode(stream, offset);\\n for (let size of sizes) {\\n offset += size;\\n offsetType.encode(stream, offset);\\n }\\n for (let item of arr) type.encode(stream, item, parent);\\n return;\\n }\\n constructor(type) {\\n this.type = type;\\n }\\n };\\n $c2d28e92708f99da$var$FLOAT_EOF = 15;\\n $c2d28e92708f99da$var$FLOAT_LOOKUP = [\\n \\\"0\\\",\\n \\\"1\\\",\\n \\\"2\\\",\\n \\\"3\\\",\\n \\\"4\\\",\\n \\\"5\\\",\\n \\\"6\\\",\\n \\\"7\\\",\\n \\\"8\\\",\\n \\\"9\\\",\\n \\\".\\\",\\n \\\"E\\\",\\n \\\"E-\\\",\\n null,\\n \\\"-\\\"\\n ];\\n $c2d28e92708f99da$var$FLOAT_ENCODE_LOOKUP = {\\n \\\".\\\": 10,\\n \\\"E\\\": 11,\\n \\\"E-\\\": 12,\\n \\\"-\\\": 14\\n };\\n $c2d28e92708f99da$export$2e2bcd8739ae039 = class {\\n static decode(stream, value) {\\n if (32 <= value && value <= 246) return value - 139;\\n if (247 <= value && value <= 250) return (value - 247) * 256 + stream.readUInt8() + 108;\\n if (251 <= value && value <= 254) return -(value - 251) * 256 - stream.readUInt8() - 108;\\n if (value === 28) return stream.readInt16BE();\\n if (value === 29) return stream.readInt32BE();\\n if (value === 30) {\\n let str = \\\"\\\";\\n while (true) {\\n let b = stream.readUInt8();\\n let n1 = b >> 4;\\n if (n1 === $c2d28e92708f99da$var$FLOAT_EOF) break;\\n str += $c2d28e92708f99da$var$FLOAT_LOOKUP[n1];\\n let n2 = b & 15;\\n if (n2 === $c2d28e92708f99da$var$FLOAT_EOF) break;\\n str += $c2d28e92708f99da$var$FLOAT_LOOKUP[n2];\\n }\\n return parseFloat(str);\\n }\\n return null;\\n }\\n static size(value) {\\n if (value.forceLarge) value = 32768;\\n if ((value | 0) !== value) {\\n let str = \\\"\\\" + value;\\n return 1 + Math.ceil((str.length + 1) / 2);\\n } else if (-107 <= value && value <= 107) return 1;\\n else if (108 <= value && value <= 1131 || -1131 <= value && value <= -108) return 2;\\n else if (-32768 <= value && value <= 32767) return 3;\\n else return 5;\\n }\\n static encode(stream, value) {\\n let val = Number(value);\\n if (value.forceLarge) {\\n stream.writeUInt8(29);\\n return stream.writeInt32BE(val);\\n } else if ((val | 0) !== val) {\\n stream.writeUInt8(30);\\n let str = \\\"\\\" + val;\\n for (let i = 0; i < str.length; i += 2) {\\n let c1 = str[i];\\n let n1 = $c2d28e92708f99da$var$FLOAT_ENCODE_LOOKUP[c1] || +c1;\\n if (i === str.length - 1) var n2 = $c2d28e92708f99da$var$FLOAT_EOF;\\n else {\\n let c2 = str[i + 1];\\n var n2 = $c2d28e92708f99da$var$FLOAT_ENCODE_LOOKUP[c2] || +c2;\\n }\\n stream.writeUInt8(n1 << 4 | n2 & 15);\\n }\\n if (n2 !== $c2d28e92708f99da$var$FLOAT_EOF) return stream.writeUInt8($c2d28e92708f99da$var$FLOAT_EOF << 4);\\n } else if (-107 <= val && val <= 107) return stream.writeUInt8(val + 139);\\n else if (108 <= val && val <= 1131) {\\n val -= 108;\\n stream.writeUInt8((val >> 8) + 247);\\n return stream.writeUInt8(val & 255);\\n } else if (-1131 <= val && val <= -108) {\\n val = -val - 108;\\n stream.writeUInt8((val >> 8) + 251);\\n return stream.writeUInt8(val & 255);\\n } else if (-32768 <= val && val <= 32767) {\\n stream.writeUInt8(28);\\n return stream.writeInt16BE(val);\\n } else {\\n stream.writeUInt8(29);\\n return stream.writeInt32BE(val);\\n }\\n }\\n };\\n $61aa549f16d58b9b$export$2e2bcd8739ae039 = class {\\n decodeOperands(type, stream, ret, operands) {\\n if (Array.isArray(type)) return operands.map((op, i) => this.decodeOperands(type[i], stream, ret, [\\n op\\n ]));\\n else if (type.decode != null) return type.decode(stream, ret, operands);\\n else switch (type) {\\n case \\\"number\\\":\\n case \\\"offset\\\":\\n case \\\"sid\\\":\\n return operands[0];\\n case \\\"boolean\\\":\\n return !!operands[0];\\n default:\\n return operands;\\n }\\n }\\n encodeOperands(type, stream, ctx, operands) {\\n if (Array.isArray(type)) return operands.map((op, i) => this.encodeOperands(type[i], stream, ctx, op)[0]);\\n else if (type.encode != null) return type.encode(stream, operands, ctx);\\n else if (typeof operands === \\\"number\\\") return [\\n operands\\n ];\\n else if (typeof operands === \\\"boolean\\\") return [\\n +operands\\n ];\\n else if (Array.isArray(operands)) return operands;\\n else return [\\n operands\\n ];\\n }\\n decode(stream, parent) {\\n let end = stream.pos + parent.length;\\n let ret = {};\\n let operands = [];\\n Object.defineProperties(ret, {\\n parent: {\\n value: parent\\n },\\n _startOffset: {\\n value: stream.pos\\n }\\n });\\n for (let key in this.fields) {\\n let field = this.fields[key];\\n ret[field[1]] = field[3];\\n }\\n while (stream.pos < end) {\\n let b = stream.readUInt8();\\n if (b < 28) {\\n if (b === 12) b = b << 8 | stream.readUInt8();\\n let field = this.fields[b];\\n if (!field) throw new Error(`Unknown operator ${b}`);\\n let val = this.decodeOperands(field[2], stream, ret, operands);\\n if (val != null) {\\n if (val instanceof (0, PropertyDescriptor)) Object.defineProperty(ret, field[1], val);\\n else ret[field[1]] = val;\\n }\\n operands = [];\\n } else operands.push((0, $c2d28e92708f99da$export$2e2bcd8739ae039).decode(stream, b));\\n }\\n return ret;\\n }\\n size(dict, parent, includePointers = true) {\\n let ctx = {\\n parent,\\n val: dict,\\n pointerSize: 0,\\n startOffset: parent.startOffset || 0\\n };\\n let len = 0;\\n for (let k in this.fields) {\\n let field = this.fields[k];\\n let val = dict[field[1]];\\n if (val == null || (0, import_fast_deep_equal.default)(val, field[3])) continue;\\n let operands = this.encodeOperands(field[2], null, ctx, val);\\n for (let op of operands) len += (0, $c2d28e92708f99da$export$2e2bcd8739ae039).size(op);\\n let key = Array.isArray(field[0]) ? field[0] : [\\n field[0]\\n ];\\n len += key.length;\\n }\\n if (includePointers) len += ctx.pointerSize;\\n return len;\\n }\\n encode(stream, dict, parent) {\\n let ctx = {\\n pointers: [],\\n startOffset: stream.pos,\\n parent,\\n val: dict,\\n pointerSize: 0\\n };\\n ctx.pointerOffset = stream.pos + this.size(dict, ctx, false);\\n for (let field of this.ops) {\\n let val = dict[field[1]];\\n if (val == null || (0, import_fast_deep_equal.default)(val, field[3])) continue;\\n let operands = this.encodeOperands(field[2], stream, ctx, val);\\n for (let op of operands) (0, $c2d28e92708f99da$export$2e2bcd8739ae039).encode(stream, op);\\n let key = Array.isArray(field[0]) ? field[0] : [\\n field[0]\\n ];\\n for (let op of key) stream.writeUInt8(op);\\n }\\n let i = 0;\\n while (i < ctx.pointers.length) {\\n let ptr = ctx.pointers[i++];\\n ptr.type.encode(stream, ptr.val, ptr.parent);\\n }\\n return;\\n }\\n constructor(ops = []) {\\n this.ops = ops;\\n this.fields = {};\\n for (let field of ops) {\\n let key = Array.isArray(field[0]) ? field[0][0] << 8 | field[0][1] : field[0];\\n this.fields[key] = field;\\n }\\n }\\n };\\n $0e34a43d05bde82c$export$2e2bcd8739ae039 = class extends Pointer {\\n decode(stream, parent, operands) {\\n this.offsetType = {\\n decode: () => operands[0]\\n };\\n return super.decode(stream, parent, operands);\\n }\\n encode(stream, value, ctx) {\\n if (!stream) {\\n this.offsetType = {\\n size: () => 0\\n };\\n this.size(value, ctx);\\n return [\\n new $0e34a43d05bde82c$var$Ptr(0)\\n ];\\n }\\n let ptr = null;\\n this.offsetType = {\\n encode: (stream2, val) => ptr = val\\n };\\n super.encode(stream, value, ctx);\\n return [\\n new $0e34a43d05bde82c$var$Ptr(ptr)\\n ];\\n }\\n constructor(type, options = {}) {\\n if (options.type == null) options.type = \\\"global\\\";\\n super(null, type, options);\\n }\\n };\\n $0e34a43d05bde82c$var$Ptr = class {\\n valueOf() {\\n return this.val;\\n }\\n constructor(val) {\\n this.val = val;\\n this.forceLarge = true;\\n }\\n };\\n $6d59db2e29cc77b3$var$CFFBlendOp = class {\\n static decode(stream, parent, operands) {\\n let numBlends = operands.pop();\\n while (operands.length > numBlends) operands.pop();\\n }\\n };\\n $6d59db2e29cc77b3$export$2e2bcd8739ae039 = new (0, $61aa549f16d58b9b$export$2e2bcd8739ae039)([\\n // key name type default\\n [\\n 6,\\n \\\"BlueValues\\\",\\n \\\"delta\\\",\\n null\\n ],\\n [\\n 7,\\n \\\"OtherBlues\\\",\\n \\\"delta\\\",\\n null\\n ],\\n [\\n 8,\\n \\\"FamilyBlues\\\",\\n \\\"delta\\\",\\n null\\n ],\\n [\\n 9,\\n \\\"FamilyOtherBlues\\\",\\n \\\"delta\\\",\\n null\\n ],\\n [\\n [\\n 12,\\n 9\\n ],\\n \\\"BlueScale\\\",\\n \\\"number\\\",\\n 0.039625\\n ],\\n [\\n [\\n 12,\\n 10\\n ],\\n \\\"BlueShift\\\",\\n \\\"number\\\",\\n 7\\n ],\\n [\\n [\\n 12,\\n 11\\n ],\\n \\\"BlueFuzz\\\",\\n \\\"number\\\",\\n 1\\n ],\\n [\\n 10,\\n \\\"StdHW\\\",\\n \\\"number\\\",\\n null\\n ],\\n [\\n 11,\\n \\\"StdVW\\\",\\n \\\"number\\\",\\n null\\n ],\\n [\\n [\\n 12,\\n 12\\n ],\\n \\\"StemSnapH\\\",\\n \\\"delta\\\",\\n null\\n ],\\n [\\n [\\n 12,\\n 13\\n ],\\n \\\"StemSnapV\\\",\\n \\\"delta\\\",\\n null\\n ],\\n [\\n [\\n 12,\\n 14\\n ],\\n \\\"ForceBold\\\",\\n \\\"boolean\\\",\\n false\\n ],\\n [\\n [\\n 12,\\n 17\\n ],\\n \\\"LanguageGroup\\\",\\n \\\"number\\\",\\n 0\\n ],\\n [\\n [\\n 12,\\n 18\\n ],\\n \\\"ExpansionFactor\\\",\\n \\\"number\\\",\\n 0.06\\n ],\\n [\\n [\\n 12,\\n 19\\n ],\\n \\\"initialRandomSeed\\\",\\n \\\"number\\\",\\n 0\\n ],\\n [\\n 20,\\n \\\"defaultWidthX\\\",\\n \\\"number\\\",\\n 0\\n ],\\n [\\n 21,\\n \\\"nominalWidthX\\\",\\n \\\"number\\\",\\n 0\\n ],\\n [\\n 22,\\n \\\"vsindex\\\",\\n \\\"number\\\",\\n 0\\n ],\\n [\\n 23,\\n \\\"blend\\\",\\n $6d59db2e29cc77b3$var$CFFBlendOp,\\n null\\n ],\\n [\\n 19,\\n \\\"Subrs\\\",\\n new (0, $0e34a43d05bde82c$export$2e2bcd8739ae039)(new (0, $43e9821ef3717eec$export$2e2bcd8739ae039)(), {\\n type: \\\"local\\\"\\n }),\\n null\\n ]\\n ]);\\n $229224aec43783c5$export$2e2bcd8739ae039 = [\\n \\\".notdef\\\",\\n \\\"space\\\",\\n \\\"exclam\\\",\\n \\\"quotedbl\\\",\\n \\\"numbersign\\\",\\n \\\"dollar\\\",\\n \\\"percent\\\",\\n \\\"ampersand\\\",\\n \\\"quoteright\\\",\\n \\\"parenleft\\\",\\n \\\"parenright\\\",\\n \\\"asterisk\\\",\\n \\\"plus\\\",\\n \\\"comma\\\",\\n \\\"hyphen\\\",\\n \\\"period\\\",\\n \\\"slash\\\",\\n \\\"zero\\\",\\n \\\"one\\\",\\n \\\"two\\\",\\n \\\"three\\\",\\n \\\"four\\\",\\n \\\"five\\\",\\n \\\"six\\\",\\n \\\"seven\\\",\\n \\\"eight\\\",\\n \\\"nine\\\",\\n \\\"colon\\\",\\n \\\"semicolon\\\",\\n \\\"less\\\",\\n \\\"equal\\\",\\n \\\"greater\\\",\\n \\\"question\\\",\\n \\\"at\\\",\\n \\\"A\\\",\\n \\\"B\\\",\\n \\\"C\\\",\\n \\\"D\\\",\\n \\\"E\\\",\\n \\\"F\\\",\\n \\\"G\\\",\\n \\\"H\\\",\\n \\\"I\\\",\\n \\\"J\\\",\\n \\\"K\\\",\\n \\\"L\\\",\\n \\\"M\\\",\\n \\\"N\\\",\\n \\\"O\\\",\\n \\\"P\\\",\\n \\\"Q\\\",\\n \\\"R\\\",\\n \\\"S\\\",\\n \\\"T\\\",\\n \\\"U\\\",\\n \\\"V\\\",\\n \\\"W\\\",\\n \\\"X\\\",\\n \\\"Y\\\",\\n \\\"Z\\\",\\n \\\"bracketleft\\\",\\n \\\"backslash\\\",\\n \\\"bracketright\\\",\\n \\\"asciicircum\\\",\\n \\\"underscore\\\",\\n \\\"quoteleft\\\",\\n \\\"a\\\",\\n \\\"b\\\",\\n \\\"c\\\",\\n \\\"d\\\",\\n \\\"e\\\",\\n \\\"f\\\",\\n \\\"g\\\",\\n \\\"h\\\",\\n \\\"i\\\",\\n \\\"j\\\",\\n \\\"k\\\",\\n \\\"l\\\",\\n \\\"m\\\",\\n \\\"n\\\",\\n \\\"o\\\",\\n \\\"p\\\",\\n \\\"q\\\",\\n \\\"r\\\",\\n \\\"s\\\",\\n \\\"t\\\",\\n \\\"u\\\",\\n \\\"v\\\",\\n \\\"w\\\",\\n \\\"x\\\",\\n \\\"y\\\",\\n \\\"z\\\",\\n \\\"braceleft\\\",\\n \\\"bar\\\",\\n \\\"braceright\\\",\\n \\\"asciitilde\\\",\\n \\\"exclamdown\\\",\\n \\\"cent\\\",\\n \\\"sterling\\\",\\n \\\"fraction\\\",\\n \\\"yen\\\",\\n \\\"florin\\\",\\n \\\"section\\\",\\n \\\"currency\\\",\\n \\\"quotesingle\\\",\\n \\\"quotedblleft\\\",\\n \\\"guillemotleft\\\",\\n \\\"guilsinglleft\\\",\\n \\\"guilsinglright\\\",\\n \\\"fi\\\",\\n \\\"fl\\\",\\n \\\"endash\\\",\\n \\\"dagger\\\",\\n \\\"daggerdbl\\\",\\n \\\"periodcentered\\\",\\n \\\"paragraph\\\",\\n \\\"bullet\\\",\\n \\\"quotesinglbase\\\",\\n \\\"quotedblbase\\\",\\n \\\"quotedblright\\\",\\n \\\"guillemotright\\\",\\n \\\"ellipsis\\\",\\n \\\"perthousand\\\",\\n \\\"questiondown\\\",\\n \\\"grave\\\",\\n \\\"acute\\\",\\n \\\"circumflex\\\",\\n \\\"tilde\\\",\\n \\\"macron\\\",\\n \\\"breve\\\",\\n \\\"dotaccent\\\",\\n \\\"dieresis\\\",\\n \\\"ring\\\",\\n \\\"cedilla\\\",\\n \\\"hungarumlaut\\\",\\n \\\"ogonek\\\",\\n \\\"caron\\\",\\n \\\"emdash\\\",\\n \\\"AE\\\",\\n \\\"ordfeminine\\\",\\n \\\"Lslash\\\",\\n \\\"Oslash\\\",\\n \\\"OE\\\",\\n \\\"ordmasculine\\\",\\n \\\"ae\\\",\\n \\\"dotlessi\\\",\\n \\\"lslash\\\",\\n \\\"oslash\\\",\\n \\\"oe\\\",\\n \\\"germandbls\\\",\\n \\\"onesuperior\\\",\\n \\\"logicalnot\\\",\\n \\\"mu\\\",\\n \\\"trademark\\\",\\n \\\"Eth\\\",\\n \\\"onehalf\\\",\\n \\\"plusminus\\\",\\n \\\"Thorn\\\",\\n \\\"onequarter\\\",\\n \\\"divide\\\",\\n \\\"brokenbar\\\",\\n \\\"degree\\\",\\n \\\"thorn\\\",\\n \\\"threequarters\\\",\\n \\\"twosuperior\\\",\\n \\\"registered\\\",\\n \\\"minus\\\",\\n \\\"eth\\\",\\n \\\"multiply\\\",\\n \\\"threesuperior\\\",\\n \\\"copyright\\\",\\n \\\"Aacute\\\",\\n \\\"Acircumflex\\\",\\n \\\"Adieresis\\\",\\n \\\"Agrave\\\",\\n \\\"Aring\\\",\\n \\\"Atilde\\\",\\n \\\"Ccedilla\\\",\\n \\\"Eacute\\\",\\n \\\"Ecircumflex\\\",\\n \\\"Edieresis\\\",\\n \\\"Egrave\\\",\\n \\\"Iacute\\\",\\n \\\"Icircumflex\\\",\\n \\\"Idieresis\\\",\\n \\\"Igrave\\\",\\n \\\"Ntilde\\\",\\n \\\"Oacute\\\",\\n \\\"Ocircumflex\\\",\\n \\\"Odieresis\\\",\\n \\\"Ograve\\\",\\n \\\"Otilde\\\",\\n \\\"Scaron\\\",\\n \\\"Uacute\\\",\\n \\\"Ucircumflex\\\",\\n \\\"Udieresis\\\",\\n \\\"Ugrave\\\",\\n \\\"Yacute\\\",\\n \\\"Ydieresis\\\",\\n \\\"Zcaron\\\",\\n \\\"aacute\\\",\\n \\\"acircumflex\\\",\\n \\\"adieresis\\\",\\n \\\"agrave\\\",\\n \\\"aring\\\",\\n \\\"atilde\\\",\\n \\\"ccedilla\\\",\\n \\\"eacute\\\",\\n \\\"ecircumflex\\\",\\n \\\"edieresis\\\",\\n \\\"egrave\\\",\\n \\\"iacute\\\",\\n \\\"icircumflex\\\",\\n \\\"idieresis\\\",\\n \\\"igrave\\\",\\n \\\"ntilde\\\",\\n \\\"oacute\\\",\\n \\\"ocircumflex\\\",\\n \\\"odieresis\\\",\\n \\\"ograve\\\",\\n \\\"otilde\\\",\\n \\\"scaron\\\",\\n \\\"uacute\\\",\\n \\\"ucircumflex\\\",\\n \\\"udieresis\\\",\\n \\\"ugrave\\\",\\n \\\"yacute\\\",\\n \\\"ydieresis\\\",\\n \\\"zcaron\\\",\\n \\\"exclamsmall\\\",\\n \\\"Hungarumlautsmall\\\",\\n \\\"dollaroldstyle\\\",\\n \\\"dollarsuperior\\\",\\n \\\"ampersandsmall\\\",\\n \\\"Acutesmall\\\",\\n \\\"parenleftsuperior\\\",\\n \\\"parenrightsuperior\\\",\\n \\\"twodotenleader\\\",\\n \\\"onedotenleader\\\",\\n \\\"zerooldstyle\\\",\\n \\\"oneoldstyle\\\",\\n \\\"twooldstyle\\\",\\n \\\"threeoldstyle\\\",\\n \\\"fouroldstyle\\\",\\n \\\"fiveoldstyle\\\",\\n \\\"sixoldstyle\\\",\\n \\\"sevenoldstyle\\\",\\n \\\"eightoldstyle\\\",\\n \\\"nineoldstyle\\\",\\n \\\"commasuperior\\\",\\n \\\"threequartersemdash\\\",\\n \\\"periodsuperior\\\",\\n \\\"questionsmall\\\",\\n \\\"asuperior\\\",\\n \\\"bsuperior\\\",\\n \\\"centsuperior\\\",\\n \\\"dsuperior\\\",\\n \\\"esuperior\\\",\\n \\\"isuperior\\\",\\n \\\"lsuperior\\\",\\n \\\"msuperior\\\",\\n \\\"nsuperior\\\",\\n \\\"osuperior\\\",\\n \\\"rsuperior\\\",\\n \\\"ssuperior\\\",\\n \\\"tsuperior\\\",\\n \\\"ff\\\",\\n \\\"ffi\\\",\\n \\\"ffl\\\",\\n \\\"parenleftinferior\\\",\\n \\\"parenrightinferior\\\",\\n \\\"Circumflexsmall\\\",\\n \\\"hyphensuperior\\\",\\n \\\"Gravesmall\\\",\\n \\\"Asmall\\\",\\n \\\"Bsmall\\\",\\n \\\"Csmall\\\",\\n \\\"Dsmall\\\",\\n \\\"Esmall\\\",\\n \\\"Fsmall\\\",\\n \\\"Gsmall\\\",\\n \\\"Hsmall\\\",\\n \\\"Ismall\\\",\\n \\\"Jsmall\\\",\\n \\\"Ksmall\\\",\\n \\\"Lsmall\\\",\\n \\\"Msmall\\\",\\n \\\"Nsmall\\\",\\n \\\"Osmall\\\",\\n \\\"Psmall\\\",\\n \\\"Qsmall\\\",\\n \\\"Rsmall\\\",\\n \\\"Ssmall\\\",\\n \\\"Tsmall\\\",\\n \\\"Usmall\\\",\\n \\\"Vsmall\\\",\\n \\\"Wsmall\\\",\\n \\\"Xsmall\\\",\\n \\\"Ysmall\\\",\\n \\\"Zsmall\\\",\\n \\\"colonmonetary\\\",\\n \\\"onefitted\\\",\\n \\\"rupiah\\\",\\n \\\"Tildesmall\\\",\\n \\\"exclamdownsmall\\\",\\n \\\"centoldstyle\\\",\\n \\\"Lslashsmall\\\",\\n \\\"Scaronsmall\\\",\\n \\\"Zcaronsmall\\\",\\n \\\"Dieresissmall\\\",\\n \\\"Brevesmall\\\",\\n \\\"Caronsmall\\\",\\n \\\"Dotaccentsmall\\\",\\n \\\"Macronsmall\\\",\\n \\\"figuredash\\\",\\n \\\"hypheninferior\\\",\\n \\\"Ogoneksmall\\\",\\n \\\"Ringsmall\\\",\\n \\\"Cedillasmall\\\",\\n \\\"questiondownsmall\\\",\\n \\\"oneeighth\\\",\\n \\\"threeeighths\\\",\\n \\\"fiveeighths\\\",\\n \\\"seveneighths\\\",\\n \\\"onethird\\\",\\n \\\"twothirds\\\",\\n \\\"zerosuperior\\\",\\n \\\"foursuperior\\\",\\n \\\"fivesuperior\\\",\\n \\\"sixsuperior\\\",\\n \\\"sevensuperior\\\",\\n \\\"eightsuperior\\\",\\n \\\"ninesuperior\\\",\\n \\\"zeroinferior\\\",\\n \\\"oneinferior\\\",\\n \\\"twoinferior\\\",\\n \\\"threeinferior\\\",\\n \\\"fourinferior\\\",\\n \\\"fiveinferior\\\",\\n \\\"sixinferior\\\",\\n \\\"seveninferior\\\",\\n \\\"eightinferior\\\",\\n \\\"nineinferior\\\",\\n \\\"centinferior\\\",\\n \\\"dollarinferior\\\",\\n \\\"periodinferior\\\",\\n \\\"commainferior\\\",\\n \\\"Agravesmall\\\",\\n \\\"Aacutesmall\\\",\\n \\\"Acircumflexsmall\\\",\\n \\\"Atildesmall\\\",\\n \\\"Adieresissmall\\\",\\n \\\"Aringsmall\\\",\\n \\\"AEsmall\\\",\\n \\\"Ccedillasmall\\\",\\n \\\"Egravesmall\\\",\\n \\\"Eacutesmall\\\",\\n \\\"Ecircumflexsmall\\\",\\n \\\"Edieresissmall\\\",\\n \\\"Igravesmall\\\",\\n \\\"Iacutesmall\\\",\\n \\\"Icircumflexsmall\\\",\\n \\\"Idieresissmall\\\",\\n \\\"Ethsmall\\\",\\n \\\"Ntildesmall\\\",\\n \\\"Ogravesmall\\\",\\n \\\"Oacutesmall\\\",\\n \\\"Ocircumflexsmall\\\",\\n \\\"Otildesmall\\\",\\n \\\"Odieresissmall\\\",\\n \\\"OEsmall\\\",\\n \\\"Oslashsmall\\\",\\n \\\"Ugravesmall\\\",\\n \\\"Uacutesmall\\\",\\n \\\"Ucircumflexsmall\\\",\\n \\\"Udieresissmall\\\",\\n \\\"Yacutesmall\\\",\\n \\\"Thornsmall\\\",\\n \\\"Ydieresissmall\\\",\\n \\\"001.000\\\",\\n \\\"001.001\\\",\\n \\\"001.002\\\",\\n \\\"001.003\\\",\\n \\\"Black\\\",\\n \\\"Bold\\\",\\n \\\"Book\\\",\\n \\\"Light\\\",\\n \\\"Medium\\\",\\n \\\"Regular\\\",\\n \\\"Roman\\\",\\n \\\"Semibold\\\"\\n ];\\n $bc0433d9b7e41f5f$export$dee0027060fa13bd = [\\n \\\"\\\",\\n \\\"\\\",\\n \\\"\\\",\\n \\\"\\\",\\n \\\"\\\",\\n \\\"\\\",\\n \\\"\\\",\\n \\\"\\\",\\n \\\"\\\",\\n \\\"\\\",\\n \\\"\\\",\\n \\\"\\\",\\n \\\"\\\",\\n \\\"\\\",\\n \\\"\\\",\\n \\\"\\\",\\n \\\"\\\",\\n \\\"\\\",\\n \\\"\\\",\\n \\\"\\\",\\n \\\"\\\",\\n \\\"\\\",\\n \\\"\\\",\\n \\\"\\\",\\n \\\"\\\",\\n \\\"\\\",\\n \\\"\\\",\\n \\\"\\\",\\n \\\"\\\",\\n \\\"\\\",\\n \\\"\\\",\\n \\\"\\\",\\n \\\"space\\\",\\n \\\"exclam\\\",\\n \\\"quotedbl\\\",\\n \\\"numbersign\\\",\\n \\\"dollar\\\",\\n \\\"percent\\\",\\n \\\"ampersand\\\",\\n \\\"quoteright\\\",\\n \\\"parenleft\\\",\\n \\\"parenright\\\",\\n \\\"asterisk\\\",\\n \\\"plus\\\",\\n \\\"comma\\\",\\n \\\"hyphen\\\",\\n \\\"period\\\",\\n \\\"slash\\\",\\n \\\"zero\\\",\\n \\\"one\\\",\\n \\\"two\\\",\\n \\\"three\\\",\\n \\\"four\\\",\\n \\\"five\\\",\\n \\\"six\\\",\\n \\\"seven\\\",\\n \\\"eight\\\",\\n \\\"nine\\\",\\n \\\"colon\\\",\\n \\\"semicolon\\\",\\n \\\"less\\\",\\n \\\"equal\\\",\\n \\\"greater\\\",\\n \\\"question\\\",\\n \\\"at\\\",\\n \\\"A\\\",\\n \\\"B\\\",\\n \\\"C\\\",\\n \\\"D\\\",\\n \\\"E\\\",\\n \\\"F\\\",\\n \\\"G\\\",\\n \\\"H\\\",\\n \\\"I\\\",\\n \\\"J\\\",\\n \\\"K\\\",\\n \\\"L\\\",\\n \\\"M\\\",\\n \\\"N\\\",\\n \\\"O\\\",\\n \\\"P\\\",\\n \\\"Q\\\",\\n \\\"R\\\",\\n \\\"S\\\",\\n \\\"T\\\",\\n \\\"U\\\",\\n \\\"V\\\",\\n \\\"W\\\",\\n \\\"X\\\",\\n \\\"Y\\\",\\n \\\"Z\\\",\\n \\\"bracketleft\\\",\\n \\\"backslash\\\",\\n \\\"bracketright\\\",\\n \\\"asciicircum\\\",\\n \\\"underscore\\\",\\n \\\"quoteleft\\\",\\n \\\"a\\\",\\n \\\"b\\\",\\n \\\"c\\\",\\n \\\"d\\\",\\n \\\"e\\\",\\n \\\"f\\\",\\n \\\"g\\\",\\n \\\"h\\\",\\n \\\"i\\\",\\n \\\"j\\\",\\n \\\"k\\\",\\n \\\"l\\\",\\n \\\"m\\\",\\n \\\"n\\\",\\n \\\"o\\\",\\n \\\"p\\\",\\n \\\"q\\\",\\n \\\"r\\\",\\n \\\"s\\\",\\n \\\"t\\\",\\n \\\"u\\\",\\n \\\"v\\\",\\n \\\"w\\\",\\n \\\"x\\\",\\n \\\"y\\\",\\n \\\"z\\\",\\n \\\"braceleft\\\",\\n \\\"bar\\\",\\n \\\"braceright\\\",\\n \\\"asciitilde\\\",\\n \\\"\\\",\\n \\\"\\\",\\n \\\"\\\",\\n \\\"\\\",\\n \\\"\\\",\\n \\\"\\\",\\n \\\"\\\",\\n \\\"\\\",\\n \\\"\\\",\\n \\\"\\\",\\n \\\"\\\",\\n \\\"\\\",\\n \\\"\\\",\\n \\\"\\\",\\n \\\"\\\",\\n \\\"\\\",\\n \\\"\\\",\\n \\\"\\\",\\n \\\"\\\",\\n \\\"\\\",\\n \\\"\\\",\\n \\\"\\\",\\n \\\"\\\",\\n \\\"\\\",\\n \\\"\\\",\\n \\\"\\\",\\n \\\"\\\",\\n \\\"\\\",\\n \\\"\\\",\\n \\\"\\\",\\n \\\"\\\",\\n \\\"\\\",\\n \\\"\\\",\\n \\\"\\\",\\n \\\"exclamdown\\\",\\n \\\"cent\\\",\\n \\\"sterling\\\",\\n \\\"fraction\\\",\\n \\\"yen\\\",\\n \\\"florin\\\",\\n \\\"section\\\",\\n \\\"currency\\\",\\n \\\"quotesingle\\\",\\n \\\"quotedblleft\\\",\\n \\\"guillemotleft\\\",\\n \\\"guilsinglleft\\\",\\n \\\"guilsinglright\\\",\\n \\\"fi\\\",\\n \\\"fl\\\",\\n \\\"\\\",\\n \\\"endash\\\",\\n \\\"dagger\\\",\\n \\\"daggerdbl\\\",\\n \\\"periodcentered\\\",\\n \\\"\\\",\\n \\\"paragraph\\\",\\n \\\"bullet\\\",\\n \\\"quotesinglbase\\\",\\n \\\"quotedblbase\\\",\\n \\\"quotedblright\\\",\\n \\\"guillemotright\\\",\\n \\\"ellipsis\\\",\\n \\\"perthousand\\\",\\n \\\"\\\",\\n \\\"questiondown\\\",\\n \\\"\\\",\\n \\\"grave\\\",\\n \\\"acute\\\",\\n \\\"circumflex\\\",\\n \\\"tilde\\\",\\n \\\"macron\\\",\\n \\\"breve\\\",\\n \\\"dotaccent\\\",\\n \\\"dieresis\\\",\\n \\\"\\\",\\n \\\"ring\\\",\\n \\\"cedilla\\\",\\n \\\"\\\",\\n \\\"hungarumlaut\\\",\\n \\\"ogonek\\\",\\n \\\"caron\\\",\\n \\\"emdash\\\",\\n \\\"\\\",\\n \\\"\\\",\\n \\\"\\\",\\n \\\"\\\",\\n \\\"\\\",\\n \\\"\\\",\\n \\\"\\\",\\n \\\"\\\",\\n \\\"\\\",\\n \\\"\\\",\\n \\\"\\\",\\n \\\"\\\",\\n \\\"\\\",\\n \\\"\\\",\\n \\\"\\\",\\n \\\"\\\",\\n \\\"AE\\\",\\n \\\"\\\",\\n \\\"ordfeminine\\\",\\n \\\"\\\",\\n \\\"\\\",\\n \\\"\\\",\\n \\\"\\\",\\n \\\"Lslash\\\",\\n \\\"Oslash\\\",\\n \\\"OE\\\",\\n \\\"ordmasculine\\\",\\n \\\"\\\",\\n \\\"\\\",\\n \\\"\\\",\\n \\\"\\\",\\n \\\"\\\",\\n \\\"ae\\\",\\n \\\"\\\",\\n \\\"\\\",\\n \\\"\\\",\\n \\\"dotlessi\\\",\\n \\\"\\\",\\n \\\"\\\",\\n \\\"lslash\\\",\\n \\\"oslash\\\",\\n \\\"oe\\\",\\n \\\"germandbls\\\"\\n ];\\n $bc0433d9b7e41f5f$export$4f58f497e14a53c3 = [\\n \\\"\\\",\\n \\\"\\\",\\n \\\"\\\",\\n \\\"\\\",\\n \\\"\\\",\\n \\\"\\\",\\n \\\"\\\",\\n \\\"\\\",\\n \\\"\\\",\\n \\\"\\\",\\n \\\"\\\",\\n \\\"\\\",\\n \\\"\\\",\\n \\\"\\\",\\n \\\"\\\",\\n \\\"\\\",\\n \\\"\\\",\\n \\\"\\\",\\n \\\"\\\",\\n \\\"\\\",\\n \\\"\\\",\\n \\\"\\\",\\n \\\"\\\",\\n \\\"\\\",\\n \\\"\\\",\\n \\\"\\\",\\n \\\"\\\",\\n \\\"\\\",\\n \\\"\\\",\\n \\\"\\\",\\n \\\"\\\",\\n \\\"\\\",\\n \\\"space\\\",\\n \\\"exclamsmall\\\",\\n \\\"Hungarumlautsmall\\\",\\n \\\"\\\",\\n \\\"dollaroldstyle\\\",\\n \\\"dollarsuperior\\\",\\n \\\"ampersandsmall\\\",\\n \\\"Acutesmall\\\",\\n \\\"parenleftsuperior\\\",\\n \\\"parenrightsuperior\\\",\\n \\\"twodotenleader\\\",\\n \\\"onedotenleader\\\",\\n \\\"comma\\\",\\n \\\"hyphen\\\",\\n \\\"period\\\",\\n \\\"fraction\\\",\\n \\\"zerooldstyle\\\",\\n \\\"oneoldstyle\\\",\\n \\\"twooldstyle\\\",\\n \\\"threeoldstyle\\\",\\n \\\"fouroldstyle\\\",\\n \\\"fiveoldstyle\\\",\\n \\\"sixoldstyle\\\",\\n \\\"sevenoldstyle\\\",\\n \\\"eightoldstyle\\\",\\n \\\"nineoldstyle\\\",\\n \\\"colon\\\",\\n \\\"semicolon\\\",\\n \\\"commasuperior\\\",\\n \\\"threequartersemdash\\\",\\n \\\"periodsuperior\\\",\\n \\\"questionsmall\\\",\\n \\\"\\\",\\n \\\"asuperior\\\",\\n \\\"bsuperior\\\",\\n \\\"centsuperior\\\",\\n \\\"dsuperior\\\",\\n \\\"esuperior\\\",\\n \\\"\\\",\\n \\\"\\\",\\n \\\"isuperior\\\",\\n \\\"\\\",\\n \\\"\\\",\\n \\\"lsuperior\\\",\\n \\\"msuperior\\\",\\n \\\"nsuperior\\\",\\n \\\"osuperior\\\",\\n \\\"\\\",\\n \\\"\\\",\\n \\\"rsuperior\\\",\\n \\\"ssuperior\\\",\\n \\\"tsuperior\\\",\\n \\\"\\\",\\n \\\"ff\\\",\\n \\\"fi\\\",\\n \\\"fl\\\",\\n \\\"ffi\\\",\\n \\\"ffl\\\",\\n \\\"parenleftinferior\\\",\\n \\\"\\\",\\n \\\"parenrightinferior\\\",\\n \\\"Circumflexsmall\\\",\\n \\\"hyphensuperior\\\",\\n \\\"Gravesmall\\\",\\n \\\"Asmall\\\",\\n \\\"Bsmall\\\",\\n \\\"Csmall\\\",\\n \\\"Dsmall\\\",\\n \\\"Esmall\\\",\\n \\\"Fsmall\\\",\\n \\\"Gsmall\\\",\\n \\\"Hsmall\\\",\\n \\\"Ismall\\\",\\n \\\"Jsmall\\\",\\n \\\"Ksmall\\\",\\n \\\"Lsmall\\\",\\n \\\"Msmall\\\",\\n \\\"Nsmall\\\",\\n \\\"Osmall\\\",\\n \\\"Psmall\\\",\\n \\\"Qsmall\\\",\\n \\\"Rsmall\\\",\\n \\\"Ssmall\\\",\\n \\\"Tsmall\\\",\\n \\\"Usmall\\\",\\n \\\"Vsmall\\\",\\n \\\"Wsmall\\\",\\n \\\"Xsmall\\\",\\n \\\"Ysmall\\\",\\n \\\"Zsmall\\\",\\n \\\"colonmonetary\\\",\\n \\\"onefitted\\\",\\n \\\"rupiah\\\",\\n \\\"Tildesmall\\\",\\n \\\"\\\",\\n \\\"\\\",\\n \\\"\\\",\\n \\\"\\\",\\n \\\"\\\",\\n \\\"\\\",\\n \\\"\\\",\\n \\\"\\\",\\n \\\"\\\",\\n \\\"\\\",\\n \\\"\\\",\\n \\\"\\\",\\n \\\"\\\",\\n \\\"\\\",\\n \\\"\\\",\\n \\\"\\\",\\n \\\"\\\",\\n \\\"\\\",\\n \\\"\\\",\\n \\\"\\\",\\n \\\"\\\",\\n \\\"\\\",\\n \\\"\\\",\\n \\\"\\\",\\n \\\"\\\",\\n \\\"\\\",\\n \\\"\\\",\\n \\\"\\\",\\n \\\"\\\",\\n \\\"\\\",\\n \\\"\\\",\\n \\\"\\\",\\n \\\"\\\",\\n \\\"\\\",\\n \\\"exclamdownsmall\\\",\\n \\\"centoldstyle\\\",\\n \\\"Lslashsmall\\\",\\n \\\"\\\",\\n \\\"\\\",\\n \\\"Scaronsmall\\\",\\n \\\"Zcaronsmall\\\",\\n \\\"Dieresissmall\\\",\\n \\\"Brevesmall\\\",\\n \\\"Caronsmall\\\",\\n \\\"\\\",\\n \\\"Dotaccentsmall\\\",\\n \\\"\\\",\\n \\\"\\\",\\n \\\"Macronsmall\\\",\\n \\\"\\\",\\n \\\"\\\",\\n \\\"figuredash\\\",\\n \\\"hypheninferior\\\",\\n \\\"\\\",\\n \\\"\\\",\\n \\\"Ogoneksmall\\\",\\n \\\"Ringsmall\\\",\\n \\\"Cedillasmall\\\",\\n \\\"\\\",\\n \\\"\\\",\\n \\\"\\\",\\n \\\"onequarter\\\",\\n \\\"onehalf\\\",\\n \\\"threequarters\\\",\\n \\\"questiondownsmall\\\",\\n \\\"oneeighth\\\",\\n \\\"threeeighths\\\",\\n \\\"fiveeighths\\\",\\n \\\"seveneighths\\\",\\n \\\"onethird\\\",\\n \\\"twothirds\\\",\\n \\\"\\\",\\n \\\"\\\",\\n \\\"zerosuperior\\\",\\n \\\"onesuperior\\\",\\n \\\"twosuperior\\\",\\n \\\"threesuperior\\\",\\n \\\"foursuperior\\\",\\n \\\"fivesuperior\\\",\\n \\\"sixsuperior\\\",\\n \\\"sevensuperior\\\",\\n \\\"eightsuperior\\\",\\n \\\"ninesuperior\\\",\\n \\\"zeroinferior\\\",\\n \\\"oneinferior\\\",\\n \\\"twoinferior\\\",\\n \\\"threeinferior\\\",\\n \\\"fourinferior\\\",\\n \\\"fiveinferior\\\",\\n \\\"sixinferior\\\",\\n \\\"seveninferior\\\",\\n \\\"eightinferior\\\",\\n \\\"nineinferior\\\",\\n \\\"centinferior\\\",\\n \\\"dollarinferior\\\",\\n \\\"periodinferior\\\",\\n \\\"commainferior\\\",\\n \\\"Agravesmall\\\",\\n \\\"Aacutesmall\\\",\\n \\\"Acircumflexsmall\\\",\\n \\\"Atildesmall\\\",\\n \\\"Adieresissmall\\\",\\n \\\"Aringsmall\\\",\\n \\\"AEsmall\\\",\\n \\\"Ccedillasmall\\\",\\n \\\"Egravesmall\\\",\\n \\\"Eacutesmall\\\",\\n \\\"Ecircumflexsmall\\\",\\n \\\"Edieresissmall\\\",\\n \\\"Igravesmall\\\",\\n \\\"Iacutesmall\\\",\\n \\\"Icircumflexsmall\\\",\\n \\\"Idieresissmall\\\",\\n \\\"Ethsmall\\\",\\n \\\"Ntildesmall\\\",\\n \\\"Ogravesmall\\\",\\n \\\"Oacutesmall\\\",\\n \\\"Ocircumflexsmall\\\",\\n \\\"Otildesmall\\\",\\n \\\"Odieresissmall\\\",\\n \\\"OEsmall\\\",\\n \\\"Oslashsmall\\\",\\n \\\"Ugravesmall\\\",\\n \\\"Uacutesmall\\\",\\n \\\"Ucircumflexsmall\\\",\\n \\\"Udieresissmall\\\",\\n \\\"Yacutesmall\\\",\\n \\\"Thornsmall\\\",\\n \\\"Ydieresissmall\\\"\\n ];\\n $ef658f5c9a1488b2$export$c33b50336c234f16 = [\\n \\\".notdef\\\",\\n \\\"space\\\",\\n \\\"exclam\\\",\\n \\\"quotedbl\\\",\\n \\\"numbersign\\\",\\n \\\"dollar\\\",\\n \\\"percent\\\",\\n \\\"ampersand\\\",\\n \\\"quoteright\\\",\\n \\\"parenleft\\\",\\n \\\"parenright\\\",\\n \\\"asterisk\\\",\\n \\\"plus\\\",\\n \\\"comma\\\",\\n \\\"hyphen\\\",\\n \\\"period\\\",\\n \\\"slash\\\",\\n \\\"zero\\\",\\n \\\"one\\\",\\n \\\"two\\\",\\n \\\"three\\\",\\n \\\"four\\\",\\n \\\"five\\\",\\n \\\"six\\\",\\n \\\"seven\\\",\\n \\\"eight\\\",\\n \\\"nine\\\",\\n \\\"colon\\\",\\n \\\"semicolon\\\",\\n \\\"less\\\",\\n \\\"equal\\\",\\n \\\"greater\\\",\\n \\\"question\\\",\\n \\\"at\\\",\\n \\\"A\\\",\\n \\\"B\\\",\\n \\\"C\\\",\\n \\\"D\\\",\\n \\\"E\\\",\\n \\\"F\\\",\\n \\\"G\\\",\\n \\\"H\\\",\\n \\\"I\\\",\\n \\\"J\\\",\\n \\\"K\\\",\\n \\\"L\\\",\\n \\\"M\\\",\\n \\\"N\\\",\\n \\\"O\\\",\\n \\\"P\\\",\\n \\\"Q\\\",\\n \\\"R\\\",\\n \\\"S\\\",\\n \\\"T\\\",\\n \\\"U\\\",\\n \\\"V\\\",\\n \\\"W\\\",\\n \\\"X\\\",\\n \\\"Y\\\",\\n \\\"Z\\\",\\n \\\"bracketleft\\\",\\n \\\"backslash\\\",\\n \\\"bracketright\\\",\\n \\\"asciicircum\\\",\\n \\\"underscore\\\",\\n \\\"quoteleft\\\",\\n \\\"a\\\",\\n \\\"b\\\",\\n \\\"c\\\",\\n \\\"d\\\",\\n \\\"e\\\",\\n \\\"f\\\",\\n \\\"g\\\",\\n \\\"h\\\",\\n \\\"i\\\",\\n \\\"j\\\",\\n \\\"k\\\",\\n \\\"l\\\",\\n \\\"m\\\",\\n \\\"n\\\",\\n \\\"o\\\",\\n \\\"p\\\",\\n \\\"q\\\",\\n \\\"r\\\",\\n \\\"s\\\",\\n \\\"t\\\",\\n \\\"u\\\",\\n \\\"v\\\",\\n \\\"w\\\",\\n \\\"x\\\",\\n \\\"y\\\",\\n \\\"z\\\",\\n \\\"braceleft\\\",\\n \\\"bar\\\",\\n \\\"braceright\\\",\\n \\\"asciitilde\\\",\\n \\\"exclamdown\\\",\\n \\\"cent\\\",\\n \\\"sterling\\\",\\n \\\"fraction\\\",\\n \\\"yen\\\",\\n \\\"florin\\\",\\n \\\"section\\\",\\n \\\"currency\\\",\\n \\\"quotesingle\\\",\\n \\\"quotedblleft\\\",\\n \\\"guillemotleft\\\",\\n \\\"guilsinglleft\\\",\\n \\\"guilsinglright\\\",\\n \\\"fi\\\",\\n \\\"fl\\\",\\n \\\"endash\\\",\\n \\\"dagger\\\",\\n \\\"daggerdbl\\\",\\n \\\"periodcentered\\\",\\n \\\"paragraph\\\",\\n \\\"bullet\\\",\\n \\\"quotesinglbase\\\",\\n \\\"quotedblbase\\\",\\n \\\"quotedblright\\\",\\n \\\"guillemotright\\\",\\n \\\"ellipsis\\\",\\n \\\"perthousand\\\",\\n \\\"questiondown\\\",\\n \\\"grave\\\",\\n \\\"acute\\\",\\n \\\"circumflex\\\",\\n \\\"tilde\\\",\\n \\\"macron\\\",\\n \\\"breve\\\",\\n \\\"dotaccent\\\",\\n \\\"dieresis\\\",\\n \\\"ring\\\",\\n \\\"cedilla\\\",\\n \\\"hungarumlaut\\\",\\n \\\"ogonek\\\",\\n \\\"caron\\\",\\n \\\"emdash\\\",\\n \\\"AE\\\",\\n \\\"ordfeminine\\\",\\n \\\"Lslash\\\",\\n \\\"Oslash\\\",\\n \\\"OE\\\",\\n \\\"ordmasculine\\\",\\n \\\"ae\\\",\\n \\\"dotlessi\\\",\\n \\\"lslash\\\",\\n \\\"oslash\\\",\\n \\\"oe\\\",\\n \\\"germandbls\\\",\\n \\\"onesuperior\\\",\\n \\\"logicalnot\\\",\\n \\\"mu\\\",\\n \\\"trademark\\\",\\n \\\"Eth\\\",\\n \\\"onehalf\\\",\\n \\\"plusminus\\\",\\n \\\"Thorn\\\",\\n \\\"onequarter\\\",\\n \\\"divide\\\",\\n \\\"brokenbar\\\",\\n \\\"degree\\\",\\n \\\"thorn\\\",\\n \\\"threequarters\\\",\\n \\\"twosuperior\\\",\\n \\\"registered\\\",\\n \\\"minus\\\",\\n \\\"eth\\\",\\n \\\"multiply\\\",\\n \\\"threesuperior\\\",\\n \\\"copyright\\\",\\n \\\"Aacute\\\",\\n \\\"Acircumflex\\\",\\n \\\"Adieresis\\\",\\n \\\"Agrave\\\",\\n \\\"Aring\\\",\\n \\\"Atilde\\\",\\n \\\"Ccedilla\\\",\\n \\\"Eacute\\\",\\n \\\"Ecircumflex\\\",\\n \\\"Edieresis\\\",\\n \\\"Egrave\\\",\\n \\\"Iacute\\\",\\n \\\"Icircumflex\\\",\\n \\\"Idieresis\\\",\\n \\\"Igrave\\\",\\n \\\"Ntilde\\\",\\n \\\"Oacute\\\",\\n \\\"Ocircumflex\\\",\\n \\\"Odieresis\\\",\\n \\\"Ograve\\\",\\n \\\"Otilde\\\",\\n \\\"Scaron\\\",\\n \\\"Uacute\\\",\\n \\\"Ucircumflex\\\",\\n \\\"Udieresis\\\",\\n \\\"Ugrave\\\",\\n \\\"Yacute\\\",\\n \\\"Ydieresis\\\",\\n \\\"Zcaron\\\",\\n \\\"aacute\\\",\\n \\\"acircumflex\\\",\\n \\\"adieresis\\\",\\n \\\"agrave\\\",\\n \\\"aring\\\",\\n \\\"atilde\\\",\\n \\\"ccedilla\\\",\\n \\\"eacute\\\",\\n \\\"ecircumflex\\\",\\n \\\"edieresis\\\",\\n \\\"egrave\\\",\\n \\\"iacute\\\",\\n \\\"icircumflex\\\",\\n \\\"idieresis\\\",\\n \\\"igrave\\\",\\n \\\"ntilde\\\",\\n \\\"oacute\\\",\\n \\\"ocircumflex\\\",\\n \\\"odieresis\\\",\\n \\\"ograve\\\",\\n \\\"otilde\\\",\\n \\\"scaron\\\",\\n \\\"uacute\\\",\\n \\\"ucircumflex\\\",\\n \\\"udieresis\\\",\\n \\\"ugrave\\\",\\n \\\"yacute\\\",\\n \\\"ydieresis\\\",\\n \\\"zcaron\\\"\\n ];\\n $ef658f5c9a1488b2$export$3ed0f9e1fee8d489 = [\\n \\\".notdef\\\",\\n \\\"space\\\",\\n \\\"exclamsmall\\\",\\n \\\"Hungarumlautsmall\\\",\\n \\\"dollaroldstyle\\\",\\n \\\"dollarsuperior\\\",\\n \\\"ampersandsmall\\\",\\n \\\"Acutesmall\\\",\\n \\\"parenleftsuperior\\\",\\n \\\"parenrightsuperior\\\",\\n \\\"twodotenleader\\\",\\n \\\"onedotenleader\\\",\\n \\\"comma\\\",\\n \\\"hyphen\\\",\\n \\\"period\\\",\\n \\\"fraction\\\",\\n \\\"zerooldstyle\\\",\\n \\\"oneoldstyle\\\",\\n \\\"twooldstyle\\\",\\n \\\"threeoldstyle\\\",\\n \\\"fouroldstyle\\\",\\n \\\"fiveoldstyle\\\",\\n \\\"sixoldstyle\\\",\\n \\\"sevenoldstyle\\\",\\n \\\"eightoldstyle\\\",\\n \\\"nineoldstyle\\\",\\n \\\"colon\\\",\\n \\\"semicolon\\\",\\n \\\"commasuperior\\\",\\n \\\"threequartersemdash\\\",\\n \\\"periodsuperior\\\",\\n \\\"questionsmall\\\",\\n \\\"asuperior\\\",\\n \\\"bsuperior\\\",\\n \\\"centsuperior\\\",\\n \\\"dsuperior\\\",\\n \\\"esuperior\\\",\\n \\\"isuperior\\\",\\n \\\"lsuperior\\\",\\n \\\"msuperior\\\",\\n \\\"nsuperior\\\",\\n \\\"osuperior\\\",\\n \\\"rsuperior\\\",\\n \\\"ssuperior\\\",\\n \\\"tsuperior\\\",\\n \\\"ff\\\",\\n \\\"fi\\\",\\n \\\"fl\\\",\\n \\\"ffi\\\",\\n \\\"ffl\\\",\\n \\\"parenleftinferior\\\",\\n \\\"parenrightinferior\\\",\\n \\\"Circumflexsmall\\\",\\n \\\"hyphensuperior\\\",\\n \\\"Gravesmall\\\",\\n \\\"Asmall\\\",\\n \\\"Bsmall\\\",\\n \\\"Csmall\\\",\\n \\\"Dsmall\\\",\\n \\\"Esmall\\\",\\n \\\"Fsmall\\\",\\n \\\"Gsmall\\\",\\n \\\"Hsmall\\\",\\n \\\"Ismall\\\",\\n \\\"Jsmall\\\",\\n \\\"Ksmall\\\",\\n \\\"Lsmall\\\",\\n \\\"Msmall\\\",\\n \\\"Nsmall\\\",\\n \\\"Osmall\\\",\\n \\\"Psmall\\\",\\n \\\"Qsmall\\\",\\n \\\"Rsmall\\\",\\n \\\"Ssmall\\\",\\n \\\"Tsmall\\\",\\n \\\"Usmall\\\",\\n \\\"Vsmall\\\",\\n \\\"Wsmall\\\",\\n \\\"Xsmall\\\",\\n \\\"Ysmall\\\",\\n \\\"Zsmall\\\",\\n \\\"colonmonetary\\\",\\n \\\"onefitted\\\",\\n \\\"rupiah\\\",\\n \\\"Tildesmall\\\",\\n \\\"exclamdownsmall\\\",\\n \\\"centoldstyle\\\",\\n \\\"Lslashsmall\\\",\\n \\\"Scaronsmall\\\",\\n \\\"Zcaronsmall\\\",\\n \\\"Dieresissmall\\\",\\n \\\"Brevesmall\\\",\\n \\\"Caronsmall\\\",\\n \\\"Dotaccentsmall\\\",\\n \\\"Macronsmall\\\",\\n \\\"figuredash\\\",\\n \\\"hypheninferior\\\",\\n \\\"Ogoneksmall\\\",\\n \\\"Ringsmall\\\",\\n \\\"Cedillasmall\\\",\\n \\\"onequarter\\\",\\n \\\"onehalf\\\",\\n \\\"threequarters\\\",\\n \\\"questiondownsmall\\\",\\n \\\"oneeighth\\\",\\n \\\"threeeighths\\\",\\n \\\"fiveeighths\\\",\\n \\\"seveneighths\\\",\\n \\\"onethird\\\",\\n \\\"twothirds\\\",\\n \\\"zerosuperior\\\",\\n \\\"onesuperior\\\",\\n \\\"twosuperior\\\",\\n \\\"threesuperior\\\",\\n \\\"foursuperior\\\",\\n \\\"fivesuperior\\\",\\n \\\"sixsuperior\\\",\\n \\\"sevensuperior\\\",\\n \\\"eightsuperior\\\",\\n \\\"ninesuperior\\\",\\n \\\"zeroinferior\\\",\\n \\\"oneinferior\\\",\\n \\\"twoinferior\\\",\\n \\\"threeinferior\\\",\\n \\\"fourinferior\\\",\\n \\\"fiveinferior\\\",\\n \\\"sixinferior\\\",\\n \\\"seveninferior\\\",\\n \\\"eightinferior\\\",\\n \\\"nineinferior\\\",\\n \\\"centinferior\\\",\\n \\\"dollarinferior\\\",\\n \\\"periodinferior\\\",\\n \\\"commainferior\\\",\\n \\\"Agravesmall\\\",\\n \\\"Aacutesmall\\\",\\n \\\"Acircumflexsmall\\\",\\n \\\"Atildesmall\\\",\\n \\\"Adieresissmall\\\",\\n \\\"Aringsmall\\\",\\n \\\"AEsmall\\\",\\n \\\"Ccedillasmall\\\",\\n \\\"Egravesmall\\\",\\n \\\"Eacutesmall\\\",\\n \\\"Ecircumflexsmall\\\",\\n \\\"Edieresissmall\\\",\\n \\\"Igravesmall\\\",\\n \\\"Iacutesmall\\\",\\n \\\"Icircumflexsmall\\\",\\n \\\"Idieresissmall\\\",\\n \\\"Ethsmall\\\",\\n \\\"Ntildesmall\\\",\\n \\\"Ogravesmall\\\",\\n \\\"Oacutesmall\\\",\\n \\\"Ocircumflexsmall\\\",\\n \\\"Otildesmall\\\",\\n \\\"Odieresissmall\\\",\\n \\\"OEsmall\\\",\\n \\\"Oslashsmall\\\",\\n \\\"Ugravesmall\\\",\\n \\\"Uacutesmall\\\",\\n \\\"Ucircumflexsmall\\\",\\n \\\"Udieresissmall\\\",\\n \\\"Yacutesmall\\\",\\n \\\"Thornsmall\\\",\\n \\\"Ydieresissmall\\\"\\n ];\\n $ef658f5c9a1488b2$export$dc28be11139d4120 = [\\n \\\".notdef\\\",\\n \\\"space\\\",\\n \\\"dollaroldstyle\\\",\\n \\\"dollarsuperior\\\",\\n \\\"parenleftsuperior\\\",\\n \\\"parenrightsuperior\\\",\\n \\\"twodotenleader\\\",\\n \\\"onedotenleader\\\",\\n \\\"comma\\\",\\n \\\"hyphen\\\",\\n \\\"period\\\",\\n \\\"fraction\\\",\\n \\\"zerooldstyle\\\",\\n \\\"oneoldstyle\\\",\\n \\\"twooldstyle\\\",\\n \\\"threeoldstyle\\\",\\n \\\"fouroldstyle\\\",\\n \\\"fiveoldstyle\\\",\\n \\\"sixoldstyle\\\",\\n \\\"sevenoldstyle\\\",\\n \\\"eightoldstyle\\\",\\n \\\"nineoldstyle\\\",\\n \\\"colon\\\",\\n \\\"semicolon\\\",\\n \\\"commasuperior\\\",\\n \\\"threequartersemdash\\\",\\n \\\"periodsuperior\\\",\\n \\\"asuperior\\\",\\n \\\"bsuperior\\\",\\n \\\"centsuperior\\\",\\n \\\"dsuperior\\\",\\n \\\"esuperior\\\",\\n \\\"isuperior\\\",\\n \\\"lsuperior\\\",\\n \\\"msuperior\\\",\\n \\\"nsuperior\\\",\\n \\\"osuperior\\\",\\n \\\"rsuperior\\\",\\n \\\"ssuperior\\\",\\n \\\"tsuperior\\\",\\n \\\"ff\\\",\\n \\\"fi\\\",\\n \\\"fl\\\",\\n \\\"ffi\\\",\\n \\\"ffl\\\",\\n \\\"parenleftinferior\\\",\\n \\\"parenrightinferior\\\",\\n \\\"hyphensuperior\\\",\\n \\\"colonmonetary\\\",\\n \\\"onefitted\\\",\\n \\\"rupiah\\\",\\n \\\"centoldstyle\\\",\\n \\\"figuredash\\\",\\n \\\"hypheninferior\\\",\\n \\\"onequarter\\\",\\n \\\"onehalf\\\",\\n \\\"threequarters\\\",\\n \\\"oneeighth\\\",\\n \\\"threeeighths\\\",\\n \\\"fiveeighths\\\",\\n \\\"seveneighths\\\",\\n \\\"onethird\\\",\\n \\\"twothirds\\\",\\n \\\"zerosuperior\\\",\\n \\\"onesuperior\\\",\\n \\\"twosuperior\\\",\\n \\\"threesuperior\\\",\\n \\\"foursuperior\\\",\\n \\\"fivesuperior\\\",\\n \\\"sixsuperior\\\",\\n \\\"sevensuperior\\\",\\n \\\"eightsuperior\\\",\\n \\\"ninesuperior\\\",\\n \\\"zeroinferior\\\",\\n \\\"oneinferior\\\",\\n \\\"twoinferior\\\",\\n \\\"threeinferior\\\",\\n \\\"fourinferior\\\",\\n \\\"fiveinferior\\\",\\n \\\"sixinferior\\\",\\n \\\"seveninferior\\\",\\n \\\"eightinferior\\\",\\n \\\"nineinferior\\\",\\n \\\"centinferior\\\",\\n \\\"dollarinferior\\\",\\n \\\"periodinferior\\\",\\n \\\"commainferior\\\"\\n ];\\n $7cbbe4e24ef3cb75$var$LangSysTable = new Struct({\\n reserved: new Reserved(uint16),\\n reqFeatureIndex: uint16,\\n featureCount: uint16,\\n featureIndexes: new ArrayT(uint16, \\\"featureCount\\\")\\n });\\n $7cbbe4e24ef3cb75$var$LangSysRecord = new Struct({\\n tag: new StringT(4),\\n langSys: new Pointer(uint16, $7cbbe4e24ef3cb75$var$LangSysTable, {\\n type: \\\"parent\\\"\\n })\\n });\\n $7cbbe4e24ef3cb75$var$Script = new Struct({\\n defaultLangSys: new Pointer(uint16, $7cbbe4e24ef3cb75$var$LangSysTable),\\n count: uint16,\\n langSysRecords: new ArrayT($7cbbe4e24ef3cb75$var$LangSysRecord, \\\"count\\\")\\n });\\n $7cbbe4e24ef3cb75$var$ScriptRecord = new Struct({\\n tag: new StringT(4),\\n script: new Pointer(uint16, $7cbbe4e24ef3cb75$var$Script, {\\n type: \\\"parent\\\"\\n })\\n });\\n $7cbbe4e24ef3cb75$export$3e15fc05ce864229 = new ArrayT($7cbbe4e24ef3cb75$var$ScriptRecord, uint16);\\n $7cbbe4e24ef3cb75$var$FeatureParams = new Struct({\\n version: uint16,\\n nameID: uint16\\n });\\n $7cbbe4e24ef3cb75$export$6e91cf7616333d5 = new Struct({\\n featureParams: new Pointer(uint16, $7cbbe4e24ef3cb75$var$FeatureParams),\\n lookupCount: uint16,\\n lookupListIndexes: new ArrayT(uint16, \\\"lookupCount\\\")\\n });\\n $7cbbe4e24ef3cb75$var$FeatureRecord = new Struct({\\n tag: new StringT(4),\\n feature: new Pointer(uint16, $7cbbe4e24ef3cb75$export$6e91cf7616333d5, {\\n type: \\\"parent\\\"\\n })\\n });\\n $7cbbe4e24ef3cb75$export$aa18130def4b6cb4 = new ArrayT($7cbbe4e24ef3cb75$var$FeatureRecord, uint16);\\n $7cbbe4e24ef3cb75$var$LookupFlags = new Struct({\\n markAttachmentType: uint8,\\n flags: new Bitfield(uint8, [\\n \\\"rightToLeft\\\",\\n \\\"ignoreBaseGlyphs\\\",\\n \\\"ignoreLigatures\\\",\\n \\\"ignoreMarks\\\",\\n \\\"useMarkFilteringSet\\\"\\n ])\\n });\\n $7cbbe4e24ef3cb75$var$RangeRecord = new Struct({\\n start: uint16,\\n end: uint16,\\n startCoverageIndex: uint16\\n });\\n $7cbbe4e24ef3cb75$export$17608c3f81a6111 = new VersionedStruct(uint16, {\\n 1: {\\n glyphCount: uint16,\\n glyphs: new ArrayT(uint16, \\\"glyphCount\\\")\\n },\\n 2: {\\n rangeCount: uint16,\\n rangeRecords: new ArrayT($7cbbe4e24ef3cb75$var$RangeRecord, \\\"rangeCount\\\")\\n }\\n });\\n $7cbbe4e24ef3cb75$var$ClassRangeRecord = new Struct({\\n start: uint16,\\n end: uint16,\\n class: uint16\\n });\\n $7cbbe4e24ef3cb75$export$843d551fbbafef71 = new VersionedStruct(uint16, {\\n 1: {\\n startGlyph: uint16,\\n glyphCount: uint16,\\n classValueArray: new ArrayT(uint16, \\\"glyphCount\\\")\\n },\\n 2: {\\n classRangeCount: uint16,\\n classRangeRecord: new ArrayT($7cbbe4e24ef3cb75$var$ClassRangeRecord, \\\"classRangeCount\\\")\\n }\\n });\\n $7cbbe4e24ef3cb75$export$8215d14a63d9fb10 = new Struct({\\n a: uint16,\\n b: uint16,\\n deltaFormat: uint16\\n });\\n $7cbbe4e24ef3cb75$var$LookupRecord = new Struct({\\n sequenceIndex: uint16,\\n lookupListIndex: uint16\\n });\\n $7cbbe4e24ef3cb75$var$Rule = new Struct({\\n glyphCount: uint16,\\n lookupCount: uint16,\\n input: new ArrayT(uint16, (t) => t.glyphCount - 1),\\n lookupRecords: new ArrayT($7cbbe4e24ef3cb75$var$LookupRecord, \\\"lookupCount\\\")\\n });\\n $7cbbe4e24ef3cb75$var$RuleSet = new ArrayT(new Pointer(uint16, $7cbbe4e24ef3cb75$var$Rule), uint16);\\n $7cbbe4e24ef3cb75$var$ClassRule = new Struct({\\n glyphCount: uint16,\\n lookupCount: uint16,\\n classes: new ArrayT(uint16, (t) => t.glyphCount - 1),\\n lookupRecords: new ArrayT($7cbbe4e24ef3cb75$var$LookupRecord, \\\"lookupCount\\\")\\n });\\n $7cbbe4e24ef3cb75$var$ClassSet = new ArrayT(new Pointer(uint16, $7cbbe4e24ef3cb75$var$ClassRule), uint16);\\n $7cbbe4e24ef3cb75$export$841858b892ce1f4c = new VersionedStruct(uint16, {\\n 1: {\\n coverage: new Pointer(uint16, $7cbbe4e24ef3cb75$export$17608c3f81a6111),\\n ruleSetCount: uint16,\\n ruleSets: new ArrayT(new Pointer(uint16, $7cbbe4e24ef3cb75$var$RuleSet), \\\"ruleSetCount\\\")\\n },\\n 2: {\\n coverage: new Pointer(uint16, $7cbbe4e24ef3cb75$export$17608c3f81a6111),\\n classDef: new Pointer(uint16, $7cbbe4e24ef3cb75$export$843d551fbbafef71),\\n classSetCnt: uint16,\\n classSet: new ArrayT(new Pointer(uint16, $7cbbe4e24ef3cb75$var$ClassSet), \\\"classSetCnt\\\")\\n },\\n 3: {\\n glyphCount: uint16,\\n lookupCount: uint16,\\n coverages: new ArrayT(new Pointer(uint16, $7cbbe4e24ef3cb75$export$17608c3f81a6111), \\\"glyphCount\\\"),\\n lookupRecords: new ArrayT($7cbbe4e24ef3cb75$var$LookupRecord, \\\"lookupCount\\\")\\n }\\n });\\n $7cbbe4e24ef3cb75$var$ChainRule = new Struct({\\n backtrackGlyphCount: uint16,\\n backtrack: new ArrayT(uint16, \\\"backtrackGlyphCount\\\"),\\n inputGlyphCount: uint16,\\n input: new ArrayT(uint16, (t) => t.inputGlyphCount - 1),\\n lookaheadGlyphCount: uint16,\\n lookahead: new ArrayT(uint16, \\\"lookaheadGlyphCount\\\"),\\n lookupCount: uint16,\\n lookupRecords: new ArrayT($7cbbe4e24ef3cb75$var$LookupRecord, \\\"lookupCount\\\")\\n });\\n $7cbbe4e24ef3cb75$var$ChainRuleSet = new ArrayT(new Pointer(uint16, $7cbbe4e24ef3cb75$var$ChainRule), uint16);\\n $7cbbe4e24ef3cb75$export$5e6d09e6861162f6 = new VersionedStruct(uint16, {\\n 1: {\\n coverage: new Pointer(uint16, $7cbbe4e24ef3cb75$export$17608c3f81a6111),\\n chainCount: uint16,\\n chainRuleSets: new ArrayT(new Pointer(uint16, $7cbbe4e24ef3cb75$var$ChainRuleSet), \\\"chainCount\\\")\\n },\\n 2: {\\n coverage: new Pointer(uint16, $7cbbe4e24ef3cb75$export$17608c3f81a6111),\\n backtrackClassDef: new Pointer(uint16, $7cbbe4e24ef3cb75$export$843d551fbbafef71),\\n inputClassDef: new Pointer(uint16, $7cbbe4e24ef3cb75$export$843d551fbbafef71),\\n lookaheadClassDef: new Pointer(uint16, $7cbbe4e24ef3cb75$export$843d551fbbafef71),\\n chainCount: uint16,\\n chainClassSet: new ArrayT(new Pointer(uint16, $7cbbe4e24ef3cb75$var$ChainRuleSet), \\\"chainCount\\\")\\n },\\n 3: {\\n backtrackGlyphCount: uint16,\\n backtrackCoverage: new ArrayT(new Pointer(uint16, $7cbbe4e24ef3cb75$export$17608c3f81a6111), \\\"backtrackGlyphCount\\\"),\\n inputGlyphCount: uint16,\\n inputCoverage: new ArrayT(new Pointer(uint16, $7cbbe4e24ef3cb75$export$17608c3f81a6111), \\\"inputGlyphCount\\\"),\\n lookaheadGlyphCount: uint16,\\n lookaheadCoverage: new ArrayT(new Pointer(uint16, $7cbbe4e24ef3cb75$export$17608c3f81a6111), \\\"lookaheadGlyphCount\\\"),\\n lookupCount: uint16,\\n lookupRecords: new ArrayT($7cbbe4e24ef3cb75$var$LookupRecord, \\\"lookupCount\\\")\\n }\\n });\\n $1a47b0c45c1c22fe$var$F2DOT14 = new Fixed(16, \\\"BE\\\", 14);\\n $1a47b0c45c1c22fe$var$RegionAxisCoordinates = new Struct({\\n startCoord: $1a47b0c45c1c22fe$var$F2DOT14,\\n peakCoord: $1a47b0c45c1c22fe$var$F2DOT14,\\n endCoord: $1a47b0c45c1c22fe$var$F2DOT14\\n });\\n $1a47b0c45c1c22fe$var$VariationRegionList = new Struct({\\n axisCount: uint16,\\n regionCount: uint16,\\n variationRegions: new ArrayT(new ArrayT($1a47b0c45c1c22fe$var$RegionAxisCoordinates, \\\"axisCount\\\"), \\\"regionCount\\\")\\n });\\n $1a47b0c45c1c22fe$var$DeltaSet = new Struct({\\n shortDeltas: new ArrayT(int16, (t) => t.parent.shortDeltaCount),\\n regionDeltas: new ArrayT(int8, (t) => t.parent.regionIndexCount - t.parent.shortDeltaCount),\\n deltas: (t) => t.shortDeltas.concat(t.regionDeltas)\\n });\\n $1a47b0c45c1c22fe$var$ItemVariationData = new Struct({\\n itemCount: uint16,\\n shortDeltaCount: uint16,\\n regionIndexCount: uint16,\\n regionIndexes: new ArrayT(uint16, \\\"regionIndexCount\\\"),\\n deltaSets: new ArrayT($1a47b0c45c1c22fe$var$DeltaSet, \\\"itemCount\\\")\\n });\\n $1a47b0c45c1c22fe$export$fe1b122a2710f241 = new Struct({\\n format: uint16,\\n variationRegionList: new Pointer(uint32, $1a47b0c45c1c22fe$var$VariationRegionList),\\n variationDataCount: uint16,\\n itemVariationData: new ArrayT(new Pointer(uint32, $1a47b0c45c1c22fe$var$ItemVariationData), \\\"variationDataCount\\\")\\n });\\n $1a47b0c45c1c22fe$var$ConditionTable = new VersionedStruct(uint16, {\\n 1: {\\n axisIndex: uint16,\\n axisIndex: uint16,\\n filterRangeMinValue: $1a47b0c45c1c22fe$var$F2DOT14,\\n filterRangeMaxValue: $1a47b0c45c1c22fe$var$F2DOT14\\n }\\n });\\n $1a47b0c45c1c22fe$var$ConditionSet = new Struct({\\n conditionCount: uint16,\\n conditionTable: new ArrayT(new Pointer(uint32, $1a47b0c45c1c22fe$var$ConditionTable), \\\"conditionCount\\\")\\n });\\n $1a47b0c45c1c22fe$var$FeatureTableSubstitutionRecord = new Struct({\\n featureIndex: uint16,\\n alternateFeatureTable: new Pointer(uint32, (0, $7cbbe4e24ef3cb75$export$6e91cf7616333d5), {\\n type: \\\"parent\\\"\\n })\\n });\\n $1a47b0c45c1c22fe$var$FeatureTableSubstitution = new Struct({\\n version: fixed32,\\n substitutionCount: uint16,\\n substitutions: new ArrayT($1a47b0c45c1c22fe$var$FeatureTableSubstitutionRecord, \\\"substitutionCount\\\")\\n });\\n $1a47b0c45c1c22fe$var$FeatureVariationRecord = new Struct({\\n conditionSet: new Pointer(uint32, $1a47b0c45c1c22fe$var$ConditionSet, {\\n type: \\\"parent\\\"\\n }),\\n featureTableSubstitution: new Pointer(uint32, $1a47b0c45c1c22fe$var$FeatureTableSubstitution, {\\n type: \\\"parent\\\"\\n })\\n });\\n $1a47b0c45c1c22fe$export$441b70b7971dd419 = new Struct({\\n majorVersion: uint16,\\n minorVersion: uint16,\\n featureVariationRecordCount: uint32,\\n featureVariationRecords: new ArrayT($1a47b0c45c1c22fe$var$FeatureVariationRecord, \\\"featureVariationRecordCount\\\")\\n });\\n $b84fd3dd9d8eddb2$var$PredefinedOp = class {\\n decode(stream, parent, operands) {\\n if (this.predefinedOps[operands[0]]) return this.predefinedOps[operands[0]];\\n return this.type.decode(stream, parent, operands);\\n }\\n size(value, ctx) {\\n return this.type.size(value, ctx);\\n }\\n encode(stream, value, ctx) {\\n let index = this.predefinedOps.indexOf(value);\\n if (index !== -1) return index;\\n return this.type.encode(stream, value, ctx);\\n }\\n constructor(predefinedOps, type) {\\n this.predefinedOps = predefinedOps;\\n this.type = type;\\n }\\n };\\n $b84fd3dd9d8eddb2$var$CFFEncodingVersion = class extends NumberT {\\n decode(stream) {\\n return uint8.decode(stream) & 127;\\n }\\n constructor() {\\n super(\\\"UInt8\\\");\\n }\\n };\\n $b84fd3dd9d8eddb2$var$Range1 = new Struct({\\n first: uint16,\\n nLeft: uint8\\n });\\n $b84fd3dd9d8eddb2$var$Range2 = new Struct({\\n first: uint16,\\n nLeft: uint16\\n });\\n $b84fd3dd9d8eddb2$var$CFFCustomEncoding = new VersionedStruct(new $b84fd3dd9d8eddb2$var$CFFEncodingVersion(), {\\n 0: {\\n nCodes: uint8,\\n codes: new ArrayT(uint8, \\\"nCodes\\\")\\n },\\n 1: {\\n nRanges: uint8,\\n ranges: new ArrayT($b84fd3dd9d8eddb2$var$Range1, \\\"nRanges\\\")\\n }\\n });\\n $b84fd3dd9d8eddb2$var$CFFEncoding = new $b84fd3dd9d8eddb2$var$PredefinedOp([\\n (0, $bc0433d9b7e41f5f$export$dee0027060fa13bd),\\n (0, $bc0433d9b7e41f5f$export$4f58f497e14a53c3)\\n ], new (0, $0e34a43d05bde82c$export$2e2bcd8739ae039)($b84fd3dd9d8eddb2$var$CFFCustomEncoding, {\\n lazy: true\\n }));\\n $b84fd3dd9d8eddb2$var$RangeArray = class extends ArrayT {\\n decode(stream, parent) {\\n let length = (0, resolveLength)(this.length, stream, parent);\\n let count = 0;\\n let res = [];\\n while (count < length) {\\n let range = this.type.decode(stream, parent);\\n range.offset = count;\\n count += range.nLeft + 1;\\n res.push(range);\\n }\\n return res;\\n }\\n };\\n $b84fd3dd9d8eddb2$var$CFFCustomCharset = new VersionedStruct(uint8, {\\n 0: {\\n glyphs: new ArrayT(uint16, (t) => t.parent.CharStrings.length - 1)\\n },\\n 1: {\\n ranges: new $b84fd3dd9d8eddb2$var$RangeArray($b84fd3dd9d8eddb2$var$Range1, (t) => t.parent.CharStrings.length - 1)\\n },\\n 2: {\\n ranges: new $b84fd3dd9d8eddb2$var$RangeArray($b84fd3dd9d8eddb2$var$Range2, (t) => t.parent.CharStrings.length - 1)\\n }\\n });\\n $b84fd3dd9d8eddb2$var$CFFCharset = new $b84fd3dd9d8eddb2$var$PredefinedOp([\\n (0, $ef658f5c9a1488b2$export$c33b50336c234f16),\\n (0, $ef658f5c9a1488b2$export$3ed0f9e1fee8d489),\\n (0, $ef658f5c9a1488b2$export$dc28be11139d4120)\\n ], new (0, $0e34a43d05bde82c$export$2e2bcd8739ae039)($b84fd3dd9d8eddb2$var$CFFCustomCharset, {\\n lazy: true\\n }));\\n $b84fd3dd9d8eddb2$var$FDRange3 = new Struct({\\n first: uint16,\\n fd: uint8\\n });\\n $b84fd3dd9d8eddb2$var$FDRange4 = new Struct({\\n first: uint32,\\n fd: uint16\\n });\\n $b84fd3dd9d8eddb2$var$FDSelect = new VersionedStruct(uint8, {\\n 0: {\\n fds: new ArrayT(uint8, (t) => t.parent.CharStrings.length)\\n },\\n 3: {\\n nRanges: uint16,\\n ranges: new ArrayT($b84fd3dd9d8eddb2$var$FDRange3, \\\"nRanges\\\"),\\n sentinel: uint16\\n },\\n 4: {\\n nRanges: uint32,\\n ranges: new ArrayT($b84fd3dd9d8eddb2$var$FDRange4, \\\"nRanges\\\"),\\n sentinel: uint32\\n }\\n });\\n $b84fd3dd9d8eddb2$var$ptr = new (0, $0e34a43d05bde82c$export$2e2bcd8739ae039)((0, $6d59db2e29cc77b3$export$2e2bcd8739ae039));\\n $b84fd3dd9d8eddb2$var$CFFPrivateOp = class {\\n decode(stream, parent, operands) {\\n parent.length = operands[0];\\n return $b84fd3dd9d8eddb2$var$ptr.decode(stream, parent, [\\n operands[1]\\n ]);\\n }\\n size(dict, ctx) {\\n return [\\n (0, $6d59db2e29cc77b3$export$2e2bcd8739ae039).size(dict, ctx, false),\\n $b84fd3dd9d8eddb2$var$ptr.size(dict, ctx)[0]\\n ];\\n }\\n encode(stream, dict, ctx) {\\n return [\\n (0, $6d59db2e29cc77b3$export$2e2bcd8739ae039).size(dict, ctx, false),\\n $b84fd3dd9d8eddb2$var$ptr.encode(stream, dict, ctx)[0]\\n ];\\n }\\n };\\n $b84fd3dd9d8eddb2$var$FontDict = new (0, $61aa549f16d58b9b$export$2e2bcd8739ae039)([\\n // key name type(s) default\\n [\\n 18,\\n \\\"Private\\\",\\n new $b84fd3dd9d8eddb2$var$CFFPrivateOp(),\\n null\\n ],\\n [\\n [\\n 12,\\n 38\\n ],\\n \\\"FontName\\\",\\n \\\"sid\\\",\\n null\\n ],\\n [\\n [\\n 12,\\n 7\\n ],\\n \\\"FontMatrix\\\",\\n \\\"array\\\",\\n [\\n 1e-3,\\n 0,\\n 0,\\n 1e-3,\\n 0,\\n 0\\n ]\\n ],\\n [\\n [\\n 12,\\n 5\\n ],\\n \\\"PaintType\\\",\\n \\\"number\\\",\\n 0\\n ]\\n ]);\\n $b84fd3dd9d8eddb2$var$CFFTopDict = new (0, $61aa549f16d58b9b$export$2e2bcd8739ae039)([\\n // key name type(s) default\\n [\\n [\\n 12,\\n 30\\n ],\\n \\\"ROS\\\",\\n [\\n \\\"sid\\\",\\n \\\"sid\\\",\\n \\\"number\\\"\\n ],\\n null\\n ],\\n [\\n 0,\\n \\\"version\\\",\\n \\\"sid\\\",\\n null\\n ],\\n [\\n 1,\\n \\\"Notice\\\",\\n \\\"sid\\\",\\n null\\n ],\\n [\\n [\\n 12,\\n 0\\n ],\\n \\\"Copyright\\\",\\n \\\"sid\\\",\\n null\\n ],\\n [\\n 2,\\n \\\"FullName\\\",\\n \\\"sid\\\",\\n null\\n ],\\n [\\n 3,\\n \\\"FamilyName\\\",\\n \\\"sid\\\",\\n null\\n ],\\n [\\n 4,\\n \\\"Weight\\\",\\n \\\"sid\\\",\\n null\\n ],\\n [\\n [\\n 12,\\n 1\\n ],\\n \\\"isFixedPitch\\\",\\n \\\"boolean\\\",\\n false\\n ],\\n [\\n [\\n 12,\\n 2\\n ],\\n \\\"ItalicAngle\\\",\\n \\\"number\\\",\\n 0\\n ],\\n [\\n [\\n 12,\\n 3\\n ],\\n \\\"UnderlinePosition\\\",\\n \\\"number\\\",\\n -100\\n ],\\n [\\n [\\n 12,\\n 4\\n ],\\n \\\"UnderlineThickness\\\",\\n \\\"number\\\",\\n 50\\n ],\\n [\\n [\\n 12,\\n 5\\n ],\\n \\\"PaintType\\\",\\n \\\"number\\\",\\n 0\\n ],\\n [\\n [\\n 12,\\n 6\\n ],\\n \\\"CharstringType\\\",\\n \\\"number\\\",\\n 2\\n ],\\n [\\n [\\n 12,\\n 7\\n ],\\n \\\"FontMatrix\\\",\\n \\\"array\\\",\\n [\\n 1e-3,\\n 0,\\n 0,\\n 1e-3,\\n 0,\\n 0\\n ]\\n ],\\n [\\n 13,\\n \\\"UniqueID\\\",\\n \\\"number\\\",\\n null\\n ],\\n [\\n 5,\\n \\\"FontBBox\\\",\\n \\\"array\\\",\\n [\\n 0,\\n 0,\\n 0,\\n 0\\n ]\\n ],\\n [\\n [\\n 12,\\n 8\\n ],\\n \\\"StrokeWidth\\\",\\n \\\"number\\\",\\n 0\\n ],\\n [\\n 14,\\n \\\"XUID\\\",\\n \\\"array\\\",\\n null\\n ],\\n [\\n 15,\\n \\\"charset\\\",\\n $b84fd3dd9d8eddb2$var$CFFCharset,\\n (0, $ef658f5c9a1488b2$export$c33b50336c234f16)\\n ],\\n [\\n 16,\\n \\\"Encoding\\\",\\n $b84fd3dd9d8eddb2$var$CFFEncoding,\\n (0, $bc0433d9b7e41f5f$export$dee0027060fa13bd)\\n ],\\n [\\n 17,\\n \\\"CharStrings\\\",\\n new (0, $0e34a43d05bde82c$export$2e2bcd8739ae039)(new (0, $43e9821ef3717eec$export$2e2bcd8739ae039)()),\\n null\\n ],\\n [\\n 18,\\n \\\"Private\\\",\\n new $b84fd3dd9d8eddb2$var$CFFPrivateOp(),\\n null\\n ],\\n [\\n [\\n 12,\\n 20\\n ],\\n \\\"SyntheticBase\\\",\\n \\\"number\\\",\\n null\\n ],\\n [\\n [\\n 12,\\n 21\\n ],\\n \\\"PostScript\\\",\\n \\\"sid\\\",\\n null\\n ],\\n [\\n [\\n 12,\\n 22\\n ],\\n \\\"BaseFontName\\\",\\n \\\"sid\\\",\\n null\\n ],\\n [\\n [\\n 12,\\n 23\\n ],\\n \\\"BaseFontBlend\\\",\\n \\\"delta\\\",\\n null\\n ],\\n // CID font specific\\n [\\n [\\n 12,\\n 31\\n ],\\n \\\"CIDFontVersion\\\",\\n \\\"number\\\",\\n 0\\n ],\\n [\\n [\\n 12,\\n 32\\n ],\\n \\\"CIDFontRevision\\\",\\n \\\"number\\\",\\n 0\\n ],\\n [\\n [\\n 12,\\n 33\\n ],\\n \\\"CIDFontType\\\",\\n \\\"number\\\",\\n 0\\n ],\\n [\\n [\\n 12,\\n 34\\n ],\\n \\\"CIDCount\\\",\\n \\\"number\\\",\\n 8720\\n ],\\n [\\n [\\n 12,\\n 35\\n ],\\n \\\"UIDBase\\\",\\n \\\"number\\\",\\n null\\n ],\\n [\\n [\\n 12,\\n 37\\n ],\\n \\\"FDSelect\\\",\\n new (0, $0e34a43d05bde82c$export$2e2bcd8739ae039)($b84fd3dd9d8eddb2$var$FDSelect),\\n null\\n ],\\n [\\n [\\n 12,\\n 36\\n ],\\n \\\"FDArray\\\",\\n new (0, $0e34a43d05bde82c$export$2e2bcd8739ae039)(new (0, $43e9821ef3717eec$export$2e2bcd8739ae039)($b84fd3dd9d8eddb2$var$FontDict)),\\n null\\n ],\\n [\\n [\\n 12,\\n 38\\n ],\\n \\\"FontName\\\",\\n \\\"sid\\\",\\n null\\n ]\\n ]);\\n $b84fd3dd9d8eddb2$var$VariationStore = new Struct({\\n length: uint16,\\n itemVariationStore: (0, $1a47b0c45c1c22fe$export$fe1b122a2710f241)\\n });\\n $b84fd3dd9d8eddb2$var$CFF2TopDict = new (0, $61aa549f16d58b9b$export$2e2bcd8739ae039)([\\n [\\n [\\n 12,\\n 7\\n ],\\n \\\"FontMatrix\\\",\\n \\\"array\\\",\\n [\\n 1e-3,\\n 0,\\n 0,\\n 1e-3,\\n 0,\\n 0\\n ]\\n ],\\n [\\n 17,\\n \\\"CharStrings\\\",\\n new (0, $0e34a43d05bde82c$export$2e2bcd8739ae039)(new (0, $43e9821ef3717eec$export$2e2bcd8739ae039)()),\\n null\\n ],\\n [\\n [\\n 12,\\n 37\\n ],\\n \\\"FDSelect\\\",\\n new (0, $0e34a43d05bde82c$export$2e2bcd8739ae039)($b84fd3dd9d8eddb2$var$FDSelect),\\n null\\n ],\\n [\\n [\\n 12,\\n 36\\n ],\\n \\\"FDArray\\\",\\n new (0, $0e34a43d05bde82c$export$2e2bcd8739ae039)(new (0, $43e9821ef3717eec$export$2e2bcd8739ae039)($b84fd3dd9d8eddb2$var$FontDict)),\\n null\\n ],\\n [\\n 24,\\n \\\"vstore\\\",\\n new (0, $0e34a43d05bde82c$export$2e2bcd8739ae039)($b84fd3dd9d8eddb2$var$VariationStore),\\n null\\n ],\\n [\\n 25,\\n \\\"maxstack\\\",\\n \\\"number\\\",\\n 193\\n ]\\n ]);\\n $b84fd3dd9d8eddb2$var$CFFTop = new VersionedStruct(fixed16, {\\n 1: {\\n hdrSize: uint8,\\n offSize: uint8,\\n nameIndex: new (0, $43e9821ef3717eec$export$2e2bcd8739ae039)(new StringT(\\\"length\\\")),\\n topDictIndex: new (0, $43e9821ef3717eec$export$2e2bcd8739ae039)($b84fd3dd9d8eddb2$var$CFFTopDict),\\n stringIndex: new (0, $43e9821ef3717eec$export$2e2bcd8739ae039)(new StringT(\\\"length\\\")),\\n globalSubrIndex: new (0, $43e9821ef3717eec$export$2e2bcd8739ae039)()\\n },\\n 2: {\\n hdrSize: uint8,\\n length: uint16,\\n topDict: $b84fd3dd9d8eddb2$var$CFF2TopDict,\\n globalSubrIndex: new (0, $43e9821ef3717eec$export$2e2bcd8739ae039)()\\n }\\n });\\n $b84fd3dd9d8eddb2$export$2e2bcd8739ae039 = $b84fd3dd9d8eddb2$var$CFFTop;\\n $822ac0d589e4e237$var$CFFFont = class _$822ac0d589e4e237$var$CFFFont {\\n static decode(stream) {\\n return new _$822ac0d589e4e237$var$CFFFont(stream);\\n }\\n decode() {\\n let start = this.stream.pos;\\n let top = (0, $b84fd3dd9d8eddb2$export$2e2bcd8739ae039).decode(this.stream);\\n for (let key in top) {\\n let val = top[key];\\n this[key] = val;\\n }\\n if (this.version < 2) {\\n if (this.topDictIndex.length !== 1) throw new Error(\\\"Only a single font is allowed in CFF\\\");\\n this.topDict = this.topDictIndex[0];\\n }\\n this.isCIDFont = this.topDict.ROS != null;\\n return this;\\n }\\n string(sid) {\\n if (this.version >= 2) return null;\\n if (sid < (0, $229224aec43783c5$export$2e2bcd8739ae039).length) return (0, $229224aec43783c5$export$2e2bcd8739ae039)[sid];\\n return this.stringIndex[sid - (0, $229224aec43783c5$export$2e2bcd8739ae039).length];\\n }\\n get postscriptName() {\\n if (this.version < 2) return this.nameIndex[0];\\n return null;\\n }\\n get fullName() {\\n return this.string(this.topDict.FullName);\\n }\\n get familyName() {\\n return this.string(this.topDict.FamilyName);\\n }\\n getCharString(glyph) {\\n this.stream.pos = this.topDict.CharStrings[glyph].offset;\\n return this.stream.readBuffer(this.topDict.CharStrings[glyph].length);\\n }\\n getGlyphName(gid) {\\n if (this.version >= 2) return null;\\n if (this.isCIDFont) return null;\\n let { charset } = this.topDict;\\n if (Array.isArray(charset)) return charset[gid];\\n if (gid === 0) return \\\".notdef\\\";\\n gid -= 1;\\n switch (charset.version) {\\n case 0:\\n return this.string(charset.glyphs[gid]);\\n case 1:\\n case 2:\\n for (let i = 0; i < charset.ranges.length; i++) {\\n let range = charset.ranges[i];\\n if (range.offset <= gid && gid <= range.offset + range.nLeft) return this.string(range.first + (gid - range.offset));\\n }\\n break;\\n }\\n return null;\\n }\\n fdForGlyph(gid) {\\n if (!this.topDict.FDSelect) return null;\\n switch (this.topDict.FDSelect.version) {\\n case 0:\\n return this.topDict.FDSelect.fds[gid];\\n case 3:\\n case 4:\\n let { ranges } = this.topDict.FDSelect;\\n let low = 0;\\n let high = ranges.length - 1;\\n while (low <= high) {\\n let mid = low + high >> 1;\\n if (gid < ranges[mid].first) high = mid - 1;\\n else if (mid < high && gid >= ranges[mid + 1].first) low = mid + 1;\\n else return ranges[mid].fd;\\n }\\n default:\\n throw new Error(`Unknown FDSelect version: ${this.topDict.FDSelect.version}`);\\n }\\n }\\n privateDictForGlyph(gid) {\\n if (this.topDict.FDSelect) {\\n let fd = this.fdForGlyph(gid);\\n if (this.topDict.FDArray[fd]) return this.topDict.FDArray[fd].Private;\\n return null;\\n }\\n if (this.version < 2) return this.topDict.Private;\\n return this.topDict.FDArray[0].Private;\\n }\\n constructor(stream) {\\n this.stream = stream;\\n this.decode();\\n }\\n };\\n $822ac0d589e4e237$export$2e2bcd8739ae039 = $822ac0d589e4e237$var$CFFFont;\\n $2bbf2bc1ce37cd8f$var$VerticalOrigin = new Struct({\\n glyphIndex: uint16,\\n vertOriginY: int16\\n });\\n $2bbf2bc1ce37cd8f$export$2e2bcd8739ae039 = new Struct({\\n majorVersion: uint16,\\n minorVersion: uint16,\\n defaultVertOriginY: int16,\\n numVertOriginYMetrics: uint16,\\n metrics: new ArrayT($2bbf2bc1ce37cd8f$var$VerticalOrigin, \\\"numVertOriginYMetrics\\\")\\n });\\n $0941618dc22a946d$export$16b227cb15d716a0 = new Struct({\\n height: uint8,\\n width: uint8,\\n horiBearingX: int8,\\n horiBearingY: int8,\\n horiAdvance: uint8,\\n vertBearingX: int8,\\n vertBearingY: int8,\\n vertAdvance: uint8\\n });\\n $0941618dc22a946d$export$62c53e75f69bfe12 = new Struct({\\n height: uint8,\\n width: uint8,\\n bearingX: int8,\\n bearingY: int8,\\n advance: uint8\\n });\\n $0941618dc22a946d$var$EBDTComponent = new Struct({\\n glyph: uint16,\\n xOffset: int8,\\n yOffset: int8\\n });\\n $0941618dc22a946d$var$ByteAligned = class {\\n };\\n $0941618dc22a946d$var$BitAligned = class {\\n };\\n $0941618dc22a946d$export$f1f5ddeb20d14f = new VersionedStruct(\\\"version\\\", {\\n 1: {\\n metrics: $0941618dc22a946d$export$62c53e75f69bfe12,\\n data: $0941618dc22a946d$var$ByteAligned\\n },\\n 2: {\\n metrics: $0941618dc22a946d$export$62c53e75f69bfe12,\\n data: $0941618dc22a946d$var$BitAligned\\n },\\n // format 3 is deprecated\\n // format 4 is not supported by Microsoft\\n 5: {\\n data: $0941618dc22a946d$var$BitAligned\\n },\\n 6: {\\n metrics: $0941618dc22a946d$export$16b227cb15d716a0,\\n data: $0941618dc22a946d$var$ByteAligned\\n },\\n 7: {\\n metrics: $0941618dc22a946d$export$16b227cb15d716a0,\\n data: $0941618dc22a946d$var$BitAligned\\n },\\n 8: {\\n metrics: $0941618dc22a946d$export$62c53e75f69bfe12,\\n pad: new Reserved(uint8),\\n numComponents: uint16,\\n components: new ArrayT($0941618dc22a946d$var$EBDTComponent, \\\"numComponents\\\")\\n },\\n 9: {\\n metrics: $0941618dc22a946d$export$16b227cb15d716a0,\\n pad: new Reserved(uint8),\\n numComponents: uint16,\\n components: new ArrayT($0941618dc22a946d$var$EBDTComponent, \\\"numComponents\\\")\\n },\\n 17: {\\n metrics: $0941618dc22a946d$export$62c53e75f69bfe12,\\n dataLen: uint32,\\n data: new BufferT(\\\"dataLen\\\")\\n },\\n 18: {\\n metrics: $0941618dc22a946d$export$16b227cb15d716a0,\\n dataLen: uint32,\\n data: new BufferT(\\\"dataLen\\\")\\n },\\n 19: {\\n dataLen: uint32,\\n data: new BufferT(\\\"dataLen\\\")\\n }\\n });\\n $9911c4c7201c13de$var$SBitLineMetrics = new Struct({\\n ascender: int8,\\n descender: int8,\\n widthMax: uint8,\\n caretSlopeNumerator: int8,\\n caretSlopeDenominator: int8,\\n caretOffset: int8,\\n minOriginSB: int8,\\n minAdvanceSB: int8,\\n maxBeforeBL: int8,\\n minAfterBL: int8,\\n pad: new Reserved(int8, 2)\\n });\\n $9911c4c7201c13de$var$CodeOffsetPair = new Struct({\\n glyphCode: uint16,\\n offset: uint16\\n });\\n $9911c4c7201c13de$var$IndexSubtable = new VersionedStruct(uint16, {\\n header: {\\n imageFormat: uint16,\\n imageDataOffset: uint32\\n },\\n 1: {\\n offsetArray: new ArrayT(uint32, (t) => t.parent.lastGlyphIndex - t.parent.firstGlyphIndex + 1)\\n },\\n 2: {\\n imageSize: uint32,\\n bigMetrics: (0, $0941618dc22a946d$export$16b227cb15d716a0)\\n },\\n 3: {\\n offsetArray: new ArrayT(uint16, (t) => t.parent.lastGlyphIndex - t.parent.firstGlyphIndex + 1)\\n },\\n 4: {\\n numGlyphs: uint32,\\n glyphArray: new ArrayT($9911c4c7201c13de$var$CodeOffsetPair, (t) => t.numGlyphs + 1)\\n },\\n 5: {\\n imageSize: uint32,\\n bigMetrics: (0, $0941618dc22a946d$export$16b227cb15d716a0),\\n numGlyphs: uint32,\\n glyphCodeArray: new ArrayT(uint16, \\\"numGlyphs\\\")\\n }\\n });\\n $9911c4c7201c13de$var$IndexSubtableArray = new Struct({\\n firstGlyphIndex: uint16,\\n lastGlyphIndex: uint16,\\n subtable: new Pointer(uint32, $9911c4c7201c13de$var$IndexSubtable)\\n });\\n $9911c4c7201c13de$var$BitmapSizeTable = new Struct({\\n indexSubTableArray: new Pointer(uint32, new ArrayT($9911c4c7201c13de$var$IndexSubtableArray, 1), {\\n type: \\\"parent\\\"\\n }),\\n indexTablesSize: uint32,\\n numberOfIndexSubTables: uint32,\\n colorRef: uint32,\\n hori: $9911c4c7201c13de$var$SBitLineMetrics,\\n vert: $9911c4c7201c13de$var$SBitLineMetrics,\\n startGlyphIndex: uint16,\\n endGlyphIndex: uint16,\\n ppemX: uint8,\\n ppemY: uint8,\\n bitDepth: uint8,\\n flags: new Bitfield(uint8, [\\n \\\"horizontal\\\",\\n \\\"vertical\\\"\\n ])\\n });\\n $9911c4c7201c13de$export$2e2bcd8739ae039 = new Struct({\\n version: uint32,\\n numSizes: uint32,\\n sizes: new ArrayT($9911c4c7201c13de$var$BitmapSizeTable, \\\"numSizes\\\")\\n });\\n $abb847051efd51b1$var$ImageTable = new Struct({\\n ppem: uint16,\\n resolution: uint16,\\n imageOffsets: new ArrayT(new Pointer(uint32, \\\"void\\\"), (t) => t.parent.parent.maxp.numGlyphs + 1)\\n });\\n $abb847051efd51b1$export$2e2bcd8739ae039 = new Struct({\\n version: uint16,\\n flags: new Bitfield(uint16, [\\n \\\"renderOutlines\\\"\\n ]),\\n numImgTables: uint32,\\n imageTables: new ArrayT(new Pointer(uint32, $abb847051efd51b1$var$ImageTable), \\\"numImgTables\\\")\\n });\\n $eb629188f3dfefdd$var$LayerRecord = new Struct({\\n gid: uint16,\\n paletteIndex: uint16\\n // Index value to use in the appropriate palette. This value must\\n });\\n $eb629188f3dfefdd$var$BaseGlyphRecord = new Struct({\\n gid: uint16,\\n // and is not rendered for color.\\n firstLayerIndex: uint16,\\n // There will be numLayers consecutive entries for this base glyph.\\n numLayers: uint16\\n });\\n $eb629188f3dfefdd$export$2e2bcd8739ae039 = new Struct({\\n version: uint16,\\n numBaseGlyphRecords: uint16,\\n baseGlyphRecord: new Pointer(uint32, new ArrayT($eb629188f3dfefdd$var$BaseGlyphRecord, \\\"numBaseGlyphRecords\\\")),\\n layerRecords: new Pointer(uint32, new ArrayT($eb629188f3dfefdd$var$LayerRecord, \\\"numLayerRecords\\\"), {\\n lazy: true\\n }),\\n numLayerRecords: uint16\\n });\\n $08734b8e7dc64587$var$ColorRecord = new Struct({\\n blue: uint8,\\n green: uint8,\\n red: uint8,\\n alpha: uint8\\n });\\n $08734b8e7dc64587$export$2e2bcd8739ae039 = new VersionedStruct(uint16, {\\n header: {\\n numPaletteEntries: uint16,\\n numPalettes: uint16,\\n numColorRecords: uint16,\\n colorRecords: new Pointer(uint32, new ArrayT($08734b8e7dc64587$var$ColorRecord, \\\"numColorRecords\\\")),\\n colorRecordIndices: new ArrayT(uint16, \\\"numPalettes\\\")\\n },\\n 0: {},\\n 1: {\\n offsetPaletteTypeArray: new Pointer(uint32, new ArrayT(uint32, \\\"numPalettes\\\")),\\n offsetPaletteLabelArray: new Pointer(uint32, new ArrayT(uint16, \\\"numPalettes\\\")),\\n offsetPaletteEntryLabelArray: new Pointer(uint32, new ArrayT(uint16, \\\"numPaletteEntries\\\"))\\n }\\n });\\n $497cef411d884e34$var$BaseCoord = new VersionedStruct(uint16, {\\n 1: {\\n coordinate: int16\\n // X or Y value, in design units\\n },\\n 2: {\\n coordinate: int16,\\n referenceGlyph: uint16,\\n baseCoordPoint: uint16\\n // Index of contour point on the referenceGlyph\\n },\\n 3: {\\n coordinate: int16,\\n deviceTable: new Pointer(uint16, (0, $7cbbe4e24ef3cb75$export$8215d14a63d9fb10))\\n // Device table for X or Y value\\n }\\n });\\n $497cef411d884e34$var$BaseValues = new Struct({\\n defaultIndex: uint16,\\n baseCoordCount: uint16,\\n baseCoords: new ArrayT(new Pointer(uint16, $497cef411d884e34$var$BaseCoord), \\\"baseCoordCount\\\")\\n });\\n $497cef411d884e34$var$FeatMinMaxRecord = new Struct({\\n tag: new StringT(4),\\n minCoord: new Pointer(uint16, $497cef411d884e34$var$BaseCoord, {\\n type: \\\"parent\\\"\\n }),\\n maxCoord: new Pointer(uint16, $497cef411d884e34$var$BaseCoord, {\\n type: \\\"parent\\\"\\n })\\n // May be NULL\\n });\\n $497cef411d884e34$var$MinMax = new Struct({\\n minCoord: new Pointer(uint16, $497cef411d884e34$var$BaseCoord),\\n maxCoord: new Pointer(uint16, $497cef411d884e34$var$BaseCoord),\\n featMinMaxCount: uint16,\\n featMinMaxRecords: new ArrayT($497cef411d884e34$var$FeatMinMaxRecord, \\\"featMinMaxCount\\\")\\n // In alphabetical order\\n });\\n $497cef411d884e34$var$BaseLangSysRecord = new Struct({\\n tag: new StringT(4),\\n minMax: new Pointer(uint16, $497cef411d884e34$var$MinMax, {\\n type: \\\"parent\\\"\\n })\\n });\\n $497cef411d884e34$var$BaseScript = new Struct({\\n baseValues: new Pointer(uint16, $497cef411d884e34$var$BaseValues),\\n defaultMinMax: new Pointer(uint16, $497cef411d884e34$var$MinMax),\\n baseLangSysCount: uint16,\\n baseLangSysRecords: new ArrayT($497cef411d884e34$var$BaseLangSysRecord, \\\"baseLangSysCount\\\")\\n // in alphabetical order by BaseLangSysTag\\n });\\n $497cef411d884e34$var$BaseScriptRecord = new Struct({\\n tag: new StringT(4),\\n script: new Pointer(uint16, $497cef411d884e34$var$BaseScript, {\\n type: \\\"parent\\\"\\n })\\n });\\n $497cef411d884e34$var$BaseScriptList = new ArrayT($497cef411d884e34$var$BaseScriptRecord, uint16);\\n $497cef411d884e34$var$BaseTagList = new ArrayT(new StringT(4), uint16);\\n $497cef411d884e34$var$Axis = new Struct({\\n baseTagList: new Pointer(uint16, $497cef411d884e34$var$BaseTagList),\\n baseScriptList: new Pointer(uint16, $497cef411d884e34$var$BaseScriptList)\\n });\\n $497cef411d884e34$export$2e2bcd8739ae039 = new VersionedStruct(uint32, {\\n header: {\\n horizAxis: new Pointer(uint16, $497cef411d884e34$var$Axis),\\n vertAxis: new Pointer(uint16, $497cef411d884e34$var$Axis)\\n // May be NULL\\n },\\n 65536: {},\\n 65537: {\\n itemVariationStore: new Pointer(uint32, (0, $1a47b0c45c1c22fe$export$fe1b122a2710f241))\\n }\\n });\\n $cf5f33c63ef209e6$var$AttachPoint = new ArrayT(uint16, uint16);\\n $cf5f33c63ef209e6$var$AttachList = new Struct({\\n coverage: new Pointer(uint16, (0, $7cbbe4e24ef3cb75$export$17608c3f81a6111)),\\n glyphCount: uint16,\\n attachPoints: new ArrayT(new Pointer(uint16, $cf5f33c63ef209e6$var$AttachPoint), \\\"glyphCount\\\")\\n });\\n $cf5f33c63ef209e6$var$CaretValue = new VersionedStruct(uint16, {\\n 1: {\\n coordinate: int16\\n },\\n 2: {\\n caretValuePoint: uint16\\n },\\n 3: {\\n coordinate: int16,\\n deviceTable: new Pointer(uint16, (0, $7cbbe4e24ef3cb75$export$8215d14a63d9fb10))\\n }\\n });\\n $cf5f33c63ef209e6$var$LigGlyph = new ArrayT(new Pointer(uint16, $cf5f33c63ef209e6$var$CaretValue), uint16);\\n $cf5f33c63ef209e6$var$LigCaretList = new Struct({\\n coverage: new Pointer(uint16, (0, $7cbbe4e24ef3cb75$export$17608c3f81a6111)),\\n ligGlyphCount: uint16,\\n ligGlyphs: new ArrayT(new Pointer(uint16, $cf5f33c63ef209e6$var$LigGlyph), \\\"ligGlyphCount\\\")\\n });\\n $cf5f33c63ef209e6$var$MarkGlyphSetsDef = new Struct({\\n markSetTableFormat: uint16,\\n markSetCount: uint16,\\n coverage: new ArrayT(new Pointer(uint32, (0, $7cbbe4e24ef3cb75$export$17608c3f81a6111)), \\\"markSetCount\\\")\\n });\\n $cf5f33c63ef209e6$export$2e2bcd8739ae039 = new VersionedStruct(uint32, {\\n header: {\\n glyphClassDef: new Pointer(uint16, (0, $7cbbe4e24ef3cb75$export$843d551fbbafef71)),\\n attachList: new Pointer(uint16, $cf5f33c63ef209e6$var$AttachList),\\n ligCaretList: new Pointer(uint16, $cf5f33c63ef209e6$var$LigCaretList),\\n markAttachClassDef: new Pointer(uint16, (0, $7cbbe4e24ef3cb75$export$843d551fbbafef71))\\n },\\n 65536: {},\\n 65538: {\\n markGlyphSetsDef: new Pointer(uint16, $cf5f33c63ef209e6$var$MarkGlyphSetsDef)\\n },\\n 65539: {\\n markGlyphSetsDef: new Pointer(uint16, $cf5f33c63ef209e6$var$MarkGlyphSetsDef),\\n itemVariationStore: new Pointer(uint32, (0, $1a47b0c45c1c22fe$export$fe1b122a2710f241))\\n }\\n });\\n $47e0e8ef515d9903$var$ValueFormat = new Bitfield(uint16, [\\n \\\"xPlacement\\\",\\n \\\"yPlacement\\\",\\n \\\"xAdvance\\\",\\n \\\"yAdvance\\\",\\n \\\"xPlaDevice\\\",\\n \\\"yPlaDevice\\\",\\n \\\"xAdvDevice\\\",\\n \\\"yAdvDevice\\\"\\n ]);\\n $47e0e8ef515d9903$var$types = {\\n xPlacement: int16,\\n yPlacement: int16,\\n xAdvance: int16,\\n yAdvance: int16,\\n xPlaDevice: new Pointer(uint16, (0, $7cbbe4e24ef3cb75$export$8215d14a63d9fb10), {\\n type: \\\"global\\\",\\n relativeTo: (ctx) => ctx.rel\\n }),\\n yPlaDevice: new Pointer(uint16, (0, $7cbbe4e24ef3cb75$export$8215d14a63d9fb10), {\\n type: \\\"global\\\",\\n relativeTo: (ctx) => ctx.rel\\n }),\\n xAdvDevice: new Pointer(uint16, (0, $7cbbe4e24ef3cb75$export$8215d14a63d9fb10), {\\n type: \\\"global\\\",\\n relativeTo: (ctx) => ctx.rel\\n }),\\n yAdvDevice: new Pointer(uint16, (0, $7cbbe4e24ef3cb75$export$8215d14a63d9fb10), {\\n type: \\\"global\\\",\\n relativeTo: (ctx) => ctx.rel\\n })\\n };\\n $47e0e8ef515d9903$var$ValueRecord = class {\\n buildStruct(parent) {\\n let struct = parent;\\n while (!struct[this.key] && struct.parent) struct = struct.parent;\\n if (!struct[this.key]) return;\\n let fields = {};\\n fields.rel = () => struct._startOffset;\\n let format = struct[this.key];\\n for (let key in format) if (format[key]) fields[key] = $47e0e8ef515d9903$var$types[key];\\n return new Struct(fields);\\n }\\n size(val, ctx) {\\n return this.buildStruct(ctx).size(val, ctx);\\n }\\n decode(stream, parent) {\\n let res = this.buildStruct(parent).decode(stream, parent);\\n delete res.rel;\\n return res;\\n }\\n constructor(key = \\\"valueFormat\\\") {\\n this.key = key;\\n }\\n };\\n $47e0e8ef515d9903$var$PairValueRecord = new Struct({\\n secondGlyph: uint16,\\n value1: new $47e0e8ef515d9903$var$ValueRecord(\\\"valueFormat1\\\"),\\n value2: new $47e0e8ef515d9903$var$ValueRecord(\\\"valueFormat2\\\")\\n });\\n $47e0e8ef515d9903$var$PairSet = new ArrayT($47e0e8ef515d9903$var$PairValueRecord, uint16);\\n $47e0e8ef515d9903$var$Class2Record = new Struct({\\n value1: new $47e0e8ef515d9903$var$ValueRecord(\\\"valueFormat1\\\"),\\n value2: new $47e0e8ef515d9903$var$ValueRecord(\\\"valueFormat2\\\")\\n });\\n $47e0e8ef515d9903$var$Anchor = new VersionedStruct(uint16, {\\n 1: {\\n xCoordinate: int16,\\n yCoordinate: int16\\n },\\n 2: {\\n xCoordinate: int16,\\n yCoordinate: int16,\\n anchorPoint: uint16\\n },\\n 3: {\\n xCoordinate: int16,\\n yCoordinate: int16,\\n xDeviceTable: new Pointer(uint16, (0, $7cbbe4e24ef3cb75$export$8215d14a63d9fb10)),\\n yDeviceTable: new Pointer(uint16, (0, $7cbbe4e24ef3cb75$export$8215d14a63d9fb10))\\n }\\n });\\n $47e0e8ef515d9903$var$EntryExitRecord = new Struct({\\n entryAnchor: new Pointer(uint16, $47e0e8ef515d9903$var$Anchor, {\\n type: \\\"parent\\\"\\n }),\\n exitAnchor: new Pointer(uint16, $47e0e8ef515d9903$var$Anchor, {\\n type: \\\"parent\\\"\\n })\\n });\\n $47e0e8ef515d9903$var$MarkRecord = new Struct({\\n class: uint16,\\n markAnchor: new Pointer(uint16, $47e0e8ef515d9903$var$Anchor, {\\n type: \\\"parent\\\"\\n })\\n });\\n $47e0e8ef515d9903$var$MarkArray = new ArrayT($47e0e8ef515d9903$var$MarkRecord, uint16);\\n $47e0e8ef515d9903$var$BaseRecord = new ArrayT(new Pointer(uint16, $47e0e8ef515d9903$var$Anchor), (t) => t.parent.classCount);\\n $47e0e8ef515d9903$var$BaseArray = new ArrayT($47e0e8ef515d9903$var$BaseRecord, uint16);\\n $47e0e8ef515d9903$var$ComponentRecord = new ArrayT(new Pointer(uint16, $47e0e8ef515d9903$var$Anchor), (t) => t.parent.parent.classCount);\\n $47e0e8ef515d9903$var$LigatureAttach = new ArrayT($47e0e8ef515d9903$var$ComponentRecord, uint16);\\n $47e0e8ef515d9903$var$LigatureArray = new ArrayT(new Pointer(uint16, $47e0e8ef515d9903$var$LigatureAttach), uint16);\\n $47e0e8ef515d9903$export$73a8cfb19cd43a0f = new VersionedStruct(\\\"lookupType\\\", {\\n 1: new VersionedStruct(uint16, {\\n 1: {\\n coverage: new Pointer(uint16, (0, $7cbbe4e24ef3cb75$export$17608c3f81a6111)),\\n valueFormat: $47e0e8ef515d9903$var$ValueFormat,\\n value: new $47e0e8ef515d9903$var$ValueRecord()\\n },\\n 2: {\\n coverage: new Pointer(uint16, (0, $7cbbe4e24ef3cb75$export$17608c3f81a6111)),\\n valueFormat: $47e0e8ef515d9903$var$ValueFormat,\\n valueCount: uint16,\\n values: new LazyArray(new $47e0e8ef515d9903$var$ValueRecord(), \\\"valueCount\\\")\\n }\\n }),\\n 2: new VersionedStruct(uint16, {\\n 1: {\\n coverage: new Pointer(uint16, (0, $7cbbe4e24ef3cb75$export$17608c3f81a6111)),\\n valueFormat1: $47e0e8ef515d9903$var$ValueFormat,\\n valueFormat2: $47e0e8ef515d9903$var$ValueFormat,\\n pairSetCount: uint16,\\n pairSets: new LazyArray(new Pointer(uint16, $47e0e8ef515d9903$var$PairSet), \\\"pairSetCount\\\")\\n },\\n 2: {\\n coverage: new Pointer(uint16, (0, $7cbbe4e24ef3cb75$export$17608c3f81a6111)),\\n valueFormat1: $47e0e8ef515d9903$var$ValueFormat,\\n valueFormat2: $47e0e8ef515d9903$var$ValueFormat,\\n classDef1: new Pointer(uint16, (0, $7cbbe4e24ef3cb75$export$843d551fbbafef71)),\\n classDef2: new Pointer(uint16, (0, $7cbbe4e24ef3cb75$export$843d551fbbafef71)),\\n class1Count: uint16,\\n class2Count: uint16,\\n classRecords: new LazyArray(new LazyArray($47e0e8ef515d9903$var$Class2Record, \\\"class2Count\\\"), \\\"class1Count\\\")\\n }\\n }),\\n 3: {\\n format: uint16,\\n coverage: new Pointer(uint16, (0, $7cbbe4e24ef3cb75$export$17608c3f81a6111)),\\n entryExitCount: uint16,\\n entryExitRecords: new ArrayT($47e0e8ef515d9903$var$EntryExitRecord, \\\"entryExitCount\\\")\\n },\\n 4: {\\n format: uint16,\\n markCoverage: new Pointer(uint16, (0, $7cbbe4e24ef3cb75$export$17608c3f81a6111)),\\n baseCoverage: new Pointer(uint16, (0, $7cbbe4e24ef3cb75$export$17608c3f81a6111)),\\n classCount: uint16,\\n markArray: new Pointer(uint16, $47e0e8ef515d9903$var$MarkArray),\\n baseArray: new Pointer(uint16, $47e0e8ef515d9903$var$BaseArray)\\n },\\n 5: {\\n format: uint16,\\n markCoverage: new Pointer(uint16, (0, $7cbbe4e24ef3cb75$export$17608c3f81a6111)),\\n ligatureCoverage: new Pointer(uint16, (0, $7cbbe4e24ef3cb75$export$17608c3f81a6111)),\\n classCount: uint16,\\n markArray: new Pointer(uint16, $47e0e8ef515d9903$var$MarkArray),\\n ligatureArray: new Pointer(uint16, $47e0e8ef515d9903$var$LigatureArray)\\n },\\n 6: {\\n format: uint16,\\n mark1Coverage: new Pointer(uint16, (0, $7cbbe4e24ef3cb75$export$17608c3f81a6111)),\\n mark2Coverage: new Pointer(uint16, (0, $7cbbe4e24ef3cb75$export$17608c3f81a6111)),\\n classCount: uint16,\\n mark1Array: new Pointer(uint16, $47e0e8ef515d9903$var$MarkArray),\\n mark2Array: new Pointer(uint16, $47e0e8ef515d9903$var$BaseArray)\\n },\\n 7: (0, $7cbbe4e24ef3cb75$export$841858b892ce1f4c),\\n 8: (0, $7cbbe4e24ef3cb75$export$5e6d09e6861162f6),\\n 9: {\\n posFormat: uint16,\\n lookupType: uint16,\\n extension: new Pointer(uint32, null)\\n }\\n });\\n $47e0e8ef515d9903$export$73a8cfb19cd43a0f.versions[9].extension.type = $47e0e8ef515d9903$export$73a8cfb19cd43a0f;\\n $47e0e8ef515d9903$export$2e2bcd8739ae039 = new VersionedStruct(uint32, {\\n header: {\\n scriptList: new Pointer(uint16, (0, $7cbbe4e24ef3cb75$export$3e15fc05ce864229)),\\n featureList: new Pointer(uint16, (0, $7cbbe4e24ef3cb75$export$aa18130def4b6cb4)),\\n lookupList: new Pointer(uint16, new (0, $7cbbe4e24ef3cb75$export$df0008c6ff2da22a)($47e0e8ef515d9903$export$73a8cfb19cd43a0f))\\n },\\n 65536: {},\\n 65537: {\\n featureVariations: new Pointer(uint32, (0, $1a47b0c45c1c22fe$export$441b70b7971dd419))\\n }\\n });\\n $d3f442064af66e06$var$Sequence = new ArrayT(uint16, uint16);\\n $d3f442064af66e06$var$AlternateSet = $d3f442064af66e06$var$Sequence;\\n $d3f442064af66e06$var$Ligature = new Struct({\\n glyph: uint16,\\n compCount: uint16,\\n components: new ArrayT(uint16, (t) => t.compCount - 1)\\n });\\n $d3f442064af66e06$var$LigatureSet = new ArrayT(new Pointer(uint16, $d3f442064af66e06$var$Ligature), uint16);\\n $d3f442064af66e06$var$GSUBLookup = new VersionedStruct(\\\"lookupType\\\", {\\n 1: new VersionedStruct(uint16, {\\n 1: {\\n coverage: new Pointer(uint16, (0, $7cbbe4e24ef3cb75$export$17608c3f81a6111)),\\n deltaGlyphID: int16\\n },\\n 2: {\\n coverage: new Pointer(uint16, (0, $7cbbe4e24ef3cb75$export$17608c3f81a6111)),\\n glyphCount: uint16,\\n substitute: new LazyArray(uint16, \\\"glyphCount\\\")\\n }\\n }),\\n 2: {\\n substFormat: uint16,\\n coverage: new Pointer(uint16, (0, $7cbbe4e24ef3cb75$export$17608c3f81a6111)),\\n count: uint16,\\n sequences: new LazyArray(new Pointer(uint16, $d3f442064af66e06$var$Sequence), \\\"count\\\")\\n },\\n 3: {\\n substFormat: uint16,\\n coverage: new Pointer(uint16, (0, $7cbbe4e24ef3cb75$export$17608c3f81a6111)),\\n count: uint16,\\n alternateSet: new LazyArray(new Pointer(uint16, $d3f442064af66e06$var$AlternateSet), \\\"count\\\")\\n },\\n 4: {\\n substFormat: uint16,\\n coverage: new Pointer(uint16, (0, $7cbbe4e24ef3cb75$export$17608c3f81a6111)),\\n count: uint16,\\n ligatureSets: new LazyArray(new Pointer(uint16, $d3f442064af66e06$var$LigatureSet), \\\"count\\\")\\n },\\n 5: (0, $7cbbe4e24ef3cb75$export$841858b892ce1f4c),\\n 6: (0, $7cbbe4e24ef3cb75$export$5e6d09e6861162f6),\\n 7: {\\n substFormat: uint16,\\n lookupType: uint16,\\n extension: new Pointer(uint32, null)\\n },\\n 8: {\\n substFormat: uint16,\\n coverage: new Pointer(uint16, (0, $7cbbe4e24ef3cb75$export$17608c3f81a6111)),\\n backtrackCoverage: new ArrayT(new Pointer(uint16, (0, $7cbbe4e24ef3cb75$export$17608c3f81a6111)), \\\"backtrackGlyphCount\\\"),\\n lookaheadGlyphCount: uint16,\\n lookaheadCoverage: new ArrayT(new Pointer(uint16, (0, $7cbbe4e24ef3cb75$export$17608c3f81a6111)), \\\"lookaheadGlyphCount\\\"),\\n glyphCount: uint16,\\n substitutes: new ArrayT(uint16, \\\"glyphCount\\\")\\n }\\n });\\n $d3f442064af66e06$var$GSUBLookup.versions[7].extension.type = $d3f442064af66e06$var$GSUBLookup;\\n $d3f442064af66e06$export$2e2bcd8739ae039 = new VersionedStruct(uint32, {\\n header: {\\n scriptList: new Pointer(uint16, (0, $7cbbe4e24ef3cb75$export$3e15fc05ce864229)),\\n featureList: new Pointer(uint16, (0, $7cbbe4e24ef3cb75$export$aa18130def4b6cb4)),\\n lookupList: new Pointer(uint16, new (0, $7cbbe4e24ef3cb75$export$df0008c6ff2da22a)($d3f442064af66e06$var$GSUBLookup))\\n },\\n 65536: {},\\n 65537: {\\n featureVariations: new Pointer(uint32, (0, $1a47b0c45c1c22fe$export$441b70b7971dd419))\\n }\\n });\\n $71cfb3c4767fbd0c$var$JstfGSUBModList = new ArrayT(uint16, uint16);\\n $71cfb3c4767fbd0c$var$JstfPriority = new Struct({\\n shrinkageEnableGSUB: new Pointer(uint16, $71cfb3c4767fbd0c$var$JstfGSUBModList),\\n shrinkageDisableGSUB: new Pointer(uint16, $71cfb3c4767fbd0c$var$JstfGSUBModList),\\n shrinkageEnableGPOS: new Pointer(uint16, $71cfb3c4767fbd0c$var$JstfGSUBModList),\\n shrinkageDisableGPOS: new Pointer(uint16, $71cfb3c4767fbd0c$var$JstfGSUBModList),\\n shrinkageJstfMax: new Pointer(uint16, new (0, $7cbbe4e24ef3cb75$export$df0008c6ff2da22a)((0, $47e0e8ef515d9903$export$73a8cfb19cd43a0f))),\\n extensionEnableGSUB: new Pointer(uint16, $71cfb3c4767fbd0c$var$JstfGSUBModList),\\n extensionDisableGSUB: new Pointer(uint16, $71cfb3c4767fbd0c$var$JstfGSUBModList),\\n extensionEnableGPOS: new Pointer(uint16, $71cfb3c4767fbd0c$var$JstfGSUBModList),\\n extensionDisableGPOS: new Pointer(uint16, $71cfb3c4767fbd0c$var$JstfGSUBModList),\\n extensionJstfMax: new Pointer(uint16, new (0, $7cbbe4e24ef3cb75$export$df0008c6ff2da22a)((0, $47e0e8ef515d9903$export$73a8cfb19cd43a0f)))\\n });\\n $71cfb3c4767fbd0c$var$JstfLangSys = new ArrayT(new Pointer(uint16, $71cfb3c4767fbd0c$var$JstfPriority), uint16);\\n $71cfb3c4767fbd0c$var$JstfLangSysRecord = new Struct({\\n tag: new StringT(4),\\n jstfLangSys: new Pointer(uint16, $71cfb3c4767fbd0c$var$JstfLangSys)\\n });\\n $71cfb3c4767fbd0c$var$JstfScript = new Struct({\\n extenderGlyphs: new Pointer(uint16, new ArrayT(uint16, uint16)),\\n defaultLangSys: new Pointer(uint16, $71cfb3c4767fbd0c$var$JstfLangSys),\\n langSysCount: uint16,\\n langSysRecords: new ArrayT($71cfb3c4767fbd0c$var$JstfLangSysRecord, \\\"langSysCount\\\")\\n });\\n $71cfb3c4767fbd0c$var$JstfScriptRecord = new Struct({\\n tag: new StringT(4),\\n script: new Pointer(uint16, $71cfb3c4767fbd0c$var$JstfScript, {\\n type: \\\"parent\\\"\\n })\\n });\\n $71cfb3c4767fbd0c$export$2e2bcd8739ae039 = new Struct({\\n version: uint32,\\n scriptCount: uint16,\\n scriptList: new ArrayT($71cfb3c4767fbd0c$var$JstfScriptRecord, \\\"scriptCount\\\")\\n });\\n $d059a6bd2d3b5b63$var$VariableSizeNumber = class {\\n decode(stream, parent) {\\n switch (this.size(0, parent)) {\\n case 1:\\n return stream.readUInt8();\\n case 2:\\n return stream.readUInt16BE();\\n case 3:\\n return stream.readUInt24BE();\\n case 4:\\n return stream.readUInt32BE();\\n }\\n }\\n size(val, parent) {\\n return (0, resolveLength)(this._size, null, parent);\\n }\\n constructor(size) {\\n this._size = size;\\n }\\n };\\n $d059a6bd2d3b5b63$var$MapDataEntry = new Struct({\\n entry: new $d059a6bd2d3b5b63$var$VariableSizeNumber((t) => ((t.parent.entryFormat & 48) >> 4) + 1),\\n outerIndex: (t) => t.entry >> (t.parent.entryFormat & 15) + 1,\\n innerIndex: (t) => t.entry & (1 << (t.parent.entryFormat & 15) + 1) - 1\\n });\\n $d059a6bd2d3b5b63$var$DeltaSetIndexMap = new Struct({\\n entryFormat: uint16,\\n mapCount: uint16,\\n mapData: new ArrayT($d059a6bd2d3b5b63$var$MapDataEntry, \\\"mapCount\\\")\\n });\\n $d059a6bd2d3b5b63$export$2e2bcd8739ae039 = new Struct({\\n majorVersion: uint16,\\n minorVersion: uint16,\\n itemVariationStore: new Pointer(uint32, (0, $1a47b0c45c1c22fe$export$fe1b122a2710f241)),\\n advanceWidthMapping: new Pointer(uint32, $d059a6bd2d3b5b63$var$DeltaSetIndexMap),\\n LSBMapping: new Pointer(uint32, $d059a6bd2d3b5b63$var$DeltaSetIndexMap),\\n RSBMapping: new Pointer(uint32, $d059a6bd2d3b5b63$var$DeltaSetIndexMap)\\n });\\n $dceeca3e1977ce30$var$Signature = new Struct({\\n format: uint32,\\n length: uint32,\\n offset: uint32\\n });\\n $dceeca3e1977ce30$var$SignatureBlock = new Struct({\\n reserved: new Reserved(uint16, 2),\\n cbSignature: uint32,\\n signature: new BufferT(\\\"cbSignature\\\")\\n });\\n $dceeca3e1977ce30$export$2e2bcd8739ae039 = new Struct({\\n ulVersion: uint32,\\n usNumSigs: uint16,\\n usFlag: uint16,\\n signatures: new ArrayT($dceeca3e1977ce30$var$Signature, \\\"usNumSigs\\\"),\\n signatureBlocks: new ArrayT($dceeca3e1977ce30$var$SignatureBlock, \\\"usNumSigs\\\")\\n });\\n $8acd740a9435aad0$var$GaspRange = new Struct({\\n rangeMaxPPEM: uint16,\\n rangeGaspBehavior: new Bitfield(uint16, [\\n \\\"grayscale\\\",\\n \\\"gridfit\\\",\\n \\\"symmetricSmoothing\\\",\\n \\\"symmetricGridfit\\\"\\n // only in version 1, for ClearType\\n ])\\n });\\n $8acd740a9435aad0$export$2e2bcd8739ae039 = new Struct({\\n version: uint16,\\n numRanges: uint16,\\n gaspRanges: new ArrayT($8acd740a9435aad0$var$GaspRange, \\\"numRanges\\\")\\n // Sorted by ppem\\n });\\n $b5f380243c34d6a0$var$DeviceRecord = new Struct({\\n pixelSize: uint8,\\n maximumWidth: uint8,\\n widths: new ArrayT(uint8, (t) => t.parent.parent.maxp.numGlyphs)\\n });\\n $b5f380243c34d6a0$export$2e2bcd8739ae039 = new Struct({\\n version: uint16,\\n numRecords: int16,\\n sizeDeviceRecord: int32,\\n records: new ArrayT($b5f380243c34d6a0$var$DeviceRecord, \\\"numRecords\\\")\\n });\\n $ca2df1256966e313$var$KernPair = new Struct({\\n left: uint16,\\n right: uint16,\\n value: int16\\n });\\n $ca2df1256966e313$var$ClassTable = new Struct({\\n firstGlyph: uint16,\\n nGlyphs: uint16,\\n offsets: new ArrayT(uint16, \\\"nGlyphs\\\"),\\n max: (t) => t.offsets.length && Math.max.apply(Math, t.offsets)\\n });\\n $ca2df1256966e313$var$Kern2Array = new Struct({\\n off: (t) => t._startOffset - t.parent.parent._startOffset,\\n len: (t) => ((t.parent.leftTable.max - t.off) / t.parent.rowWidth + 1) * (t.parent.rowWidth / 2),\\n values: new LazyArray(int16, \\\"len\\\")\\n });\\n $ca2df1256966e313$var$KernSubtable = new VersionedStruct(\\\"format\\\", {\\n 0: {\\n nPairs: uint16,\\n searchRange: uint16,\\n entrySelector: uint16,\\n rangeShift: uint16,\\n pairs: new ArrayT($ca2df1256966e313$var$KernPair, \\\"nPairs\\\")\\n },\\n 2: {\\n rowWidth: uint16,\\n leftTable: new Pointer(uint16, $ca2df1256966e313$var$ClassTable, {\\n type: \\\"parent\\\"\\n }),\\n rightTable: new Pointer(uint16, $ca2df1256966e313$var$ClassTable, {\\n type: \\\"parent\\\"\\n }),\\n array: new Pointer(uint16, $ca2df1256966e313$var$Kern2Array, {\\n type: \\\"parent\\\"\\n })\\n },\\n 3: {\\n glyphCount: uint16,\\n kernValueCount: uint8,\\n leftClassCount: uint8,\\n rightClassCount: uint8,\\n flags: uint8,\\n kernValue: new ArrayT(int16, \\\"kernValueCount\\\"),\\n leftClass: new ArrayT(uint8, \\\"glyphCount\\\"),\\n rightClass: new ArrayT(uint8, \\\"glyphCount\\\"),\\n kernIndex: new ArrayT(uint8, (t) => t.leftClassCount * t.rightClassCount)\\n }\\n });\\n $ca2df1256966e313$var$KernTable = new VersionedStruct(\\\"version\\\", {\\n 0: {\\n subVersion: uint16,\\n length: uint16,\\n format: uint8,\\n coverage: new Bitfield(uint8, [\\n \\\"horizontal\\\",\\n \\\"minimum\\\",\\n \\\"crossStream\\\",\\n \\\"override\\\"\\n // If set to 1 the value in this table replaces the accumulated value\\n ]),\\n subtable: $ca2df1256966e313$var$KernSubtable,\\n padding: new Reserved(uint8, (t) => t.length - t._currentOffset)\\n },\\n 1: {\\n length: uint32,\\n coverage: new Bitfield(uint8, [\\n null,\\n null,\\n null,\\n null,\\n null,\\n \\\"variation\\\",\\n \\\"crossStream\\\",\\n \\\"vertical\\\"\\n // Set if table has vertical kerning values\\n ]),\\n format: uint8,\\n tupleIndex: uint16,\\n subtable: $ca2df1256966e313$var$KernSubtable,\\n padding: new Reserved(uint8, (t) => t.length - t._currentOffset)\\n }\\n });\\n $ca2df1256966e313$export$2e2bcd8739ae039 = new VersionedStruct(uint16, {\\n 0: {\\n nTables: uint16,\\n tables: new ArrayT($ca2df1256966e313$var$KernTable, \\\"nTables\\\")\\n },\\n 1: {\\n reserved: new Reserved(uint16),\\n nTables: uint32,\\n tables: new ArrayT($ca2df1256966e313$var$KernTable, \\\"nTables\\\")\\n }\\n });\\n $7a9f92b0c46ebe33$export$2e2bcd8739ae039 = new Struct({\\n version: uint16,\\n numGlyphs: uint16,\\n yPels: new ArrayT(uint8, \\\"numGlyphs\\\")\\n });\\n $2b2ccc419d152631$export$2e2bcd8739ae039 = new Struct({\\n version: uint16,\\n fontNumber: uint32,\\n pitch: uint16,\\n xHeight: uint16,\\n style: uint16,\\n typeFamily: uint16,\\n capHeight: uint16,\\n symbolSet: uint16,\\n typeface: new StringT(16),\\n characterComplement: new StringT(8),\\n fileName: new StringT(6),\\n strokeWeight: new StringT(1),\\n widthType: new StringT(1),\\n serifStyle: uint8,\\n reserved: new Reserved(uint8)\\n });\\n $ca5b40b9bcda9c9b$var$Ratio = new Struct({\\n bCharSet: uint8,\\n xRatio: uint8,\\n yStartRatio: uint8,\\n yEndRatio: uint8\\n // Ending y-Ratio value\\n });\\n $ca5b40b9bcda9c9b$var$vTable = new Struct({\\n yPelHeight: uint16,\\n yMax: int16,\\n yMin: int16\\n // Minimum value (in pels) for this yPelHeight\\n });\\n $ca5b40b9bcda9c9b$var$VdmxGroup = new Struct({\\n recs: uint16,\\n startsz: uint8,\\n endsz: uint8,\\n entries: new ArrayT($ca5b40b9bcda9c9b$var$vTable, \\\"recs\\\")\\n // The VDMX records\\n });\\n $ca5b40b9bcda9c9b$export$2e2bcd8739ae039 = new Struct({\\n version: uint16,\\n numRecs: uint16,\\n numRatios: uint16,\\n ratioRanges: new ArrayT($ca5b40b9bcda9c9b$var$Ratio, \\\"numRatios\\\"),\\n offsets: new ArrayT(uint16, \\\"numRatios\\\"),\\n groups: new ArrayT($ca5b40b9bcda9c9b$var$VdmxGroup, \\\"numRecs\\\")\\n // The actual VDMX groupings\\n });\\n $69530a3c40755af0$export$2e2bcd8739ae039 = new Struct({\\n version: uint16,\\n ascent: int16,\\n descent: int16,\\n lineGap: int16,\\n advanceHeightMax: int16,\\n minTopSideBearing: int16,\\n minBottomSideBearing: int16,\\n yMaxExtent: int16,\\n caretSlopeRise: int16,\\n caretSlopeRun: int16,\\n caretOffset: int16,\\n reserved: new Reserved(int16, 4),\\n metricDataFormat: int16,\\n numberOfMetrics: uint16\\n // Number of advance heights in the Vertical Metrics table\\n });\\n $344073dd270f0e62$var$VmtxEntry = new Struct({\\n advance: uint16,\\n bearing: int16\\n // The top sidebearing of the glyph\\n });\\n $344073dd270f0e62$export$2e2bcd8739ae039 = new Struct({\\n metrics: new LazyArray($344073dd270f0e62$var$VmtxEntry, (t) => t.parent.vhea.numberOfMetrics),\\n bearings: new LazyArray(int16, (t) => t.parent.maxp.numGlyphs - t.parent.vhea.numberOfMetrics)\\n });\\n $3793b781918cfced$var$shortFrac = new Fixed(16, \\\"BE\\\", 14);\\n $3793b781918cfced$var$Correspondence = new Struct({\\n fromCoord: $3793b781918cfced$var$shortFrac,\\n toCoord: $3793b781918cfced$var$shortFrac\\n });\\n $3793b781918cfced$var$Segment = new Struct({\\n pairCount: uint16,\\n correspondence: new ArrayT($3793b781918cfced$var$Correspondence, \\\"pairCount\\\")\\n });\\n $3793b781918cfced$export$2e2bcd8739ae039 = new Struct({\\n version: fixed32,\\n axisCount: uint32,\\n segment: new ArrayT($3793b781918cfced$var$Segment, \\\"axisCount\\\")\\n });\\n $6cb7dd5f47d82580$var$UnboundedArrayAccessor = class {\\n getItem(index) {\\n if (this._items[index] == null) {\\n let pos = this.stream.pos;\\n this.stream.pos = this.base + this.type.size(null, this.parent) * index;\\n this._items[index] = this.type.decode(this.stream, this.parent);\\n this.stream.pos = pos;\\n }\\n return this._items[index];\\n }\\n inspect() {\\n return `[UnboundedArray ${this.type.constructor.name}]`;\\n }\\n constructor(type, stream, parent) {\\n this.type = type;\\n this.stream = stream;\\n this.parent = parent;\\n this.base = this.stream.pos;\\n this._items = [];\\n }\\n };\\n $6cb7dd5f47d82580$export$c5af1eebc882e39a = class extends ArrayT {\\n decode(stream, parent) {\\n return new $6cb7dd5f47d82580$var$UnboundedArrayAccessor(this.type, stream, parent);\\n }\\n constructor(type) {\\n super(type, 0);\\n }\\n };\\n $6cb7dd5f47d82580$export$8351f8c2ae2f103c = function(ValueType = uint16) {\\n class Shadow {\\n decode(stream, ctx) {\\n ctx = ctx.parent.parent;\\n return this.type.decode(stream, ctx);\\n }\\n size(val, ctx) {\\n ctx = ctx.parent.parent;\\n return this.type.size(val, ctx);\\n }\\n encode(stream, val, ctx) {\\n ctx = ctx.parent.parent;\\n return this.type.encode(stream, val, ctx);\\n }\\n constructor(type) {\\n this.type = type;\\n }\\n }\\n ValueType = new Shadow(ValueType);\\n let BinarySearchHeader = new Struct({\\n unitSize: uint16,\\n nUnits: uint16,\\n searchRange: uint16,\\n entrySelector: uint16,\\n rangeShift: uint16\\n });\\n let LookupSegmentSingle = new Struct({\\n lastGlyph: uint16,\\n firstGlyph: uint16,\\n value: ValueType\\n });\\n let LookupSegmentArray = new Struct({\\n lastGlyph: uint16,\\n firstGlyph: uint16,\\n values: new Pointer(uint16, new ArrayT(ValueType, (t) => t.lastGlyph - t.firstGlyph + 1), {\\n type: \\\"parent\\\"\\n })\\n });\\n let LookupSingle = new Struct({\\n glyph: uint16,\\n value: ValueType\\n });\\n return new VersionedStruct(uint16, {\\n 0: {\\n values: new $6cb7dd5f47d82580$export$c5af1eebc882e39a(ValueType)\\n // length == number of glyphs maybe?\\n },\\n 2: {\\n binarySearchHeader: BinarySearchHeader,\\n segments: new ArrayT(LookupSegmentSingle, (t) => t.binarySearchHeader.nUnits)\\n },\\n 4: {\\n binarySearchHeader: BinarySearchHeader,\\n segments: new ArrayT(LookupSegmentArray, (t) => t.binarySearchHeader.nUnits)\\n },\\n 6: {\\n binarySearchHeader: BinarySearchHeader,\\n segments: new ArrayT(LookupSingle, (t) => t.binarySearchHeader.nUnits)\\n },\\n 8: {\\n firstGlyph: uint16,\\n count: uint16,\\n values: new ArrayT(ValueType, \\\"count\\\")\\n }\\n });\\n };\\n $6a3746e8c708f5a3$var$BslnSubtable = new VersionedStruct(\\\"format\\\", {\\n 0: {\\n deltas: new ArrayT(int16, 32)\\n },\\n 1: {\\n deltas: new ArrayT(int16, 32),\\n mappingData: new (0, $6cb7dd5f47d82580$export$8351f8c2ae2f103c)(uint16)\\n },\\n 2: {\\n standardGlyph: uint16,\\n controlPoints: new ArrayT(uint16, 32)\\n },\\n 3: {\\n standardGlyph: uint16,\\n controlPoints: new ArrayT(uint16, 32),\\n mappingData: new (0, $6cb7dd5f47d82580$export$8351f8c2ae2f103c)(uint16)\\n }\\n });\\n $6a3746e8c708f5a3$export$2e2bcd8739ae039 = new Struct({\\n version: fixed32,\\n format: uint16,\\n defaultBaseline: uint16,\\n subtable: $6a3746e8c708f5a3$var$BslnSubtable\\n });\\n $d0c76fac617b308a$var$Setting = new Struct({\\n setting: uint16,\\n nameIndex: int16,\\n name: (t) => t.parent.parent.parent.name.records.fontFeatures[t.nameIndex]\\n });\\n $d0c76fac617b308a$var$FeatureName = new Struct({\\n feature: uint16,\\n nSettings: uint16,\\n settingTable: new Pointer(uint32, new ArrayT($d0c76fac617b308a$var$Setting, \\\"nSettings\\\"), {\\n type: \\\"parent\\\"\\n }),\\n featureFlags: new Bitfield(uint8, [\\n null,\\n null,\\n null,\\n null,\\n null,\\n null,\\n \\\"hasDefault\\\",\\n \\\"exclusive\\\"\\n ]),\\n defaultSetting: uint8,\\n nameIndex: int16,\\n name: (t) => t.parent.parent.name.records.fontFeatures[t.nameIndex]\\n });\\n $d0c76fac617b308a$export$2e2bcd8739ae039 = new Struct({\\n version: fixed32,\\n featureNameCount: uint16,\\n reserved1: new Reserved(uint16),\\n reserved2: new Reserved(uint32),\\n featureNames: new ArrayT($d0c76fac617b308a$var$FeatureName, \\\"featureNameCount\\\")\\n });\\n $e83fd065f00fcd01$var$Axis = new Struct({\\n axisTag: new StringT(4),\\n minValue: fixed32,\\n defaultValue: fixed32,\\n maxValue: fixed32,\\n flags: uint16,\\n nameID: uint16,\\n name: (t) => t.parent.parent.name.records.fontFeatures[t.nameID]\\n });\\n $e83fd065f00fcd01$var$Instance = new Struct({\\n nameID: uint16,\\n name: (t) => t.parent.parent.name.records.fontFeatures[t.nameID],\\n flags: uint16,\\n coord: new ArrayT(fixed32, (t) => t.parent.axisCount),\\n postscriptNameID: new Optional(uint16, (t) => t.parent.instanceSize - t._currentOffset > 0)\\n });\\n $e83fd065f00fcd01$export$2e2bcd8739ae039 = new Struct({\\n version: fixed32,\\n offsetToData: uint16,\\n countSizePairs: uint16,\\n axisCount: uint16,\\n axisSize: uint16,\\n instanceCount: uint16,\\n instanceSize: uint16,\\n axis: new ArrayT($e83fd065f00fcd01$var$Axis, \\\"axisCount\\\"),\\n instance: new ArrayT($e83fd065f00fcd01$var$Instance, \\\"instanceCount\\\")\\n });\\n $dbe33c8d3a7f131c$var$shortFrac = new Fixed(16, \\\"BE\\\", 14);\\n $dbe33c8d3a7f131c$var$Offset = class {\\n static decode(stream, parent) {\\n return parent.flags ? stream.readUInt32BE() : stream.readUInt16BE() * 2;\\n }\\n };\\n $dbe33c8d3a7f131c$var$gvar = new Struct({\\n version: uint16,\\n reserved: new Reserved(uint16),\\n axisCount: uint16,\\n globalCoordCount: uint16,\\n globalCoords: new Pointer(uint32, new ArrayT(new ArrayT($dbe33c8d3a7f131c$var$shortFrac, \\\"axisCount\\\"), \\\"globalCoordCount\\\")),\\n glyphCount: uint16,\\n flags: uint16,\\n offsetToData: uint32,\\n offsets: new ArrayT(new Pointer($dbe33c8d3a7f131c$var$Offset, \\\"void\\\", {\\n relativeTo: (ctx) => ctx.offsetToData,\\n allowNull: false\\n }), (t) => t.glyphCount + 1)\\n });\\n $dbe33c8d3a7f131c$export$2e2bcd8739ae039 = $dbe33c8d3a7f131c$var$gvar;\\n $05b01887df96c4ee$var$ClassTable = new Struct({\\n length: uint16,\\n coverage: uint16,\\n subFeatureFlags: uint32,\\n stateTable: new (0, $6cb7dd5f47d82580$export$105027425199cc51)()\\n });\\n $05b01887df96c4ee$var$WidthDeltaRecord = new Struct({\\n justClass: uint32,\\n beforeGrowLimit: fixed32,\\n beforeShrinkLimit: fixed32,\\n afterGrowLimit: fixed32,\\n afterShrinkLimit: fixed32,\\n growFlags: uint16,\\n shrinkFlags: uint16\\n });\\n $05b01887df96c4ee$var$WidthDeltaCluster = new ArrayT($05b01887df96c4ee$var$WidthDeltaRecord, uint32);\\n $05b01887df96c4ee$var$ActionData = new VersionedStruct(\\\"actionType\\\", {\\n 0: {\\n lowerLimit: fixed32,\\n upperLimit: fixed32,\\n order: uint16,\\n glyphs: new ArrayT(uint16, uint16)\\n },\\n 1: {\\n addGlyph: uint16\\n },\\n 2: {\\n substThreshold: fixed32,\\n addGlyph: uint16,\\n substGlyph: uint16\\n },\\n 3: {},\\n 4: {\\n variationAxis: uint32,\\n minimumLimit: fixed32,\\n noStretchValue: fixed32,\\n maximumLimit: fixed32\\n },\\n 5: {\\n flags: uint16,\\n glyph: uint16\\n }\\n });\\n $05b01887df96c4ee$var$Action = new Struct({\\n actionClass: uint16,\\n actionType: uint16,\\n actionLength: uint32,\\n actionData: $05b01887df96c4ee$var$ActionData,\\n padding: new Reserved(uint8, (t) => t.actionLength - t._currentOffset)\\n });\\n $05b01887df96c4ee$var$PostcompensationAction = new ArrayT($05b01887df96c4ee$var$Action, uint32);\\n $05b01887df96c4ee$var$PostCompensationTable = new Struct({\\n lookupTable: new (0, $6cb7dd5f47d82580$export$8351f8c2ae2f103c)(new Pointer(uint16, $05b01887df96c4ee$var$PostcompensationAction))\\n });\\n $05b01887df96c4ee$var$JustificationTable = new Struct({\\n classTable: new Pointer(uint16, $05b01887df96c4ee$var$ClassTable, {\\n type: \\\"parent\\\"\\n }),\\n wdcOffset: uint16,\\n postCompensationTable: new Pointer(uint16, $05b01887df96c4ee$var$PostCompensationTable, {\\n type: \\\"parent\\\"\\n }),\\n widthDeltaClusters: new (0, $6cb7dd5f47d82580$export$8351f8c2ae2f103c)(new Pointer(uint16, $05b01887df96c4ee$var$WidthDeltaCluster, {\\n type: \\\"parent\\\",\\n relativeTo: (ctx) => ctx.wdcOffset\\n }))\\n });\\n $05b01887df96c4ee$export$2e2bcd8739ae039 = new Struct({\\n version: uint32,\\n format: uint16,\\n horizontal: new Pointer(uint16, $05b01887df96c4ee$var$JustificationTable),\\n vertical: new Pointer(uint16, $05b01887df96c4ee$var$JustificationTable)\\n });\\n $03ee6ebd54db1053$var$LigatureData = {\\n action: uint16\\n };\\n $03ee6ebd54db1053$var$ContextualData = {\\n markIndex: uint16,\\n currentIndex: uint16\\n };\\n $03ee6ebd54db1053$var$InsertionData = {\\n currentInsertIndex: uint16,\\n markedInsertIndex: uint16\\n };\\n $03ee6ebd54db1053$var$SubstitutionTable = new Struct({\\n items: new (0, $6cb7dd5f47d82580$export$c5af1eebc882e39a)(new Pointer(uint32, new (0, $6cb7dd5f47d82580$export$8351f8c2ae2f103c)()))\\n });\\n $03ee6ebd54db1053$var$SubtableData = new VersionedStruct(\\\"type\\\", {\\n 0: {\\n stateTable: new (0, $6cb7dd5f47d82580$export$79f7d93d790934ba)()\\n },\\n 1: {\\n stateTable: new (0, $6cb7dd5f47d82580$export$79f7d93d790934ba)($03ee6ebd54db1053$var$ContextualData),\\n substitutionTable: new Pointer(uint32, $03ee6ebd54db1053$var$SubstitutionTable)\\n },\\n 2: {\\n stateTable: new (0, $6cb7dd5f47d82580$export$79f7d93d790934ba)($03ee6ebd54db1053$var$LigatureData),\\n ligatureActions: new Pointer(uint32, new (0, $6cb7dd5f47d82580$export$c5af1eebc882e39a)(uint32)),\\n components: new Pointer(uint32, new (0, $6cb7dd5f47d82580$export$c5af1eebc882e39a)(uint16)),\\n ligatureList: new Pointer(uint32, new (0, $6cb7dd5f47d82580$export$c5af1eebc882e39a)(uint16))\\n },\\n 4: {\\n lookupTable: new (0, $6cb7dd5f47d82580$export$8351f8c2ae2f103c)()\\n },\\n 5: {\\n stateTable: new (0, $6cb7dd5f47d82580$export$79f7d93d790934ba)($03ee6ebd54db1053$var$InsertionData),\\n insertionActions: new Pointer(uint32, new (0, $6cb7dd5f47d82580$export$c5af1eebc882e39a)(uint16))\\n }\\n });\\n $03ee6ebd54db1053$var$Subtable = new Struct({\\n length: uint32,\\n coverage: uint24,\\n type: uint8,\\n subFeatureFlags: uint32,\\n table: $03ee6ebd54db1053$var$SubtableData,\\n padding: new Reserved(uint8, (t) => t.length - t._currentOffset)\\n });\\n $03ee6ebd54db1053$var$FeatureEntry = new Struct({\\n featureType: uint16,\\n featureSetting: uint16,\\n enableFlags: uint32,\\n disableFlags: uint32\\n });\\n $03ee6ebd54db1053$var$MorxChain = new Struct({\\n defaultFlags: uint32,\\n chainLength: uint32,\\n nFeatureEntries: uint32,\\n nSubtables: uint32,\\n features: new ArrayT($03ee6ebd54db1053$var$FeatureEntry, \\\"nFeatureEntries\\\"),\\n subtables: new ArrayT($03ee6ebd54db1053$var$Subtable, \\\"nSubtables\\\")\\n });\\n $03ee6ebd54db1053$export$2e2bcd8739ae039 = new Struct({\\n version: uint16,\\n unused: new Reserved(uint16),\\n nChains: uint32,\\n chains: new ArrayT($03ee6ebd54db1053$var$MorxChain, \\\"nChains\\\")\\n });\\n $b7492a80b0d1a056$var$OpticalBounds = new Struct({\\n left: int16,\\n top: int16,\\n right: int16,\\n bottom: int16\\n });\\n $b7492a80b0d1a056$export$2e2bcd8739ae039 = new Struct({\\n version: fixed32,\\n format: uint16,\\n lookupTable: new (0, $6cb7dd5f47d82580$export$8351f8c2ae2f103c)($b7492a80b0d1a056$var$OpticalBounds)\\n });\\n $c3395722bea751e2$var$tables = {};\\n $c3395722bea751e2$export$2e2bcd8739ae039 = $c3395722bea751e2$var$tables;\\n $c3395722bea751e2$var$tables.cmap = (0, $26a62205ad06574e$export$2e2bcd8739ae039);\\n $c3395722bea751e2$var$tables.head = (0, $f2612a29f92ac062$export$2e2bcd8739ae039);\\n $c3395722bea751e2$var$tables.hhea = (0, $2c179dd593583073$export$2e2bcd8739ae039);\\n $c3395722bea751e2$var$tables.hmtx = (0, $bdc9060542264b85$export$2e2bcd8739ae039);\\n $c3395722bea751e2$var$tables.maxp = (0, $dbf51cb3d3fe409d$export$2e2bcd8739ae039);\\n $c3395722bea751e2$var$tables.name = (0, $2bcf221753ec8e32$export$2e2bcd8739ae039);\\n $c3395722bea751e2$var$tables[\\\"OS/2\\\"] = (0, $84b272aa31b70606$export$2e2bcd8739ae039);\\n $c3395722bea751e2$var$tables.post = (0, $32d9e2eb9565d93c$export$2e2bcd8739ae039);\\n $c3395722bea751e2$var$tables.fpgm = (0, $5c0f37ca5ffb1850$export$2e2bcd8739ae039);\\n $c3395722bea751e2$var$tables.loca = (0, $2b2b260902b1c57e$export$2e2bcd8739ae039);\\n $c3395722bea751e2$var$tables.prep = (0, $7afb878c7bea4f66$export$2e2bcd8739ae039);\\n $c3395722bea751e2$var$tables[\\\"cvt \\\"] = (0, $5202bd9d9ad8eaac$export$2e2bcd8739ae039);\\n $c3395722bea751e2$var$tables.glyf = (0, $6c92b6371bce8bd9$export$2e2bcd8739ae039);\\n $c3395722bea751e2$var$tables[\\\"CFF \\\"] = (0, $822ac0d589e4e237$export$2e2bcd8739ae039);\\n $c3395722bea751e2$var$tables[\\\"CFF2\\\"] = (0, $822ac0d589e4e237$export$2e2bcd8739ae039);\\n $c3395722bea751e2$var$tables.VORG = (0, $2bbf2bc1ce37cd8f$export$2e2bcd8739ae039);\\n $c3395722bea751e2$var$tables.EBLC = (0, $9911c4c7201c13de$export$2e2bcd8739ae039);\\n $c3395722bea751e2$var$tables.CBLC = $c3395722bea751e2$var$tables.EBLC;\\n $c3395722bea751e2$var$tables.sbix = (0, $abb847051efd51b1$export$2e2bcd8739ae039);\\n $c3395722bea751e2$var$tables.COLR = (0, $eb629188f3dfefdd$export$2e2bcd8739ae039);\\n $c3395722bea751e2$var$tables.CPAL = (0, $08734b8e7dc64587$export$2e2bcd8739ae039);\\n $c3395722bea751e2$var$tables.BASE = (0, $497cef411d884e34$export$2e2bcd8739ae039);\\n $c3395722bea751e2$var$tables.GDEF = (0, $cf5f33c63ef209e6$export$2e2bcd8739ae039);\\n $c3395722bea751e2$var$tables.GPOS = (0, $47e0e8ef515d9903$export$2e2bcd8739ae039);\\n $c3395722bea751e2$var$tables.GSUB = (0, $d3f442064af66e06$export$2e2bcd8739ae039);\\n $c3395722bea751e2$var$tables.JSTF = (0, $71cfb3c4767fbd0c$export$2e2bcd8739ae039);\\n $c3395722bea751e2$var$tables.HVAR = (0, $d059a6bd2d3b5b63$export$2e2bcd8739ae039);\\n $c3395722bea751e2$var$tables.DSIG = (0, $dceeca3e1977ce30$export$2e2bcd8739ae039);\\n $c3395722bea751e2$var$tables.gasp = (0, $8acd740a9435aad0$export$2e2bcd8739ae039);\\n $c3395722bea751e2$var$tables.hdmx = (0, $b5f380243c34d6a0$export$2e2bcd8739ae039);\\n $c3395722bea751e2$var$tables.kern = (0, $ca2df1256966e313$export$2e2bcd8739ae039);\\n $c3395722bea751e2$var$tables.LTSH = (0, $7a9f92b0c46ebe33$export$2e2bcd8739ae039);\\n $c3395722bea751e2$var$tables.PCLT = (0, $2b2ccc419d152631$export$2e2bcd8739ae039);\\n $c3395722bea751e2$var$tables.VDMX = (0, $ca5b40b9bcda9c9b$export$2e2bcd8739ae039);\\n $c3395722bea751e2$var$tables.vhea = (0, $69530a3c40755af0$export$2e2bcd8739ae039);\\n $c3395722bea751e2$var$tables.vmtx = (0, $344073dd270f0e62$export$2e2bcd8739ae039);\\n $c3395722bea751e2$var$tables.avar = (0, $3793b781918cfced$export$2e2bcd8739ae039);\\n $c3395722bea751e2$var$tables.bsln = (0, $6a3746e8c708f5a3$export$2e2bcd8739ae039);\\n $c3395722bea751e2$var$tables.feat = (0, $d0c76fac617b308a$export$2e2bcd8739ae039);\\n $c3395722bea751e2$var$tables.fvar = (0, $e83fd065f00fcd01$export$2e2bcd8739ae039);\\n $c3395722bea751e2$var$tables.gvar = (0, $dbe33c8d3a7f131c$export$2e2bcd8739ae039);\\n $c3395722bea751e2$var$tables.just = (0, $05b01887df96c4ee$export$2e2bcd8739ae039);\\n $c3395722bea751e2$var$tables.morx = (0, $03ee6ebd54db1053$export$2e2bcd8739ae039);\\n $c3395722bea751e2$var$tables.opbd = (0, $b7492a80b0d1a056$export$2e2bcd8739ae039);\\n $816c07a04b6dba87$var$TableEntry = new Struct({\\n tag: new StringT(4),\\n checkSum: uint32,\\n offset: new Pointer(uint32, \\\"void\\\", {\\n type: \\\"global\\\"\\n }),\\n length: uint32\\n });\\n $816c07a04b6dba87$var$Directory = new Struct({\\n tag: new StringT(4),\\n numTables: uint16,\\n searchRange: uint16,\\n entrySelector: uint16,\\n rangeShift: uint16,\\n tables: new ArrayT($816c07a04b6dba87$var$TableEntry, \\\"numTables\\\")\\n });\\n $816c07a04b6dba87$var$Directory.process = function() {\\n let tables = {};\\n for (let table of this.tables) tables[table.tag] = table;\\n this.tables = tables;\\n };\\n $816c07a04b6dba87$var$Directory.preEncode = function() {\\n if (!Array.isArray(this.tables)) {\\n let tables = [];\\n for (let tag in this.tables) {\\n let table = this.tables[tag];\\n if (table) tables.push({\\n tag,\\n checkSum: 0,\\n offset: new VoidPointer((0, $c3395722bea751e2$export$2e2bcd8739ae039)[tag], table),\\n length: (0, $c3395722bea751e2$export$2e2bcd8739ae039)[tag].size(table)\\n });\\n }\\n this.tables = tables;\\n }\\n this.tag = \\\"true\\\";\\n this.numTables = this.tables.length;\\n let maxExponentFor2 = Math.floor(Math.log(this.numTables) / Math.LN2);\\n let maxPowerOf2 = Math.pow(2, maxExponentFor2);\\n this.searchRange = maxPowerOf2 * 16;\\n this.entrySelector = Math.log(maxPowerOf2) / Math.LN2;\\n this.rangeShift = this.numTables * 16 - this.searchRange;\\n };\\n $816c07a04b6dba87$export$2e2bcd8739ae039 = $816c07a04b6dba87$var$Directory;\\n $12727730ddfc8bfe$export$3d28c1996ced1f14 = new TextDecoder(\\\"ascii\\\");\\n $12727730ddfc8bfe$var$CHARS = \\\"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\\\";\\n $12727730ddfc8bfe$var$LOOKUP = new Uint8Array(256);\\n for (let i = 0; i < $12727730ddfc8bfe$var$CHARS.length; i++) $12727730ddfc8bfe$var$LOOKUP[$12727730ddfc8bfe$var$CHARS.charCodeAt(i)] = i;\\n $f08dd41ef10b694c$export$2e2bcd8739ae039 = class {\\n findSubtable(cmapTable, pairs) {\\n for (let [platformID, encodingID] of pairs) for (let cmap of cmapTable.tables) {\\n if (cmap.platformID === platformID && cmap.encodingID === encodingID) return cmap.table;\\n }\\n return null;\\n }\\n lookup(codepoint, variationSelector) {\\n if (this.encoding) codepoint = this.encoding.get(codepoint) || codepoint;\\n else if (variationSelector) {\\n let gid = this.getVariationSelector(codepoint, variationSelector);\\n if (gid) return gid;\\n }\\n let cmap = this.cmap;\\n switch (cmap.version) {\\n case 0:\\n return cmap.codeMap.get(codepoint) || 0;\\n case 4: {\\n let min = 0;\\n let max = cmap.segCount - 1;\\n while (min <= max) {\\n let mid = min + max >> 1;\\n if (codepoint < cmap.startCode.get(mid)) max = mid - 1;\\n else if (codepoint > cmap.endCode.get(mid)) min = mid + 1;\\n else {\\n let rangeOffset = cmap.idRangeOffset.get(mid);\\n let gid;\\n if (rangeOffset === 0) gid = codepoint + cmap.idDelta.get(mid);\\n else {\\n let index = rangeOffset / 2 + (codepoint - cmap.startCode.get(mid)) - (cmap.segCount - mid);\\n gid = cmap.glyphIndexArray.get(index) || 0;\\n if (gid !== 0) gid += cmap.idDelta.get(mid);\\n }\\n return gid & 65535;\\n }\\n }\\n return 0;\\n }\\n case 8:\\n throw new Error(\\\"TODO: cmap format 8\\\");\\n case 6:\\n case 10:\\n return cmap.glyphIndices.get(codepoint - cmap.firstCode) || 0;\\n case 12:\\n case 13: {\\n let min = 0;\\n let max = cmap.nGroups - 1;\\n while (min <= max) {\\n let mid = min + max >> 1;\\n let group = cmap.groups.get(mid);\\n if (codepoint < group.startCharCode) max = mid - 1;\\n else if (codepoint > group.endCharCode) min = mid + 1;\\n else {\\n if (cmap.version === 12) return group.glyphID + (codepoint - group.startCharCode);\\n else return group.glyphID;\\n }\\n }\\n return 0;\\n }\\n case 14:\\n throw new Error(\\\"TODO: cmap format 14\\\");\\n default:\\n throw new Error(`Unknown cmap format ${cmap.version}`);\\n }\\n }\\n getVariationSelector(codepoint, variationSelector) {\\n if (!this.uvs) return 0;\\n let selectors = this.uvs.varSelectors.toArray();\\n let i = (0, $12727730ddfc8bfe$export$2e0ae67339d5f1ac)(selectors, (x) => variationSelector - x.varSelector);\\n let sel = selectors[i];\\n if (i !== -1 && sel.defaultUVS) i = (0, $12727730ddfc8bfe$export$2e0ae67339d5f1ac)(sel.defaultUVS, (x) => codepoint < x.startUnicodeValue ? -1 : codepoint > x.startUnicodeValue + x.additionalCount ? 1 : 0);\\n if (i !== -1 && sel.nonDefaultUVS) {\\n i = (0, $12727730ddfc8bfe$export$2e0ae67339d5f1ac)(sel.nonDefaultUVS, (x) => codepoint - x.unicodeValue);\\n if (i !== -1) return sel.nonDefaultUVS[i].glyphID;\\n }\\n return 0;\\n }\\n getCharacterSet() {\\n let cmap = this.cmap;\\n switch (cmap.version) {\\n case 0:\\n return (0, $12727730ddfc8bfe$export$d02631cccf789723)(0, cmap.codeMap.length);\\n case 4: {\\n let res = [];\\n let endCodes = cmap.endCode.toArray();\\n for (let i = 0; i < endCodes.length; i++) {\\n let tail = endCodes[i] + 1;\\n let start = cmap.startCode.get(i);\\n res.push(...(0, $12727730ddfc8bfe$export$d02631cccf789723)(start, tail));\\n }\\n return res;\\n }\\n case 8:\\n throw new Error(\\\"TODO: cmap format 8\\\");\\n case 6:\\n case 10:\\n return (0, $12727730ddfc8bfe$export$d02631cccf789723)(cmap.firstCode, cmap.firstCode + cmap.glyphIndices.length);\\n case 12:\\n case 13: {\\n let res = [];\\n for (let group of cmap.groups.toArray()) res.push(...(0, $12727730ddfc8bfe$export$d02631cccf789723)(group.startCharCode, group.endCharCode + 1));\\n return res;\\n }\\n case 14:\\n throw new Error(\\\"TODO: cmap format 14\\\");\\n default:\\n throw new Error(`Unknown cmap format ${cmap.version}`);\\n }\\n }\\n codePointsForGlyph(gid) {\\n let cmap = this.cmap;\\n switch (cmap.version) {\\n case 0: {\\n let res = [];\\n for (let i = 0; i < 256; i++) if (cmap.codeMap.get(i) === gid) res.push(i);\\n return res;\\n }\\n case 4: {\\n let res = [];\\n for (let i = 0; i < cmap.segCount; i++) {\\n let end = cmap.endCode.get(i);\\n let start = cmap.startCode.get(i);\\n let rangeOffset = cmap.idRangeOffset.get(i);\\n let delta = cmap.idDelta.get(i);\\n for (var c = start; c <= end; c++) {\\n let g = 0;\\n if (rangeOffset === 0) g = c + delta;\\n else {\\n let index = rangeOffset / 2 + (c - start) - (cmap.segCount - i);\\n g = cmap.glyphIndexArray.get(index) || 0;\\n if (g !== 0) g += delta;\\n }\\n if (g === gid) res.push(c);\\n }\\n }\\n return res;\\n }\\n case 12: {\\n let res = [];\\n for (let group of cmap.groups.toArray()) if (gid >= group.glyphID && gid <= group.glyphID + (group.endCharCode - group.startCharCode)) res.push(group.startCharCode + (gid - group.glyphID));\\n return res;\\n }\\n case 13: {\\n let res = [];\\n for (let group of cmap.groups.toArray()) if (gid === group.glyphID) res.push(...(0, $12727730ddfc8bfe$export$d02631cccf789723)(group.startCharCode, group.endCharCode + 1));\\n return res;\\n }\\n default:\\n throw new Error(`Unknown cmap format ${cmap.version}`);\\n }\\n }\\n constructor(cmapTable) {\\n this.encoding = null;\\n this.cmap = this.findSubtable(cmapTable, [\\n // 32-bit subtables\\n [\\n 3,\\n 10\\n ],\\n [\\n 0,\\n 6\\n ],\\n [\\n 0,\\n 4\\n ],\\n // 16-bit subtables\\n [\\n 3,\\n 1\\n ],\\n [\\n 0,\\n 3\\n ],\\n [\\n 0,\\n 2\\n ],\\n [\\n 0,\\n 1\\n ],\\n [\\n 0,\\n 0\\n ]\\n ]);\\n if (!this.cmap) for (let cmap of cmapTable.tables) {\\n let encoding = (0, $e449ad78d50845fe$export$badc544e0651b6b1)(cmap.platformID, cmap.encodingID, cmap.table.language - 1);\\n let mapping = (0, $e449ad78d50845fe$export$1dceb3c14ed68bee)(encoding);\\n if (mapping) {\\n this.cmap = cmap.table;\\n this.encoding = mapping;\\n }\\n }\\n if (!this.cmap) throw new Error(\\\"Could not find a supported cmap table\\\");\\n this.uvs = this.findSubtable(cmapTable, [\\n [\\n 0,\\n 5\\n ]\\n ]);\\n if (this.uvs && this.uvs.version !== 14) this.uvs = null;\\n }\\n };\\n (0, __decorate)([\\n (0, $e71565f2ce09cb6b$export$69a3209f1a06c04d)\\n ], $f08dd41ef10b694c$export$2e2bcd8739ae039.prototype, \\\"getCharacterSet\\\", null);\\n (0, __decorate)([\\n (0, $e71565f2ce09cb6b$export$69a3209f1a06c04d)\\n ], $f08dd41ef10b694c$export$2e2bcd8739ae039.prototype, \\\"codePointsForGlyph\\\", null);\\n $0bba3a9db57637f3$export$2e2bcd8739ae039 = class {\\n process(glyphs, positions) {\\n for (let glyphIndex = 0; glyphIndex < glyphs.length - 1; glyphIndex++) {\\n let left = glyphs[glyphIndex].id;\\n let right = glyphs[glyphIndex + 1].id;\\n positions[glyphIndex].xAdvance += this.getKerning(left, right);\\n }\\n }\\n getKerning(left, right) {\\n let res = 0;\\n for (let table of this.kern.tables) {\\n if (table.coverage.crossStream) continue;\\n switch (table.version) {\\n case 0:\\n if (!table.coverage.horizontal) continue;\\n break;\\n case 1:\\n if (table.coverage.vertical || table.coverage.variation) continue;\\n break;\\n default:\\n throw new Error(`Unsupported kerning table version ${table.version}`);\\n }\\n let val = 0;\\n let s = table.subtable;\\n switch (table.format) {\\n case 0:\\n let pairIdx = (0, $12727730ddfc8bfe$export$2e0ae67339d5f1ac)(s.pairs, function(pair) {\\n return left - pair.left || right - pair.right;\\n });\\n if (pairIdx >= 0) val = s.pairs[pairIdx].value;\\n break;\\n case 2:\\n let leftOffset = 0, rightOffset = 0;\\n if (left >= s.leftTable.firstGlyph && left < s.leftTable.firstGlyph + s.leftTable.nGlyphs) leftOffset = s.leftTable.offsets[left - s.leftTable.firstGlyph];\\n else leftOffset = s.array.off;\\n if (right >= s.rightTable.firstGlyph && right < s.rightTable.firstGlyph + s.rightTable.nGlyphs) rightOffset = s.rightTable.offsets[right - s.rightTable.firstGlyph];\\n let index = (leftOffset + rightOffset - s.array.off) / 2;\\n val = s.array.values.get(index);\\n break;\\n case 3:\\n if (left >= s.glyphCount || right >= s.glyphCount) return 0;\\n val = s.kernValue[s.kernIndex[s.leftClass[left] * s.rightClassCount + s.rightClass[right]]];\\n break;\\n default:\\n throw new Error(`Unsupported kerning sub-table format ${table.format}`);\\n }\\n if (table.coverage.override) res = val;\\n else res += val;\\n }\\n return res;\\n }\\n constructor(font) {\\n this.kern = font.kern;\\n }\\n };\\n $0a4bdfeb6dfd6f5e$export$2e2bcd8739ae039 = class {\\n positionGlyphs(glyphs, positions) {\\n let clusterStart = 0;\\n let clusterEnd = 0;\\n for (let index = 0; index < glyphs.length; index++) {\\n let glyph = glyphs[index];\\n if (glyph.isMark) clusterEnd = index;\\n else {\\n if (clusterStart !== clusterEnd) this.positionCluster(glyphs, positions, clusterStart, clusterEnd);\\n clusterStart = clusterEnd = index;\\n }\\n }\\n if (clusterStart !== clusterEnd) this.positionCluster(glyphs, positions, clusterStart, clusterEnd);\\n return positions;\\n }\\n positionCluster(glyphs, positions, clusterStart, clusterEnd) {\\n let base = glyphs[clusterStart];\\n let baseBox = base.cbox.copy();\\n if (base.codePoints.length > 1)\\n baseBox.minX += (base.codePoints.length - 1) * baseBox.width / base.codePoints.length;\\n let xOffset = -positions[clusterStart].xAdvance;\\n let yOffset = 0;\\n let yGap = this.font.unitsPerEm / 16;\\n for (let index = clusterStart + 1; index <= clusterEnd; index++) {\\n let mark = glyphs[index];\\n let markBox = mark.cbox;\\n let position = positions[index];\\n let combiningClass = this.getCombiningClass(mark.codePoints[0]);\\n if (combiningClass !== \\\"Not_Reordered\\\") {\\n position.xOffset = position.yOffset = 0;\\n switch (combiningClass) {\\n case \\\"Double_Above\\\":\\n case \\\"Double_Below\\\":\\n position.xOffset += baseBox.minX - markBox.width / 2 - markBox.minX;\\n break;\\n case \\\"Attached_Below_Left\\\":\\n case \\\"Below_Left\\\":\\n case \\\"Above_Left\\\":\\n position.xOffset += baseBox.minX - markBox.minX;\\n break;\\n case \\\"Attached_Above_Right\\\":\\n case \\\"Below_Right\\\":\\n case \\\"Above_Right\\\":\\n position.xOffset += baseBox.maxX - markBox.width - markBox.minX;\\n break;\\n default:\\n position.xOffset += baseBox.minX + (baseBox.width - markBox.width) / 2 - markBox.minX;\\n }\\n switch (combiningClass) {\\n case \\\"Double_Below\\\":\\n case \\\"Below_Left\\\":\\n case \\\"Below\\\":\\n case \\\"Below_Right\\\":\\n case \\\"Attached_Below_Left\\\":\\n case \\\"Attached_Below\\\":\\n if (combiningClass === \\\"Attached_Below_Left\\\" || combiningClass === \\\"Attached_Below\\\") baseBox.minY += yGap;\\n position.yOffset = -baseBox.minY - markBox.maxY;\\n baseBox.minY += markBox.height;\\n break;\\n case \\\"Double_Above\\\":\\n case \\\"Above_Left\\\":\\n case \\\"Above\\\":\\n case \\\"Above_Right\\\":\\n case \\\"Attached_Above\\\":\\n case \\\"Attached_Above_Right\\\":\\n if (combiningClass === \\\"Attached_Above\\\" || combiningClass === \\\"Attached_Above_Right\\\") baseBox.maxY += yGap;\\n position.yOffset = baseBox.maxY - markBox.minY;\\n baseBox.maxY += markBox.height;\\n break;\\n }\\n position.xAdvance = position.yAdvance = 0;\\n position.xOffset += xOffset;\\n position.yOffset += yOffset;\\n } else {\\n xOffset -= position.xAdvance;\\n yOffset -= position.yAdvance;\\n }\\n }\\n return;\\n }\\n getCombiningClass(codePoint) {\\n let combiningClass = (0, $747425b437e121da$export$c03b919c6651ed55)(codePoint);\\n if ((codePoint & -256) === 3584) {\\n if (combiningClass === \\\"Not_Reordered\\\") switch (codePoint) {\\n case 3633:\\n case 3636:\\n case 3637:\\n case 3638:\\n case 3639:\\n case 3655:\\n case 3660:\\n case 3645:\\n case 3662:\\n return \\\"Above_Right\\\";\\n case 3761:\\n case 3764:\\n case 3765:\\n case 3766:\\n case 3767:\\n case 3771:\\n case 3788:\\n case 3789:\\n return \\\"Above\\\";\\n case 3772:\\n return \\\"Below\\\";\\n }\\n else if (codePoint === 3642) return \\\"Below_Right\\\";\\n }\\n switch (combiningClass) {\\n // Hebrew\\n case \\\"CCC10\\\":\\n case \\\"CCC11\\\":\\n case \\\"CCC12\\\":\\n case \\\"CCC13\\\":\\n case \\\"CCC14\\\":\\n case \\\"CCC15\\\":\\n case \\\"CCC16\\\":\\n case \\\"CCC17\\\":\\n case \\\"CCC18\\\":\\n case \\\"CCC20\\\":\\n case \\\"CCC22\\\":\\n return \\\"Below\\\";\\n case \\\"CCC23\\\":\\n return \\\"Attached_Above\\\";\\n case \\\"CCC24\\\":\\n return \\\"Above_Right\\\";\\n case \\\"CCC25\\\":\\n case \\\"CCC19\\\":\\n return \\\"Above_Left\\\";\\n case \\\"CCC26\\\":\\n return \\\"Above\\\";\\n case \\\"CCC21\\\":\\n break;\\n // Arabic and Syriac\\n case \\\"CCC27\\\":\\n case \\\"CCC28\\\":\\n case \\\"CCC30\\\":\\n case \\\"CCC31\\\":\\n case \\\"CCC33\\\":\\n case \\\"CCC34\\\":\\n case \\\"CCC35\\\":\\n case \\\"CCC36\\\":\\n return \\\"Above\\\";\\n case \\\"CCC29\\\":\\n case \\\"CCC32\\\":\\n return \\\"Below\\\";\\n // Thai\\n case \\\"CCC103\\\":\\n return \\\"Below_Right\\\";\\n case \\\"CCC107\\\":\\n return \\\"Above_Right\\\";\\n // Lao\\n case \\\"CCC118\\\":\\n return \\\"Below\\\";\\n case \\\"CCC122\\\":\\n return \\\"Above\\\";\\n // Tibetan\\n case \\\"CCC129\\\":\\n case \\\"CCC132\\\":\\n return \\\"Below\\\";\\n case \\\"CCC130\\\":\\n return \\\"Above\\\";\\n }\\n return combiningClass;\\n }\\n constructor(font) {\\n this.font = font;\\n }\\n };\\n $f34600ab9d7f70d8$export$2e2bcd8739ae039 = class _$f34600ab9d7f70d8$export$2e2bcd8739ae039 {\\n /**\\n * The width of the bounding box\\n * @type {number}\\n */\\n get width() {\\n return this.maxX - this.minX;\\n }\\n /**\\n * The height of the bounding box\\n * @type {number}\\n */\\n get height() {\\n return this.maxY - this.minY;\\n }\\n addPoint(x, y) {\\n if (Math.abs(x) !== Infinity) {\\n if (x < this.minX) this.minX = x;\\n if (x > this.maxX) this.maxX = x;\\n }\\n if (Math.abs(y) !== Infinity) {\\n if (y < this.minY) this.minY = y;\\n if (y > this.maxY) this.maxY = y;\\n }\\n }\\n copy() {\\n return new _$f34600ab9d7f70d8$export$2e2bcd8739ae039(this.minX, this.minY, this.maxX, this.maxY);\\n }\\n constructor(minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity) {\\n this.minX = minX;\\n this.minY = minY;\\n this.maxX = maxX;\\n this.maxY = maxY;\\n }\\n };\\n $130d1a642ebcd2b7$var$UNICODE_SCRIPTS = {\\n Caucasian_Albanian: \\\"aghb\\\",\\n Arabic: \\\"arab\\\",\\n Imperial_Aramaic: \\\"armi\\\",\\n Armenian: \\\"armn\\\",\\n Avestan: \\\"avst\\\",\\n Balinese: \\\"bali\\\",\\n Bamum: \\\"bamu\\\",\\n Bassa_Vah: \\\"bass\\\",\\n Batak: \\\"batk\\\",\\n Bengali: [\\n \\\"bng2\\\",\\n \\\"beng\\\"\\n ],\\n Bopomofo: \\\"bopo\\\",\\n Brahmi: \\\"brah\\\",\\n Braille: \\\"brai\\\",\\n Buginese: \\\"bugi\\\",\\n Buhid: \\\"buhd\\\",\\n Chakma: \\\"cakm\\\",\\n Canadian_Aboriginal: \\\"cans\\\",\\n Carian: \\\"cari\\\",\\n Cham: \\\"cham\\\",\\n Cherokee: \\\"cher\\\",\\n Coptic: \\\"copt\\\",\\n Cypriot: \\\"cprt\\\",\\n Cyrillic: \\\"cyrl\\\",\\n Devanagari: [\\n \\\"dev2\\\",\\n \\\"deva\\\"\\n ],\\n Deseret: \\\"dsrt\\\",\\n Duployan: \\\"dupl\\\",\\n Egyptian_Hieroglyphs: \\\"egyp\\\",\\n Elbasan: \\\"elba\\\",\\n Ethiopic: \\\"ethi\\\",\\n Georgian: \\\"geor\\\",\\n Glagolitic: \\\"glag\\\",\\n Gothic: \\\"goth\\\",\\n Grantha: \\\"gran\\\",\\n Greek: \\\"grek\\\",\\n Gujarati: [\\n \\\"gjr2\\\",\\n \\\"gujr\\\"\\n ],\\n Gurmukhi: [\\n \\\"gur2\\\",\\n \\\"guru\\\"\\n ],\\n Hangul: \\\"hang\\\",\\n Han: \\\"hani\\\",\\n Hanunoo: \\\"hano\\\",\\n Hebrew: \\\"hebr\\\",\\n Hiragana: \\\"hira\\\",\\n Pahawh_Hmong: \\\"hmng\\\",\\n Katakana_Or_Hiragana: \\\"hrkt\\\",\\n Old_Italic: \\\"ital\\\",\\n Javanese: \\\"java\\\",\\n Kayah_Li: \\\"kali\\\",\\n Katakana: \\\"kana\\\",\\n Kharoshthi: \\\"khar\\\",\\n Khmer: \\\"khmr\\\",\\n Khojki: \\\"khoj\\\",\\n Kannada: [\\n \\\"knd2\\\",\\n \\\"knda\\\"\\n ],\\n Kaithi: \\\"kthi\\\",\\n Tai_Tham: \\\"lana\\\",\\n Lao: \\\"lao \\\",\\n Latin: \\\"latn\\\",\\n Lepcha: \\\"lepc\\\",\\n Limbu: \\\"limb\\\",\\n Linear_A: \\\"lina\\\",\\n Linear_B: \\\"linb\\\",\\n Lisu: \\\"lisu\\\",\\n Lycian: \\\"lyci\\\",\\n Lydian: \\\"lydi\\\",\\n Mahajani: \\\"mahj\\\",\\n Mandaic: \\\"mand\\\",\\n Manichaean: \\\"mani\\\",\\n Mende_Kikakui: \\\"mend\\\",\\n Meroitic_Cursive: \\\"merc\\\",\\n Meroitic_Hieroglyphs: \\\"mero\\\",\\n Malayalam: [\\n \\\"mlm2\\\",\\n \\\"mlym\\\"\\n ],\\n Modi: \\\"modi\\\",\\n Mongolian: \\\"mong\\\",\\n Mro: \\\"mroo\\\",\\n Meetei_Mayek: \\\"mtei\\\",\\n Myanmar: [\\n \\\"mym2\\\",\\n \\\"mymr\\\"\\n ],\\n Old_North_Arabian: \\\"narb\\\",\\n Nabataean: \\\"nbat\\\",\\n Nko: \\\"nko \\\",\\n Ogham: \\\"ogam\\\",\\n Ol_Chiki: \\\"olck\\\",\\n Old_Turkic: \\\"orkh\\\",\\n Oriya: [\\n \\\"ory2\\\",\\n \\\"orya\\\"\\n ],\\n Osmanya: \\\"osma\\\",\\n Palmyrene: \\\"palm\\\",\\n Pau_Cin_Hau: \\\"pauc\\\",\\n Old_Permic: \\\"perm\\\",\\n Phags_Pa: \\\"phag\\\",\\n Inscriptional_Pahlavi: \\\"phli\\\",\\n Psalter_Pahlavi: \\\"phlp\\\",\\n Phoenician: \\\"phnx\\\",\\n Miao: \\\"plrd\\\",\\n Inscriptional_Parthian: \\\"prti\\\",\\n Rejang: \\\"rjng\\\",\\n Runic: \\\"runr\\\",\\n Samaritan: \\\"samr\\\",\\n Old_South_Arabian: \\\"sarb\\\",\\n Saurashtra: \\\"saur\\\",\\n Shavian: \\\"shaw\\\",\\n Sharada: \\\"shrd\\\",\\n Siddham: \\\"sidd\\\",\\n Khudawadi: \\\"sind\\\",\\n Sinhala: \\\"sinh\\\",\\n Sora_Sompeng: \\\"sora\\\",\\n Sundanese: \\\"sund\\\",\\n Syloti_Nagri: \\\"sylo\\\",\\n Syriac: \\\"syrc\\\",\\n Tagbanwa: \\\"tagb\\\",\\n Takri: \\\"takr\\\",\\n Tai_Le: \\\"tale\\\",\\n New_Tai_Lue: \\\"talu\\\",\\n Tamil: [\\n \\\"tml2\\\",\\n \\\"taml\\\"\\n ],\\n Tai_Viet: \\\"tavt\\\",\\n Telugu: [\\n \\\"tel2\\\",\\n \\\"telu\\\"\\n ],\\n Tifinagh: \\\"tfng\\\",\\n Tagalog: \\\"tglg\\\",\\n Thaana: \\\"thaa\\\",\\n Thai: \\\"thai\\\",\\n Tibetan: \\\"tibt\\\",\\n Tirhuta: \\\"tirh\\\",\\n Ugaritic: \\\"ugar\\\",\\n Vai: \\\"vai \\\",\\n Warang_Citi: \\\"wara\\\",\\n Old_Persian: \\\"xpeo\\\",\\n Cuneiform: \\\"xsux\\\",\\n Yi: \\\"yi \\\",\\n Inherited: \\\"zinh\\\",\\n Common: \\\"zyyy\\\",\\n Unknown: \\\"zzzz\\\"\\n };\\n $130d1a642ebcd2b7$var$OPENTYPE_SCRIPTS = {};\\n for (let script in $130d1a642ebcd2b7$var$UNICODE_SCRIPTS) {\\n let tag = $130d1a642ebcd2b7$var$UNICODE_SCRIPTS[script];\\n if (Array.isArray(tag)) for (let t of tag) $130d1a642ebcd2b7$var$OPENTYPE_SCRIPTS[t] = script;\\n else $130d1a642ebcd2b7$var$OPENTYPE_SCRIPTS[tag] = script;\\n }\\n $130d1a642ebcd2b7$var$RTL = {\\n arab: true,\\n hebr: true,\\n syrc: true,\\n thaa: true,\\n cprt: true,\\n khar: true,\\n phnx: true,\\n \\\"nko \\\": true,\\n lydi: true,\\n avst: true,\\n armi: true,\\n phli: true,\\n prti: true,\\n sarb: true,\\n orkh: true,\\n samr: true,\\n mand: true,\\n merc: true,\\n mero: true,\\n // Unicode 7.0 (not listed on http://www.microsoft.com/typography/otspec/scripttags.htm)\\n mani: true,\\n mend: true,\\n nbat: true,\\n narb: true,\\n palm: true,\\n phlp: true\\n // Psalter Pahlavi\\n };\\n $be07b3e97a42687a$export$2e2bcd8739ae039 = class {\\n /**\\n * The total advance width of the run.\\n * @type {number}\\n */\\n get advanceWidth() {\\n let width = 0;\\n for (let position of this.positions) width += position.xAdvance;\\n return width;\\n }\\n /**\\n * The total advance height of the run.\\n * @type {number}\\n */\\n get advanceHeight() {\\n let height = 0;\\n for (let position of this.positions) height += position.yAdvance;\\n return height;\\n }\\n /**\\n * The bounding box containing all glyphs in the run.\\n * @type {BBox}\\n */\\n get bbox() {\\n let bbox = new (0, $f34600ab9d7f70d8$export$2e2bcd8739ae039)();\\n let x = 0;\\n let y = 0;\\n for (let index = 0; index < this.glyphs.length; index++) {\\n let glyph = this.glyphs[index];\\n let p = this.positions[index];\\n let b = glyph.bbox;\\n bbox.addPoint(b.minX + x + p.xOffset, b.minY + y + p.yOffset);\\n bbox.addPoint(b.maxX + x + p.xOffset, b.maxY + y + p.yOffset);\\n x += p.xAdvance;\\n y += p.yAdvance;\\n }\\n return bbox;\\n }\\n constructor(glyphs, features, script, language, direction) {\\n this.glyphs = glyphs;\\n this.positions = null;\\n this.script = script;\\n this.language = language || null;\\n this.direction = direction || $130d1a642ebcd2b7$export$9fddb9d0dd7d8a54(script);\\n this.features = {};\\n if (Array.isArray(features)) for (let tag of features) this.features[tag] = true;\\n else if (typeof features === \\\"object\\\") this.features = features;\\n }\\n };\\n $1ac75d9a55b67f01$export$2e2bcd8739ae039 = class {\\n constructor(xAdvance = 0, yAdvance = 0, xOffset = 0, yOffset = 0) {\\n this.xAdvance = xAdvance;\\n this.yAdvance = yAdvance;\\n this.xOffset = xOffset;\\n this.yOffset = yOffset;\\n }\\n };\\n $3b6302b64eccc32c$var$features = {\\n allTypographicFeatures: {\\n code: 0,\\n exclusive: false,\\n allTypeFeatures: 0\\n },\\n ligatures: {\\n code: 1,\\n exclusive: false,\\n requiredLigatures: 0,\\n commonLigatures: 2,\\n rareLigatures: 4,\\n // logos: 6\\n rebusPictures: 8,\\n diphthongLigatures: 10,\\n squaredLigatures: 12,\\n abbrevSquaredLigatures: 14,\\n symbolLigatures: 16,\\n contextualLigatures: 18,\\n historicalLigatures: 20\\n },\\n cursiveConnection: {\\n code: 2,\\n exclusive: true,\\n unconnected: 0,\\n partiallyConnected: 1,\\n cursive: 2\\n },\\n letterCase: {\\n code: 3,\\n exclusive: true\\n },\\n // upperAndLowerCase: 0 # deprecated\\n // allCaps: 1 # deprecated\\n // allLowerCase: 2 # deprecated\\n // smallCaps: 3 # deprecated\\n // initialCaps: 4 # deprecated\\n // initialCapsAndSmallCaps: 5 # deprecated\\n verticalSubstitution: {\\n code: 4,\\n exclusive: false,\\n substituteVerticalForms: 0\\n },\\n linguisticRearrangement: {\\n code: 5,\\n exclusive: false,\\n linguisticRearrangement: 0\\n },\\n numberSpacing: {\\n code: 6,\\n exclusive: true,\\n monospacedNumbers: 0,\\n proportionalNumbers: 1,\\n thirdWidthNumbers: 2,\\n quarterWidthNumbers: 3\\n },\\n smartSwash: {\\n code: 8,\\n exclusive: false,\\n wordInitialSwashes: 0,\\n wordFinalSwashes: 2,\\n // lineInitialSwashes: 4\\n // lineFinalSwashes: 6\\n nonFinalSwashes: 8\\n },\\n diacritics: {\\n code: 9,\\n exclusive: true,\\n showDiacritics: 0,\\n hideDiacritics: 1,\\n decomposeDiacritics: 2\\n },\\n verticalPosition: {\\n code: 10,\\n exclusive: true,\\n normalPosition: 0,\\n superiors: 1,\\n inferiors: 2,\\n ordinals: 3,\\n scientificInferiors: 4\\n },\\n fractions: {\\n code: 11,\\n exclusive: true,\\n noFractions: 0,\\n verticalFractions: 1,\\n diagonalFractions: 2\\n },\\n overlappingCharacters: {\\n code: 13,\\n exclusive: false,\\n preventOverlap: 0\\n },\\n typographicExtras: {\\n code: 14,\\n exclusive: false,\\n // hyphensToEmDash: 0\\n // hyphenToEnDash: 2\\n slashedZero: 4\\n },\\n // formInterrobang: 6\\n // smartQuotes: 8\\n // periodsToEllipsis: 10\\n mathematicalExtras: {\\n code: 15,\\n exclusive: false,\\n // hyphenToMinus: 0\\n // asteristoMultiply: 2\\n // slashToDivide: 4\\n // inequalityLigatures: 6\\n // exponents: 8\\n mathematicalGreek: 10\\n },\\n ornamentSets: {\\n code: 16,\\n exclusive: true,\\n noOrnaments: 0,\\n dingbats: 1,\\n piCharacters: 2,\\n fleurons: 3,\\n decorativeBorders: 4,\\n internationalSymbols: 5,\\n mathSymbols: 6\\n },\\n characterAlternatives: {\\n code: 17,\\n exclusive: true,\\n noAlternates: 0\\n },\\n // user defined options\\n designComplexity: {\\n code: 18,\\n exclusive: true,\\n designLevel1: 0,\\n designLevel2: 1,\\n designLevel3: 2,\\n designLevel4: 3,\\n designLevel5: 4\\n },\\n styleOptions: {\\n code: 19,\\n exclusive: true,\\n noStyleOptions: 0,\\n displayText: 1,\\n engravedText: 2,\\n illuminatedCaps: 3,\\n titlingCaps: 4,\\n tallCaps: 5\\n },\\n characterShape: {\\n code: 20,\\n exclusive: true,\\n traditionalCharacters: 0,\\n simplifiedCharacters: 1,\\n JIS1978Characters: 2,\\n JIS1983Characters: 3,\\n JIS1990Characters: 4,\\n traditionalAltOne: 5,\\n traditionalAltTwo: 6,\\n traditionalAltThree: 7,\\n traditionalAltFour: 8,\\n traditionalAltFive: 9,\\n expertCharacters: 10,\\n JIS2004Characters: 11,\\n hojoCharacters: 12,\\n NLCCharacters: 13,\\n traditionalNamesCharacters: 14\\n },\\n numberCase: {\\n code: 21,\\n exclusive: true,\\n lowerCaseNumbers: 0,\\n upperCaseNumbers: 1\\n },\\n textSpacing: {\\n code: 22,\\n exclusive: true,\\n proportionalText: 0,\\n monospacedText: 1,\\n halfWidthText: 2,\\n thirdWidthText: 3,\\n quarterWidthText: 4,\\n altProportionalText: 5,\\n altHalfWidthText: 6\\n },\\n transliteration: {\\n code: 23,\\n exclusive: true,\\n noTransliteration: 0\\n },\\n // hanjaToHangul: 1\\n // hiraganaToKatakana: 2\\n // katakanaToHiragana: 3\\n // kanaToRomanization: 4\\n // romanizationToHiragana: 5\\n // romanizationToKatakana: 6\\n // hanjaToHangulAltOne: 7\\n // hanjaToHangulAltTwo: 8\\n // hanjaToHangulAltThree: 9\\n annotation: {\\n code: 24,\\n exclusive: true,\\n noAnnotation: 0,\\n boxAnnotation: 1,\\n roundedBoxAnnotation: 2,\\n circleAnnotation: 3,\\n invertedCircleAnnotation: 4,\\n parenthesisAnnotation: 5,\\n periodAnnotation: 6,\\n romanNumeralAnnotation: 7,\\n diamondAnnotation: 8,\\n invertedBoxAnnotation: 9,\\n invertedRoundedBoxAnnotation: 10\\n },\\n kanaSpacing: {\\n code: 25,\\n exclusive: true,\\n fullWidthKana: 0,\\n proportionalKana: 1\\n },\\n ideographicSpacing: {\\n code: 26,\\n exclusive: true,\\n fullWidthIdeographs: 0,\\n proportionalIdeographs: 1,\\n halfWidthIdeographs: 2\\n },\\n unicodeDecomposition: {\\n code: 27,\\n exclusive: false,\\n canonicalComposition: 0,\\n compatibilityComposition: 2,\\n transcodingComposition: 4\\n },\\n rubyKana: {\\n code: 28,\\n exclusive: false,\\n // noRubyKana: 0 # deprecated - use rubyKanaOff instead\\n // rubyKana: 1 # deprecated - use rubyKanaOn instead\\n rubyKana: 2\\n },\\n CJKSymbolAlternatives: {\\n code: 29,\\n exclusive: true,\\n noCJKSymbolAlternatives: 0,\\n CJKSymbolAltOne: 1,\\n CJKSymbolAltTwo: 2,\\n CJKSymbolAltThree: 3,\\n CJKSymbolAltFour: 4,\\n CJKSymbolAltFive: 5\\n },\\n ideographicAlternatives: {\\n code: 30,\\n exclusive: true,\\n noIdeographicAlternatives: 0,\\n ideographicAltOne: 1,\\n ideographicAltTwo: 2,\\n ideographicAltThree: 3,\\n ideographicAltFour: 4,\\n ideographicAltFive: 5\\n },\\n CJKVerticalRomanPlacement: {\\n code: 31,\\n exclusive: true,\\n CJKVerticalRomanCentered: 0,\\n CJKVerticalRomanHBaseline: 1\\n },\\n italicCJKRoman: {\\n code: 32,\\n exclusive: false,\\n // noCJKItalicRoman: 0 # deprecated - use CJKItalicRomanOff instead\\n // CJKItalicRoman: 1 # deprecated - use CJKItalicRomanOn instead\\n CJKItalicRoman: 2\\n },\\n caseSensitiveLayout: {\\n code: 33,\\n exclusive: false,\\n caseSensitiveLayout: 0,\\n caseSensitiveSpacing: 2\\n },\\n alternateKana: {\\n code: 34,\\n exclusive: false,\\n alternateHorizKana: 0,\\n alternateVertKana: 2\\n },\\n stylisticAlternatives: {\\n code: 35,\\n exclusive: false,\\n noStylisticAlternates: 0,\\n stylisticAltOne: 2,\\n stylisticAltTwo: 4,\\n stylisticAltThree: 6,\\n stylisticAltFour: 8,\\n stylisticAltFive: 10,\\n stylisticAltSix: 12,\\n stylisticAltSeven: 14,\\n stylisticAltEight: 16,\\n stylisticAltNine: 18,\\n stylisticAltTen: 20,\\n stylisticAltEleven: 22,\\n stylisticAltTwelve: 24,\\n stylisticAltThirteen: 26,\\n stylisticAltFourteen: 28,\\n stylisticAltFifteen: 30,\\n stylisticAltSixteen: 32,\\n stylisticAltSeventeen: 34,\\n stylisticAltEighteen: 36,\\n stylisticAltNineteen: 38,\\n stylisticAltTwenty: 40\\n },\\n contextualAlternates: {\\n code: 36,\\n exclusive: false,\\n contextualAlternates: 0,\\n swashAlternates: 2,\\n contextualSwashAlternates: 4\\n },\\n lowerCase: {\\n code: 37,\\n exclusive: true,\\n defaultLowerCase: 0,\\n lowerCaseSmallCaps: 1,\\n lowerCasePetiteCaps: 2\\n },\\n upperCase: {\\n code: 38,\\n exclusive: true,\\n defaultUpperCase: 0,\\n upperCaseSmallCaps: 1,\\n upperCasePetiteCaps: 2\\n },\\n languageTag: {\\n code: 39,\\n exclusive: true\\n },\\n CJKRomanSpacing: {\\n code: 103,\\n exclusive: true,\\n halfWidthCJKRoman: 0,\\n proportionalCJKRoman: 1,\\n defaultCJKRoman: 2,\\n fullWidthCJKRoman: 3\\n }\\n };\\n $3b6302b64eccc32c$var$feature = (name, selector) => [\\n $3b6302b64eccc32c$var$features[name].code,\\n $3b6302b64eccc32c$var$features[name][selector]\\n ];\\n $3b6302b64eccc32c$var$OTMapping = {\\n rlig: $3b6302b64eccc32c$var$feature(\\\"ligatures\\\", \\\"requiredLigatures\\\"),\\n clig: $3b6302b64eccc32c$var$feature(\\\"ligatures\\\", \\\"contextualLigatures\\\"),\\n dlig: $3b6302b64eccc32c$var$feature(\\\"ligatures\\\", \\\"rareLigatures\\\"),\\n hlig: $3b6302b64eccc32c$var$feature(\\\"ligatures\\\", \\\"historicalLigatures\\\"),\\n liga: $3b6302b64eccc32c$var$feature(\\\"ligatures\\\", \\\"commonLigatures\\\"),\\n hist: $3b6302b64eccc32c$var$feature(\\\"ligatures\\\", \\\"historicalLigatures\\\"),\\n smcp: $3b6302b64eccc32c$var$feature(\\\"lowerCase\\\", \\\"lowerCaseSmallCaps\\\"),\\n pcap: $3b6302b64eccc32c$var$feature(\\\"lowerCase\\\", \\\"lowerCasePetiteCaps\\\"),\\n frac: $3b6302b64eccc32c$var$feature(\\\"fractions\\\", \\\"diagonalFractions\\\"),\\n dnom: $3b6302b64eccc32c$var$feature(\\\"fractions\\\", \\\"diagonalFractions\\\"),\\n numr: $3b6302b64eccc32c$var$feature(\\\"fractions\\\", \\\"diagonalFractions\\\"),\\n afrc: $3b6302b64eccc32c$var$feature(\\\"fractions\\\", \\\"verticalFractions\\\"),\\n // aalt\\n // abvf, abvm, abvs, akhn, blwf, blwm, blws, cfar, cjct, cpsp, falt, isol, jalt, ljmo, mset?\\n // ltra, ltrm, nukt, pref, pres, pstf, psts, rand, rkrf, rphf, rtla, rtlm, size, tjmo, tnum?\\n // unic, vatu, vhal, vjmo, vpal, vrt2\\n // dist -> trak table?\\n // kern, vkrn -> kern table\\n // lfbd + opbd + rtbd -> opbd table?\\n // mark, mkmk -> acnt table?\\n // locl -> languageTag + ltag table\\n case: $3b6302b64eccc32c$var$feature(\\\"caseSensitiveLayout\\\", \\\"caseSensitiveLayout\\\"),\\n ccmp: $3b6302b64eccc32c$var$feature(\\\"unicodeDecomposition\\\", \\\"canonicalComposition\\\"),\\n cpct: $3b6302b64eccc32c$var$feature(\\\"CJKVerticalRomanPlacement\\\", \\\"CJKVerticalRomanCentered\\\"),\\n valt: $3b6302b64eccc32c$var$feature(\\\"CJKVerticalRomanPlacement\\\", \\\"CJKVerticalRomanCentered\\\"),\\n swsh: $3b6302b64eccc32c$var$feature(\\\"contextualAlternates\\\", \\\"swashAlternates\\\"),\\n cswh: $3b6302b64eccc32c$var$feature(\\\"contextualAlternates\\\", \\\"contextualSwashAlternates\\\"),\\n curs: $3b6302b64eccc32c$var$feature(\\\"cursiveConnection\\\", \\\"cursive\\\"),\\n c2pc: $3b6302b64eccc32c$var$feature(\\\"upperCase\\\", \\\"upperCasePetiteCaps\\\"),\\n c2sc: $3b6302b64eccc32c$var$feature(\\\"upperCase\\\", \\\"upperCaseSmallCaps\\\"),\\n init: $3b6302b64eccc32c$var$feature(\\\"smartSwash\\\", \\\"wordInitialSwashes\\\"),\\n fin2: $3b6302b64eccc32c$var$feature(\\\"smartSwash\\\", \\\"wordFinalSwashes\\\"),\\n medi: $3b6302b64eccc32c$var$feature(\\\"smartSwash\\\", \\\"nonFinalSwashes\\\"),\\n med2: $3b6302b64eccc32c$var$feature(\\\"smartSwash\\\", \\\"nonFinalSwashes\\\"),\\n fin3: $3b6302b64eccc32c$var$feature(\\\"smartSwash\\\", \\\"wordFinalSwashes\\\"),\\n fina: $3b6302b64eccc32c$var$feature(\\\"smartSwash\\\", \\\"wordFinalSwashes\\\"),\\n pkna: $3b6302b64eccc32c$var$feature(\\\"kanaSpacing\\\", \\\"proportionalKana\\\"),\\n half: $3b6302b64eccc32c$var$feature(\\\"textSpacing\\\", \\\"halfWidthText\\\"),\\n halt: $3b6302b64eccc32c$var$feature(\\\"textSpacing\\\", \\\"altHalfWidthText\\\"),\\n hkna: $3b6302b64eccc32c$var$feature(\\\"alternateKana\\\", \\\"alternateHorizKana\\\"),\\n vkna: $3b6302b64eccc32c$var$feature(\\\"alternateKana\\\", \\\"alternateVertKana\\\"),\\n // hngl: feature 'transliteration', 'hanjaToHangulSelector' # deprecated\\n ital: $3b6302b64eccc32c$var$feature(\\\"italicCJKRoman\\\", \\\"CJKItalicRoman\\\"),\\n lnum: $3b6302b64eccc32c$var$feature(\\\"numberCase\\\", \\\"upperCaseNumbers\\\"),\\n onum: $3b6302b64eccc32c$var$feature(\\\"numberCase\\\", \\\"lowerCaseNumbers\\\"),\\n mgrk: $3b6302b64eccc32c$var$feature(\\\"mathematicalExtras\\\", \\\"mathematicalGreek\\\"),\\n // nalt: not enough info. what type of annotation?\\n // ornm: ditto, which ornament style?\\n calt: $3b6302b64eccc32c$var$feature(\\\"contextualAlternates\\\", \\\"contextualAlternates\\\"),\\n vrt2: $3b6302b64eccc32c$var$feature(\\\"verticalSubstitution\\\", \\\"substituteVerticalForms\\\"),\\n vert: $3b6302b64eccc32c$var$feature(\\\"verticalSubstitution\\\", \\\"substituteVerticalForms\\\"),\\n tnum: $3b6302b64eccc32c$var$feature(\\\"numberSpacing\\\", \\\"monospacedNumbers\\\"),\\n pnum: $3b6302b64eccc32c$var$feature(\\\"numberSpacing\\\", \\\"proportionalNumbers\\\"),\\n sups: $3b6302b64eccc32c$var$feature(\\\"verticalPosition\\\", \\\"superiors\\\"),\\n subs: $3b6302b64eccc32c$var$feature(\\\"verticalPosition\\\", \\\"inferiors\\\"),\\n ordn: $3b6302b64eccc32c$var$feature(\\\"verticalPosition\\\", \\\"ordinals\\\"),\\n pwid: $3b6302b64eccc32c$var$feature(\\\"textSpacing\\\", \\\"proportionalText\\\"),\\n hwid: $3b6302b64eccc32c$var$feature(\\\"textSpacing\\\", \\\"halfWidthText\\\"),\\n qwid: $3b6302b64eccc32c$var$feature(\\\"textSpacing\\\", \\\"quarterWidthText\\\"),\\n twid: $3b6302b64eccc32c$var$feature(\\\"textSpacing\\\", \\\"thirdWidthText\\\"),\\n fwid: $3b6302b64eccc32c$var$feature(\\\"textSpacing\\\", \\\"proportionalText\\\"),\\n palt: $3b6302b64eccc32c$var$feature(\\\"textSpacing\\\", \\\"altProportionalText\\\"),\\n trad: $3b6302b64eccc32c$var$feature(\\\"characterShape\\\", \\\"traditionalCharacters\\\"),\\n smpl: $3b6302b64eccc32c$var$feature(\\\"characterShape\\\", \\\"simplifiedCharacters\\\"),\\n jp78: $3b6302b64eccc32c$var$feature(\\\"characterShape\\\", \\\"JIS1978Characters\\\"),\\n jp83: $3b6302b64eccc32c$var$feature(\\\"characterShape\\\", \\\"JIS1983Characters\\\"),\\n jp90: $3b6302b64eccc32c$var$feature(\\\"characterShape\\\", \\\"JIS1990Characters\\\"),\\n jp04: $3b6302b64eccc32c$var$feature(\\\"characterShape\\\", \\\"JIS2004Characters\\\"),\\n expt: $3b6302b64eccc32c$var$feature(\\\"characterShape\\\", \\\"expertCharacters\\\"),\\n hojo: $3b6302b64eccc32c$var$feature(\\\"characterShape\\\", \\\"hojoCharacters\\\"),\\n nlck: $3b6302b64eccc32c$var$feature(\\\"characterShape\\\", \\\"NLCCharacters\\\"),\\n tnam: $3b6302b64eccc32c$var$feature(\\\"characterShape\\\", \\\"traditionalNamesCharacters\\\"),\\n ruby: $3b6302b64eccc32c$var$feature(\\\"rubyKana\\\", \\\"rubyKana\\\"),\\n titl: $3b6302b64eccc32c$var$feature(\\\"styleOptions\\\", \\\"titlingCaps\\\"),\\n zero: $3b6302b64eccc32c$var$feature(\\\"typographicExtras\\\", \\\"slashedZero\\\"),\\n ss01: $3b6302b64eccc32c$var$feature(\\\"stylisticAlternatives\\\", \\\"stylisticAltOne\\\"),\\n ss02: $3b6302b64eccc32c$var$feature(\\\"stylisticAlternatives\\\", \\\"stylisticAltTwo\\\"),\\n ss03: $3b6302b64eccc32c$var$feature(\\\"stylisticAlternatives\\\", \\\"stylisticAltThree\\\"),\\n ss04: $3b6302b64eccc32c$var$feature(\\\"stylisticAlternatives\\\", \\\"stylisticAltFour\\\"),\\n ss05: $3b6302b64eccc32c$var$feature(\\\"stylisticAlternatives\\\", \\\"stylisticAltFive\\\"),\\n ss06: $3b6302b64eccc32c$var$feature(\\\"stylisticAlternatives\\\", \\\"stylisticAltSix\\\"),\\n ss07: $3b6302b64eccc32c$var$feature(\\\"stylisticAlternatives\\\", \\\"stylisticAltSeven\\\"),\\n ss08: $3b6302b64eccc32c$var$feature(\\\"stylisticAlternatives\\\", \\\"stylisticAltEight\\\"),\\n ss09: $3b6302b64eccc32c$var$feature(\\\"stylisticAlternatives\\\", \\\"stylisticAltNine\\\"),\\n ss10: $3b6302b64eccc32c$var$feature(\\\"stylisticAlternatives\\\", \\\"stylisticAltTen\\\"),\\n ss11: $3b6302b64eccc32c$var$feature(\\\"stylisticAlternatives\\\", \\\"stylisticAltEleven\\\"),\\n ss12: $3b6302b64eccc32c$var$feature(\\\"stylisticAlternatives\\\", \\\"stylisticAltTwelve\\\"),\\n ss13: $3b6302b64eccc32c$var$feature(\\\"stylisticAlternatives\\\", \\\"stylisticAltThirteen\\\"),\\n ss14: $3b6302b64eccc32c$var$feature(\\\"stylisticAlternatives\\\", \\\"stylisticAltFourteen\\\"),\\n ss15: $3b6302b64eccc32c$var$feature(\\\"stylisticAlternatives\\\", \\\"stylisticAltFifteen\\\"),\\n ss16: $3b6302b64eccc32c$var$feature(\\\"stylisticAlternatives\\\", \\\"stylisticAltSixteen\\\"),\\n ss17: $3b6302b64eccc32c$var$feature(\\\"stylisticAlternatives\\\", \\\"stylisticAltSeventeen\\\"),\\n ss18: $3b6302b64eccc32c$var$feature(\\\"stylisticAlternatives\\\", \\\"stylisticAltEighteen\\\"),\\n ss19: $3b6302b64eccc32c$var$feature(\\\"stylisticAlternatives\\\", \\\"stylisticAltNineteen\\\"),\\n ss20: $3b6302b64eccc32c$var$feature(\\\"stylisticAlternatives\\\", \\\"stylisticAltTwenty\\\")\\n };\\n for (let i = 1; i <= 99; i++) $3b6302b64eccc32c$var$OTMapping[`cv${`00${i}`.slice(-2)}`] = [\\n $3b6302b64eccc32c$var$features.characterAlternatives.code,\\n i\\n ];\\n $3b6302b64eccc32c$var$AATMapping = {};\\n for (let ot in $3b6302b64eccc32c$var$OTMapping) {\\n let aat = $3b6302b64eccc32c$var$OTMapping[ot];\\n if ($3b6302b64eccc32c$var$AATMapping[aat[0]] == null) $3b6302b64eccc32c$var$AATMapping[aat[0]] = {};\\n $3b6302b64eccc32c$var$AATMapping[aat[0]][aat[1]] = ot;\\n }\\n $ff5ce077dae0f144$export$2e2bcd8739ae039 = class {\\n lookup(glyph) {\\n switch (this.table.version) {\\n case 0:\\n return this.table.values.getItem(glyph);\\n case 2:\\n case 4: {\\n let min = 0;\\n let max = this.table.binarySearchHeader.nUnits - 1;\\n while (min <= max) {\\n var mid = min + max >> 1;\\n var seg = this.table.segments[mid];\\n if (seg.firstGlyph === 65535) return null;\\n if (glyph < seg.firstGlyph) max = mid - 1;\\n else if (glyph > seg.lastGlyph) min = mid + 1;\\n else {\\n if (this.table.version === 2) return seg.value;\\n else return seg.values[glyph - seg.firstGlyph];\\n }\\n }\\n return null;\\n }\\n case 6: {\\n let min = 0;\\n let max = this.table.binarySearchHeader.nUnits - 1;\\n while (min <= max) {\\n var mid = min + max >> 1;\\n var seg = this.table.segments[mid];\\n if (seg.glyph === 65535) return null;\\n if (glyph < seg.glyph) max = mid - 1;\\n else if (glyph > seg.glyph) min = mid + 1;\\n else return seg.value;\\n }\\n return null;\\n }\\n case 8:\\n return this.table.values[glyph - this.table.firstGlyph];\\n default:\\n throw new Error(`Unknown lookup table format: ${this.table.version}`);\\n }\\n }\\n glyphsForValue(classValue) {\\n let res = [];\\n switch (this.table.version) {\\n case 2:\\n case 4:\\n for (let segment of this.table.segments) if (this.table.version === 2 && segment.value === classValue) res.push(...(0, $12727730ddfc8bfe$export$d02631cccf789723)(segment.firstGlyph, segment.lastGlyph + 1));\\n else {\\n for (let index = 0; index < segment.values.length; index++) if (segment.values[index] === classValue) res.push(segment.firstGlyph + index);\\n }\\n break;\\n case 6:\\n for (let segment of this.table.segments) if (segment.value === classValue) res.push(segment.glyph);\\n break;\\n case 8:\\n for (let i = 0; i < this.table.values.length; i++) if (this.table.values[i] === classValue) res.push(this.table.firstGlyph + i);\\n break;\\n default:\\n throw new Error(`Unknown lookup table format: ${this.table.version}`);\\n }\\n return res;\\n }\\n constructor(table) {\\n this.table = table;\\n }\\n };\\n (0, __decorate)([\\n (0, $e71565f2ce09cb6b$export$69a3209f1a06c04d)\\n ], $ff5ce077dae0f144$export$2e2bcd8739ae039.prototype, \\\"glyphsForValue\\\", null);\\n $50c7aac9316f2948$var$START_OF_TEXT_STATE = 0;\\n $50c7aac9316f2948$var$END_OF_TEXT_CLASS = 0;\\n $50c7aac9316f2948$var$OUT_OF_BOUNDS_CLASS = 1;\\n $50c7aac9316f2948$var$DELETED_GLYPH_CLASS = 2;\\n $50c7aac9316f2948$var$DONT_ADVANCE = 16384;\\n $50c7aac9316f2948$export$2e2bcd8739ae039 = class {\\n process(glyphs, reverse, processEntry) {\\n let currentState = $50c7aac9316f2948$var$START_OF_TEXT_STATE;\\n let index = reverse ? glyphs.length - 1 : 0;\\n let dir = reverse ? -1 : 1;\\n while (dir === 1 && index <= glyphs.length || dir === -1 && index >= -1) {\\n let glyph = null;\\n let classCode = $50c7aac9316f2948$var$OUT_OF_BOUNDS_CLASS;\\n let shouldAdvance = true;\\n if (index === glyphs.length || index === -1) classCode = $50c7aac9316f2948$var$END_OF_TEXT_CLASS;\\n else {\\n glyph = glyphs[index];\\n if (glyph.id === 65535) classCode = $50c7aac9316f2948$var$DELETED_GLYPH_CLASS;\\n else {\\n classCode = this.lookupTable.lookup(glyph.id);\\n if (classCode == null) classCode = $50c7aac9316f2948$var$OUT_OF_BOUNDS_CLASS;\\n }\\n }\\n let row = this.stateTable.stateArray.getItem(currentState);\\n let entryIndex = row[classCode];\\n let entry = this.stateTable.entryTable.getItem(entryIndex);\\n if (classCode !== $50c7aac9316f2948$var$END_OF_TEXT_CLASS && classCode !== $50c7aac9316f2948$var$DELETED_GLYPH_CLASS) {\\n processEntry(glyph, entry, index);\\n shouldAdvance = !(entry.flags & $50c7aac9316f2948$var$DONT_ADVANCE);\\n }\\n currentState = entry.newState;\\n if (shouldAdvance) index += dir;\\n }\\n return glyphs;\\n }\\n /**\\n * Performs a depth-first traversal of the glyph strings\\n * represented by the state machine.\\n */\\n traverse(opts, state = 0, visited = /* @__PURE__ */ new Set()) {\\n if (visited.has(state)) return;\\n visited.add(state);\\n let { nClasses, stateArray, entryTable } = this.stateTable;\\n let row = stateArray.getItem(state);\\n for (let classCode = 4; classCode < nClasses; classCode++) {\\n let entryIndex = row[classCode];\\n let entry = entryTable.getItem(entryIndex);\\n for (let glyph of this.lookupTable.glyphsForValue(classCode)) {\\n if (opts.enter) opts.enter(glyph, entry);\\n if (entry.newState !== 0) this.traverse(opts, entry.newState, visited);\\n if (opts.exit) opts.exit(glyph, entry);\\n }\\n }\\n }\\n constructor(stateTable) {\\n this.stateTable = stateTable;\\n this.lookupTable = new (0, $ff5ce077dae0f144$export$2e2bcd8739ae039)(stateTable.classTable);\\n }\\n };\\n $55f71433a605c87d$var$MARK_FIRST = 32768;\\n $55f71433a605c87d$var$MARK_LAST = 8192;\\n $55f71433a605c87d$var$VERB = 15;\\n $55f71433a605c87d$var$SET_MARK = 32768;\\n $55f71433a605c87d$var$SET_COMPONENT = 32768;\\n $55f71433a605c87d$var$PERFORM_ACTION = 8192;\\n $55f71433a605c87d$var$LAST_MASK = 2147483648;\\n $55f71433a605c87d$var$STORE_MASK = 1073741824;\\n $55f71433a605c87d$var$OFFSET_MASK = 1073741823;\\n $55f71433a605c87d$var$REVERSE_DIRECTION = 4194304;\\n $55f71433a605c87d$var$CURRENT_INSERT_BEFORE = 2048;\\n $55f71433a605c87d$var$MARKED_INSERT_BEFORE = 1024;\\n $55f71433a605c87d$var$CURRENT_INSERT_COUNT = 992;\\n $55f71433a605c87d$var$MARKED_INSERT_COUNT = 31;\\n $55f71433a605c87d$export$2e2bcd8739ae039 = class {\\n // Processes an array of glyphs and applies the specified features\\n // Features should be in the form of {featureType:{featureSetting:boolean}}\\n process(glyphs, features = {}) {\\n for (let chain of this.morx.chains) {\\n let flags = chain.defaultFlags;\\n for (let feature of chain.features) {\\n let f;\\n if (f = features[feature.featureType]) {\\n if (f[feature.featureSetting]) {\\n flags &= feature.disableFlags;\\n flags |= feature.enableFlags;\\n } else if (f[feature.featureSetting] === false) {\\n flags |= ~feature.disableFlags;\\n flags &= ~feature.enableFlags;\\n }\\n }\\n }\\n for (let subtable of chain.subtables) if (subtable.subFeatureFlags & flags) this.processSubtable(subtable, glyphs);\\n }\\n let index = glyphs.length - 1;\\n while (index >= 0) {\\n if (glyphs[index].id === 65535) glyphs.splice(index, 1);\\n index--;\\n }\\n return glyphs;\\n }\\n processSubtable(subtable, glyphs) {\\n this.subtable = subtable;\\n this.glyphs = glyphs;\\n if (this.subtable.type === 4) {\\n this.processNoncontextualSubstitutions(this.subtable, this.glyphs);\\n return;\\n }\\n this.ligatureStack = [];\\n this.markedGlyph = null;\\n this.firstGlyph = null;\\n this.lastGlyph = null;\\n this.markedIndex = null;\\n let stateMachine = this.getStateMachine(subtable);\\n let process2 = this.getProcessor();\\n let reverse = !!(this.subtable.coverage & $55f71433a605c87d$var$REVERSE_DIRECTION);\\n return stateMachine.process(this.glyphs, reverse, process2);\\n }\\n getStateMachine(subtable) {\\n return new (0, $50c7aac9316f2948$export$2e2bcd8739ae039)(subtable.table.stateTable);\\n }\\n getProcessor() {\\n switch (this.subtable.type) {\\n case 0:\\n return this.processIndicRearragement;\\n case 1:\\n return this.processContextualSubstitution;\\n case 2:\\n return this.processLigature;\\n case 4:\\n return this.processNoncontextualSubstitutions;\\n case 5:\\n return this.processGlyphInsertion;\\n default:\\n throw new Error(`Invalid morx subtable type: ${this.subtable.type}`);\\n }\\n }\\n processIndicRearragement(glyph, entry, index) {\\n if (entry.flags & $55f71433a605c87d$var$MARK_FIRST) this.firstGlyph = index;\\n if (entry.flags & $55f71433a605c87d$var$MARK_LAST) this.lastGlyph = index;\\n $55f71433a605c87d$var$reorderGlyphs(this.glyphs, entry.flags & $55f71433a605c87d$var$VERB, this.firstGlyph, this.lastGlyph);\\n }\\n processContextualSubstitution(glyph, entry, index) {\\n let subsitutions = this.subtable.table.substitutionTable.items;\\n if (entry.markIndex !== 65535) {\\n let lookup = subsitutions.getItem(entry.markIndex);\\n let lookupTable = new (0, $ff5ce077dae0f144$export$2e2bcd8739ae039)(lookup);\\n glyph = this.glyphs[this.markedGlyph];\\n var gid = lookupTable.lookup(glyph.id);\\n if (gid) this.glyphs[this.markedGlyph] = this.font.getGlyph(gid, glyph.codePoints);\\n }\\n if (entry.currentIndex !== 65535) {\\n let lookup = subsitutions.getItem(entry.currentIndex);\\n let lookupTable = new (0, $ff5ce077dae0f144$export$2e2bcd8739ae039)(lookup);\\n glyph = this.glyphs[index];\\n var gid = lookupTable.lookup(glyph.id);\\n if (gid) this.glyphs[index] = this.font.getGlyph(gid, glyph.codePoints);\\n }\\n if (entry.flags & $55f71433a605c87d$var$SET_MARK) this.markedGlyph = index;\\n }\\n processLigature(glyph, entry, index) {\\n if (entry.flags & $55f71433a605c87d$var$SET_COMPONENT) this.ligatureStack.push(index);\\n if (entry.flags & $55f71433a605c87d$var$PERFORM_ACTION) {\\n let actions = this.subtable.table.ligatureActions;\\n let components = this.subtable.table.components;\\n let ligatureList = this.subtable.table.ligatureList;\\n let actionIndex = entry.action;\\n let last = false;\\n let ligatureIndex = 0;\\n let codePoints = [];\\n let ligatureGlyphs = [];\\n while (!last) {\\n let componentGlyph = this.ligatureStack.pop();\\n codePoints.unshift(...this.glyphs[componentGlyph].codePoints);\\n let action = actions.getItem(actionIndex++);\\n last = !!(action & $55f71433a605c87d$var$LAST_MASK);\\n let store = !!(action & $55f71433a605c87d$var$STORE_MASK);\\n let offset = (action & $55f71433a605c87d$var$OFFSET_MASK) << 2 >> 2;\\n offset += this.glyphs[componentGlyph].id;\\n let component = components.getItem(offset);\\n ligatureIndex += component;\\n if (last || store) {\\n let ligatureEntry = ligatureList.getItem(ligatureIndex);\\n this.glyphs[componentGlyph] = this.font.getGlyph(ligatureEntry, codePoints);\\n ligatureGlyphs.push(componentGlyph);\\n ligatureIndex = 0;\\n codePoints = [];\\n } else this.glyphs[componentGlyph] = this.font.getGlyph(65535);\\n }\\n this.ligatureStack.push(...ligatureGlyphs);\\n }\\n }\\n processNoncontextualSubstitutions(subtable, glyphs, index) {\\n let lookupTable = new (0, $ff5ce077dae0f144$export$2e2bcd8739ae039)(subtable.table.lookupTable);\\n for (index = 0; index < glyphs.length; index++) {\\n let glyph = glyphs[index];\\n if (glyph.id !== 65535) {\\n let gid = lookupTable.lookup(glyph.id);\\n if (gid) glyphs[index] = this.font.getGlyph(gid, glyph.codePoints);\\n }\\n }\\n }\\n _insertGlyphs(glyphIndex, insertionActionIndex, count, isBefore) {\\n let insertions = [];\\n while (count--) {\\n let gid = this.subtable.table.insertionActions.getItem(insertionActionIndex++);\\n insertions.push(this.font.getGlyph(gid));\\n }\\n if (!isBefore) glyphIndex++;\\n this.glyphs.splice(glyphIndex, 0, ...insertions);\\n }\\n processGlyphInsertion(glyph, entry, index) {\\n if (entry.flags & $55f71433a605c87d$var$SET_MARK) this.markedIndex = index;\\n if (entry.markedInsertIndex !== 65535) {\\n let count = (entry.flags & $55f71433a605c87d$var$MARKED_INSERT_COUNT) >>> 5;\\n let isBefore = !!(entry.flags & $55f71433a605c87d$var$MARKED_INSERT_BEFORE);\\n this._insertGlyphs(this.markedIndex, entry.markedInsertIndex, count, isBefore);\\n }\\n if (entry.currentInsertIndex !== 65535) {\\n let count = (entry.flags & $55f71433a605c87d$var$CURRENT_INSERT_COUNT) >>> 5;\\n let isBefore = !!(entry.flags & $55f71433a605c87d$var$CURRENT_INSERT_BEFORE);\\n this._insertGlyphs(index, entry.currentInsertIndex, count, isBefore);\\n }\\n }\\n getSupportedFeatures() {\\n let features = [];\\n for (let chain of this.morx.chains) for (let feature of chain.features) features.push([\\n feature.featureType,\\n feature.featureSetting\\n ]);\\n return features;\\n }\\n generateInputs(gid) {\\n if (!this.inputCache) this.generateInputCache();\\n return this.inputCache[gid] || [];\\n }\\n generateInputCache() {\\n this.inputCache = {};\\n for (let chain of this.morx.chains) {\\n let flags = chain.defaultFlags;\\n for (let subtable of chain.subtables) if (subtable.subFeatureFlags & flags) this.generateInputsForSubtable(subtable);\\n }\\n }\\n generateInputsForSubtable(subtable) {\\n if (subtable.type !== 2) return;\\n let reverse = !!(subtable.coverage & $55f71433a605c87d$var$REVERSE_DIRECTION);\\n if (reverse) throw new Error(\\\"Reverse subtable, not supported.\\\");\\n this.subtable = subtable;\\n this.ligatureStack = [];\\n let stateMachine = this.getStateMachine(subtable);\\n let process2 = this.getProcessor();\\n let input = [];\\n let stack = [];\\n this.glyphs = [];\\n stateMachine.traverse({\\n enter: (glyph, entry) => {\\n let glyphs = this.glyphs;\\n stack.push({\\n glyphs: glyphs.slice(),\\n ligatureStack: this.ligatureStack.slice()\\n });\\n let g = this.font.getGlyph(glyph);\\n input.push(g);\\n glyphs.push(input[input.length - 1]);\\n process2(glyphs[glyphs.length - 1], entry, glyphs.length - 1);\\n let count = 0;\\n let found = 0;\\n for (let i = 0; i < glyphs.length && count <= 1; i++) if (glyphs[i].id !== 65535) {\\n count++;\\n found = glyphs[i].id;\\n }\\n if (count === 1) {\\n let result = input.map((g2) => g2.id);\\n let cache2 = this.inputCache[found];\\n if (cache2) cache2.push(result);\\n else this.inputCache[found] = [\\n result\\n ];\\n }\\n },\\n exit: () => {\\n ({ glyphs: this.glyphs, ligatureStack: this.ligatureStack } = stack.pop());\\n input.pop();\\n }\\n });\\n }\\n constructor(font) {\\n this.processIndicRearragement = this.processIndicRearragement.bind(this);\\n this.processContextualSubstitution = this.processContextualSubstitution.bind(this);\\n this.processLigature = this.processLigature.bind(this);\\n this.processNoncontextualSubstitutions = this.processNoncontextualSubstitutions.bind(this);\\n this.processGlyphInsertion = this.processGlyphInsertion.bind(this);\\n this.font = font;\\n this.morx = font.morx;\\n this.inputCache = null;\\n }\\n };\\n (0, __decorate)([\\n (0, $e71565f2ce09cb6b$export$69a3209f1a06c04d)\\n ], $55f71433a605c87d$export$2e2bcd8739ae039.prototype, \\\"getStateMachine\\\", null);\\n $ba6dd74203be8728$export$2e2bcd8739ae039 = class {\\n substitute(glyphRun) {\\n if (glyphRun.direction === \\\"rtl\\\") glyphRun.glyphs.reverse();\\n this.morxProcessor.process(glyphRun.glyphs, $3b6302b64eccc32c$export$b813f7d2a1677c16(glyphRun.features));\\n }\\n getAvailableFeatures(script, language) {\\n return $3b6302b64eccc32c$export$bd6df347a4f391c4(this.morxProcessor.getSupportedFeatures());\\n }\\n stringsForGlyph(gid) {\\n let glyphStrings = this.morxProcessor.generateInputs(gid);\\n let result = /* @__PURE__ */ new Set();\\n for (let glyphs of glyphStrings) this._addStrings(glyphs, 0, result, \\\"\\\");\\n return result;\\n }\\n _addStrings(glyphs, index, strings, string) {\\n let codePoints = this.font._cmapProcessor.codePointsForGlyph(glyphs[index]);\\n for (let codePoint of codePoints) {\\n let s = string + String.fromCodePoint(codePoint);\\n if (index < glyphs.length - 1) this._addStrings(glyphs, index + 1, strings, s);\\n else strings.add(s);\\n }\\n }\\n constructor(font) {\\n this.font = font;\\n this.morxProcessor = new (0, $55f71433a605c87d$export$2e2bcd8739ae039)(font);\\n this.fallbackPosition = false;\\n }\\n };\\n $94d7a73bd2edfc9a$export$2e2bcd8739ae039 = class {\\n /**\\n * Adds the given features to the last stage.\\n * Ignores features that have already been applied.\\n */\\n _addFeatures(features, global) {\\n let stageIndex = this.stages.length - 1;\\n let stage = this.stages[stageIndex];\\n for (let feature of features) if (this.allFeatures[feature] == null) {\\n stage.push(feature);\\n this.allFeatures[feature] = stageIndex;\\n if (global) this.globalFeatures[feature] = true;\\n }\\n }\\n /**\\n * Add features to the last stage\\n */\\n add(arg, global = true) {\\n if (this.stages.length === 0) this.stages.push([]);\\n if (typeof arg === \\\"string\\\") arg = [\\n arg\\n ];\\n if (Array.isArray(arg)) this._addFeatures(arg, global);\\n else if (typeof arg === \\\"object\\\") {\\n this._addFeatures(arg.global || [], true);\\n this._addFeatures(arg.local || [], false);\\n } else throw new Error(\\\"Unsupported argument to ShapingPlan#add\\\");\\n }\\n /**\\n * Add a new stage\\n */\\n addStage(arg, global) {\\n if (typeof arg === \\\"function\\\") this.stages.push(arg, []);\\n else {\\n this.stages.push([]);\\n this.add(arg, global);\\n }\\n }\\n setFeatureOverrides(features) {\\n if (Array.isArray(features)) this.add(features);\\n else if (typeof features === \\\"object\\\") for (let tag in features) {\\n if (features[tag]) this.add(tag);\\n else if (this.allFeatures[tag] != null) {\\n let stage = this.stages[this.allFeatures[tag]];\\n stage.splice(stage.indexOf(tag), 1);\\n delete this.allFeatures[tag];\\n delete this.globalFeatures[tag];\\n }\\n }\\n }\\n /**\\n * Assigns the global features to the given glyphs\\n */\\n assignGlobalFeatures(glyphs) {\\n for (let glyph of glyphs) for (let feature in this.globalFeatures) glyph.features[feature] = true;\\n }\\n /**\\n * Executes the planned stages using the given OTProcessor\\n */\\n process(processor, glyphs, positions) {\\n for (let stage of this.stages) {\\n if (typeof stage === \\\"function\\\") {\\n if (!positions) stage(this.font, glyphs, this);\\n } else if (stage.length > 0) processor.applyFeatures(stage, glyphs, positions);\\n }\\n }\\n constructor(font, script, direction) {\\n this.font = font;\\n this.script = script;\\n this.direction = direction;\\n this.stages = [];\\n this.globalFeatures = {};\\n this.allFeatures = {};\\n }\\n };\\n $649970d87335b30f$var$VARIATION_FEATURES = [\\n \\\"rvrn\\\"\\n ];\\n $649970d87335b30f$var$COMMON_FEATURES = [\\n \\\"ccmp\\\",\\n \\\"locl\\\",\\n \\\"rlig\\\",\\n \\\"mark\\\",\\n \\\"mkmk\\\"\\n ];\\n $649970d87335b30f$var$FRACTIONAL_FEATURES = [\\n \\\"frac\\\",\\n \\\"numr\\\",\\n \\\"dnom\\\"\\n ];\\n $649970d87335b30f$var$HORIZONTAL_FEATURES = [\\n \\\"calt\\\",\\n \\\"clig\\\",\\n \\\"liga\\\",\\n \\\"rclt\\\",\\n \\\"curs\\\",\\n \\\"kern\\\"\\n ];\\n $649970d87335b30f$var$DIRECTIONAL_FEATURES = {\\n ltr: [\\n \\\"ltra\\\",\\n \\\"ltrm\\\"\\n ],\\n rtl: [\\n \\\"rtla\\\",\\n \\\"rtlm\\\"\\n ]\\n };\\n $649970d87335b30f$export$2e2bcd8739ae039 = class {\\n static plan(plan, glyphs, features) {\\n this.planPreprocessing(plan);\\n this.planFeatures(plan);\\n this.planPostprocessing(plan, features);\\n plan.assignGlobalFeatures(glyphs);\\n this.assignFeatures(plan, glyphs);\\n }\\n static planPreprocessing(plan) {\\n plan.add({\\n global: [\\n ...$649970d87335b30f$var$VARIATION_FEATURES,\\n ...$649970d87335b30f$var$DIRECTIONAL_FEATURES[plan.direction]\\n ],\\n local: $649970d87335b30f$var$FRACTIONAL_FEATURES\\n });\\n }\\n static planFeatures(plan) {\\n }\\n static planPostprocessing(plan, userFeatures) {\\n plan.add([\\n ...$649970d87335b30f$var$COMMON_FEATURES,\\n ...$649970d87335b30f$var$HORIZONTAL_FEATURES\\n ]);\\n plan.setFeatureOverrides(userFeatures);\\n }\\n static assignFeatures(plan, glyphs) {\\n for (let i = 0; i < glyphs.length; i++) {\\n let glyph = glyphs[i];\\n if (glyph.codePoints[0] === 8260) {\\n let start = i;\\n let end = i + 1;\\n while (start > 0 && (0, $747425b437e121da$export$727d9dbc4fbb948f)(glyphs[start - 1].codePoints[0])) {\\n glyphs[start - 1].features.numr = true;\\n glyphs[start - 1].features.frac = true;\\n start--;\\n }\\n while (end < glyphs.length && (0, $747425b437e121da$export$727d9dbc4fbb948f)(glyphs[end].codePoints[0])) {\\n glyphs[end].features.dnom = true;\\n glyphs[end].features.frac = true;\\n end++;\\n }\\n glyph.features.frac = true;\\n i = end - 1;\\n }\\n }\\n }\\n };\\n (0, _define_property)($649970d87335b30f$export$2e2bcd8739ae039, \\\"zeroMarkWidths\\\", \\\"AFTER_GPOS\\\");\\n $764eb544bbe1ccf0$var$trie = new (0, import_unicode_trie2.default)((0, $12727730ddfc8bfe$export$94fdf11bafc8de6b)(\\\"APABAAAAAAAAOAAAAf0BAv7tmi1MxDAUx7vtvjhAgcDgkEgEAnmXEBIMCYaEcygEiqBQ4FAkCE4ikUgMiiBJSAgSiUQSDMn9L9eSl6bddddug9t7yS/trevre+3r27pcNxZiG+yCfdCVv/9LeQxOwRm4AJegD27ALbgD9+ABPJF+z+BN/h7yDj5k/VOWX6SdmU5+wLWknggxDxaS8u0qiiX4uiz9XamQ3wzDMAzDMAzDMAzDVI/h959V/v7BMAzDMAzDMLlyNTNiMSdewVxbiA44B4/guz1qW58VYlMI0WsJ0W+N6kXw0spvPtdwhtkwnGM6uLaV4Xyzg3v3PM9DPfQ/sOg4xPWjipy31P8LTqbU304c/cLCUmWJLNB2Uz2U1KTeRKNmKHVMfbJC+/0loTZRH/W5cvEvBJPMbREkWt3FD1NcqXZBSpuE2Ad0PBehPtNrPtIEdYP+hiRt/V1jIiE69X4NT/uVZI3PUHE9bm5M7ePGdZWy951v7Nn6j8v1WWKP3mt6ttnsigx6VN7Vc0VomSSGqW2mGNP1muZPl7LfjNUaKNFtDGVf2fvE9O7VlBS5j333c5p/eeoOqcs1R/hIqDWLJ7TTlksirVT1SI7l8k4Yp+g3jafGcrU1RM6l9th80XOpnlN97bDNY4i4s61B0Si/ipa0uHMl6zqEjlFfCZm/TM8KmzQDjmuTAQ==\\\"));\\n $764eb544bbe1ccf0$var$FEATURES = [\\n \\\"isol\\\",\\n \\\"fina\\\",\\n \\\"fin2\\\",\\n \\\"fin3\\\",\\n \\\"medi\\\",\\n \\\"med2\\\",\\n \\\"init\\\"\\n ];\\n $764eb544bbe1ccf0$var$ShapingClasses = {\\n Non_Joining: 0,\\n Left_Joining: 1,\\n Right_Joining: 2,\\n Dual_Joining: 3,\\n Join_Causing: 3,\\n ALAPH: 4,\\n \\\"DALATH RISH\\\": 5,\\n Transparent: 6\\n };\\n $764eb544bbe1ccf0$var$ISOL = \\\"isol\\\";\\n $764eb544bbe1ccf0$var$FINA = \\\"fina\\\";\\n $764eb544bbe1ccf0$var$FIN2 = \\\"fin2\\\";\\n $764eb544bbe1ccf0$var$FIN3 = \\\"fin3\\\";\\n $764eb544bbe1ccf0$var$MEDI = \\\"medi\\\";\\n $764eb544bbe1ccf0$var$MED2 = \\\"med2\\\";\\n $764eb544bbe1ccf0$var$INIT = \\\"init\\\";\\n $764eb544bbe1ccf0$var$NONE = null;\\n $764eb544bbe1ccf0$var$STATE_TABLE = [\\n // Non_Joining, Left_Joining, Right_Joining, Dual_Joining, ALAPH, DALATH RISH\\n // State 0: prev was U, not willing to join.\\n [\\n [\\n $764eb544bbe1ccf0$var$NONE,\\n $764eb544bbe1ccf0$var$NONE,\\n 0\\n ],\\n [\\n $764eb544bbe1ccf0$var$NONE,\\n $764eb544bbe1ccf0$var$ISOL,\\n 2\\n ],\\n [\\n $764eb544bbe1ccf0$var$NONE,\\n $764eb544bbe1ccf0$var$ISOL,\\n 1\\n ],\\n [\\n $764eb544bbe1ccf0$var$NONE,\\n $764eb544bbe1ccf0$var$ISOL,\\n 2\\n ],\\n [\\n $764eb544bbe1ccf0$var$NONE,\\n $764eb544bbe1ccf0$var$ISOL,\\n 1\\n ],\\n [\\n $764eb544bbe1ccf0$var$NONE,\\n $764eb544bbe1ccf0$var$ISOL,\\n 6\\n ]\\n ],\\n // State 1: prev was R or ISOL/ALAPH, not willing to join.\\n [\\n [\\n $764eb544bbe1ccf0$var$NONE,\\n $764eb544bbe1ccf0$var$NONE,\\n 0\\n ],\\n [\\n $764eb544bbe1ccf0$var$NONE,\\n $764eb544bbe1ccf0$var$ISOL,\\n 2\\n ],\\n [\\n $764eb544bbe1ccf0$var$NONE,\\n $764eb544bbe1ccf0$var$ISOL,\\n 1\\n ],\\n [\\n $764eb544bbe1ccf0$var$NONE,\\n $764eb544bbe1ccf0$var$ISOL,\\n 2\\n ],\\n [\\n $764eb544bbe1ccf0$var$NONE,\\n $764eb544bbe1ccf0$var$FIN2,\\n 5\\n ],\\n [\\n $764eb544bbe1ccf0$var$NONE,\\n $764eb544bbe1ccf0$var$ISOL,\\n 6\\n ]\\n ],\\n // State 2: prev was D/L in ISOL form, willing to join.\\n [\\n [\\n $764eb544bbe1ccf0$var$NONE,\\n $764eb544bbe1ccf0$var$NONE,\\n 0\\n ],\\n [\\n $764eb544bbe1ccf0$var$NONE,\\n $764eb544bbe1ccf0$var$ISOL,\\n 2\\n ],\\n [\\n $764eb544bbe1ccf0$var$INIT,\\n $764eb544bbe1ccf0$var$FINA,\\n 1\\n ],\\n [\\n $764eb544bbe1ccf0$var$INIT,\\n $764eb544bbe1ccf0$var$FINA,\\n 3\\n ],\\n [\\n $764eb544bbe1ccf0$var$INIT,\\n $764eb544bbe1ccf0$var$FINA,\\n 4\\n ],\\n [\\n $764eb544bbe1ccf0$var$INIT,\\n $764eb544bbe1ccf0$var$FINA,\\n 6\\n ]\\n ],\\n // State 3: prev was D in FINA form, willing to join.\\n [\\n [\\n $764eb544bbe1ccf0$var$NONE,\\n $764eb544bbe1ccf0$var$NONE,\\n 0\\n ],\\n [\\n $764eb544bbe1ccf0$var$NONE,\\n $764eb544bbe1ccf0$var$ISOL,\\n 2\\n ],\\n [\\n $764eb544bbe1ccf0$var$MEDI,\\n $764eb544bbe1ccf0$var$FINA,\\n 1\\n ],\\n [\\n $764eb544bbe1ccf0$var$MEDI,\\n $764eb544bbe1ccf0$var$FINA,\\n 3\\n ],\\n [\\n $764eb544bbe1ccf0$var$MEDI,\\n $764eb544bbe1ccf0$var$FINA,\\n 4\\n ],\\n [\\n $764eb544bbe1ccf0$var$MEDI,\\n $764eb544bbe1ccf0$var$FINA,\\n 6\\n ]\\n ],\\n // State 4: prev was FINA ALAPH, not willing to join.\\n [\\n [\\n $764eb544bbe1ccf0$var$NONE,\\n $764eb544bbe1ccf0$var$NONE,\\n 0\\n ],\\n [\\n $764eb544bbe1ccf0$var$NONE,\\n $764eb544bbe1ccf0$var$ISOL,\\n 2\\n ],\\n [\\n $764eb544bbe1ccf0$var$MED2,\\n $764eb544bbe1ccf0$var$ISOL,\\n 1\\n ],\\n [\\n $764eb544bbe1ccf0$var$MED2,\\n $764eb544bbe1ccf0$var$ISOL,\\n 2\\n ],\\n [\\n $764eb544bbe1ccf0$var$MED2,\\n $764eb544bbe1ccf0$var$FIN2,\\n 5\\n ],\\n [\\n $764eb544bbe1ccf0$var$MED2,\\n $764eb544bbe1ccf0$var$ISOL,\\n 6\\n ]\\n ],\\n // State 5: prev was FIN2/FIN3 ALAPH, not willing to join.\\n [\\n [\\n $764eb544bbe1ccf0$var$NONE,\\n $764eb544bbe1ccf0$var$NONE,\\n 0\\n ],\\n [\\n $764eb544bbe1ccf0$var$NONE,\\n $764eb544bbe1ccf0$var$ISOL,\\n 2\\n ],\\n [\\n $764eb544bbe1ccf0$var$ISOL,\\n $764eb544bbe1ccf0$var$ISOL,\\n 1\\n ],\\n [\\n $764eb544bbe1ccf0$var$ISOL,\\n $764eb544bbe1ccf0$var$ISOL,\\n 2\\n ],\\n [\\n $764eb544bbe1ccf0$var$ISOL,\\n $764eb544bbe1ccf0$var$FIN2,\\n 5\\n ],\\n [\\n $764eb544bbe1ccf0$var$ISOL,\\n $764eb544bbe1ccf0$var$ISOL,\\n 6\\n ]\\n ],\\n // State 6: prev was DALATH/RISH, not willing to join.\\n [\\n [\\n $764eb544bbe1ccf0$var$NONE,\\n $764eb544bbe1ccf0$var$NONE,\\n 0\\n ],\\n [\\n $764eb544bbe1ccf0$var$NONE,\\n $764eb544bbe1ccf0$var$ISOL,\\n 2\\n ],\\n [\\n $764eb544bbe1ccf0$var$NONE,\\n $764eb544bbe1ccf0$var$ISOL,\\n 1\\n ],\\n [\\n $764eb544bbe1ccf0$var$NONE,\\n $764eb544bbe1ccf0$var$ISOL,\\n 2\\n ],\\n [\\n $764eb544bbe1ccf0$var$NONE,\\n $764eb544bbe1ccf0$var$FIN3,\\n 5\\n ],\\n [\\n $764eb544bbe1ccf0$var$NONE,\\n $764eb544bbe1ccf0$var$ISOL,\\n 6\\n ]\\n ]\\n ];\\n $764eb544bbe1ccf0$export$2e2bcd8739ae039 = class extends (0, $649970d87335b30f$export$2e2bcd8739ae039) {\\n static planFeatures(plan) {\\n plan.add([\\n \\\"ccmp\\\",\\n \\\"locl\\\"\\n ]);\\n for (let i = 0; i < $764eb544bbe1ccf0$var$FEATURES.length; i++) {\\n let feature = $764eb544bbe1ccf0$var$FEATURES[i];\\n plan.addStage(feature, false);\\n }\\n plan.addStage(\\\"mset\\\");\\n }\\n static assignFeatures(plan, glyphs) {\\n super.assignFeatures(plan, glyphs);\\n let prev = -1;\\n let state = 0;\\n let actions = [];\\n for (let i = 0; i < glyphs.length; i++) {\\n let curAction, prevAction;\\n var glyph = glyphs[i];\\n let type = $764eb544bbe1ccf0$var$getShapingClass(glyph.codePoints[0]);\\n if (type === $764eb544bbe1ccf0$var$ShapingClasses.Transparent) {\\n actions[i] = $764eb544bbe1ccf0$var$NONE;\\n continue;\\n }\\n [prevAction, curAction, state] = $764eb544bbe1ccf0$var$STATE_TABLE[state][type];\\n if (prevAction !== $764eb544bbe1ccf0$var$NONE && prev !== -1) actions[prev] = prevAction;\\n actions[i] = curAction;\\n prev = i;\\n }\\n for (let index = 0; index < glyphs.length; index++) {\\n let feature;\\n var glyph = glyphs[index];\\n if (feature = actions[index]) glyph.features[feature] = true;\\n }\\n }\\n };\\n $85d408632270248b$export$2e2bcd8739ae039 = class {\\n reset(options = {}, index = 0) {\\n this.options = options;\\n this.flags = options.flags || {};\\n this.markAttachmentType = options.markAttachmentType || 0;\\n this.index = index;\\n }\\n get cur() {\\n return this.glyphs[this.index] || null;\\n }\\n shouldIgnore(glyph) {\\n return this.flags.ignoreMarks && glyph.isMark || this.flags.ignoreBaseGlyphs && glyph.isBase || this.flags.ignoreLigatures && glyph.isLigature || this.markAttachmentType && glyph.isMark && glyph.markAttachmentType !== this.markAttachmentType;\\n }\\n move(dir) {\\n this.index += dir;\\n while (0 <= this.index && this.index < this.glyphs.length && this.shouldIgnore(this.glyphs[this.index])) this.index += dir;\\n if (0 > this.index || this.index >= this.glyphs.length) return null;\\n return this.glyphs[this.index];\\n }\\n next() {\\n return this.move(1);\\n }\\n prev() {\\n return this.move(-1);\\n }\\n peek(count = 1) {\\n let idx = this.index;\\n let res = this.increment(count);\\n this.index = idx;\\n return res;\\n }\\n peekIndex(count = 1) {\\n let idx = this.index;\\n this.increment(count);\\n let res = this.index;\\n this.index = idx;\\n return res;\\n }\\n increment(count = 1) {\\n let dir = count < 0 ? -1 : 1;\\n count = Math.abs(count);\\n while (count--) this.move(dir);\\n return this.glyphs[this.index];\\n }\\n constructor(glyphs, options) {\\n this.glyphs = glyphs;\\n this.reset(options);\\n }\\n };\\n $a83b9c36aaa94fd3$var$DEFAULT_SCRIPTS = [\\n \\\"DFLT\\\",\\n \\\"dflt\\\",\\n \\\"latn\\\"\\n ];\\n $a83b9c36aaa94fd3$export$2e2bcd8739ae039 = class {\\n findScript(script) {\\n if (this.table.scriptList == null) return null;\\n if (!Array.isArray(script)) script = [\\n script\\n ];\\n for (let s of script) for (let entry of this.table.scriptList) {\\n if (entry.tag === s) return entry;\\n }\\n return null;\\n }\\n selectScript(script, language, direction) {\\n let changed = false;\\n let entry;\\n if (!this.script || script !== this.scriptTag) {\\n entry = this.findScript(script);\\n if (!entry) entry = this.findScript($a83b9c36aaa94fd3$var$DEFAULT_SCRIPTS);\\n if (!entry) return this.scriptTag;\\n this.scriptTag = entry.tag;\\n this.script = entry.script;\\n this.language = null;\\n this.languageTag = null;\\n changed = true;\\n }\\n if (!direction || direction !== this.direction) this.direction = direction || $130d1a642ebcd2b7$export$9fddb9d0dd7d8a54(script);\\n if (language && language.length < 4) language += \\\" \\\".repeat(4 - language.length);\\n if (!language || language !== this.languageTag) {\\n this.language = null;\\n for (let lang of this.script.langSysRecords) if (lang.tag === language) {\\n this.language = lang.langSys;\\n this.languageTag = lang.tag;\\n break;\\n }\\n if (!this.language) {\\n this.language = this.script.defaultLangSys;\\n this.languageTag = null;\\n }\\n changed = true;\\n }\\n if (changed) {\\n this.features = {};\\n if (this.language) for (let featureIndex of this.language.featureIndexes) {\\n let record = this.table.featureList[featureIndex];\\n let substituteFeature = this.substituteFeatureForVariations(featureIndex);\\n this.features[record.tag] = substituteFeature || record.feature;\\n }\\n }\\n return this.scriptTag;\\n }\\n lookupsForFeatures(userFeatures = [], exclude) {\\n let lookups = [];\\n for (let tag of userFeatures) {\\n let feature = this.features[tag];\\n if (!feature) continue;\\n for (let lookupIndex of feature.lookupListIndexes) {\\n if (exclude && exclude.indexOf(lookupIndex) !== -1) continue;\\n lookups.push({\\n feature: tag,\\n index: lookupIndex,\\n lookup: this.table.lookupList.get(lookupIndex)\\n });\\n }\\n }\\n lookups.sort((a, b) => a.index - b.index);\\n return lookups;\\n }\\n substituteFeatureForVariations(featureIndex) {\\n if (this.variationsIndex === -1) return null;\\n let record = this.table.featureVariations.featureVariationRecords[this.variationsIndex];\\n let substitutions = record.featureTableSubstitution.substitutions;\\n for (let substitution of substitutions) {\\n if (substitution.featureIndex === featureIndex) return substitution.alternateFeatureTable;\\n }\\n return null;\\n }\\n findVariationsIndex(coords) {\\n let variations = this.table.featureVariations;\\n if (!variations) return -1;\\n let records = variations.featureVariationRecords;\\n for (let i = 0; i < records.length; i++) {\\n let conditions = records[i].conditionSet.conditionTable;\\n if (this.variationConditionsMatch(conditions, coords)) return i;\\n }\\n return -1;\\n }\\n variationConditionsMatch(conditions, coords) {\\n return conditions.every((condition) => {\\n let coord = condition.axisIndex < coords.length ? coords[condition.axisIndex] : 0;\\n return condition.filterRangeMinValue <= coord && coord <= condition.filterRangeMaxValue;\\n });\\n }\\n applyFeatures(userFeatures, glyphs, advances) {\\n let lookups = this.lookupsForFeatures(userFeatures);\\n this.applyLookups(lookups, glyphs, advances);\\n }\\n applyLookups(lookups, glyphs, positions) {\\n this.glyphs = glyphs;\\n this.positions = positions;\\n this.glyphIterator = new (0, $85d408632270248b$export$2e2bcd8739ae039)(glyphs);\\n for (let { feature, lookup } of lookups) {\\n this.currentFeature = feature;\\n this.glyphIterator.reset(lookup.flags);\\n while (this.glyphIterator.index < glyphs.length) {\\n if (!(feature in this.glyphIterator.cur.features)) {\\n this.glyphIterator.next();\\n continue;\\n }\\n for (let table of lookup.subTables) {\\n let res = this.applyLookup(lookup.lookupType, table);\\n if (res) break;\\n }\\n this.glyphIterator.next();\\n }\\n }\\n }\\n applyLookup(lookup, table) {\\n throw new Error(\\\"applyLookup must be implemented by subclasses\\\");\\n }\\n applyLookupList(lookupRecords) {\\n let options = this.glyphIterator.options;\\n let glyphIndex = this.glyphIterator.index;\\n for (let lookupRecord of lookupRecords) {\\n this.glyphIterator.reset(options, glyphIndex);\\n this.glyphIterator.increment(lookupRecord.sequenceIndex);\\n let lookup = this.table.lookupList.get(lookupRecord.lookupListIndex);\\n this.glyphIterator.reset(lookup.flags, this.glyphIterator.index);\\n for (let table of lookup.subTables) {\\n if (this.applyLookup(lookup.lookupType, table)) break;\\n }\\n }\\n this.glyphIterator.reset(options, glyphIndex);\\n return true;\\n }\\n coverageIndex(coverage, glyph) {\\n if (glyph == null) glyph = this.glyphIterator.cur.id;\\n switch (coverage.version) {\\n case 1:\\n return coverage.glyphs.indexOf(glyph);\\n case 2:\\n for (let range of coverage.rangeRecords) {\\n if (range.start <= glyph && glyph <= range.end) return range.startCoverageIndex + glyph - range.start;\\n }\\n break;\\n }\\n return -1;\\n }\\n match(sequenceIndex, sequence, fn, matched) {\\n let pos = this.glyphIterator.index;\\n let glyph = this.glyphIterator.increment(sequenceIndex);\\n let idx = 0;\\n while (idx < sequence.length && glyph && fn(sequence[idx], glyph)) {\\n if (matched) matched.push(this.glyphIterator.index);\\n idx++;\\n glyph = this.glyphIterator.next();\\n }\\n this.glyphIterator.index = pos;\\n if (idx < sequence.length) return false;\\n return matched || true;\\n }\\n sequenceMatches(sequenceIndex, sequence) {\\n return this.match(sequenceIndex, sequence, (component, glyph) => component === glyph.id);\\n }\\n sequenceMatchIndices(sequenceIndex, sequence) {\\n return this.match(sequenceIndex, sequence, (component, glyph) => {\\n if (!(this.currentFeature in glyph.features)) return false;\\n return component === glyph.id;\\n }, []);\\n }\\n coverageSequenceMatches(sequenceIndex, sequence) {\\n return this.match(sequenceIndex, sequence, (coverage, glyph) => this.coverageIndex(coverage, glyph.id) >= 0);\\n }\\n getClassID(glyph, classDef) {\\n switch (classDef.version) {\\n case 1:\\n let i = glyph - classDef.startGlyph;\\n if (i >= 0 && i < classDef.classValueArray.length) return classDef.classValueArray[i];\\n break;\\n case 2:\\n for (let range of classDef.classRangeRecord) {\\n if (range.start <= glyph && glyph <= range.end) return range.class;\\n }\\n break;\\n }\\n return 0;\\n }\\n classSequenceMatches(sequenceIndex, sequence, classDef) {\\n return this.match(sequenceIndex, sequence, (classID, glyph) => classID === this.getClassID(glyph.id, classDef));\\n }\\n applyContext(table) {\\n let index, set;\\n switch (table.version) {\\n case 1:\\n index = this.coverageIndex(table.coverage);\\n if (index === -1) return false;\\n set = table.ruleSets[index];\\n for (let rule of set) {\\n if (this.sequenceMatches(1, rule.input)) return this.applyLookupList(rule.lookupRecords);\\n }\\n break;\\n case 2:\\n if (this.coverageIndex(table.coverage) === -1) return false;\\n index = this.getClassID(this.glyphIterator.cur.id, table.classDef);\\n if (index === -1) return false;\\n set = table.classSet[index];\\n for (let rule of set) {\\n if (this.classSequenceMatches(1, rule.classes, table.classDef)) return this.applyLookupList(rule.lookupRecords);\\n }\\n break;\\n case 3:\\n if (this.coverageSequenceMatches(0, table.coverages)) return this.applyLookupList(table.lookupRecords);\\n break;\\n }\\n return false;\\n }\\n applyChainingContext(table) {\\n let index;\\n switch (table.version) {\\n case 1:\\n index = this.coverageIndex(table.coverage);\\n if (index === -1) return false;\\n let set = table.chainRuleSets[index];\\n for (let rule of set) {\\n if (this.sequenceMatches(-rule.backtrack.length, rule.backtrack) && this.sequenceMatches(1, rule.input) && this.sequenceMatches(1 + rule.input.length, rule.lookahead)) return this.applyLookupList(rule.lookupRecords);\\n }\\n break;\\n case 2:\\n if (this.coverageIndex(table.coverage) === -1) return false;\\n index = this.getClassID(this.glyphIterator.cur.id, table.inputClassDef);\\n let rules = table.chainClassSet[index];\\n if (!rules) return false;\\n for (let rule of rules) {\\n if (this.classSequenceMatches(-rule.backtrack.length, rule.backtrack, table.backtrackClassDef) && this.classSequenceMatches(1, rule.input, table.inputClassDef) && this.classSequenceMatches(1 + rule.input.length, rule.lookahead, table.lookaheadClassDef)) return this.applyLookupList(rule.lookupRecords);\\n }\\n break;\\n case 3:\\n if (this.coverageSequenceMatches(-table.backtrackGlyphCount, table.backtrackCoverage) && this.coverageSequenceMatches(0, table.inputCoverage) && this.coverageSequenceMatches(table.inputGlyphCount, table.lookaheadCoverage)) return this.applyLookupList(table.lookupRecords);\\n break;\\n }\\n return false;\\n }\\n constructor(font, table) {\\n this.font = font;\\n this.table = table;\\n this.script = null;\\n this.scriptTag = null;\\n this.language = null;\\n this.languageTag = null;\\n this.features = {};\\n this.lookups = {};\\n this.variationsIndex = font._variationProcessor ? this.findVariationsIndex(font._variationProcessor.normalizedCoords) : -1;\\n this.selectScript();\\n this.glyphs = [];\\n this.positions = [];\\n this.ligatureID = 1;\\n this.currentFeature = null;\\n }\\n };\\n $10e7b257e1a9a756$export$2e2bcd8739ae039 = class _$10e7b257e1a9a756$export$2e2bcd8739ae039 {\\n get id() {\\n return this._id;\\n }\\n set id(id) {\\n this._id = id;\\n this.substituted = true;\\n let GDEF = this._font.GDEF;\\n if (GDEF && GDEF.glyphClassDef) {\\n let classID = (0, $a83b9c36aaa94fd3$export$2e2bcd8739ae039).prototype.getClassID(id, GDEF.glyphClassDef);\\n this.isBase = classID === 1;\\n this.isLigature = classID === 2;\\n this.isMark = classID === 3;\\n this.markAttachmentType = GDEF.markAttachClassDef ? (0, $a83b9c36aaa94fd3$export$2e2bcd8739ae039).prototype.getClassID(id, GDEF.markAttachClassDef) : 0;\\n } else {\\n this.isMark = this.codePoints.length > 0 && this.codePoints.every((0, $747425b437e121da$export$e33ad6871e762338));\\n this.isBase = !this.isMark;\\n this.isLigature = this.codePoints.length > 1;\\n this.markAttachmentType = 0;\\n }\\n }\\n copy() {\\n return new _$10e7b257e1a9a756$export$2e2bcd8739ae039(this._font, this.id, this.codePoints, this.features);\\n }\\n constructor(font, id, codePoints = [], features) {\\n this._font = font;\\n this.codePoints = codePoints;\\n this.id = id;\\n this.features = {};\\n if (Array.isArray(features)) for (let i = 0; i < features.length; i++) {\\n let feature = features[i];\\n this.features[feature] = true;\\n }\\n else if (typeof features === \\\"object\\\") Object.assign(this.features, features);\\n this.ligatureID = null;\\n this.ligatureComponent = null;\\n this.isLigated = false;\\n this.cursiveAttachment = null;\\n this.markAttachment = null;\\n this.shaperInfo = null;\\n this.substituted = false;\\n this.isMultiplied = false;\\n }\\n };\\n $e1c6bbc8cb416f8c$export$2e2bcd8739ae039 = class extends (0, $649970d87335b30f$export$2e2bcd8739ae039) {\\n static planFeatures(plan) {\\n plan.add([\\n \\\"ljmo\\\",\\n \\\"vjmo\\\",\\n \\\"tjmo\\\"\\n ], false);\\n }\\n static assignFeatures(plan, glyphs) {\\n let state = 0;\\n let i = 0;\\n while (i < glyphs.length) {\\n let action;\\n let glyph = glyphs[i];\\n let code = glyph.codePoints[0];\\n let type = $e1c6bbc8cb416f8c$var$getType(code);\\n [action, state] = $e1c6bbc8cb416f8c$var$STATE_TABLE[state][type];\\n switch (action) {\\n case $e1c6bbc8cb416f8c$var$DECOMPOSE:\\n if (!plan.font.hasGlyphForCodePoint(code)) i = $e1c6bbc8cb416f8c$var$decompose(glyphs, i, plan.font);\\n break;\\n case $e1c6bbc8cb416f8c$var$COMPOSE:\\n i = $e1c6bbc8cb416f8c$var$compose(glyphs, i, plan.font);\\n break;\\n case $e1c6bbc8cb416f8c$var$TONE_MARK:\\n $e1c6bbc8cb416f8c$var$reorderToneMark(glyphs, i, plan.font);\\n break;\\n case $e1c6bbc8cb416f8c$var$INVALID:\\n i = $e1c6bbc8cb416f8c$var$insertDottedCircle(glyphs, i, plan.font);\\n break;\\n }\\n i++;\\n }\\n }\\n };\\n (0, _define_property)($e1c6bbc8cb416f8c$export$2e2bcd8739ae039, \\\"zeroMarkWidths\\\", \\\"NONE\\\");\\n $e1c6bbc8cb416f8c$var$HANGUL_BASE = 44032;\\n $e1c6bbc8cb416f8c$var$HANGUL_END = 55204;\\n $e1c6bbc8cb416f8c$var$HANGUL_COUNT = $e1c6bbc8cb416f8c$var$HANGUL_END - $e1c6bbc8cb416f8c$var$HANGUL_BASE + 1;\\n $e1c6bbc8cb416f8c$var$L_BASE = 4352;\\n $e1c6bbc8cb416f8c$var$V_BASE = 4449;\\n $e1c6bbc8cb416f8c$var$T_BASE = 4519;\\n $e1c6bbc8cb416f8c$var$L_COUNT = 19;\\n $e1c6bbc8cb416f8c$var$V_COUNT = 21;\\n $e1c6bbc8cb416f8c$var$T_COUNT = 28;\\n $e1c6bbc8cb416f8c$var$L_END = $e1c6bbc8cb416f8c$var$L_BASE + $e1c6bbc8cb416f8c$var$L_COUNT - 1;\\n $e1c6bbc8cb416f8c$var$V_END = $e1c6bbc8cb416f8c$var$V_BASE + $e1c6bbc8cb416f8c$var$V_COUNT - 1;\\n $e1c6bbc8cb416f8c$var$T_END = $e1c6bbc8cb416f8c$var$T_BASE + $e1c6bbc8cb416f8c$var$T_COUNT - 1;\\n $e1c6bbc8cb416f8c$var$DOTTED_CIRCLE = 9676;\\n $e1c6bbc8cb416f8c$var$isL = (code) => 4352 <= code && code <= 4447 || 43360 <= code && code <= 43388;\\n $e1c6bbc8cb416f8c$var$isV = (code) => 4448 <= code && code <= 4519 || 55216 <= code && code <= 55238;\\n $e1c6bbc8cb416f8c$var$isT = (code) => 4520 <= code && code <= 4607 || 55243 <= code && code <= 55291;\\n $e1c6bbc8cb416f8c$var$isTone = (code) => 12334 <= code && code <= 12335;\\n $e1c6bbc8cb416f8c$var$isLVT = (code) => $e1c6bbc8cb416f8c$var$HANGUL_BASE <= code && code <= $e1c6bbc8cb416f8c$var$HANGUL_END;\\n $e1c6bbc8cb416f8c$var$isLV = (code) => code - $e1c6bbc8cb416f8c$var$HANGUL_BASE < $e1c6bbc8cb416f8c$var$HANGUL_COUNT && (code - $e1c6bbc8cb416f8c$var$HANGUL_BASE) % $e1c6bbc8cb416f8c$var$T_COUNT === 0;\\n $e1c6bbc8cb416f8c$var$isCombiningL = (code) => $e1c6bbc8cb416f8c$var$L_BASE <= code && code <= $e1c6bbc8cb416f8c$var$L_END;\\n $e1c6bbc8cb416f8c$var$isCombiningV = (code) => $e1c6bbc8cb416f8c$var$V_BASE <= code && code <= $e1c6bbc8cb416f8c$var$V_END;\\n $e1c6bbc8cb416f8c$var$isCombiningT = (code) => $e1c6bbc8cb416f8c$var$T_BASE + 1 && 1 <= code && code <= $e1c6bbc8cb416f8c$var$T_END;\\n $e1c6bbc8cb416f8c$var$X = 0;\\n $e1c6bbc8cb416f8c$var$L = 1;\\n $e1c6bbc8cb416f8c$var$V = 2;\\n $e1c6bbc8cb416f8c$var$T = 3;\\n $e1c6bbc8cb416f8c$var$LV = 4;\\n $e1c6bbc8cb416f8c$var$LVT = 5;\\n $e1c6bbc8cb416f8c$var$M = 6;\\n $e1c6bbc8cb416f8c$var$NO_ACTION = 0;\\n $e1c6bbc8cb416f8c$var$DECOMPOSE = 1;\\n $e1c6bbc8cb416f8c$var$COMPOSE = 2;\\n $e1c6bbc8cb416f8c$var$TONE_MARK = 4;\\n $e1c6bbc8cb416f8c$var$INVALID = 5;\\n $e1c6bbc8cb416f8c$var$STATE_TABLE = [\\n // X L V T LV LVT M\\n // State 0: start state\\n [\\n [\\n $e1c6bbc8cb416f8c$var$NO_ACTION,\\n 0\\n ],\\n [\\n $e1c6bbc8cb416f8c$var$NO_ACTION,\\n 1\\n ],\\n [\\n $e1c6bbc8cb416f8c$var$NO_ACTION,\\n 0\\n ],\\n [\\n $e1c6bbc8cb416f8c$var$NO_ACTION,\\n 0\\n ],\\n [\\n $e1c6bbc8cb416f8c$var$DECOMPOSE,\\n 2\\n ],\\n [\\n $e1c6bbc8cb416f8c$var$DECOMPOSE,\\n 3\\n ],\\n [\\n $e1c6bbc8cb416f8c$var$INVALID,\\n 0\\n ]\\n ],\\n // State 1: <L>\\n [\\n [\\n $e1c6bbc8cb416f8c$var$NO_ACTION,\\n 0\\n ],\\n [\\n $e1c6bbc8cb416f8c$var$NO_ACTION,\\n 1\\n ],\\n [\\n $e1c6bbc8cb416f8c$var$COMPOSE,\\n 2\\n ],\\n [\\n $e1c6bbc8cb416f8c$var$NO_ACTION,\\n 0\\n ],\\n [\\n $e1c6bbc8cb416f8c$var$DECOMPOSE,\\n 2\\n ],\\n [\\n $e1c6bbc8cb416f8c$var$DECOMPOSE,\\n 3\\n ],\\n [\\n $e1c6bbc8cb416f8c$var$INVALID,\\n 0\\n ]\\n ],\\n // State 2: <L,V> or <LV>\\n [\\n [\\n $e1c6bbc8cb416f8c$var$NO_ACTION,\\n 0\\n ],\\n [\\n $e1c6bbc8cb416f8c$var$NO_ACTION,\\n 1\\n ],\\n [\\n $e1c6bbc8cb416f8c$var$NO_ACTION,\\n 0\\n ],\\n [\\n $e1c6bbc8cb416f8c$var$COMPOSE,\\n 3\\n ],\\n [\\n $e1c6bbc8cb416f8c$var$DECOMPOSE,\\n 2\\n ],\\n [\\n $e1c6bbc8cb416f8c$var$DECOMPOSE,\\n 3\\n ],\\n [\\n $e1c6bbc8cb416f8c$var$TONE_MARK,\\n 0\\n ]\\n ],\\n // State 3: <L,V,T> or <LVT>\\n [\\n [\\n $e1c6bbc8cb416f8c$var$NO_ACTION,\\n 0\\n ],\\n [\\n $e1c6bbc8cb416f8c$var$NO_ACTION,\\n 1\\n ],\\n [\\n $e1c6bbc8cb416f8c$var$NO_ACTION,\\n 0\\n ],\\n [\\n $e1c6bbc8cb416f8c$var$NO_ACTION,\\n 0\\n ],\\n [\\n $e1c6bbc8cb416f8c$var$DECOMPOSE,\\n 2\\n ],\\n [\\n $e1c6bbc8cb416f8c$var$DECOMPOSE,\\n 3\\n ],\\n [\\n $e1c6bbc8cb416f8c$var$TONE_MARK,\\n 0\\n ]\\n ]\\n ];\\n $4b0735ca6c692ea5$exports = {};\\n $4b0735ca6c692ea5$exports = JSON.parse('{\\\"stateTable\\\":[[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],[0,2,3,4,5,6,7,8,9,0,10,11,11,12,13,14,15,16,17],[0,0,0,18,19,20,21,22,23,0,24,0,0,25,26,0,0,27,0],[0,0,0,28,29,30,31,32,33,0,34,0,0,35,36,0,0,37,0],[0,0,0,38,5,7,7,8,9,0,10,0,0,0,13,0,0,16,0],[0,39,0,0,0,40,41,0,9,0,10,0,0,0,42,0,39,0,0],[0,0,0,0,43,44,44,8,9,0,0,0,0,12,43,0,0,0,0],[0,0,0,0,43,44,44,8,9,0,0,0,0,0,43,0,0,0,0],[0,0,0,45,46,47,48,49,9,0,10,0,0,0,42,0,0,0,0],[0,0,0,0,0,50,0,0,51,0,10,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0,52,0,0,0,0,0,0,0,0],[0,0,0,53,54,55,56,57,58,0,59,0,0,60,61,0,0,62,0],[0,0,0,4,5,7,7,8,9,0,10,0,0,0,13,0,0,16,0],[0,63,64,0,0,40,41,0,9,0,10,0,0,0,42,0,63,0,0],[0,2,3,4,5,6,7,8,9,0,10,11,11,12,13,0,2,16,0],[0,0,0,18,65,20,21,22,23,0,24,0,0,25,26,0,0,27,0],[0,0,0,0,66,67,67,8,9,0,10,0,0,0,68,0,0,0,0],[0,0,0,69,0,70,70,0,71,0,72,0,0,0,0,0,0,0,0],[0,0,0,73,19,74,74,22,23,0,24,0,0,0,26,0,0,27,0],[0,75,0,0,0,76,77,0,23,0,24,0,0,0,78,0,75,0,0],[0,0,0,0,79,80,80,22,23,0,0,0,0,25,79,0,0,0,0],[0,0,0,18,19,20,74,22,23,0,24,0,0,25,26,0,0,27,0],[0,0,0,81,82,83,84,85,23,0,24,0,0,0,78,0,0,0,0],[0,0,0,0,0,86,0,0,87,0,24,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0,88,0,0,0,0,0,0,0,0],[0,0,0,18,19,74,74,22,23,0,24,0,0,0,26,0,0,27,0],[0,89,90,0,0,76,77,0,23,0,24,0,0,0,78,0,89,0,0],[0,0,0,0,91,92,92,22,23,0,24,0,0,0,93,0,0,0,0],[0,0,0,94,29,95,31,32,33,0,34,0,0,0,36,0,0,37,0],[0,96,0,0,0,97,98,0,33,0,34,0,0,0,99,0,96,0,0],[0,0,0,0,100,101,101,32,33,0,0,0,0,35,100,0,0,0,0],[0,0,0,0,100,101,101,32,33,0,0,0,0,0,100,0,0,0,0],[0,0,0,102,103,104,105,106,33,0,34,0,0,0,99,0,0,0,0],[0,0,0,0,0,107,0,0,108,0,34,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0,109,0,0,0,0,0,0,0,0],[0,0,0,28,29,95,31,32,33,0,34,0,0,0,36,0,0,37,0],[0,110,111,0,0,97,98,0,33,0,34,0,0,0,99,0,110,0,0],[0,0,0,0,112,113,113,32,33,0,34,0,0,0,114,0,0,0,0],[0,0,0,0,5,7,7,8,9,0,10,0,0,0,13,0,0,16,0],[0,0,0,115,116,117,118,8,9,0,10,0,0,119,120,0,0,16,0],[0,0,0,0,0,121,121,0,9,0,10,0,0,0,42,0,0,0,0],[0,39,0,122,0,123,123,8,9,0,10,0,0,0,42,0,39,0,0],[0,124,64,0,0,0,0,0,0,0,0,0,0,0,0,0,124,0,0],[0,39,0,0,0,121,125,0,9,0,10,0,0,0,42,0,39,0,0],[0,0,0,0,0,126,126,8,0,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,46,47,48,49,9,0,10,0,0,0,42,0,0,0,0],[0,0,0,0,0,47,47,49,9,0,10,0,0,0,42,0,0,0,0],[0,0,0,0,0,127,127,49,9,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,128,127,127,49,9,0,0,0,0,0,0,0,0,0,0],[0,0,0,129,130,131,132,133,9,0,10,0,0,0,42,0,0,0,0],[0,0,0,0,0,0,0,0,0,0,10,0,0,0,0,0,0,0,0],[0,0,0,0,0,50,0,0,0,0,10,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0,134,0,0,0,0,0,0,0,0],[0,0,0,135,54,56,56,57,58,0,59,0,0,0,61,0,0,62,0],[0,136,0,0,0,137,138,0,58,0,59,0,0,0,139,0,136,0,0],[0,0,0,0,140,141,141,57,58,0,0,0,0,60,140,0,0,0,0],[0,0,0,0,140,141,141,57,58,0,0,0,0,0,140,0,0,0,0],[0,0,0,142,143,144,145,146,58,0,59,0,0,0,139,0,0,0,0],[0,0,0,0,0,147,0,0,148,0,59,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0,149,0,0,0,0,0,0,0,0],[0,0,0,53,54,56,56,57,58,0,59,0,0,0,61,0,0,62,0],[0,150,151,0,0,137,138,0,58,0,59,0,0,0,139,0,150,0,0],[0,0,0,0,152,153,153,57,58,0,59,0,0,0,154,0,0,0,0],[0,0,0,155,116,156,157,8,9,0,10,0,0,158,120,0,0,16,0],[0,0,0,0,0,121,121,0,9,0,10,0,0,0,0,0,0,0,0],[0,75,3,4,5,159,160,8,161,0,162,0,11,12,163,0,75,16,0],[0,0,0,0,0,40,164,0,9,0,10,0,0,0,42,0,0,0,0],[0,0,0,0,165,44,44,8,9,0,0,0,0,0,165,0,0,0,0],[0,124,64,0,0,40,164,0,9,0,10,0,0,0,42,0,124,0,0],[0,0,0,0,0,70,70,0,71,0,72,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,71,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,166,0,0,167,0,72,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0,168,0,0,0,0,0,0,0,0],[0,0,0,0,19,74,74,22,23,0,24,0,0,0,26,0,0,27,0],[0,0,0,0,79,80,80,22,23,0,0,0,0,0,79,0,0,0,0],[0,0,0,169,170,171,172,22,23,0,24,0,0,173,174,0,0,27,0],[0,0,0,0,0,175,175,0,23,0,24,0,0,0,78,0,0,0,0],[0,75,0,176,0,177,177,22,23,0,24,0,0,0,78,0,75,0,0],[0,178,90,0,0,0,0,0,0,0,0,0,0,0,0,0,178,0,0],[0,75,0,0,0,175,179,0,23,0,24,0,0,0,78,0,75,0,0],[0,0,0,0,0,180,180,22,0,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,82,83,84,85,23,0,24,0,0,0,78,0,0,0,0],[0,0,0,0,0,83,83,85,23,0,24,0,0,0,78,0,0,0,0],[0,0,0,0,0,181,181,85,23,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,182,181,181,85,23,0,0,0,0,0,0,0,0,0,0],[0,0,0,183,184,185,186,187,23,0,24,0,0,0,78,0,0,0,0],[0,0,0,0,0,0,0,0,0,0,24,0,0,0,0,0,0,0,0],[0,0,0,0,0,86,0,0,0,0,24,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0,188,0,0,0,0,0,0,0,0],[0,0,0,189,170,190,191,22,23,0,24,0,0,192,174,0,0,27,0],[0,0,0,0,0,175,175,0,23,0,24,0,0,0,0,0,0,0,0],[0,0,0,0,0,76,193,0,23,0,24,0,0,0,78,0,0,0,0],[0,0,0,0,194,80,80,22,23,0,0,0,0,0,194,0,0,0,0],[0,178,90,0,0,76,193,0,23,0,24,0,0,0,78,0,178,0,0],[0,0,0,0,29,95,31,32,33,0,34,0,0,0,36,0,0,37,0],[0,0,0,0,100,101,101,32,33,0,0,0,0,0,100,0,0,0,0],[0,0,0,195,196,197,198,32,33,0,34,0,0,199,200,0,0,37,0],[0,0,0,0,0,201,201,0,33,0,34,0,0,0,99,0,0,0,0],[0,96,0,202,0,203,203,32,33,0,34,0,0,0,99,0,96,0,0],[0,204,111,0,0,0,0,0,0,0,0,0,0,0,0,0,204,0,0],[0,96,0,0,0,201,205,0,33,0,34,0,0,0,99,0,96,0,0],[0,0,0,0,0,206,206,32,0,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,103,104,105,106,33,0,34,0,0,0,99,0,0,0,0],[0,0,0,0,0,104,104,106,33,0,34,0,0,0,99,0,0,0,0],[0,0,0,0,0,207,207,106,33,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,208,207,207,106,33,0,0,0,0,0,0,0,0,0,0],[0,0,0,209,210,211,212,213,33,0,34,0,0,0,99,0,0,0,0],[0,0,0,0,0,0,0,0,0,0,34,0,0,0,0,0,0,0,0],[0,0,0,0,0,107,0,0,0,0,34,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0,214,0,0,0,0,0,0,0,0],[0,0,0,215,196,216,217,32,33,0,34,0,0,218,200,0,0,37,0],[0,0,0,0,0,201,201,0,33,0,34,0,0,0,0,0,0,0,0],[0,0,0,0,0,97,219,0,33,0,34,0,0,0,99,0,0,0,0],[0,0,0,0,220,101,101,32,33,0,0,0,0,0,220,0,0,0,0],[0,204,111,0,0,97,219,0,33,0,34,0,0,0,99,0,204,0,0],[0,0,0,221,116,222,222,8,9,0,10,0,0,0,120,0,0,16,0],[0,223,0,0,0,40,224,0,9,0,10,0,0,0,42,0,223,0,0],[0,0,0,0,225,44,44,8,9,0,0,0,0,119,225,0,0,0,0],[0,0,0,115,116,117,222,8,9,0,10,0,0,119,120,0,0,16,0],[0,0,0,115,116,222,222,8,9,0,10,0,0,0,120,0,0,16,0],[0,226,64,0,0,40,224,0,9,0,10,0,0,0,42,0,226,0,0],[0,0,0,0,0,0,0,0,9,0,0,0,0,0,0,0,0,0,0],[0,39,0,0,0,121,121,0,9,0,10,0,0,0,42,0,39,0,0],[0,0,0,0,0,44,44,8,9,0,0,0,0,0,0,0,0,0,0],[0,0,0,227,0,228,229,0,9,0,10,0,0,230,0,0,0,0,0],[0,39,0,122,0,121,121,0,9,0,10,0,0,0,42,0,39,0,0],[0,0,0,0,0,0,0,8,0,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,231,231,49,0,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,232,0,0,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,130,131,132,133,9,0,10,0,0,0,42,0,0,0,0],[0,0,0,0,0,131,131,133,9,0,10,0,0,0,42,0,0,0,0],[0,0,0,0,0,233,233,133,9,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,234,233,233,133,9,0,0,0,0,0,0,0,0,0,0],[0,0,0,235,236,237,238,239,9,0,10,0,0,0,42,0,0,0,0],[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,54,56,56,57,58,0,59,0,0,0,61,0,0,62,0],[0,0,0,240,241,242,243,57,58,0,59,0,0,244,245,0,0,62,0],[0,0,0,0,0,246,246,0,58,0,59,0,0,0,139,0,0,0,0],[0,136,0,247,0,248,248,57,58,0,59,0,0,0,139,0,136,0,0],[0,249,151,0,0,0,0,0,0,0,0,0,0,0,0,0,249,0,0],[0,136,0,0,0,246,250,0,58,0,59,0,0,0,139,0,136,0,0],[0,0,0,0,0,251,251,57,0,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,143,144,145,146,58,0,59,0,0,0,139,0,0,0,0],[0,0,0,0,0,144,144,146,58,0,59,0,0,0,139,0,0,0,0],[0,0,0,0,0,252,252,146,58,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,253,252,252,146,58,0,0,0,0,0,0,0,0,0,0],[0,0,0,254,255,256,257,258,58,0,59,0,0,0,139,0,0,0,0],[0,0,0,0,0,0,0,0,0,0,59,0,0,0,0,0,0,0,0],[0,0,0,0,0,147,0,0,0,0,59,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0,259,0,0,0,0,0,0,0,0],[0,0,0,260,241,261,262,57,58,0,59,0,0,263,245,0,0,62,0],[0,0,0,0,0,246,246,0,58,0,59,0,0,0,0,0,0,0,0],[0,0,0,0,0,137,264,0,58,0,59,0,0,0,139,0,0,0,0],[0,0,0,0,265,141,141,57,58,0,0,0,0,0,265,0,0,0,0],[0,249,151,0,0,137,264,0,58,0,59,0,0,0,139,0,249,0,0],[0,0,0,221,116,222,222,8,9,0,10,0,0,0,120,0,0,16,0],[0,0,0,0,225,44,44,8,9,0,0,0,0,158,225,0,0,0,0],[0,0,0,155,116,156,222,8,9,0,10,0,0,158,120,0,0,16,0],[0,0,0,155,116,222,222,8,9,0,10,0,0,0,120,0,0,16,0],[0,0,0,0,43,266,266,8,161,0,24,0,0,12,267,0,0,0,0],[0,75,0,176,43,268,268,269,161,0,24,0,0,0,267,0,75,0,0],[0,0,0,0,0,270,0,0,271,0,162,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0,272,0,0,0,0,0,0,0,0],[0,273,274,0,0,40,41,0,9,0,10,0,0,0,42,0,273,0,0],[0,0,0,40,0,123,123,8,9,0,10,0,0,0,42,0,0,0,0],[0,0,0,0,0,121,275,0,9,0,10,0,0,0,42,0,0,0,0],[0,0,0,0,0,0,0,0,0,0,72,0,0,0,0,0,0,0,0],[0,0,0,0,0,166,0,0,0,0,72,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0,276,0,0,0,0,0,0,0,0],[0,0,0,277,170,278,278,22,23,0,24,0,0,0,174,0,0,27,0],[0,279,0,0,0,76,280,0,23,0,24,0,0,0,78,0,279,0,0],[0,0,0,0,281,80,80,22,23,0,0,0,0,173,281,0,0,0,0],[0,0,0,169,170,171,278,22,23,0,24,0,0,173,174,0,0,27,0],[0,0,0,169,170,278,278,22,23,0,24,0,0,0,174,0,0,27,0],[0,282,90,0,0,76,280,0,23,0,24,0,0,0,78,0,282,0,0],[0,0,0,0,0,0,0,0,23,0,0,0,0,0,0,0,0,0,0],[0,75,0,0,0,175,175,0,23,0,24,0,0,0,78,0,75,0,0],[0,0,0,0,0,80,80,22,23,0,0,0,0,0,0,0,0,0,0],[0,0,0,283,0,284,285,0,23,0,24,0,0,286,0,0,0,0,0],[0,75,0,176,0,175,175,0,23,0,24,0,0,0,78,0,75,0,0],[0,0,0,0,0,0,0,22,0,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,287,287,85,0,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,288,0,0,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,184,185,186,187,23,0,24,0,0,0,78,0,0,0,0],[0,0,0,0,0,185,185,187,23,0,24,0,0,0,78,0,0,0,0],[0,0,0,0,0,289,289,187,23,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,290,289,289,187,23,0,0,0,0,0,0,0,0,0,0],[0,0,0,291,292,293,294,295,23,0,24,0,0,0,78,0,0,0,0],[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],[0,0,0,277,170,278,278,22,23,0,24,0,0,0,174,0,0,27,0],[0,0,0,0,281,80,80,22,23,0,0,0,0,192,281,0,0,0,0],[0,0,0,189,170,190,278,22,23,0,24,0,0,192,174,0,0,27,0],[0,0,0,189,170,278,278,22,23,0,24,0,0,0,174,0,0,27,0],[0,0,0,76,0,177,177,22,23,0,24,0,0,0,78,0,0,0,0],[0,0,0,0,0,175,296,0,23,0,24,0,0,0,78,0,0,0,0],[0,0,0,297,196,298,298,32,33,0,34,0,0,0,200,0,0,37,0],[0,299,0,0,0,97,300,0,33,0,34,0,0,0,99,0,299,0,0],[0,0,0,0,301,101,101,32,33,0,0,0,0,199,301,0,0,0,0],[0,0,0,195,196,197,298,32,33,0,34,0,0,199,200,0,0,37,0],[0,0,0,195,196,298,298,32,33,0,34,0,0,0,200,0,0,37,0],[0,302,111,0,0,97,300,0,33,0,34,0,0,0,99,0,302,0,0],[0,0,0,0,0,0,0,0,33,0,0,0,0,0,0,0,0,0,0],[0,96,0,0,0,201,201,0,33,0,34,0,0,0,99,0,96,0,0],[0,0,0,0,0,101,101,32,33,0,0,0,0,0,0,0,0,0,0],[0,0,0,303,0,304,305,0,33,0,34,0,0,306,0,0,0,0,0],[0,96,0,202,0,201,201,0,33,0,34,0,0,0,99,0,96,0,0],[0,0,0,0,0,0,0,32,0,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,307,307,106,0,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,308,0,0,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,210,211,212,213,33,0,34,0,0,0,99,0,0,0,0],[0,0,0,0,0,211,211,213,33,0,34,0,0,0,99,0,0,0,0],[0,0,0,0,0,309,309,213,33,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,310,309,309,213,33,0,0,0,0,0,0,0,0,0,0],[0,0,0,311,312,313,314,315,33,0,34,0,0,0,99,0,0,0,0],[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],[0,0,0,297,196,298,298,32,33,0,34,0,0,0,200,0,0,37,0],[0,0,0,0,301,101,101,32,33,0,0,0,0,218,301,0,0,0,0],[0,0,0,215,196,216,298,32,33,0,34,0,0,218,200,0,0,37,0],[0,0,0,215,196,298,298,32,33,0,34,0,0,0,200,0,0,37,0],[0,0,0,97,0,203,203,32,33,0,34,0,0,0,99,0,0,0,0],[0,0,0,0,0,201,316,0,33,0,34,0,0,0,99,0,0,0,0],[0,0,0,0,116,222,222,8,9,0,10,0,0,0,120,0,0,16,0],[0,0,0,0,225,44,44,8,9,0,0,0,0,0,225,0,0,0,0],[0,0,0,317,318,319,320,8,9,0,10,0,0,321,322,0,0,16,0],[0,223,0,323,0,123,123,8,9,0,10,0,0,0,42,0,223,0,0],[0,223,0,0,0,121,324,0,9,0,10,0,0,0,42,0,223,0,0],[0,0,0,325,318,326,327,8,9,0,10,0,0,328,322,0,0,16,0],[0,0,0,64,0,121,121,0,9,0,10,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,9,0,0,0,0,230,0,0,0,0,0],[0,0,0,227,0,228,121,0,9,0,10,0,0,230,0,0,0,0,0],[0,0,0,227,0,121,121,0,9,0,10,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,49,0,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,46,0,0],[0,0,0,0,0,329,329,133,0,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,330,0,0,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,236,237,238,239,9,0,10,0,0,0,42,0,0,0,0],[0,0,0,0,0,237,237,239,9,0,10,0,0,0,42,0,0,0,0],[0,0,0,0,0,331,331,239,9,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,332,331,331,239,9,0,0,0,0,0,0,0,0,0,0],[0,0,0,333,40,121,334,0,9,0,10,0,0,0,42,0,0,0,0],[0,0,0,335,241,336,336,57,58,0,59,0,0,0,245,0,0,62,0],[0,337,0,0,0,137,338,0,58,0,59,0,0,0,139,0,337,0,0],[0,0,0,0,339,141,141,57,58,0,0,0,0,244,339,0,0,0,0],[0,0,0,240,241,242,336,57,58,0,59,0,0,244,245,0,0,62,0],[0,0,0,240,241,336,336,57,58,0,59,0,0,0,245,0,0,62,0],[0,340,151,0,0,137,338,0,58,0,59,0,0,0,139,0,340,0,0],[0,0,0,0,0,0,0,0,58,0,0,0,0,0,0,0,0,0,0],[0,136,0,0,0,246,246,0,58,0,59,0,0,0,139,0,136,0,0],[0,0,0,0,0,141,141,57,58,0,0,0,0,0,0,0,0,0,0],[0,0,0,341,0,342,343,0,58,0,59,0,0,344,0,0,0,0,0],[0,136,0,247,0,246,246,0,58,0,59,0,0,0,139,0,136,0,0],[0,0,0,0,0,0,0,57,0,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,345,345,146,0,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,346,0,0,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,255,256,257,258,58,0,59,0,0,0,139,0,0,0,0],[0,0,0,0,0,256,256,258,58,0,59,0,0,0,139,0,0,0,0],[0,0,0,0,0,347,347,258,58,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,348,347,347,258,58,0,0,0,0,0,0,0,0,0,0],[0,0,0,349,350,351,352,353,58,0,59,0,0,0,139,0,0,0,0],[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],[0,0,0,335,241,336,336,57,58,0,59,0,0,0,245,0,0,62,0],[0,0,0,0,339,141,141,57,58,0,0,0,0,263,339,0,0,0,0],[0,0,0,260,241,261,336,57,58,0,59,0,0,263,245,0,0,62,0],[0,0,0,260,241,336,336,57,58,0,59,0,0,0,245,0,0,62,0],[0,0,0,137,0,248,248,57,58,0,59,0,0,0,139,0,0,0,0],[0,0,0,0,0,246,354,0,58,0,59,0,0,0,139,0,0,0,0],[0,0,0,0,0,126,126,8,23,0,0,0,0,0,0,0,0,0,0],[0,355,90,0,0,121,125,0,9,0,10,0,0,0,42,0,355,0,0],[0,0,0,0,0,356,356,269,23,0,0,0,0,0,0,0,0,0,0],[0,0,0,357,358,359,360,361,161,0,162,0,0,0,362,0,0,0,0],[0,0,0,0,0,0,0,0,0,0,162,0,0,0,0,0,0,0,0],[0,0,0,0,0,270,0,0,0,0,162,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0,363,0,0,0,0,0,0,0,0],[0,0,0,364,116,365,366,8,161,0,162,0,0,367,120,0,0,16,0],[0,0,0,0,0,368,368,0,161,0,162,0,0,0,0,0,0,0,0],[0,0,0,40,0,121,121,0,9,0,10,0,0,0,42,0,0,0,0],[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,170,278,278,22,23,0,24,0,0,0,174,0,0,27,0],[0,0,0,0,281,80,80,22,23,0,0,0,0,0,281,0,0,0,0],[0,0,0,369,370,371,372,22,23,0,24,0,0,373,374,0,0,27,0],[0,279,0,375,0,177,177,22,23,0,24,0,0,0,78,0,279,0,0],[0,279,0,0,0,175,376,0,23,0,24,0,0,0,78,0,279,0,0],[0,0,0,377,370,378,379,22,23,0,24,0,0,380,374,0,0,27,0],[0,0,0,90,0,175,175,0,23,0,24,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,23,0,0,0,0,286,0,0,0,0,0],[0,0,0,283,0,284,175,0,23,0,24,0,0,286,0,0,0,0,0],[0,0,0,283,0,175,175,0,23,0,24,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,85,0,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,82,0,0],[0,0,0,0,0,381,381,187,0,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,382,0,0,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,292,293,294,295,23,0,24,0,0,0,78,0,0,0,0],[0,0,0,0,0,293,293,295,23,0,24,0,0,0,78,0,0,0,0],[0,0,0,0,0,383,383,295,23,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,384,383,383,295,23,0,0,0,0,0,0,0,0,0,0],[0,0,0,385,76,175,386,0,23,0,24,0,0,0,78,0,0,0,0],[0,0,0,76,0,175,175,0,23,0,24,0,0,0,78,0,0,0,0],[0,0,0,0,196,298,298,32,33,0,34,0,0,0,200,0,0,37,0],[0,0,0,0,301,101,101,32,33,0,0,0,0,0,301,0,0,0,0],[0,0,0,387,388,389,390,32,33,0,34,0,0,391,392,0,0,37,0],[0,299,0,393,0,203,203,32,33,0,34,0,0,0,99,0,299,0,0],[0,299,0,0,0,201,394,0,33,0,34,0,0,0,99,0,299,0,0],[0,0,0,395,388,396,397,32,33,0,34,0,0,398,392,0,0,37,0],[0,0,0,111,0,201,201,0,33,0,34,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,33,0,0,0,0,306,0,0,0,0,0],[0,0,0,303,0,304,201,0,33,0,34,0,0,306,0,0,0,0,0],[0,0,0,303,0,201,201,0,33,0,34,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,106,0,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,0,0],[0,0,0,0,0,399,399,213,0,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,400,0,0,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,312,313,314,315,33,0,34,0,0,0,99,0,0,0,0],[0,0,0,0,0,313,313,315,33,0,34,0,0,0,99,0,0,0,0],[0,0,0,0,0,401,401,315,33,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,402,401,401,315,33,0,0,0,0,0,0,0,0,0,0],[0,0,0,403,97,201,404,0,33,0,34,0,0,0,99,0,0,0,0],[0,0,0,97,0,201,201,0,33,0,34,0,0,0,99,0,0,0,0],[0,0,0,405,318,406,406,8,9,0,10,0,0,0,322,0,0,16,0],[0,407,0,0,0,40,408,0,9,0,10,0,0,0,42,0,407,0,0],[0,0,0,0,409,44,44,8,9,0,0,0,0,321,409,0,0,0,0],[0,0,0,317,318,319,406,8,9,0,10,0,0,321,322,0,0,16,0],[0,0,0,317,318,406,406,8,9,0,10,0,0,0,322,0,0,16,0],[0,410,64,0,0,40,408,0,9,0,10,0,0,0,42,0,410,0,0],[0,223,0,0,0,121,121,0,9,0,10,0,0,0,42,0,223,0,0],[0,223,0,323,0,121,121,0,9,0,10,0,0,0,42,0,223,0,0],[0,0,0,405,318,406,406,8,9,0,10,0,0,0,322,0,0,16,0],[0,0,0,0,409,44,44,8,9,0,0,0,0,328,409,0,0,0,0],[0,0,0,325,318,326,406,8,9,0,10,0,0,328,322,0,0,16,0],[0,0,0,325,318,406,406,8,9,0,10,0,0,0,322,0,0,16,0],[0,0,0,0,0,0,0,133,0,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,130,0,0],[0,0,0,0,0,411,411,239,0,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,412,0,0,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,40,121,334,0,9,0,10,0,0,0,42,0,0,0,0],[0,0,0,0,413,0,0,0,9,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,241,336,336,57,58,0,59,0,0,0,245,0,0,62,0],[0,0,0,0,339,141,141,57,58,0,0,0,0,0,339,0,0,0,0],[0,0,0,414,415,416,417,57,58,0,59,0,0,418,419,0,0,62,0],[0,337,0,420,0,248,248,57,58,0,59,0,0,0,139,0,337,0,0],[0,337,0,0,0,246,421,0,58,0,59,0,0,0,139,0,337,0,0],[0,0,0,422,415,423,424,57,58,0,59,0,0,425,419,0,0,62,0],[0,0,0,151,0,246,246,0,58,0,59,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,58,0,0,0,0,344,0,0,0,0,0],[0,0,0,341,0,342,246,0,58,0,59,0,0,344,0,0,0,0,0],[0,0,0,341,0,246,246,0,58,0,59,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,146,0,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,143,0,0],[0,0,0,0,0,426,426,258,0,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,427,0,0,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,350,351,352,353,58,0,59,0,0,0,139,0,0,0,0],[0,0,0,0,0,351,351,353,58,0,59,0,0,0,139,0,0,0,0],[0,0,0,0,0,428,428,353,58,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,429,428,428,353,58,0,0,0,0,0,0,0,0,0,0],[0,0,0,430,137,246,431,0,58,0,59,0,0,0,139,0,0,0,0],[0,0,0,137,0,246,246,0,58,0,59,0,0,0,139,0,0,0,0],[0,0,0,432,116,433,434,8,161,0,162,0,0,435,120,0,0,16,0],[0,0,0,0,0,180,180,269,0,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,358,359,360,361,161,0,162,0,0,0,362,0,0,0,0],[0,0,0,0,0,359,359,361,161,0,162,0,0,0,362,0,0,0,0],[0,0,0,0,0,436,436,361,161,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,437,436,436,361,161,0,0,0,0,0,0,0,0,0,0],[0,0,0,438,439,440,441,442,161,0,162,0,0,0,362,0,0,0,0],[0,443,274,0,0,0,0,0,0,0,0,0,0,0,0,0,443,0,0],[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],[0,0,0,444,116,445,445,8,161,0,162,0,0,0,120,0,0,16,0],[0,0,0,0,225,44,44,8,161,0,0,0,0,367,225,0,0,0,0],[0,0,0,364,116,365,445,8,161,0,162,0,0,367,120,0,0,16,0],[0,0,0,364,116,445,445,8,161,0,162,0,0,0,120,0,0,16,0],[0,0,0,0,0,0,0,0,161,0,0,0,0,0,0,0,0,0,0],[0,0,0,446,370,447,447,22,23,0,24,0,0,0,374,0,0,27,0],[0,448,0,0,0,76,449,0,23,0,24,0,0,0,78,0,448,0,0],[0,0,0,0,450,80,80,22,23,0,0,0,0,373,450,0,0,0,0],[0,0,0,369,370,371,447,22,23,0,24,0,0,373,374,0,0,27,0],[0,0,0,369,370,447,447,22,23,0,24,0,0,0,374,0,0,27,0],[0,451,90,0,0,76,449,0,23,0,24,0,0,0,78,0,451,0,0],[0,279,0,0,0,175,175,0,23,0,24,0,0,0,78,0,279,0,0],[0,279,0,375,0,175,175,0,23,0,24,0,0,0,78,0,279,0,0],[0,0,0,446,370,447,447,22,23,0,24,0,0,0,374,0,0,27,0],[0,0,0,0,450,80,80,22,23,0,0,0,0,380,450,0,0,0,0],[0,0,0,377,370,378,447,22,23,0,24,0,0,380,374,0,0,27,0],[0,0,0,377,370,447,447,22,23,0,24,0,0,0,374,0,0,27,0],[0,0,0,0,0,0,0,187,0,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,184,0,0],[0,0,0,0,0,452,452,295,0,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,453,0,0,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,76,175,386,0,23,0,24,0,0,0,78,0,0,0,0],[0,0,0,0,454,0,0,0,23,0,0,0,0,0,0,0,0,0,0],[0,0,0,455,388,456,456,32,33,0,34,0,0,0,392,0,0,37,0],[0,457,0,0,0,97,458,0,33,0,34,0,0,0,99,0,457,0,0],[0,0,0,0,459,101,101,32,33,0,0,0,0,391,459,0,0,0,0],[0,0,0,387,388,389,456,32,33,0,34,0,0,391,392,0,0,37,0],[0,0,0,387,388,456,456,32,33,0,34,0,0,0,392,0,0,37,0],[0,460,111,0,0,97,458,0,33,0,34,0,0,0,99,0,460,0,0],[0,299,0,0,0,201,201,0,33,0,34,0,0,0,99,0,299,0,0],[0,299,0,393,0,201,201,0,33,0,34,0,0,0,99,0,299,0,0],[0,0,0,455,388,456,456,32,33,0,34,0,0,0,392,0,0,37,0],[0,0,0,0,459,101,101,32,33,0,0,0,0,398,459,0,0,0,0],[0,0,0,395,388,396,456,32,33,0,34,0,0,398,392,0,0,37,0],[0,0,0,395,388,456,456,32,33,0,34,0,0,0,392,0,0,37,0],[0,0,0,0,0,0,0,213,0,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,210,0,0],[0,0,0,0,0,461,461,315,0,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,462,0,0,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,97,201,404,0,33,0,34,0,0,0,99,0,0,0,0],[0,0,0,0,463,0,0,0,33,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,318,406,406,8,9,0,10,0,0,0,322,0,0,16,0],[0,0,0,0,409,44,44,8,9,0,0,0,0,0,409,0,0,0,0],[0,0,0,464,465,466,467,8,9,0,10,0,0,468,469,0,0,16,0],[0,407,0,470,0,123,123,8,9,0,10,0,0,0,42,0,407,0,0],[0,407,0,0,0,121,471,0,9,0,10,0,0,0,42,0,407,0,0],[0,0,0,472,465,473,474,8,9,0,10,0,0,475,469,0,0,16,0],[0,0,0,0,0,0,0,239,0,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,236,0,0],[0,0,0,0,0,0,476,0,0,0,0,0,0,0,0,0,0,0,0],[0,0,0,477,415,478,478,57,58,0,59,0,0,0,419,0,0,62,0],[0,479,0,0,0,137,480,0,58,0,59,0,0,0,139,0,479,0,0],[0,0,0,0,481,141,141,57,58,0,0,0,0,418,481,0,0,0,0],[0,0,0,414,415,416,478,57,58,0,59,0,0,418,419,0,0,62,0],[0,0,0,414,415,478,478,57,58,0,59,0,0,0,419,0,0,62,0],[0,482,151,0,0,137,480,0,58,0,59,0,0,0,139,0,482,0,0],[0,337,0,0,0,246,246,0,58,0,59,0,0,0,139,0,337,0,0],[0,337,0,420,0,246,246,0,58,0,59,0,0,0,139,0,337,0,0],[0,0,0,477,415,478,478,57,58,0,59,0,0,0,419,0,0,62,0],[0,0,0,0,481,141,141,57,58,0,0,0,0,425,481,0,0,0,0],[0,0,0,422,415,423,478,57,58,0,59,0,0,425,419,0,0,62,0],[0,0,0,422,415,478,478,57,58,0,59,0,0,0,419,0,0,62,0],[0,0,0,0,0,0,0,258,0,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,0,0],[0,0,0,0,0,483,483,353,0,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,484,0,0,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,137,246,431,0,58,0,59,0,0,0,139,0,0,0,0],[0,0,0,0,485,0,0,0,58,0,0,0,0,0,0,0,0,0,0],[0,0,0,444,116,445,445,8,161,0,162,0,0,0,120,0,0,16,0],[0,0,0,0,225,44,44,8,161,0,0,0,0,435,225,0,0,0,0],[0,0,0,432,116,433,445,8,161,0,162,0,0,435,120,0,0,16,0],[0,0,0,432,116,445,445,8,161,0,162,0,0,0,120,0,0,16,0],[0,0,0,0,0,486,486,361,0,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,487,0,0,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,439,440,441,442,161,0,162,0,0,0,362,0,0,0,0],[0,0,0,0,0,440,440,442,161,0,162,0,0,0,362,0,0,0,0],[0,0,0,0,0,488,488,442,161,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,489,488,488,442,161,0,0,0,0,0,0,0,0,0,0],[0,0,0,490,491,492,493,494,161,0,162,0,0,0,362,0,0,0,0],[0,0,0,495,0,496,497,0,161,0,162,0,0,498,0,0,0,0,0],[0,0,0,0,116,445,445,8,161,0,162,0,0,0,120,0,0,16,0],[0,0,0,0,225,44,44,8,161,0,0,0,0,0,225,0,0,0,0],[0,0,0,0,370,447,447,22,23,0,24,0,0,0,374,0,0,27,0],[0,0,0,0,450,80,80,22,23,0,0,0,0,0,450,0,0,0,0],[0,0,0,499,500,501,502,22,23,0,24,0,0,503,504,0,0,27,0],[0,448,0,505,0,177,177,22,23,0,24,0,0,0,78,0,448,0,0],[0,448,0,0,0,175,506,0,23,0,24,0,0,0,78,0,448,0,0],[0,0,0,507,500,508,509,22,23,0,24,0,0,510,504,0,0,27,0],[0,0,0,0,0,0,0,295,0,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,292,0,0],[0,0,0,0,0,0,511,0,0,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,388,456,456,32,33,0,34,0,0,0,392,0,0,37,0],[0,0,0,0,459,101,101,32,33,0,0,0,0,0,459,0,0,0,0],[0,0,0,512,513,514,515,32,33,0,34,0,0,516,517,0,0,37,0],[0,457,0,518,0,203,203,32,33,0,34,0,0,0,99,0,457,0,0],[0,457,0,0,0,201,519,0,33,0,34,0,0,0,99,0,457,0,0],[0,0,0,520,513,521,522,32,33,0,34,0,0,523,517,0,0,37,0],[0,0,0,0,0,0,0,315,0,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,312,0,0],[0,0,0,0,0,0,524,0,0,0,0,0,0,0,0,0,0,0,0],[0,0,0,525,465,526,526,8,9,0,10,0,0,0,469,0,0,16,0],[0,527,0,0,0,40,528,0,9,0,10,0,0,0,42,0,527,0,0],[0,0,0,0,529,44,44,8,9,0,0,0,0,468,529,0,0,0,0],[0,0,0,464,465,466,526,8,9,0,10,0,0,468,469,0,0,16,0],[0,0,0,464,465,526,526,8,9,0,10,0,0,0,469,0,0,16,0],[0,530,64,0,0,40,528,0,9,0,10,0,0,0,42,0,530,0,0],[0,407,0,0,0,121,121,0,9,0,10,0,0,0,42,0,407,0,0],[0,407,0,470,0,121,121,0,9,0,10,0,0,0,42,0,407,0,0],[0,0,0,525,465,526,526,8,9,0,10,0,0,0,469,0,0,16,0],[0,0,0,0,529,44,44,8,9,0,0,0,0,475,529,0,0,0,0],[0,0,0,472,465,473,526,8,9,0,10,0,0,475,469,0,0,16,0],[0,0,0,472,465,526,526,8,9,0,10,0,0,0,469,0,0,16,0],[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,40,0,0],[0,0,0,0,415,478,478,57,58,0,59,0,0,0,419,0,0,62,0],[0,0,0,0,481,141,141,57,58,0,0,0,0,0,481,0,0,0,0],[0,0,0,531,532,533,534,57,58,0,59,0,0,535,536,0,0,62,0],[0,479,0,537,0,248,248,57,58,0,59,0,0,0,139,0,479,0,0],[0,479,0,0,0,246,538,0,58,0,59,0,0,0,139,0,479,0,0],[0,0,0,539,532,540,541,57,58,0,59,0,0,542,536,0,0,62,0],[0,0,0,0,0,0,0,353,0,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,350,0,0],[0,0,0,0,0,0,543,0,0,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,361,0,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,358,0,0],[0,0,0,0,0,544,544,442,0,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,545,0,0,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,491,492,493,494,161,0,162,0,0,0,362,0,0,0,0],[0,0,0,0,0,492,492,494,161,0,162,0,0,0,362,0,0,0,0],[0,0,0,0,0,546,546,494,161,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,547,546,546,494,161,0,0,0,0,0,0,0,0,0,0],[0,0,0,548,549,368,550,0,161,0,162,0,0,0,362,0,0,0,0],[0,0,0,274,0,368,368,0,161,0,162,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,161,0,0,0,0,498,0,0,0,0,0],[0,0,0,495,0,496,368,0,161,0,162,0,0,498,0,0,0,0,0],[0,0,0,495,0,368,368,0,161,0,162,0,0,0,0,0,0,0,0],[0,0,0,551,500,552,552,22,23,0,24,0,0,0,504,0,0,27,0],[0,553,0,0,0,76,554,0,23,0,24,0,0,0,78,0,553,0,0],[0,0,0,0,555,80,80,22,23,0,0,0,0,503,555,0,0,0,0],[0,0,0,499,500,501,552,22,23,0,24,0,0,503,504,0,0,27,0],[0,0,0,499,500,552,552,22,23,0,24,0,0,0,504,0,0,27,0],[0,556,90,0,0,76,554,0,23,0,24,0,0,0,78,0,556,0,0],[0,448,0,0,0,175,175,0,23,0,24,0,0,0,78,0,448,0,0],[0,448,0,505,0,175,175,0,23,0,24,0,0,0,78,0,448,0,0],[0,0,0,551,500,552,552,22,23,0,24,0,0,0,504,0,0,27,0],[0,0,0,0,555,80,80,22,23,0,0,0,0,510,555,0,0,0,0],[0,0,0,507,500,508,552,22,23,0,24,0,0,510,504,0,0,27,0],[0,0,0,507,500,552,552,22,23,0,24,0,0,0,504,0,0,27,0],[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,76,0,0],[0,0,0,557,513,558,558,32,33,0,34,0,0,0,517,0,0,37,0],[0,559,0,0,0,97,560,0,33,0,34,0,0,0,99,0,559,0,0],[0,0,0,0,561,101,101,32,33,0,0,0,0,516,561,0,0,0,0],[0,0,0,512,513,514,558,32,33,0,34,0,0,516,517,0,0,37,0],[0,0,0,512,513,558,558,32,33,0,34,0,0,0,517,0,0,37,0],[0,562,111,0,0,97,560,0,33,0,34,0,0,0,99,0,562,0,0],[0,457,0,0,0,201,201,0,33,0,34,0,0,0,99,0,457,0,0],[0,457,0,518,0,201,201,0,33,0,34,0,0,0,99,0,457,0,0],[0,0,0,557,513,558,558,32,33,0,34,0,0,0,517,0,0,37,0],[0,0,0,0,561,101,101,32,33,0,0,0,0,523,561,0,0,0,0],[0,0,0,520,513,521,558,32,33,0,34,0,0,523,517,0,0,37,0],[0,0,0,520,513,558,558,32,33,0,34,0,0,0,517,0,0,37,0],[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,97,0,0],[0,0,0,0,465,526,526,8,9,0,10,0,0,0,469,0,0,16,0],[0,0,0,0,529,44,44,8,9,0,0,0,0,0,529,0,0,0,0],[0,0,0,563,66,564,565,8,9,0,10,0,0,566,68,0,0,16,0],[0,527,0,567,0,123,123,8,9,0,10,0,0,0,42,0,527,0,0],[0,527,0,0,0,121,568,0,9,0,10,0,0,0,42,0,527,0,0],[0,0,0,569,66,570,571,8,9,0,10,0,0,572,68,0,0,16,0],[0,0,0,573,532,574,574,57,58,0,59,0,0,0,536,0,0,62,0],[0,575,0,0,0,137,576,0,58,0,59,0,0,0,139,0,575,0,0],[0,0,0,0,577,141,141,57,58,0,0,0,0,535,577,0,0,0,0],[0,0,0,531,532,533,574,57,58,0,59,0,0,535,536,0,0,62,0],[0,0,0,531,532,574,574,57,58,0,59,0,0,0,536,0,0,62,0],[0,578,151,0,0,137,576,0,58,0,59,0,0,0,139,0,578,0,0],[0,479,0,0,0,246,246,0,58,0,59,0,0,0,139,0,479,0,0],[0,479,0,537,0,246,246,0,58,0,59,0,0,0,139,0,479,0,0],[0,0,0,573,532,574,574,57,58,0,59,0,0,0,536,0,0,62,0],[0,0,0,0,577,141,141,57,58,0,0,0,0,542,577,0,0,0,0],[0,0,0,539,532,540,574,57,58,0,59,0,0,542,536,0,0,62,0],[0,0,0,539,532,574,574,57,58,0,59,0,0,0,536,0,0,62,0],[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,137,0,0],[0,0,0,0,0,0,0,442,0,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,439,0,0],[0,0,0,0,0,579,579,494,0,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,580,0,0,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,549,368,550,0,161,0,162,0,0,0,362,0,0,0,0],[0,0,0,0,0,368,368,0,161,0,162,0,0,0,362,0,0,0,0],[0,0,0,0,581,0,0,0,161,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,500,552,552,22,23,0,24,0,0,0,504,0,0,27,0],[0,0,0,0,555,80,80,22,23,0,0,0,0,0,555,0,0,0,0],[0,0,0,582,91,583,584,22,23,0,24,0,0,585,93,0,0,27,0],[0,553,0,586,0,177,177,22,23,0,24,0,0,0,78,0,553,0,0],[0,553,0,0,0,175,587,0,23,0,24,0,0,0,78,0,553,0,0],[0,0,0,588,91,589,590,22,23,0,24,0,0,591,93,0,0,27,0],[0,0,0,0,513,558,558,32,33,0,34,0,0,0,517,0,0,37,0],[0,0,0,0,561,101,101,32,33,0,0,0,0,0,561,0,0,0,0],[0,0,0,592,112,593,594,32,33,0,34,0,0,595,114,0,0,37,0],[0,559,0,596,0,203,203,32,33,0,34,0,0,0,99,0,559,0,0],[0,559,0,0,0,201,597,0,33,0,34,0,0,0,99,0,559,0,0],[0,0,0,598,112,599,600,32,33,0,34,0,0,601,114,0,0,37,0],[0,0,0,602,66,67,67,8,9,0,10,0,0,0,68,0,0,16,0],[0,0,0,0,165,44,44,8,9,0,0,0,0,566,165,0,0,0,0],[0,0,0,563,66,564,67,8,9,0,10,0,0,566,68,0,0,16,0],[0,0,0,563,66,67,67,8,9,0,10,0,0,0,68,0,0,16,0],[0,527,0,0,0,121,121,0,9,0,10,0,0,0,42,0,527,0,0],[0,527,0,567,0,121,121,0,9,0,10,0,0,0,42,0,527,0,0],[0,0,0,602,66,67,67,8,9,0,10,0,0,0,68,0,0,16,0],[0,0,0,0,165,44,44,8,9,0,0,0,0,572,165,0,0,0,0],[0,0,0,569,66,570,67,8,9,0,10,0,0,572,68,0,0,16,0],[0,0,0,569,66,67,67,8,9,0,10,0,0,0,68,0,0,16,0],[0,0,0,0,532,574,574,57,58,0,59,0,0,0,536,0,0,62,0],[0,0,0,0,577,141,141,57,58,0,0,0,0,0,577,0,0,0,0],[0,0,0,603,152,604,605,57,58,0,59,0,0,606,154,0,0,62,0],[0,575,0,607,0,248,248,57,58,0,59,0,0,0,139,0,575,0,0],[0,575,0,0,0,246,608,0,58,0,59,0,0,0,139,0,575,0,0],[0,0,0,609,152,610,611,57,58,0,59,0,0,612,154,0,0,62,0],[0,0,0,0,0,0,0,494,0,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,491,0,0],[0,0,0,0,0,0,613,0,0,0,0,0,0,0,0,0,0,0,0],[0,0,0,614,91,92,92,22,23,0,24,0,0,0,93,0,0,27,0],[0,0,0,0,194,80,80,22,23,0,0,0,0,585,194,0,0,0,0],[0,0,0,582,91,583,92,22,23,0,24,0,0,585,93,0,0,27,0],[0,0,0,582,91,92,92,22,23,0,24,0,0,0,93,0,0,27,0],[0,553,0,0,0,175,175,0,23,0,24,0,0,0,78,0,553,0,0],[0,553,0,586,0,175,175,0,23,0,24,0,0,0,78,0,553,0,0],[0,0,0,614,91,92,92,22,23,0,24,0,0,0,93,0,0,27,0],[0,0,0,0,194,80,80,22,23,0,0,0,0,591,194,0,0,0,0],[0,0,0,588,91,589,92,22,23,0,24,0,0,591,93,0,0,27,0],[0,0,0,588,91,92,92,22,23,0,24,0,0,0,93,0,0,27,0],[0,0,0,615,112,113,113,32,33,0,34,0,0,0,114,0,0,37,0],[0,0,0,0,220,101,101,32,33,0,0,0,0,595,220,0,0,0,0],[0,0,0,592,112,593,113,32,33,0,34,0,0,595,114,0,0,37,0],[0,0,0,592,112,113,113,32,33,0,34,0,0,0,114,0,0,37,0],[0,559,0,0,0,201,201,0,33,0,34,0,0,0,99,0,559,0,0],[0,559,0,596,0,201,201,0,33,0,34,0,0,0,99,0,559,0,0],[0,0,0,615,112,113,113,32,33,0,34,0,0,0,114,0,0,37,0],[0,0,0,0,220,101,101,32,33,0,0,0,0,601,220,0,0,0,0],[0,0,0,598,112,599,113,32,33,0,34,0,0,601,114,0,0,37,0],[0,0,0,598,112,113,113,32,33,0,34,0,0,0,114,0,0,37,0],[0,0,0,0,66,67,67,8,9,0,10,0,0,0,68,0,0,16,0],[0,0,0,616,152,153,153,57,58,0,59,0,0,0,154,0,0,62,0],[0,0,0,0,265,141,141,57,58,0,0,0,0,606,265,0,0,0,0],[0,0,0,603,152,604,153,57,58,0,59,0,0,606,154,0,0,62,0],[0,0,0,603,152,153,153,57,58,0,59,0,0,0,154,0,0,62,0],[0,575,0,0,0,246,246,0,58,0,59,0,0,0,139,0,575,0,0],[0,575,0,607,0,246,246,0,58,0,59,0,0,0,139,0,575,0,0],[0,0,0,616,152,153,153,57,58,0,59,0,0,0,154,0,0,62,0],[0,0,0,0,265,141,141,57,58,0,0,0,0,612,265,0,0,0,0],[0,0,0,609,152,610,153,57,58,0,59,0,0,612,154,0,0,62,0],[0,0,0,609,152,153,153,57,58,0,59,0,0,0,154,0,0,62,0],[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,549,0,0],[0,0,0,0,91,92,92,22,23,0,24,0,0,0,93,0,0,27,0],[0,0,0,0,112,113,113,32,33,0,34,0,0,0,114,0,0,37,0],[0,0,0,0,152,153,153,57,58,0,59,0,0,0,154,0,0,62,0]],\\\"accepting\\\":[false,true,true,true,true,true,false,false,true,true,true,true,true,true,true,true,true,true,true,true,false,true,true,true,true,true,true,true,true,true,false,true,true,true,true,true,true,true,true,true,true,true,false,true,false,true,true,false,false,true,true,true,true,true,true,false,false,true,true,true,true,true,true,true,true,true,true,false,true,true,false,true,true,true,false,true,true,true,false,true,false,true,true,false,false,true,true,true,true,true,true,true,false,true,true,false,true,true,true,false,true,false,true,true,false,false,true,true,true,true,true,true,true,false,true,true,true,false,true,true,true,false,true,false,true,true,false,false,false,true,true,false,false,true,true,true,true,true,true,false,true,false,true,true,false,false,true,true,true,true,true,true,true,false,true,true,false,true,true,true,true,true,true,true,true,true,true,true,true,true,true,false,true,true,true,false,true,false,true,true,false,false,false,true,true,false,false,true,true,true,false,true,true,true,true,true,true,false,true,true,true,false,true,false,true,true,false,false,false,true,true,false,false,true,true,true,false,true,true,true,true,true,false,true,true,true,true,true,false,true,true,false,false,false,false,true,true,false,false,true,true,true,false,true,true,true,false,true,false,true,true,false,false,false,true,true,false,false,true,true,true,false,true,true,true,true,false,true,false,true,true,true,true,true,true,true,true,true,false,true,true,true,true,true,false,true,true,false,false,false,false,true,true,false,false,true,true,true,false,true,true,true,true,true,false,true,true,false,false,false,false,true,true,false,false,true,true,true,true,false,true,true,true,true,true,true,false,true,true,false,false,false,false,true,false,true,false,true,true,true,true,true,false,true,true,false,false,false,false,true,true,false,false,true,true,true,false,true,true,false,false,true,false,true,true,false,true,true,false,true,true,false,true,true,true,true,true,true,false,true,true,false,false,false,false,true,false,true,true,false,true,true,true,true,true,true,false,true,true,false,false,false,false,true,false,true,false,true,true,true,true,false,false,false,true,true,false,true,true,true,true,true,true,false,true,true,false,false,false,false,true,false,true,false,true,true,false,false,true,true,false,false,true,true,true,false,true,false,true,true,true,true,false,false,false,true,false,true,true,true,true,false,false,false,true,true,false,true,true,true,true,true,true,false,true,true,false,true,false,true,true,true,true,false,false,false,false,false,false,false,true,true,false,false,true,true,false,true,true,true,true,false,true,true,true,true,true,true,false,true,true,false,true,true,false,true,true,true,true,true,true,false,true,true,false,true,false,true,true,true,true,true,true,false,true,true,true,true,true,true,false,true,true,false,false,false,false,false,true,true,false,true,false,true,true,true,true,true,false,true,true,true,true,true,false,true,true,true,true,true,false,true,true,true,false,true,true,true,true,false,false,false,true,false,true,true,true,true,true,false,true,true,true,false,true,true,true,true,true,false,true,true,true,true,false,true,true,true,true,true,false,true,true,false,true,true,true],\\\"tags\\\":[[],[\\\"broken_cluster\\\"],[\\\"consonant_syllable\\\"],[\\\"vowel_syllable\\\"],[\\\"broken_cluster\\\"],[\\\"broken_cluster\\\"],[],[],[\\\"broken_cluster\\\"],[\\\"broken_cluster\\\"],[\\\"broken_cluster\\\"],[\\\"standalone_cluster\\\"],[\\\"broken_cluster\\\"],[\\\"broken_cluster\\\"],[\\\"broken_cluster\\\"],[\\\"consonant_syllable\\\"],[\\\"broken_cluster\\\"],[\\\"symbol_cluster\\\"],[\\\"consonant_syllable\\\"],[\\\"consonant_syllable\\\"],[],[\\\"consonant_syllable\\\"],[\\\"consonant_syllable\\\"],[\\\"consonant_syllable\\\"],[\\\"consonant_syllable\\\"],[\\\"consonant_syllable\\\"],[\\\"consonant_syllable\\\"],[\\\"consonant_syllable\\\"],[\\\"vowel_syllable\\\"],[\\\"vowel_syllable\\\"],[],[\\\"vowel_syllable\\\"],[\\\"vowel_syllable\\\"],[\\\"vowel_syllable\\\"],[\\\"vowel_syllable\\\"],[\\\"vowel_syllable\\\"],[\\\"vowel_syllable\\\"],[\\\"vowel_syllable\\\"],[\\\"broken_cluster\\\"],[\\\"broken_cluster\\\"],[\\\"broken_cluster\\\"],[\\\"broken_cluster\\\"],[],[\\\"broken_cluster\\\"],[],[\\\"broken_cluster\\\"],[\\\"broken_cluster\\\"],[],[],[\\\"broken_cluster\\\"],[\\\"broken_cluster\\\"],[\\\"broken_cluster\\\"],[\\\"broken_cluster\\\"],[\\\"standalone_cluster\\\"],[\\\"standalone_cluster\\\"],[],[],[\\\"standalone_cluster\\\"],[\\\"standalone_cluster\\\"],[\\\"standalone_cluster\\\"],[\\\"standalone_cluster\\\"],[\\\"standalone_cluster\\\"],[\\\"standalone_cluster\\\"],[\\\"broken_cluster\\\"],[\\\"broken_cluster\\\"],[\\\"consonant_syllable\\\",\\\"broken_cluster\\\"],[\\\"broken_cluster\\\"],[],[\\\"broken_cluster\\\"],[\\\"symbol_cluster\\\"],[],[\\\"symbol_cluster\\\"],[\\\"symbol_cluster\\\"],[\\\"consonant_syllable\\\"],[],[\\\"consonant_syllable\\\"],[\\\"consonant_syllable\\\"],[\\\"consonant_syllable\\\"],[],[\\\"consonant_syllable\\\"],[],[\\\"consonant_syllable\\\"],[\\\"consonant_syllable\\\"],[],[],[\\\"consonant_syllable\\\"],[\\\"consonant_syllable\\\"],[\\\"consonant_syllable\\\"],[\\\"consonant_syllable\\\"],[\\\"consonant_syllable\\\"],[\\\"consonant_syllable\\\"],[\\\"consonant_syllable\\\"],[],[\\\"consonant_syllable\\\"],[\\\"vowel_syllable\\\"],[],[\\\"vowel_syllable\\\"],[\\\"vowel_syllable\\\"],[\\\"vowel_syllable\\\"],[],[\\\"vowel_syllable\\\"],[],[\\\"vowel_syllable\\\"],[\\\"vowel_syllable\\\"],[],[],[\\\"vowel_syllable\\\"],[\\\"vowel_syllable\\\"],[\\\"vowel_syllable\\\"],[\\\"vowel_syllable\\\"],[\\\"vowel_syllable\\\"],[\\\"vowel_syllable\\\"],[\\\"vowel_syllable\\\"],[],[\\\"vowel_syllable\\\"],[\\\"broken_cluster\\\"],[\\\"broken_cluster\\\"],[],[\\\"broken_cluster\\\"],[\\\"broken_cluster\\\"],[\\\"broken_cluster\\\"],[],[\\\"broken_cluster\\\"],[],[\\\"broken_cluster\\\"],[\\\"broken_cluster\\\"],[],[],[],[\\\"broken_cluster\\\"],[\\\"broken_cluster\\\"],[],[],[\\\"broken_cluster\\\"],[\\\"broken_cluster\\\"],[\\\"standalone_cluster\\\"],[\\\"standalone_cluster\\\"],[\\\"standalone_cluster\\\"],[\\\"standalone_cluster\\\"],[],[\\\"standalone_cluster\\\"],[],[\\\"standalone_cluster\\\"],[\\\"standalone_cluster\\\"],[],[],[\\\"standalone_cluster\\\"],[\\\"standalone_cluster\\\"],[\\\"standalone_cluster\\\"],[\\\"standalone_cluster\\\"],[\\\"standalone_cluster\\\"],[\\\"standalone_cluster\\\"],[\\\"standalone_cluster\\\"],[],[\\\"standalone_cluster\\\"],[\\\"broken_cluster\\\"],[],[\\\"broken_cluster\\\"],[\\\"broken_cluster\\\"],[\\\"consonant_syllable\\\"],[\\\"consonant_syllable\\\"],[\\\"consonant_syllable\\\",\\\"broken_cluster\\\"],[\\\"consonant_syllable\\\",\\\"broken_cluster\\\"],[\\\"broken_cluster\\\"],[\\\"broken_cluster\\\"],[\\\"broken_cluster\\\"],[\\\"symbol_cluster\\\"],[\\\"symbol_cluster\\\"],[\\\"symbol_cluster\\\"],[\\\"consonant_syllable\\\"],[\\\"consonant_syllable\\\"],[],[\\\"consonant_syllable\\\"],[\\\"consonant_syllable\\\"],[\\\"consonant_syllable\\\"],[],[\\\"consonant_syllable\\\"],[],[\\\"consonant_syllable\\\"],[\\\"consonant_syllable\\\"],[],[],[],[\\\"consonant_syllable\\\"],[\\\"consonant_syllable\\\"],[],[],[\\\"consonant_syllable\\\"],[\\\"consonant_syllable\\\"],[\\\"consonant_syllable\\\"],[],[\\\"consonant_syllable\\\"],[\\\"consonant_syllable\\\"],[\\\"consonant_syllable\\\"],[\\\"consonant_syllable\\\"],[\\\"vowel_syllable\\\"],[\\\"vowel_syllable\\\"],[],[\\\"vowel_syllable\\\"],[\\\"vowel_syllable\\\"],[\\\"vowel_syllable\\\"],[],[\\\"vowel_syllable\\\"],[],[\\\"vowel_syllable\\\"],[\\\"vowel_syllable\\\"],[],[],[],[\\\"vowel_syllable\\\"],[\\\"vowel_syllable\\\"],[],[],[\\\"vowel_syllable\\\"],[\\\"vowel_syllable\\\"],[\\\"vowel_syllable\\\"],[],[\\\"vowel_syllable\\\"],[\\\"vowel_syllable\\\"],[\\\"vowel_syllable\\\"],[\\\"vowel_syllable\\\"],[\\\"broken_cluster\\\"],[],[\\\"broken_cluster\\\"],[\\\"broken_cluster\\\"],[\\\"broken_cluster\\\"],[\\\"broken_cluster\\\"],[\\\"broken_cluster\\\"],[],[\\\"broken_cluster\\\"],[\\\"broken_cluster\\\"],[],[],[],[],[\\\"broken_cluster\\\"],[\\\"broken_cluster\\\"],[],[],[\\\"broken_cluster\\\"],[\\\"standalone_cluster\\\"],[\\\"standalone_cluster\\\"],[],[\\\"standalone_cluster\\\"],[\\\"standalone_cluster\\\"],[\\\"standalone_cluster\\\"],[],[\\\"standalone_cluster\\\"],[],[\\\"standalone_cluster\\\"],[\\\"standalone_cluster\\\"],[],[],[],[\\\"standalone_cluster\\\"],[\\\"standalone_cluster\\\"],[],[],[\\\"standalone_cluster\\\"],[\\\"standalone_cluster\\\"],[\\\"standalone_cluster\\\"],[],[\\\"standalone_cluster\\\"],[\\\"standalone_cluster\\\"],[\\\"standalone_cluster\\\"],[\\\"standalone_cluster\\\"],[],[\\\"broken_cluster\\\"],[],[\\\"consonant_syllable\\\",\\\"broken_cluster\\\"],[\\\"consonant_syllable\\\",\\\"broken_cluster\\\"],[\\\"consonant_syllable\\\",\\\"broken_cluster\\\"],[\\\"consonant_syllable\\\",\\\"broken_cluster\\\"],[\\\"consonant_syllable\\\",\\\"broken_cluster\\\"],[\\\"consonant_syllable\\\",\\\"broken_cluster\\\"],[\\\"broken_cluster\\\"],[\\\"symbol_cluster\\\"],[\\\"consonant_syllable\\\"],[],[\\\"consonant_syllable\\\"],[\\\"consonant_syllable\\\"],[\\\"consonant_syllable\\\"],[\\\"consonant_syllable\\\"],[\\\"consonant_syllable\\\"],[],[\\\"consonant_syllable\\\"],[\\\"consonant_syllable\\\"],[],[],[],[],[\\\"consonant_syllable\\\"],[\\\"consonant_syllable\\\"],[],[],[\\\"consonant_syllable\\\"],[\\\"consonant_syllable\\\"],[\\\"vowel_syllable\\\"],[],[\\\"vowel_syllable\\\"],[\\\"vowel_syllable\\\"],[\\\"vowel_syllable\\\"],[\\\"vowel_syllable\\\"],[\\\"vowel_syllable\\\"],[],[\\\"vowel_syllable\\\"],[\\\"vowel_syllable\\\"],[],[],[],[],[\\\"vowel_syllable\\\"],[\\\"vowel_syllable\\\"],[],[],[\\\"vowel_syllable\\\"],[\\\"vowel_syllable\\\"],[\\\"broken_cluster\\\"],[\\\"broken_cluster\\\"],[],[\\\"broken_cluster\\\"],[\\\"broken_cluster\\\"],[\\\"broken_cluster\\\"],[\\\"broken_cluster\\\"],[\\\"broken_cluster\\\"],[\\\"broken_cluster\\\"],[],[\\\"broken_cluster\\\"],[\\\"broken_cluster\\\"],[],[],[],[],[\\\"broken_cluster\\\"],[],[\\\"standalone_cluster\\\"],[],[\\\"standalone_cluster\\\"],[\\\"standalone_cluster\\\"],[\\\"standalone_cluster\\\"],[\\\"standalone_cluster\\\"],[\\\"standalone_cluster\\\"],[],[\\\"standalone_cluster\\\"],[\\\"standalone_cluster\\\"],[],[],[],[],[\\\"standalone_cluster\\\"],[\\\"standalone_cluster\\\"],[],[],[\\\"standalone_cluster\\\"],[\\\"standalone_cluster\\\"],[\\\"consonant_syllable\\\",\\\"broken_cluster\\\"],[],[\\\"consonant_syllable\\\",\\\"broken_cluster\\\"],[\\\"consonant_syllable\\\",\\\"broken_cluster\\\"],[],[],[\\\"consonant_syllable\\\",\\\"broken_cluster\\\"],[],[\\\"consonant_syllable\\\",\\\"broken_cluster\\\"],[\\\"consonant_syllable\\\",\\\"broken_cluster\\\"],[],[\\\"consonant_syllable\\\",\\\"broken_cluster\\\"],[\\\"consonant_syllable\\\",\\\"broken_cluster\\\"],[],[\\\"consonant_syllable\\\"],[\\\"consonant_syllable\\\"],[],[\\\"consonant_syllable\\\"],[\\\"consonant_syllable\\\"],[\\\"consonant_syllable\\\"],[\\\"consonant_syllable\\\"],[\\\"consonant_syllable\\\"],[\\\"consonant_syllable\\\"],[],[\\\"consonant_syllable\\\"],[\\\"consonant_syllable\\\"],[],[],[],[],[\\\"consonant_syllable\\\"],[],[\\\"vowel_syllable\\\"],[\\\"vowel_syllable\\\"],[],[\\\"vowel_syllable\\\"],[\\\"vowel_syllable\\\"],[\\\"vowel_syllable\\\"],[\\\"vowel_syllable\\\"],[\\\"vowel_syllable\\\"],[\\\"vowel_syllable\\\"],[],[\\\"vowel_syllable\\\"],[\\\"vowel_syllable\\\"],[],[],[],[],[\\\"vowel_syllable\\\"],[],[\\\"broken_cluster\\\"],[],[\\\"broken_cluster\\\"],[\\\"broken_cluster\\\"],[\\\"broken_cluster\\\"],[\\\"broken_cluster\\\"],[],[],[],[\\\"standalone_cluster\\\"],[\\\"standalone_cluster\\\"],[],[\\\"standalone_cluster\\\"],[\\\"standalone_cluster\\\"],[\\\"standalone_cluster\\\"],[\\\"standalone_cluster\\\"],[\\\"standalone_cluster\\\"],[\\\"standalone_cluster\\\"],[],[\\\"standalone_cluster\\\"],[\\\"standalone_cluster\\\"],[],[],[],[],[\\\"standalone_cluster\\\"],[],[\\\"consonant_syllable\\\",\\\"broken_cluster\\\"],[],[\\\"consonant_syllable\\\",\\\"broken_cluster\\\"],[\\\"consonant_syllable\\\",\\\"broken_cluster\\\"],[],[],[\\\"consonant_syllable\\\",\\\"broken_cluster\\\"],[\\\"consonant_syllable\\\",\\\"broken_cluster\\\"],[],[],[\\\"consonant_syllable\\\",\\\"broken_cluster\\\"],[\\\"consonant_syllable\\\",\\\"broken_cluster\\\"],[\\\"consonant_syllable\\\",\\\"broken_cluster\\\"],[],[\\\"consonant_syllable\\\"],[],[\\\"consonant_syllable\\\"],[\\\"consonant_syllable\\\"],[\\\"consonant_syllable\\\"],[\\\"consonant_syllable\\\"],[],[],[],[\\\"vowel_syllable\\\"],[],[\\\"vowel_syllable\\\"],[\\\"vowel_syllable\\\"],[\\\"vowel_syllable\\\"],[\\\"vowel_syllable\\\"],[],[],[],[\\\"broken_cluster\\\"],[\\\"broken_cluster\\\"],[],[\\\"broken_cluster\\\"],[\\\"broken_cluster\\\"],[\\\"broken_cluster\\\"],[\\\"broken_cluster\\\"],[\\\"broken_cluster\\\"],[\\\"broken_cluster\\\"],[],[\\\"broken_cluster\\\"],[\\\"broken_cluster\\\"],[],[\\\"standalone_cluster\\\"],[],[\\\"standalone_cluster\\\"],[\\\"standalone_cluster\\\"],[\\\"standalone_cluster\\\"],[\\\"standalone_cluster\\\"],[],[],[],[],[],[],[],[\\\"consonant_syllable\\\",\\\"broken_cluster\\\"],[\\\"consonant_syllable\\\",\\\"broken_cluster\\\"],[],[],[\\\"consonant_syllable\\\",\\\"broken_cluster\\\"],[\\\"consonant_syllable\\\",\\\"broken_cluster\\\"],[],[\\\"consonant_syllable\\\",\\\"broken_cluster\\\"],[\\\"consonant_syllable\\\",\\\"broken_cluster\\\"],[\\\"consonant_syllable\\\"],[\\\"consonant_syllable\\\"],[],[\\\"consonant_syllable\\\"],[\\\"consonant_syllable\\\"],[\\\"consonant_syllable\\\"],[\\\"consonant_syllable\\\"],[\\\"consonant_syllable\\\"],[\\\"consonant_syllable\\\"],[],[\\\"consonant_syllable\\\"],[\\\"consonant_syllable\\\"],[],[\\\"vowel_syllable\\\"],[\\\"vowel_syllable\\\"],[],[\\\"vowel_syllable\\\"],[\\\"vowel_syllable\\\"],[\\\"vowel_syllable\\\"],[\\\"vowel_syllable\\\"],[\\\"vowel_syllable\\\"],[\\\"vowel_syllable\\\"],[],[\\\"vowel_syllable\\\"],[\\\"vowel_syllable\\\"],[],[\\\"broken_cluster\\\"],[],[\\\"broken_cluster\\\"],[\\\"broken_cluster\\\"],[\\\"broken_cluster\\\"],[\\\"broken_cluster\\\"],[\\\"standalone_cluster\\\"],[\\\"standalone_cluster\\\"],[],[\\\"standalone_cluster\\\"],[\\\"standalone_cluster\\\"],[\\\"standalone_cluster\\\"],[\\\"standalone_cluster\\\"],[\\\"standalone_cluster\\\"],[\\\"standalone_cluster\\\"],[],[\\\"standalone_cluster\\\"],[\\\"standalone_cluster\\\"],[],[],[],[],[],[\\\"consonant_syllable\\\",\\\"broken_cluster\\\"],[\\\"consonant_syllable\\\",\\\"broken_cluster\\\"],[],[\\\"consonant_syllable\\\"],[],[\\\"consonant_syllable\\\"],[\\\"consonant_syllable\\\"],[\\\"consonant_syllable\\\"],[\\\"consonant_syllable\\\"],[\\\"vowel_syllable\\\"],[],[\\\"vowel_syllable\\\"],[\\\"vowel_syllable\\\"],[\\\"vowel_syllable\\\"],[\\\"vowel_syllable\\\"],[\\\"broken_cluster\\\"],[],[\\\"broken_cluster\\\"],[\\\"broken_cluster\\\"],[\\\"broken_cluster\\\"],[\\\"broken_cluster\\\"],[\\\"broken_cluster\\\"],[],[\\\"broken_cluster\\\"],[\\\"broken_cluster\\\"],[\\\"standalone_cluster\\\"],[],[\\\"standalone_cluster\\\"],[\\\"standalone_cluster\\\"],[\\\"standalone_cluster\\\"],[\\\"standalone_cluster\\\"],[],[],[],[\\\"consonant_syllable\\\"],[],[\\\"consonant_syllable\\\"],[\\\"consonant_syllable\\\"],[\\\"consonant_syllable\\\"],[\\\"consonant_syllable\\\"],[\\\"consonant_syllable\\\"],[],[\\\"consonant_syllable\\\"],[\\\"consonant_syllable\\\"],[\\\"vowel_syllable\\\"],[],[\\\"vowel_syllable\\\"],[\\\"vowel_syllable\\\"],[\\\"vowel_syllable\\\"],[\\\"vowel_syllable\\\"],[\\\"vowel_syllable\\\"],[],[\\\"vowel_syllable\\\"],[\\\"vowel_syllable\\\"],[\\\"broken_cluster\\\"],[\\\"standalone_cluster\\\"],[],[\\\"standalone_cluster\\\"],[\\\"standalone_cluster\\\"],[\\\"standalone_cluster\\\"],[\\\"standalone_cluster\\\"],[\\\"standalone_cluster\\\"],[],[\\\"standalone_cluster\\\"],[\\\"standalone_cluster\\\"],[],[\\\"consonant_syllable\\\"],[\\\"vowel_syllable\\\"],[\\\"standalone_cluster\\\"]]}');\\n $aa333a9607471296$exports = {};\\n $aa333a9607471296$exports = JSON.parse('{\\\"categories\\\":[\\\"O\\\",\\\"IND\\\",\\\"S\\\",\\\"GB\\\",\\\"B\\\",\\\"FM\\\",\\\"CGJ\\\",\\\"VMAbv\\\",\\\"VMPst\\\",\\\"VAbv\\\",\\\"VPst\\\",\\\"CMBlw\\\",\\\"VPre\\\",\\\"VBlw\\\",\\\"H\\\",\\\"VMBlw\\\",\\\"CMAbv\\\",\\\"MBlw\\\",\\\"CS\\\",\\\"R\\\",\\\"SUB\\\",\\\"MPst\\\",\\\"MPre\\\",\\\"FAbv\\\",\\\"FPst\\\",\\\"FBlw\\\",\\\"null\\\",\\\"SMAbv\\\",\\\"SMBlw\\\",\\\"VMPre\\\",\\\"ZWNJ\\\",\\\"ZWJ\\\",\\\"WJ\\\",\\\"M\\\",\\\"VS\\\",\\\"N\\\",\\\"HN\\\",\\\"MAbv\\\"],\\\"decompositions\\\":{\\\"2507\\\":[2503,2494],\\\"2508\\\":[2503,2519],\\\"2888\\\":[2887,2902],\\\"2891\\\":[2887,2878],\\\"2892\\\":[2887,2903],\\\"3018\\\":[3014,3006],\\\"3019\\\":[3015,3006],\\\"3020\\\":[3014,3031],\\\"3144\\\":[3142,3158],\\\"3264\\\":[3263,3285],\\\"3271\\\":[3270,3285],\\\"3272\\\":[3270,3286],\\\"3274\\\":[3270,3266],\\\"3275\\\":[3270,3266,3285],\\\"3402\\\":[3398,3390],\\\"3403\\\":[3399,3390],\\\"3404\\\":[3398,3415],\\\"3546\\\":[3545,3530],\\\"3548\\\":[3545,3535],\\\"3549\\\":[3545,3535,3530],\\\"3550\\\":[3545,3551],\\\"3635\\\":[3661,3634],\\\"3763\\\":[3789,3762],\\\"3955\\\":[3953,3954],\\\"3957\\\":[3953,3956],\\\"3958\\\":[4018,3968],\\\"3959\\\":[4018,3953,3968],\\\"3960\\\":[4019,3968],\\\"3961\\\":[4019,3953,3968],\\\"3969\\\":[3953,3968],\\\"6971\\\":[6970,6965],\\\"6973\\\":[6972,6965],\\\"6976\\\":[6974,6965],\\\"6977\\\":[6975,6965],\\\"6979\\\":[6978,6965],\\\"69934\\\":[69937,69927],\\\"69935\\\":[69938,69927],\\\"70475\\\":[70471,70462],\\\"70476\\\":[70471,70487],\\\"70843\\\":[70841,70842],\\\"70844\\\":[70841,70832],\\\"70846\\\":[70841,70845],\\\"71098\\\":[71096,71087],\\\"71099\\\":[71097,71087]},\\\"stateTable\\\":[[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],[2,2,3,4,4,5,0,6,7,8,9,10,11,12,13,14,15,16,0,17,18,11,19,20,21,22,0,0,0,23,0,0,2,0,0,24,0,25],[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,26,0,0,0],[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,27,28,0,0,0,0,0,27,0,0,0],[0,0,0,0,0,29,0,30,31,32,33,34,35,36,37,38,39,40,0,0,41,35,42,43,44,45,0,0,0,46,0,0,0,0,39,0,0,47],[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,5,0,6,7,0,0,0,0,0,0,14,0,0,0,0,0,0,0,20,21,22,0,0,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,5,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,20,21,22,0,0,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,5,0,6,7,8,9,0,0,12,0,14,0,0,0,0,0,0,0,20,21,22,0,0,0,23,0,0,0,0,0,0,0,0],[0,0,0,0,0,5,0,6,7,0,9,0,0,0,0,14,0,0,0,0,0,0,0,20,21,22,0,0,0,23,0,0,0,0,0,0,0,0],[0,0,0,0,0,5,0,6,7,8,9,10,11,12,13,14,0,16,0,0,18,11,19,20,21,22,0,0,0,23,0,0,0,0,0,0,0,25],[0,0,0,0,0,5,0,6,7,8,9,0,11,12,0,14,0,0,0,0,0,0,0,20,21,22,0,0,0,23,0,0,0,0,0,0,0,0],[0,0,0,0,0,5,0,6,7,0,9,0,0,12,0,14,0,0,0,0,0,0,0,20,21,22,0,0,0,23,0,0,0,0,0,0,0,0],[0,0,0,0,18,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,5,0,0,7,0,0,0,0,0,0,14,0,0,0,0,0,0,0,20,21,22,0,0,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,5,0,6,7,8,9,10,11,12,13,14,15,16,0,0,18,11,19,20,21,22,0,0,0,23,0,0,0,0,0,0,0,25],[0,0,0,0,0,5,0,6,7,8,9,0,11,12,0,14,0,0,0,0,0,11,0,20,21,22,0,0,0,23,0,0,0,0,0,0,0,0],[0,0,0,4,4,5,0,6,7,8,9,10,11,12,13,14,15,16,0,0,18,11,19,20,21,22,0,0,0,23,0,0,0,0,0,0,0,25],[0,0,0,0,0,5,0,6,7,8,9,48,11,12,13,14,48,16,0,0,18,11,19,20,21,22,0,0,0,23,0,0,0,0,49,0,0,25],[0,0,0,0,0,5,0,6,7,8,9,0,11,12,0,14,0,16,0,0,0,11,0,20,21,22,0,0,0,23,0,0,0,0,0,0,0,25],[0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,20,21,22,0,0,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,21,0,0,0,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,21,22,0,0,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,5,0,6,7,0,0,0,0,0,0,14,0,0,0,0,0,0,0,20,21,22,0,0,0,23,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,50,0,51,0],[0,0,0,0,0,5,0,6,7,8,9,0,11,12,0,14,0,16,0,0,0,11,0,20,21,22,0,0,0,23,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,27,28,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,28,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,29,0,30,31,0,0,0,0,0,0,38,0,0,0,0,0,0,0,43,44,45,0,0,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,29,0,0,31,0,0,0,0,0,0,0,0,0,0,0,0,0,0,43,44,45,0,0,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,29,0,30,31,32,33,0,0,36,0,38,0,0,0,0,0,0,0,43,44,45,0,0,0,46,0,0,0,0,0,0,0,0],[0,0,0,0,0,29,0,30,31,0,33,0,0,0,0,38,0,0,0,0,0,0,0,43,44,45,0,0,0,46,0,0,0,0,0,0,0,0],[0,0,0,0,0,29,0,30,31,32,33,34,35,36,37,38,0,40,0,0,41,35,42,43,44,45,0,0,0,46,0,0,0,0,0,0,0,47],[0,0,0,0,0,29,0,30,31,32,33,0,35,36,0,38,0,0,0,0,0,0,0,43,44,45,0,0,0,46,0,0,0,0,0,0,0,0],[0,0,0,0,0,29,0,30,31,0,33,0,0,36,0,38,0,0,0,0,0,0,0,43,44,45,0,0,0,46,0,0,0,0,0,0,0,0],[0,0,0,0,41,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,29,0,0,31,0,0,0,0,0,0,38,0,0,0,0,0,0,0,43,44,45,0,0,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,29,0,30,31,32,33,34,35,36,37,38,39,40,0,0,41,35,42,43,44,45,0,0,0,46,0,0,0,0,0,0,0,47],[0,0,0,0,0,29,0,30,31,32,33,0,35,36,0,38,0,0,0,0,0,35,0,43,44,45,0,0,0,46,0,0,0,0,0,0,0,0],[0,0,0,0,0,29,0,30,31,32,33,52,35,36,37,38,52,40,0,0,41,35,42,43,44,45,0,0,0,46,0,0,0,0,53,0,0,47],[0,0,0,0,0,29,0,30,31,32,33,0,35,36,0,38,0,40,0,0,0,35,0,43,44,45,0,0,0,46,0,0,0,0,0,0,0,47],[0,0,0,0,0,29,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,43,44,45,0,0,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,29,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,44,0,0,0,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,29,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,44,45,0,0,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,29,0,30,31,0,0,0,0,0,0,38,0,0,0,0,0,0,0,43,44,45,0,0,0,46,0,0,0,0,0,0,0,0],[0,0,0,0,0,29,0,30,31,32,33,0,35,36,0,38,0,40,0,0,0,35,0,43,44,45,0,0,0,46,0,0,0,0,0,0,0,0],[0,0,0,0,0,5,0,6,7,8,9,48,11,12,13,14,0,16,0,0,18,11,19,20,21,22,0,0,0,23,0,0,0,0,0,0,0,25],[0,0,0,0,0,5,0,6,7,8,9,48,11,12,13,14,48,16,0,0,18,11,19,20,21,22,0,0,0,23,0,0,0,0,0,0,0,25],[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,51,0],[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,54,0,0],[0,0,0,0,0,29,0,30,31,32,33,52,35,36,37,38,0,40,0,0,41,35,42,43,44,45,0,0,0,46,0,0,0,0,0,0,0,47],[0,0,0,0,0,29,0,30,31,32,33,52,35,36,37,38,52,40,0,0,41,35,42,43,44,45,0,0,0,46,0,0,0,0,0,0,0,47],[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,50,0,51,0]],\\\"accepting\\\":[false,true,true,true,true,true,true,true,true,true,true,true,true,false,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true],\\\"tags\\\":[[],[\\\"broken_cluster\\\"],[\\\"independent_cluster\\\"],[\\\"symbol_cluster\\\"],[\\\"standard_cluster\\\"],[\\\"broken_cluster\\\"],[\\\"broken_cluster\\\"],[\\\"broken_cluster\\\"],[\\\"broken_cluster\\\"],[\\\"broken_cluster\\\"],[\\\"broken_cluster\\\"],[\\\"broken_cluster\\\"],[\\\"broken_cluster\\\"],[],[\\\"broken_cluster\\\"],[\\\"broken_cluster\\\"],[\\\"broken_cluster\\\"],[\\\"broken_cluster\\\"],[\\\"broken_cluster\\\"],[\\\"broken_cluster\\\"],[\\\"broken_cluster\\\"],[\\\"broken_cluster\\\"],[\\\"broken_cluster\\\"],[\\\"broken_cluster\\\"],[\\\"numeral_cluster\\\"],[\\\"broken_cluster\\\"],[\\\"independent_cluster\\\"],[\\\"symbol_cluster\\\"],[\\\"symbol_cluster\\\"],[\\\"standard_cluster\\\"],[\\\"standard_cluster\\\"],[\\\"standard_cluster\\\"],[\\\"standard_cluster\\\"],[\\\"standard_cluster\\\"],[\\\"standard_cluster\\\"],[\\\"standard_cluster\\\"],[\\\"standard_cluster\\\"],[\\\"virama_terminated_cluster\\\"],[\\\"standard_cluster\\\"],[\\\"standard_cluster\\\"],[\\\"standard_cluster\\\"],[\\\"standard_cluster\\\"],[\\\"standard_cluster\\\"],[\\\"standard_cluster\\\"],[\\\"standard_cluster\\\"],[\\\"standard_cluster\\\"],[\\\"standard_cluster\\\"],[\\\"standard_cluster\\\"],[\\\"broken_cluster\\\"],[\\\"broken_cluster\\\"],[\\\"numeral_cluster\\\"],[\\\"number_joiner_terminated_cluster\\\"],[\\\"standard_cluster\\\"],[\\\"standard_cluster\\\"],[\\\"numeral_cluster\\\"]]}');\\n $90a9d3398ee54fe5$export$a513ea61a7bee91c = {\\n X: 1,\\n C: 2,\\n V: 4,\\n N: 8,\\n H: 16,\\n ZWNJ: 32,\\n ZWJ: 64,\\n M: 128,\\n SM: 256,\\n VD: 512,\\n A: 1024,\\n Placeholder: 2048,\\n Dotted_Circle: 4096,\\n RS: 8192,\\n Coeng: 16384,\\n Repha: 32768,\\n Ra: 65536,\\n CM: 131072,\\n Symbol: 262144\\n // Avagraha, etc that take marks (SM,A,VD).\\n };\\n $90a9d3398ee54fe5$export$1a1f61c9c4dd9df0 = {\\n Start: 1,\\n Ra_To_Become_Reph: 2,\\n Pre_M: 4,\\n Pre_C: 8,\\n Base_C: 16,\\n After_Main: 32,\\n Above_C: 64,\\n Before_Sub: 128,\\n Below_C: 256,\\n After_Sub: 512,\\n Before_Post: 1024,\\n Post_C: 2048,\\n After_Post: 4096,\\n Final_C: 8192,\\n SMVD: 16384,\\n End: 32768\\n };\\n $90a9d3398ee54fe5$export$8519deaa7de2b07 = $90a9d3398ee54fe5$export$a513ea61a7bee91c.C | $90a9d3398ee54fe5$export$a513ea61a7bee91c.Ra | $90a9d3398ee54fe5$export$a513ea61a7bee91c.CM | $90a9d3398ee54fe5$export$a513ea61a7bee91c.V | $90a9d3398ee54fe5$export$a513ea61a7bee91c.Placeholder | $90a9d3398ee54fe5$export$a513ea61a7bee91c.Dotted_Circle;\\n $90a9d3398ee54fe5$export$bbcd928767338e0d = $90a9d3398ee54fe5$export$a513ea61a7bee91c.ZWJ | $90a9d3398ee54fe5$export$a513ea61a7bee91c.ZWNJ;\\n $90a9d3398ee54fe5$export$ca9599b2a300afc = $90a9d3398ee54fe5$export$a513ea61a7bee91c.H | $90a9d3398ee54fe5$export$a513ea61a7bee91c.Coeng;\\n $90a9d3398ee54fe5$export$e99d119da76a0fc5 = {\\n Default: {\\n hasOldSpec: false,\\n virama: 0,\\n basePos: \\\"Last\\\",\\n rephPos: $90a9d3398ee54fe5$export$1a1f61c9c4dd9df0.Before_Post,\\n rephMode: \\\"Implicit\\\",\\n blwfMode: \\\"Pre_And_Post\\\"\\n },\\n Devanagari: {\\n hasOldSpec: true,\\n virama: 2381,\\n basePos: \\\"Last\\\",\\n rephPos: $90a9d3398ee54fe5$export$1a1f61c9c4dd9df0.Before_Post,\\n rephMode: \\\"Implicit\\\",\\n blwfMode: \\\"Pre_And_Post\\\"\\n },\\n Bengali: {\\n hasOldSpec: true,\\n virama: 2509,\\n basePos: \\\"Last\\\",\\n rephPos: $90a9d3398ee54fe5$export$1a1f61c9c4dd9df0.After_Sub,\\n rephMode: \\\"Implicit\\\",\\n blwfMode: \\\"Pre_And_Post\\\"\\n },\\n Gurmukhi: {\\n hasOldSpec: true,\\n virama: 2637,\\n basePos: \\\"Last\\\",\\n rephPos: $90a9d3398ee54fe5$export$1a1f61c9c4dd9df0.Before_Sub,\\n rephMode: \\\"Implicit\\\",\\n blwfMode: \\\"Pre_And_Post\\\"\\n },\\n Gujarati: {\\n hasOldSpec: true,\\n virama: 2765,\\n basePos: \\\"Last\\\",\\n rephPos: $90a9d3398ee54fe5$export$1a1f61c9c4dd9df0.Before_Post,\\n rephMode: \\\"Implicit\\\",\\n blwfMode: \\\"Pre_And_Post\\\"\\n },\\n Oriya: {\\n hasOldSpec: true,\\n virama: 2893,\\n basePos: \\\"Last\\\",\\n rephPos: $90a9d3398ee54fe5$export$1a1f61c9c4dd9df0.After_Main,\\n rephMode: \\\"Implicit\\\",\\n blwfMode: \\\"Pre_And_Post\\\"\\n },\\n Tamil: {\\n hasOldSpec: true,\\n virama: 3021,\\n basePos: \\\"Last\\\",\\n rephPos: $90a9d3398ee54fe5$export$1a1f61c9c4dd9df0.After_Post,\\n rephMode: \\\"Implicit\\\",\\n blwfMode: \\\"Pre_And_Post\\\"\\n },\\n Telugu: {\\n hasOldSpec: true,\\n virama: 3149,\\n basePos: \\\"Last\\\",\\n rephPos: $90a9d3398ee54fe5$export$1a1f61c9c4dd9df0.After_Post,\\n rephMode: \\\"Explicit\\\",\\n blwfMode: \\\"Post_Only\\\"\\n },\\n Kannada: {\\n hasOldSpec: true,\\n virama: 3277,\\n basePos: \\\"Last\\\",\\n rephPos: $90a9d3398ee54fe5$export$1a1f61c9c4dd9df0.After_Post,\\n rephMode: \\\"Implicit\\\",\\n blwfMode: \\\"Post_Only\\\"\\n },\\n Malayalam: {\\n hasOldSpec: true,\\n virama: 3405,\\n basePos: \\\"Last\\\",\\n rephPos: $90a9d3398ee54fe5$export$1a1f61c9c4dd9df0.After_Main,\\n rephMode: \\\"Log_Repha\\\",\\n blwfMode: \\\"Pre_And_Post\\\"\\n },\\n // Handled by UniversalShaper\\n // Sinhala: {\\n // hasOldSpec: false,\\n // virama: 0x0DCA,\\n // basePos: 'Last_Sinhala',\\n // rephPos: POSITIONS.After_Main,\\n // rephMode: 'Explicit',\\n // blwfMode: 'Pre_And_Post'\\n // },\\n Khmer: {\\n hasOldSpec: false,\\n virama: 6098,\\n basePos: \\\"First\\\",\\n rephPos: $90a9d3398ee54fe5$export$1a1f61c9c4dd9df0.Ra_To_Become_Reph,\\n rephMode: \\\"Vis_Repha\\\",\\n blwfMode: \\\"Pre_And_Post\\\"\\n }\\n };\\n $90a9d3398ee54fe5$export$f647c9cfdd77d95a = {\\n // Khmer\\n 6078: [\\n 6081,\\n 6078\\n ],\\n 6079: [\\n 6081,\\n 6079\\n ],\\n 6080: [\\n 6081,\\n 6080\\n ],\\n 6084: [\\n 6081,\\n 6084\\n ],\\n 6085: [\\n 6081,\\n 6085\\n ]\\n };\\n ({ decompositions: $7826f90f6f0cecc9$var$decompositions } = (0, /* @__PURE__ */ $parcel$interopDefault2($aa333a9607471296$exports)));\\n $7826f90f6f0cecc9$var$trie = new (0, import_unicode_trie2.default)((0, $12727730ddfc8bfe$export$94fdf11bafc8de6b)(\\\"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\\\"));\\n $7826f90f6f0cecc9$var$stateMachine = new (0, import_dfa.default)((0, /* @__PURE__ */ $parcel$interopDefault2($4b0735ca6c692ea5$exports)));\\n $7826f90f6f0cecc9$export$2e2bcd8739ae039 = class extends (0, $649970d87335b30f$export$2e2bcd8739ae039) {\\n static planFeatures(plan) {\\n plan.addStage($7826f90f6f0cecc9$var$setupSyllables);\\n plan.addStage([\\n \\\"locl\\\",\\n \\\"ccmp\\\"\\n ]);\\n plan.addStage($7826f90f6f0cecc9$var$initialReordering);\\n plan.addStage(\\\"nukt\\\");\\n plan.addStage(\\\"akhn\\\");\\n plan.addStage(\\\"rphf\\\", false);\\n plan.addStage(\\\"rkrf\\\");\\n plan.addStage(\\\"pref\\\", false);\\n plan.addStage(\\\"blwf\\\", false);\\n plan.addStage(\\\"abvf\\\", false);\\n plan.addStage(\\\"half\\\", false);\\n plan.addStage(\\\"pstf\\\", false);\\n plan.addStage(\\\"vatu\\\");\\n plan.addStage(\\\"cjct\\\");\\n plan.addStage(\\\"cfar\\\", false);\\n plan.addStage($7826f90f6f0cecc9$var$finalReordering);\\n plan.addStage({\\n local: [\\n \\\"init\\\"\\n ],\\n global: [\\n \\\"pres\\\",\\n \\\"abvs\\\",\\n \\\"blws\\\",\\n \\\"psts\\\",\\n \\\"haln\\\",\\n \\\"dist\\\",\\n \\\"abvm\\\",\\n \\\"blwm\\\",\\n \\\"calt\\\",\\n \\\"clig\\\"\\n ]\\n });\\n plan.unicodeScript = $130d1a642ebcd2b7$export$ce50e82f12a827a4(plan.script);\\n plan.indicConfig = (0, $90a9d3398ee54fe5$export$e99d119da76a0fc5)[plan.unicodeScript] || (0, $90a9d3398ee54fe5$export$e99d119da76a0fc5).Default;\\n plan.isOldSpec = plan.indicConfig.hasOldSpec && plan.script[plan.script.length - 1] !== \\\"2\\\";\\n }\\n static assignFeatures(plan, glyphs) {\\n for (let i = glyphs.length - 1; i >= 0; i--) {\\n let codepoint = glyphs[i].codePoints[0];\\n let d = (0, $90a9d3398ee54fe5$export$f647c9cfdd77d95a)[codepoint] || $7826f90f6f0cecc9$var$decompositions[codepoint];\\n if (d) {\\n let decomposed = d.map((c) => {\\n let g = plan.font.glyphForCodePoint(c);\\n return new (0, $10e7b257e1a9a756$export$2e2bcd8739ae039)(plan.font, g.id, [\\n c\\n ], glyphs[i].features);\\n });\\n glyphs.splice(i, 1, ...decomposed);\\n }\\n }\\n }\\n };\\n (0, _define_property)($7826f90f6f0cecc9$export$2e2bcd8739ae039, \\\"zeroMarkWidths\\\", \\\"NONE\\\");\\n $7826f90f6f0cecc9$var$IndicInfo = class {\\n constructor(category, position, syllableType, syllable) {\\n this.category = category;\\n this.position = position;\\n this.syllableType = syllableType;\\n this.syllable = syllable;\\n }\\n };\\n ({ categories: $7ab494fe977143c6$var$categories, decompositions: $7ab494fe977143c6$var$decompositions } = (0, /* @__PURE__ */ $parcel$interopDefault2($aa333a9607471296$exports)));\\n $7ab494fe977143c6$var$trie = new (0, import_unicode_trie2.default)((0, $12727730ddfc8bfe$export$94fdf11bafc8de6b)(\\\"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\\\"));\\n $7ab494fe977143c6$var$stateMachine = new (0, import_dfa.default)((0, /* @__PURE__ */ $parcel$interopDefault2($aa333a9607471296$exports)));\\n $7ab494fe977143c6$export$2e2bcd8739ae039 = class extends (0, $649970d87335b30f$export$2e2bcd8739ae039) {\\n static planFeatures(plan) {\\n plan.addStage($7ab494fe977143c6$var$setupSyllables);\\n plan.addStage([\\n \\\"locl\\\",\\n \\\"ccmp\\\",\\n \\\"nukt\\\",\\n \\\"akhn\\\"\\n ]);\\n plan.addStage($7ab494fe977143c6$var$clearSubstitutionFlags);\\n plan.addStage([\\n \\\"rphf\\\"\\n ], false);\\n plan.addStage($7ab494fe977143c6$var$recordRphf);\\n plan.addStage($7ab494fe977143c6$var$clearSubstitutionFlags);\\n plan.addStage([\\n \\\"pref\\\"\\n ]);\\n plan.addStage($7ab494fe977143c6$var$recordPref);\\n plan.addStage([\\n \\\"rkrf\\\",\\n \\\"abvf\\\",\\n \\\"blwf\\\",\\n \\\"half\\\",\\n \\\"pstf\\\",\\n \\\"vatu\\\",\\n \\\"cjct\\\"\\n ]);\\n plan.addStage($7ab494fe977143c6$var$reorder);\\n plan.addStage([\\n \\\"abvs\\\",\\n \\\"blws\\\",\\n \\\"pres\\\",\\n \\\"psts\\\",\\n \\\"dist\\\",\\n \\\"abvm\\\",\\n \\\"blwm\\\"\\n ]);\\n }\\n static assignFeatures(plan, glyphs) {\\n for (let i = glyphs.length - 1; i >= 0; i--) {\\n let codepoint = glyphs[i].codePoints[0];\\n if ($7ab494fe977143c6$var$decompositions[codepoint]) {\\n let decomposed = $7ab494fe977143c6$var$decompositions[codepoint].map((c) => {\\n let g = plan.font.glyphForCodePoint(c);\\n return new (0, $10e7b257e1a9a756$export$2e2bcd8739ae039)(plan.font, g.id, [\\n c\\n ], glyphs[i].features);\\n });\\n glyphs.splice(i, 1, ...decomposed);\\n }\\n }\\n }\\n };\\n (0, _define_property)($7ab494fe977143c6$export$2e2bcd8739ae039, \\\"zeroMarkWidths\\\", \\\"BEFORE_GPOS\\\");\\n $7ab494fe977143c6$var$USEInfo = class {\\n constructor(category, syllableType, syllable) {\\n this.category = category;\\n this.syllableType = syllableType;\\n this.syllable = syllable;\\n }\\n };\\n $102b6fe50f1d50b4$var$SHAPERS = {\\n arab: (0, $764eb544bbe1ccf0$export$2e2bcd8739ae039),\\n mong: (0, $764eb544bbe1ccf0$export$2e2bcd8739ae039),\\n syrc: (0, $764eb544bbe1ccf0$export$2e2bcd8739ae039),\\n \\\"nko \\\": (0, $764eb544bbe1ccf0$export$2e2bcd8739ae039),\\n phag: (0, $764eb544bbe1ccf0$export$2e2bcd8739ae039),\\n mand: (0, $764eb544bbe1ccf0$export$2e2bcd8739ae039),\\n mani: (0, $764eb544bbe1ccf0$export$2e2bcd8739ae039),\\n phlp: (0, $764eb544bbe1ccf0$export$2e2bcd8739ae039),\\n hang: (0, $e1c6bbc8cb416f8c$export$2e2bcd8739ae039),\\n bng2: (0, $7826f90f6f0cecc9$export$2e2bcd8739ae039),\\n beng: (0, $7826f90f6f0cecc9$export$2e2bcd8739ae039),\\n dev2: (0, $7826f90f6f0cecc9$export$2e2bcd8739ae039),\\n deva: (0, $7826f90f6f0cecc9$export$2e2bcd8739ae039),\\n gjr2: (0, $7826f90f6f0cecc9$export$2e2bcd8739ae039),\\n gujr: (0, $7826f90f6f0cecc9$export$2e2bcd8739ae039),\\n guru: (0, $7826f90f6f0cecc9$export$2e2bcd8739ae039),\\n gur2: (0, $7826f90f6f0cecc9$export$2e2bcd8739ae039),\\n knda: (0, $7826f90f6f0cecc9$export$2e2bcd8739ae039),\\n knd2: (0, $7826f90f6f0cecc9$export$2e2bcd8739ae039),\\n mlm2: (0, $7826f90f6f0cecc9$export$2e2bcd8739ae039),\\n mlym: (0, $7826f90f6f0cecc9$export$2e2bcd8739ae039),\\n ory2: (0, $7826f90f6f0cecc9$export$2e2bcd8739ae039),\\n orya: (0, $7826f90f6f0cecc9$export$2e2bcd8739ae039),\\n taml: (0, $7826f90f6f0cecc9$export$2e2bcd8739ae039),\\n tml2: (0, $7826f90f6f0cecc9$export$2e2bcd8739ae039),\\n telu: (0, $7826f90f6f0cecc9$export$2e2bcd8739ae039),\\n tel2: (0, $7826f90f6f0cecc9$export$2e2bcd8739ae039),\\n khmr: (0, $7826f90f6f0cecc9$export$2e2bcd8739ae039),\\n bali: (0, $7ab494fe977143c6$export$2e2bcd8739ae039),\\n batk: (0, $7ab494fe977143c6$export$2e2bcd8739ae039),\\n brah: (0, $7ab494fe977143c6$export$2e2bcd8739ae039),\\n bugi: (0, $7ab494fe977143c6$export$2e2bcd8739ae039),\\n buhd: (0, $7ab494fe977143c6$export$2e2bcd8739ae039),\\n cakm: (0, $7ab494fe977143c6$export$2e2bcd8739ae039),\\n cham: (0, $7ab494fe977143c6$export$2e2bcd8739ae039),\\n dupl: (0, $7ab494fe977143c6$export$2e2bcd8739ae039),\\n egyp: (0, $7ab494fe977143c6$export$2e2bcd8739ae039),\\n gran: (0, $7ab494fe977143c6$export$2e2bcd8739ae039),\\n hano: (0, $7ab494fe977143c6$export$2e2bcd8739ae039),\\n java: (0, $7ab494fe977143c6$export$2e2bcd8739ae039),\\n kthi: (0, $7ab494fe977143c6$export$2e2bcd8739ae039),\\n kali: (0, $7ab494fe977143c6$export$2e2bcd8739ae039),\\n khar: (0, $7ab494fe977143c6$export$2e2bcd8739ae039),\\n khoj: (0, $7ab494fe977143c6$export$2e2bcd8739ae039),\\n sind: (0, $7ab494fe977143c6$export$2e2bcd8739ae039),\\n lepc: (0, $7ab494fe977143c6$export$2e2bcd8739ae039),\\n limb: (0, $7ab494fe977143c6$export$2e2bcd8739ae039),\\n mahj: (0, $7ab494fe977143c6$export$2e2bcd8739ae039),\\n // mand: UniversalShaper, // Mandaic\\n // mani: UniversalShaper, // Manichaean\\n mtei: (0, $7ab494fe977143c6$export$2e2bcd8739ae039),\\n modi: (0, $7ab494fe977143c6$export$2e2bcd8739ae039),\\n // mong: UniversalShaper, // Mongolian\\n // 'nko ': UniversalShaper, // N’Ko\\n hmng: (0, $7ab494fe977143c6$export$2e2bcd8739ae039),\\n // phag: UniversalShaper, // Phags-pa\\n // phlp: UniversalShaper, // Psalter Pahlavi\\n rjng: (0, $7ab494fe977143c6$export$2e2bcd8739ae039),\\n saur: (0, $7ab494fe977143c6$export$2e2bcd8739ae039),\\n shrd: (0, $7ab494fe977143c6$export$2e2bcd8739ae039),\\n sidd: (0, $7ab494fe977143c6$export$2e2bcd8739ae039),\\n sinh: (0, $7826f90f6f0cecc9$export$2e2bcd8739ae039),\\n sund: (0, $7ab494fe977143c6$export$2e2bcd8739ae039),\\n sylo: (0, $7ab494fe977143c6$export$2e2bcd8739ae039),\\n tglg: (0, $7ab494fe977143c6$export$2e2bcd8739ae039),\\n tagb: (0, $7ab494fe977143c6$export$2e2bcd8739ae039),\\n tale: (0, $7ab494fe977143c6$export$2e2bcd8739ae039),\\n lana: (0, $7ab494fe977143c6$export$2e2bcd8739ae039),\\n tavt: (0, $7ab494fe977143c6$export$2e2bcd8739ae039),\\n takr: (0, $7ab494fe977143c6$export$2e2bcd8739ae039),\\n tibt: (0, $7ab494fe977143c6$export$2e2bcd8739ae039),\\n tfng: (0, $7ab494fe977143c6$export$2e2bcd8739ae039),\\n tirh: (0, $7ab494fe977143c6$export$2e2bcd8739ae039),\\n latn: (0, $649970d87335b30f$export$2e2bcd8739ae039),\\n DFLT: (0, $649970d87335b30f$export$2e2bcd8739ae039)\\n };\\n $0a876c45f1f7c41c$export$2e2bcd8739ae039 = class extends (0, $a83b9c36aaa94fd3$export$2e2bcd8739ae039) {\\n applyLookup(lookupType, table) {\\n switch (lookupType) {\\n case 1: {\\n let index = this.coverageIndex(table.coverage);\\n if (index === -1) return false;\\n let glyph = this.glyphIterator.cur;\\n switch (table.version) {\\n case 1:\\n glyph.id = glyph.id + table.deltaGlyphID & 65535;\\n break;\\n case 2:\\n glyph.id = table.substitute.get(index);\\n break;\\n }\\n return true;\\n }\\n case 2: {\\n let index = this.coverageIndex(table.coverage);\\n if (index !== -1) {\\n let sequence = table.sequences.get(index);\\n if (sequence.length === 0) {\\n this.glyphs.splice(this.glyphIterator.index, 1);\\n return true;\\n }\\n this.glyphIterator.cur.id = sequence[0];\\n this.glyphIterator.cur.ligatureComponent = 0;\\n let features = this.glyphIterator.cur.features;\\n let curGlyph = this.glyphIterator.cur;\\n let replacement = sequence.slice(1).map((gid, i) => {\\n let glyph = new (0, $10e7b257e1a9a756$export$2e2bcd8739ae039)(this.font, gid, void 0, features);\\n glyph.shaperInfo = curGlyph.shaperInfo;\\n glyph.isLigated = curGlyph.isLigated;\\n glyph.ligatureComponent = i + 1;\\n glyph.substituted = true;\\n glyph.isMultiplied = true;\\n return glyph;\\n });\\n this.glyphs.splice(this.glyphIterator.index + 1, 0, ...replacement);\\n return true;\\n }\\n return false;\\n }\\n case 3: {\\n let index = this.coverageIndex(table.coverage);\\n if (index !== -1) {\\n let USER_INDEX = 0;\\n this.glyphIterator.cur.id = table.alternateSet.get(index)[USER_INDEX];\\n return true;\\n }\\n return false;\\n }\\n case 4: {\\n let index = this.coverageIndex(table.coverage);\\n if (index === -1) return false;\\n for (let ligature of table.ligatureSets.get(index)) {\\n let matched = this.sequenceMatchIndices(1, ligature.components);\\n if (!matched) continue;\\n let curGlyph = this.glyphIterator.cur;\\n let characters = curGlyph.codePoints.slice();\\n for (let index2 of matched) characters.push(...this.glyphs[index2].codePoints);\\n let ligatureGlyph = new (0, $10e7b257e1a9a756$export$2e2bcd8739ae039)(this.font, ligature.glyph, characters, curGlyph.features);\\n ligatureGlyph.shaperInfo = curGlyph.shaperInfo;\\n ligatureGlyph.isLigated = true;\\n ligatureGlyph.substituted = true;\\n let isMarkLigature = curGlyph.isMark;\\n for (let i = 0; i < matched.length && isMarkLigature; i++) isMarkLigature = this.glyphs[matched[i]].isMark;\\n ligatureGlyph.ligatureID = isMarkLigature ? null : this.ligatureID++;\\n let lastLigID = curGlyph.ligatureID;\\n let lastNumComps = curGlyph.codePoints.length;\\n let curComps = lastNumComps;\\n let idx = this.glyphIterator.index + 1;\\n for (let matchIndex of matched) {\\n if (isMarkLigature) idx = matchIndex;\\n else while (idx < matchIndex) {\\n var ligatureComponent = curComps - lastNumComps + Math.min(this.glyphs[idx].ligatureComponent || 1, lastNumComps);\\n this.glyphs[idx].ligatureID = ligatureGlyph.ligatureID;\\n this.glyphs[idx].ligatureComponent = ligatureComponent;\\n idx++;\\n }\\n lastLigID = this.glyphs[idx].ligatureID;\\n lastNumComps = this.glyphs[idx].codePoints.length;\\n curComps += lastNumComps;\\n idx++;\\n }\\n if (lastLigID && !isMarkLigature) for (let i = idx; i < this.glyphs.length; i++) {\\n if (this.glyphs[i].ligatureID === lastLigID) {\\n var ligatureComponent = curComps - lastNumComps + Math.min(this.glyphs[i].ligatureComponent || 1, lastNumComps);\\n this.glyphs[i].ligatureComponent = ligatureComponent;\\n } else break;\\n }\\n for (let i = matched.length - 1; i >= 0; i--) this.glyphs.splice(matched[i], 1);\\n this.glyphs[this.glyphIterator.index] = ligatureGlyph;\\n return true;\\n }\\n return false;\\n }\\n case 5:\\n return this.applyContext(table);\\n case 6:\\n return this.applyChainingContext(table);\\n case 7:\\n return this.applyLookup(table.lookupType, table.extension);\\n default:\\n throw new Error(`GSUB lookupType ${lookupType} is not supported`);\\n }\\n }\\n };\\n $c96c93587d49c14d$export$2e2bcd8739ae039 = class extends (0, $a83b9c36aaa94fd3$export$2e2bcd8739ae039) {\\n applyPositionValue(sequenceIndex, value) {\\n let position = this.positions[this.glyphIterator.peekIndex(sequenceIndex)];\\n if (value.xAdvance != null) position.xAdvance += value.xAdvance;\\n if (value.yAdvance != null) position.yAdvance += value.yAdvance;\\n if (value.xPlacement != null) position.xOffset += value.xPlacement;\\n if (value.yPlacement != null) position.yOffset += value.yPlacement;\\n let variationProcessor = this.font._variationProcessor;\\n let variationStore = this.font.GDEF && this.font.GDEF.itemVariationStore;\\n if (variationProcessor && variationStore) {\\n if (value.xPlaDevice) position.xOffset += variationProcessor.getDelta(variationStore, value.xPlaDevice.a, value.xPlaDevice.b);\\n if (value.yPlaDevice) position.yOffset += variationProcessor.getDelta(variationStore, value.yPlaDevice.a, value.yPlaDevice.b);\\n if (value.xAdvDevice) position.xAdvance += variationProcessor.getDelta(variationStore, value.xAdvDevice.a, value.xAdvDevice.b);\\n if (value.yAdvDevice) position.yAdvance += variationProcessor.getDelta(variationStore, value.yAdvDevice.a, value.yAdvDevice.b);\\n }\\n }\\n applyLookup(lookupType, table) {\\n switch (lookupType) {\\n case 1: {\\n let index = this.coverageIndex(table.coverage);\\n if (index === -1) return false;\\n switch (table.version) {\\n case 1:\\n this.applyPositionValue(0, table.value);\\n break;\\n case 2:\\n this.applyPositionValue(0, table.values.get(index));\\n break;\\n }\\n return true;\\n }\\n case 2: {\\n let nextGlyph = this.glyphIterator.peek();\\n if (!nextGlyph) return false;\\n let index = this.coverageIndex(table.coverage);\\n if (index === -1) return false;\\n switch (table.version) {\\n case 1:\\n let set = table.pairSets.get(index);\\n for (let pair2 of set) if (pair2.secondGlyph === nextGlyph.id) {\\n this.applyPositionValue(0, pair2.value1);\\n this.applyPositionValue(1, pair2.value2);\\n return true;\\n }\\n return false;\\n case 2:\\n let class1 = this.getClassID(this.glyphIterator.cur.id, table.classDef1);\\n let class2 = this.getClassID(nextGlyph.id, table.classDef2);\\n if (class1 === -1 || class2 === -1) return false;\\n var pair = table.classRecords.get(class1).get(class2);\\n this.applyPositionValue(0, pair.value1);\\n this.applyPositionValue(1, pair.value2);\\n return true;\\n }\\n }\\n case 3: {\\n let nextIndex = this.glyphIterator.peekIndex();\\n let nextGlyph = this.glyphs[nextIndex];\\n if (!nextGlyph) return false;\\n let curRecord = table.entryExitRecords[this.coverageIndex(table.coverage)];\\n if (!curRecord || !curRecord.exitAnchor) return false;\\n let nextRecord = table.entryExitRecords[this.coverageIndex(table.coverage, nextGlyph.id)];\\n if (!nextRecord || !nextRecord.entryAnchor) return false;\\n let entry = this.getAnchor(nextRecord.entryAnchor);\\n let exit = this.getAnchor(curRecord.exitAnchor);\\n let cur = this.positions[this.glyphIterator.index];\\n let next = this.positions[nextIndex];\\n let d;\\n switch (this.direction) {\\n case \\\"ltr\\\":\\n cur.xAdvance = exit.x + cur.xOffset;\\n d = entry.x + next.xOffset;\\n next.xAdvance -= d;\\n next.xOffset -= d;\\n break;\\n case \\\"rtl\\\":\\n d = exit.x + cur.xOffset;\\n cur.xAdvance -= d;\\n cur.xOffset -= d;\\n next.xAdvance = entry.x + next.xOffset;\\n break;\\n }\\n if (this.glyphIterator.flags.rightToLeft) {\\n this.glyphIterator.cur.cursiveAttachment = nextIndex;\\n cur.yOffset = entry.y - exit.y;\\n } else {\\n nextGlyph.cursiveAttachment = this.glyphIterator.index;\\n cur.yOffset = exit.y - entry.y;\\n }\\n return true;\\n }\\n case 4: {\\n let markIndex = this.coverageIndex(table.markCoverage);\\n if (markIndex === -1) return false;\\n let baseGlyphIndex = this.glyphIterator.index;\\n while (--baseGlyphIndex >= 0 && (this.glyphs[baseGlyphIndex].isMark || this.glyphs[baseGlyphIndex].ligatureComponent > 0)) ;\\n if (baseGlyphIndex < 0) return false;\\n let baseIndex = this.coverageIndex(table.baseCoverage, this.glyphs[baseGlyphIndex].id);\\n if (baseIndex === -1) return false;\\n let markRecord = table.markArray[markIndex];\\n let baseAnchor = table.baseArray[baseIndex][markRecord.class];\\n this.applyAnchor(markRecord, baseAnchor, baseGlyphIndex);\\n return true;\\n }\\n case 5: {\\n let markIndex = this.coverageIndex(table.markCoverage);\\n if (markIndex === -1) return false;\\n let baseGlyphIndex = this.glyphIterator.index;\\n while (--baseGlyphIndex >= 0 && this.glyphs[baseGlyphIndex].isMark) ;\\n if (baseGlyphIndex < 0) return false;\\n let ligIndex = this.coverageIndex(table.ligatureCoverage, this.glyphs[baseGlyphIndex].id);\\n if (ligIndex === -1) return false;\\n let ligAttach = table.ligatureArray[ligIndex];\\n let markGlyph = this.glyphIterator.cur;\\n let ligGlyph = this.glyphs[baseGlyphIndex];\\n let compIndex = ligGlyph.ligatureID && ligGlyph.ligatureID === markGlyph.ligatureID && markGlyph.ligatureComponent > 0 ? Math.min(markGlyph.ligatureComponent, ligGlyph.codePoints.length) - 1 : ligGlyph.codePoints.length - 1;\\n let markRecord = table.markArray[markIndex];\\n let baseAnchor = ligAttach[compIndex][markRecord.class];\\n this.applyAnchor(markRecord, baseAnchor, baseGlyphIndex);\\n return true;\\n }\\n case 6: {\\n let mark1Index = this.coverageIndex(table.mark1Coverage);\\n if (mark1Index === -1) return false;\\n let prevIndex = this.glyphIterator.peekIndex(-1);\\n let prev = this.glyphs[prevIndex];\\n if (!prev || !prev.isMark) return false;\\n let cur = this.glyphIterator.cur;\\n let good = false;\\n if (cur.ligatureID === prev.ligatureID) {\\n if (!cur.ligatureID) good = true;\\n else if (cur.ligatureComponent === prev.ligatureComponent) good = true;\\n } else if (cur.ligatureID && !cur.ligatureComponent || prev.ligatureID && !prev.ligatureComponent) good = true;\\n if (!good) return false;\\n let mark2Index = this.coverageIndex(table.mark2Coverage, prev.id);\\n if (mark2Index === -1) return false;\\n let markRecord = table.mark1Array[mark1Index];\\n let baseAnchor = table.mark2Array[mark2Index][markRecord.class];\\n this.applyAnchor(markRecord, baseAnchor, prevIndex);\\n return true;\\n }\\n case 7:\\n return this.applyContext(table);\\n case 8:\\n return this.applyChainingContext(table);\\n case 9:\\n return this.applyLookup(table.lookupType, table.extension);\\n default:\\n throw new Error(`Unsupported GPOS table: ${lookupType}`);\\n }\\n }\\n applyAnchor(markRecord, baseAnchor, baseGlyphIndex) {\\n let baseCoords = this.getAnchor(baseAnchor);\\n let markCoords = this.getAnchor(markRecord.markAnchor);\\n let basePos = this.positions[baseGlyphIndex];\\n let markPos = this.positions[this.glyphIterator.index];\\n markPos.xOffset = baseCoords.x - markCoords.x;\\n markPos.yOffset = baseCoords.y - markCoords.y;\\n this.glyphIterator.cur.markAttachment = baseGlyphIndex;\\n }\\n getAnchor(anchor) {\\n let x = anchor.xCoordinate;\\n let y = anchor.yCoordinate;\\n let variationProcessor = this.font._variationProcessor;\\n let variationStore = this.font.GDEF && this.font.GDEF.itemVariationStore;\\n if (variationProcessor && variationStore) {\\n if (anchor.xDeviceTable) x += variationProcessor.getDelta(variationStore, anchor.xDeviceTable.a, anchor.xDeviceTable.b);\\n if (anchor.yDeviceTable) y += variationProcessor.getDelta(variationStore, anchor.yDeviceTable.a, anchor.yDeviceTable.b);\\n }\\n return {\\n x,\\n y\\n };\\n }\\n applyFeatures(userFeatures, glyphs, advances) {\\n super.applyFeatures(userFeatures, glyphs, advances);\\n for (var i = 0; i < this.glyphs.length; i++) this.fixCursiveAttachment(i);\\n this.fixMarkAttachment();\\n }\\n fixCursiveAttachment(i) {\\n let glyph = this.glyphs[i];\\n if (glyph.cursiveAttachment != null) {\\n let j = glyph.cursiveAttachment;\\n glyph.cursiveAttachment = null;\\n this.fixCursiveAttachment(j);\\n this.positions[i].yOffset += this.positions[j].yOffset;\\n }\\n }\\n fixMarkAttachment() {\\n for (let i = 0; i < this.glyphs.length; i++) {\\n let glyph = this.glyphs[i];\\n if (glyph.markAttachment != null) {\\n let j = glyph.markAttachment;\\n this.positions[i].xOffset += this.positions[j].xOffset;\\n this.positions[i].yOffset += this.positions[j].yOffset;\\n if (this.direction === \\\"ltr\\\") for (let k = j; k < i; k++) {\\n this.positions[i].xOffset -= this.positions[k].xAdvance;\\n this.positions[i].yOffset -= this.positions[k].yAdvance;\\n }\\n else for (let k = j + 1; k < i + 1; k++) {\\n this.positions[i].xOffset += this.positions[k].xAdvance;\\n this.positions[i].yOffset += this.positions[k].yAdvance;\\n }\\n }\\n }\\n }\\n };\\n $a62492810de27e3d$export$2e2bcd8739ae039 = class {\\n setup(glyphRun) {\\n this.glyphInfos = glyphRun.glyphs.map((glyph) => new (0, $10e7b257e1a9a756$export$2e2bcd8739ae039)(this.font, glyph.id, [\\n ...glyph.codePoints\\n ]));\\n let script = null;\\n if (this.GPOSProcessor) script = this.GPOSProcessor.selectScript(glyphRun.script, glyphRun.language, glyphRun.direction);\\n if (this.GSUBProcessor) script = this.GSUBProcessor.selectScript(glyphRun.script, glyphRun.language, glyphRun.direction);\\n this.shaper = $102b6fe50f1d50b4$export$7877a478dd30fd3d(script);\\n this.plan = new (0, $94d7a73bd2edfc9a$export$2e2bcd8739ae039)(this.font, script, glyphRun.direction);\\n this.shaper.plan(this.plan, this.glyphInfos, glyphRun.features);\\n for (let key in this.plan.allFeatures) glyphRun.features[key] = true;\\n }\\n substitute(glyphRun) {\\n if (this.GSUBProcessor) {\\n this.plan.process(this.GSUBProcessor, this.glyphInfos);\\n glyphRun.glyphs = this.glyphInfos.map((glyphInfo) => this.font.getGlyph(glyphInfo.id, glyphInfo.codePoints));\\n }\\n }\\n position(glyphRun) {\\n if (this.shaper.zeroMarkWidths === \\\"BEFORE_GPOS\\\") this.zeroMarkAdvances(glyphRun.positions);\\n if (this.GPOSProcessor) this.plan.process(this.GPOSProcessor, this.glyphInfos, glyphRun.positions);\\n if (this.shaper.zeroMarkWidths === \\\"AFTER_GPOS\\\") this.zeroMarkAdvances(glyphRun.positions);\\n if (glyphRun.direction === \\\"rtl\\\") {\\n glyphRun.glyphs.reverse();\\n glyphRun.positions.reverse();\\n }\\n return this.GPOSProcessor && this.GPOSProcessor.features;\\n }\\n zeroMarkAdvances(positions) {\\n for (let i = 0; i < this.glyphInfos.length; i++) if (this.glyphInfos[i].isMark) {\\n positions[i].xAdvance = 0;\\n positions[i].yAdvance = 0;\\n }\\n }\\n cleanup() {\\n this.glyphInfos = null;\\n this.plan = null;\\n this.shaper = null;\\n }\\n getAvailableFeatures(script, language) {\\n let features = [];\\n if (this.GSUBProcessor) {\\n this.GSUBProcessor.selectScript(script, language);\\n features.push(...Object.keys(this.GSUBProcessor.features));\\n }\\n if (this.GPOSProcessor) {\\n this.GPOSProcessor.selectScript(script, language);\\n features.push(...Object.keys(this.GPOSProcessor.features));\\n }\\n return features;\\n }\\n constructor(font) {\\n this.font = font;\\n this.glyphInfos = null;\\n this.plan = null;\\n this.GSUBProcessor = null;\\n this.GPOSProcessor = null;\\n this.fallbackPosition = true;\\n if (font.GSUB) this.GSUBProcessor = new (0, $0a876c45f1f7c41c$export$2e2bcd8739ae039)(font, font.GSUB);\\n if (font.GPOS) this.GPOSProcessor = new (0, $c96c93587d49c14d$export$2e2bcd8739ae039)(font, font.GPOS);\\n }\\n };\\n $4c0a7fa5df7a9ab1$export$2e2bcd8739ae039 = class {\\n layout(string, features, script, language, direction) {\\n if (typeof features === \\\"string\\\") {\\n direction = language;\\n language = script;\\n script = features;\\n features = [];\\n }\\n if (typeof string === \\\"string\\\") {\\n if (script == null) script = $130d1a642ebcd2b7$export$e5cb25e204fb8450(string);\\n var glyphs = this.font.glyphsForString(string);\\n } else {\\n if (script == null) {\\n let codePoints = [];\\n for (let glyph of string) codePoints.push(...glyph.codePoints);\\n script = $130d1a642ebcd2b7$export$16fab0757cfc223d(codePoints);\\n }\\n var glyphs = string;\\n }\\n let glyphRun = new (0, $be07b3e97a42687a$export$2e2bcd8739ae039)(glyphs, features, script, language, direction);\\n if (glyphs.length === 0) {\\n glyphRun.positions = [];\\n return glyphRun;\\n }\\n if (this.engine && this.engine.setup) this.engine.setup(glyphRun);\\n this.substitute(glyphRun);\\n this.position(glyphRun);\\n this.hideDefaultIgnorables(glyphRun.glyphs, glyphRun.positions);\\n if (this.engine && this.engine.cleanup) this.engine.cleanup();\\n return glyphRun;\\n }\\n substitute(glyphRun) {\\n if (this.engine && this.engine.substitute) this.engine.substitute(glyphRun);\\n }\\n position(glyphRun) {\\n glyphRun.positions = glyphRun.glyphs.map((glyph) => new (0, $1ac75d9a55b67f01$export$2e2bcd8739ae039)(glyph.advanceWidth));\\n let positioned = null;\\n if (this.engine && this.engine.position) positioned = this.engine.position(glyphRun);\\n if (!positioned && (!this.engine || this.engine.fallbackPosition)) {\\n if (!this.unicodeLayoutEngine) this.unicodeLayoutEngine = new (0, $0a4bdfeb6dfd6f5e$export$2e2bcd8739ae039)(this.font);\\n this.unicodeLayoutEngine.positionGlyphs(glyphRun.glyphs, glyphRun.positions);\\n }\\n if ((!positioned || !positioned.kern) && glyphRun.features.kern !== false && this.font.kern) {\\n if (!this.kernProcessor) this.kernProcessor = new (0, $0bba3a9db57637f3$export$2e2bcd8739ae039)(this.font);\\n this.kernProcessor.process(glyphRun.glyphs, glyphRun.positions);\\n glyphRun.features.kern = true;\\n }\\n }\\n hideDefaultIgnorables(glyphs, positions) {\\n let space = this.font.glyphForCodePoint(32);\\n for (let i = 0; i < glyphs.length; i++) if (this.isDefaultIgnorable(glyphs[i].codePoints[0])) {\\n glyphs[i] = space;\\n positions[i].xAdvance = 0;\\n positions[i].yAdvance = 0;\\n }\\n }\\n isDefaultIgnorable(ch) {\\n let plane = ch >> 16;\\n if (plane === 0)\\n switch (ch >> 8) {\\n case 0:\\n return ch === 173;\\n case 3:\\n return ch === 847;\\n case 6:\\n return ch === 1564;\\n case 23:\\n return 6068 <= ch && ch <= 6069;\\n case 24:\\n return 6155 <= ch && ch <= 6158;\\n case 32:\\n return 8203 <= ch && ch <= 8207 || 8234 <= ch && ch <= 8238 || 8288 <= ch && ch <= 8303;\\n case 254:\\n return 65024 <= ch && ch <= 65039 || ch === 65279;\\n case 255:\\n return 65520 <= ch && ch <= 65528;\\n default:\\n return false;\\n }\\n else\\n switch (plane) {\\n case 1:\\n return 113824 <= ch && ch <= 113827 || 119155 <= ch && ch <= 119162;\\n case 14:\\n return 917504 <= ch && ch <= 921599;\\n default:\\n return false;\\n }\\n }\\n getAvailableFeatures(script, language) {\\n let features = [];\\n if (this.engine) features.push(...this.engine.getAvailableFeatures(script, language));\\n if (this.font.kern && features.indexOf(\\\"kern\\\") === -1) features.push(\\\"kern\\\");\\n return features;\\n }\\n stringsForGlyph(gid) {\\n let result = /* @__PURE__ */ new Set();\\n let codePoints = this.font._cmapProcessor.codePointsForGlyph(gid);\\n for (let codePoint of codePoints) result.add(String.fromCodePoint(codePoint));\\n if (this.engine && this.engine.stringsForGlyph) for (let string of this.engine.stringsForGlyph(gid)) result.add(string);\\n return Array.from(result);\\n }\\n constructor(font) {\\n this.font = font;\\n this.unicodeLayoutEngine = null;\\n this.kernProcessor = null;\\n if (this.font.morx) this.engine = new (0, $ba6dd74203be8728$export$2e2bcd8739ae039)(this.font);\\n else if (this.font.GSUB || this.font.GPOS) this.engine = new (0, $a62492810de27e3d$export$2e2bcd8739ae039)(this.font);\\n }\\n };\\n $f43aec954cdfdf21$var$SVG_COMMANDS = {\\n moveTo: \\\"M\\\",\\n lineTo: \\\"L\\\",\\n quadraticCurveTo: \\\"Q\\\",\\n bezierCurveTo: \\\"C\\\",\\n closePath: \\\"Z\\\"\\n };\\n $f43aec954cdfdf21$export$2e2bcd8739ae039 = class _$f43aec954cdfdf21$export$2e2bcd8739ae039 {\\n /**\\n * Compiles the path to a JavaScript function that can be applied with\\n * a graphics context in order to render the path.\\n * @return {string}\\n */\\n toFunction() {\\n return (ctx) => {\\n this.commands.forEach((c) => {\\n return ctx[c.command].apply(ctx, c.args);\\n });\\n };\\n }\\n /**\\n * Converts the path to an SVG path data string\\n * @return {string}\\n */\\n toSVG() {\\n let cmds = this.commands.map((c) => {\\n let args = c.args.map((arg) => Math.round(arg * 100) / 100);\\n return `${$f43aec954cdfdf21$var$SVG_COMMANDS[c.command]}${args.join(\\\" \\\")}`;\\n });\\n return cmds.join(\\\"\\\");\\n }\\n /**\\n * Gets the \\\"control box\\\" of a path.\\n * This is like the bounding box, but it includes all points including\\n * control points of bezier segments and is much faster to compute than\\n * the real bounding box.\\n * @type {BBox}\\n */\\n get cbox() {\\n if (!this._cbox) {\\n let cbox = new (0, $f34600ab9d7f70d8$export$2e2bcd8739ae039)();\\n for (let command of this.commands) for (let i = 0; i < command.args.length; i += 2) cbox.addPoint(command.args[i], command.args[i + 1]);\\n this._cbox = Object.freeze(cbox);\\n }\\n return this._cbox;\\n }\\n /**\\n * Gets the exact bounding box of the path by evaluating curve segments.\\n * Slower to compute than the control box, but more accurate.\\n * @type {BBox}\\n */\\n get bbox() {\\n if (this._bbox) return this._bbox;\\n let bbox = new (0, $f34600ab9d7f70d8$export$2e2bcd8739ae039)();\\n let cx = 0, cy = 0;\\n let f = (t) => Math.pow(1 - t, 3) * p0[i] + 3 * Math.pow(1 - t, 2) * t * p1[i] + 3 * (1 - t) * Math.pow(t, 2) * p2[i] + Math.pow(t, 3) * p3[i];\\n for (let c of this.commands) switch (c.command) {\\n case \\\"moveTo\\\":\\n case \\\"lineTo\\\":\\n let [x, y] = c.args;\\n bbox.addPoint(x, y);\\n cx = x;\\n cy = y;\\n break;\\n case \\\"quadraticCurveTo\\\":\\n case \\\"bezierCurveTo\\\":\\n if (c.command === \\\"quadraticCurveTo\\\") {\\n var [qp1x, qp1y, p3x, p3y] = c.args;\\n var cp1x = cx + 2 / 3 * (qp1x - cx);\\n var cp1y = cy + 2 / 3 * (qp1y - cy);\\n var cp2x = p3x + 2 / 3 * (qp1x - p3x);\\n var cp2y = p3y + 2 / 3 * (qp1y - p3y);\\n } else var [cp1x, cp1y, cp2x, cp2y, p3x, p3y] = c.args;\\n bbox.addPoint(p3x, p3y);\\n var p0 = [\\n cx,\\n cy\\n ];\\n var p1 = [\\n cp1x,\\n cp1y\\n ];\\n var p2 = [\\n cp2x,\\n cp2y\\n ];\\n var p3 = [\\n p3x,\\n p3y\\n ];\\n for (var i = 0; i <= 1; i++) {\\n let b = 6 * p0[i] - 12 * p1[i] + 6 * p2[i];\\n let a = -3 * p0[i] + 9 * p1[i] - 9 * p2[i] + 3 * p3[i];\\n c = 3 * p1[i] - 3 * p0[i];\\n if (a === 0) {\\n if (b === 0) continue;\\n let t = -c / b;\\n if (0 < t && t < 1) {\\n if (i === 0) bbox.addPoint(f(t), bbox.maxY);\\n else if (i === 1) bbox.addPoint(bbox.maxX, f(t));\\n }\\n continue;\\n }\\n let b2ac = Math.pow(b, 2) - 4 * c * a;\\n if (b2ac < 0) continue;\\n let t1 = (-b + Math.sqrt(b2ac)) / (2 * a);\\n if (0 < t1 && t1 < 1) {\\n if (i === 0) bbox.addPoint(f(t1), bbox.maxY);\\n else if (i === 1) bbox.addPoint(bbox.maxX, f(t1));\\n }\\n let t2 = (-b - Math.sqrt(b2ac)) / (2 * a);\\n if (0 < t2 && t2 < 1) {\\n if (i === 0) bbox.addPoint(f(t2), bbox.maxY);\\n else if (i === 1) bbox.addPoint(bbox.maxX, f(t2));\\n }\\n }\\n cx = p3x;\\n cy = p3y;\\n break;\\n }\\n return this._bbox = Object.freeze(bbox);\\n }\\n /**\\n * Applies a mapping function to each point in the path.\\n * @param {function} fn\\n * @return {Path}\\n */\\n mapPoints(fn) {\\n let path = new _$f43aec954cdfdf21$export$2e2bcd8739ae039();\\n for (let c of this.commands) {\\n let args = [];\\n for (let i = 0; i < c.args.length; i += 2) {\\n let [x, y] = fn(c.args[i], c.args[i + 1]);\\n args.push(x, y);\\n }\\n path[c.command](...args);\\n }\\n return path;\\n }\\n /**\\n * Transforms the path by the given matrix.\\n */\\n transform(m0, m1, m2, m3, m4, m5) {\\n return this.mapPoints((x, y) => {\\n const tx = m0 * x + m2 * y + m4;\\n const ty = m1 * x + m3 * y + m5;\\n return [\\n tx,\\n ty\\n ];\\n });\\n }\\n /**\\n * Translates the path by the given offset.\\n */\\n translate(x, y) {\\n return this.transform(1, 0, 0, 1, x, y);\\n }\\n /**\\n * Rotates the path by the given angle (in radians).\\n */\\n rotate(angle) {\\n let cos = Math.cos(angle);\\n let sin = Math.sin(angle);\\n return this.transform(cos, sin, -sin, cos, 0, 0);\\n }\\n /**\\n * Scales the path.\\n */\\n scale(scaleX, scaleY = scaleX) {\\n return this.transform(scaleX, 0, 0, scaleY, 0, 0);\\n }\\n constructor() {\\n this.commands = [];\\n this._bbox = null;\\n this._cbox = null;\\n }\\n };\\n for (let command of [\\n \\\"moveTo\\\",\\n \\\"lineTo\\\",\\n \\\"quadraticCurveTo\\\",\\n \\\"bezierCurveTo\\\",\\n \\\"closePath\\\"\\n ]) $f43aec954cdfdf21$export$2e2bcd8739ae039.prototype[command] = function(...args) {\\n this._bbox = this._cbox = null;\\n this.commands.push({\\n command,\\n args\\n });\\n return this;\\n };\\n $7713b9b7b438dff8$export$2e2bcd8739ae039 = [\\n \\\".notdef\\\",\\n \\\".null\\\",\\n \\\"nonmarkingreturn\\\",\\n \\\"space\\\",\\n \\\"exclam\\\",\\n \\\"quotedbl\\\",\\n \\\"numbersign\\\",\\n \\\"dollar\\\",\\n \\\"percent\\\",\\n \\\"ampersand\\\",\\n \\\"quotesingle\\\",\\n \\\"parenleft\\\",\\n \\\"parenright\\\",\\n \\\"asterisk\\\",\\n \\\"plus\\\",\\n \\\"comma\\\",\\n \\\"hyphen\\\",\\n \\\"period\\\",\\n \\\"slash\\\",\\n \\\"zero\\\",\\n \\\"one\\\",\\n \\\"two\\\",\\n \\\"three\\\",\\n \\\"four\\\",\\n \\\"five\\\",\\n \\\"six\\\",\\n \\\"seven\\\",\\n \\\"eight\\\",\\n \\\"nine\\\",\\n \\\"colon\\\",\\n \\\"semicolon\\\",\\n \\\"less\\\",\\n \\\"equal\\\",\\n \\\"greater\\\",\\n \\\"question\\\",\\n \\\"at\\\",\\n \\\"A\\\",\\n \\\"B\\\",\\n \\\"C\\\",\\n \\\"D\\\",\\n \\\"E\\\",\\n \\\"F\\\",\\n \\\"G\\\",\\n \\\"H\\\",\\n \\\"I\\\",\\n \\\"J\\\",\\n \\\"K\\\",\\n \\\"L\\\",\\n \\\"M\\\",\\n \\\"N\\\",\\n \\\"O\\\",\\n \\\"P\\\",\\n \\\"Q\\\",\\n \\\"R\\\",\\n \\\"S\\\",\\n \\\"T\\\",\\n \\\"U\\\",\\n \\\"V\\\",\\n \\\"W\\\",\\n \\\"X\\\",\\n \\\"Y\\\",\\n \\\"Z\\\",\\n \\\"bracketleft\\\",\\n \\\"backslash\\\",\\n \\\"bracketright\\\",\\n \\\"asciicircum\\\",\\n \\\"underscore\\\",\\n \\\"grave\\\",\\n \\\"a\\\",\\n \\\"b\\\",\\n \\\"c\\\",\\n \\\"d\\\",\\n \\\"e\\\",\\n \\\"f\\\",\\n \\\"g\\\",\\n \\\"h\\\",\\n \\\"i\\\",\\n \\\"j\\\",\\n \\\"k\\\",\\n \\\"l\\\",\\n \\\"m\\\",\\n \\\"n\\\",\\n \\\"o\\\",\\n \\\"p\\\",\\n \\\"q\\\",\\n \\\"r\\\",\\n \\\"s\\\",\\n \\\"t\\\",\\n \\\"u\\\",\\n \\\"v\\\",\\n \\\"w\\\",\\n \\\"x\\\",\\n \\\"y\\\",\\n \\\"z\\\",\\n \\\"braceleft\\\",\\n \\\"bar\\\",\\n \\\"braceright\\\",\\n \\\"asciitilde\\\",\\n \\\"Adieresis\\\",\\n \\\"Aring\\\",\\n \\\"Ccedilla\\\",\\n \\\"Eacute\\\",\\n \\\"Ntilde\\\",\\n \\\"Odieresis\\\",\\n \\\"Udieresis\\\",\\n \\\"aacute\\\",\\n \\\"agrave\\\",\\n \\\"acircumflex\\\",\\n \\\"adieresis\\\",\\n \\\"atilde\\\",\\n \\\"aring\\\",\\n \\\"ccedilla\\\",\\n \\\"eacute\\\",\\n \\\"egrave\\\",\\n \\\"ecircumflex\\\",\\n \\\"edieresis\\\",\\n \\\"iacute\\\",\\n \\\"igrave\\\",\\n \\\"icircumflex\\\",\\n \\\"idieresis\\\",\\n \\\"ntilde\\\",\\n \\\"oacute\\\",\\n \\\"ograve\\\",\\n \\\"ocircumflex\\\",\\n \\\"odieresis\\\",\\n \\\"otilde\\\",\\n \\\"uacute\\\",\\n \\\"ugrave\\\",\\n \\\"ucircumflex\\\",\\n \\\"udieresis\\\",\\n \\\"dagger\\\",\\n \\\"degree\\\",\\n \\\"cent\\\",\\n \\\"sterling\\\",\\n \\\"section\\\",\\n \\\"bullet\\\",\\n \\\"paragraph\\\",\\n \\\"germandbls\\\",\\n \\\"registered\\\",\\n \\\"copyright\\\",\\n \\\"trademark\\\",\\n \\\"acute\\\",\\n \\\"dieresis\\\",\\n \\\"notequal\\\",\\n \\\"AE\\\",\\n \\\"Oslash\\\",\\n \\\"infinity\\\",\\n \\\"plusminus\\\",\\n \\\"lessequal\\\",\\n \\\"greaterequal\\\",\\n \\\"yen\\\",\\n \\\"mu\\\",\\n \\\"partialdiff\\\",\\n \\\"summation\\\",\\n \\\"product\\\",\\n \\\"pi\\\",\\n \\\"integral\\\",\\n \\\"ordfeminine\\\",\\n \\\"ordmasculine\\\",\\n \\\"Omega\\\",\\n \\\"ae\\\",\\n \\\"oslash\\\",\\n \\\"questiondown\\\",\\n \\\"exclamdown\\\",\\n \\\"logicalnot\\\",\\n \\\"radical\\\",\\n \\\"florin\\\",\\n \\\"approxequal\\\",\\n \\\"Delta\\\",\\n \\\"guillemotleft\\\",\\n \\\"guillemotright\\\",\\n \\\"ellipsis\\\",\\n \\\"nonbreakingspace\\\",\\n \\\"Agrave\\\",\\n \\\"Atilde\\\",\\n \\\"Otilde\\\",\\n \\\"OE\\\",\\n \\\"oe\\\",\\n \\\"endash\\\",\\n \\\"emdash\\\",\\n \\\"quotedblleft\\\",\\n \\\"quotedblright\\\",\\n \\\"quoteleft\\\",\\n \\\"quoteright\\\",\\n \\\"divide\\\",\\n \\\"lozenge\\\",\\n \\\"ydieresis\\\",\\n \\\"Ydieresis\\\",\\n \\\"fraction\\\",\\n \\\"currency\\\",\\n \\\"guilsinglleft\\\",\\n \\\"guilsinglright\\\",\\n \\\"fi\\\",\\n \\\"fl\\\",\\n \\\"daggerdbl\\\",\\n \\\"periodcentered\\\",\\n \\\"quotesinglbase\\\",\\n \\\"quotedblbase\\\",\\n \\\"perthousand\\\",\\n \\\"Acircumflex\\\",\\n \\\"Ecircumflex\\\",\\n \\\"Aacute\\\",\\n \\\"Edieresis\\\",\\n \\\"Egrave\\\",\\n \\\"Iacute\\\",\\n \\\"Icircumflex\\\",\\n \\\"Idieresis\\\",\\n \\\"Igrave\\\",\\n \\\"Oacute\\\",\\n \\\"Ocircumflex\\\",\\n \\\"apple\\\",\\n \\\"Ograve\\\",\\n \\\"Uacute\\\",\\n \\\"Ucircumflex\\\",\\n \\\"Ugrave\\\",\\n \\\"dotlessi\\\",\\n \\\"circumflex\\\",\\n \\\"tilde\\\",\\n \\\"macron\\\",\\n \\\"breve\\\",\\n \\\"dotaccent\\\",\\n \\\"ring\\\",\\n \\\"cedilla\\\",\\n \\\"hungarumlaut\\\",\\n \\\"ogonek\\\",\\n \\\"caron\\\",\\n \\\"Lslash\\\",\\n \\\"lslash\\\",\\n \\\"Scaron\\\",\\n \\\"scaron\\\",\\n \\\"Zcaron\\\",\\n \\\"zcaron\\\",\\n \\\"brokenbar\\\",\\n \\\"Eth\\\",\\n \\\"eth\\\",\\n \\\"Yacute\\\",\\n \\\"yacute\\\",\\n \\\"Thorn\\\",\\n \\\"thorn\\\",\\n \\\"minus\\\",\\n \\\"multiply\\\",\\n \\\"onesuperior\\\",\\n \\\"twosuperior\\\",\\n \\\"threesuperior\\\",\\n \\\"onehalf\\\",\\n \\\"onequarter\\\",\\n \\\"threequarters\\\",\\n \\\"franc\\\",\\n \\\"Gbreve\\\",\\n \\\"gbreve\\\",\\n \\\"Idotaccent\\\",\\n \\\"Scedilla\\\",\\n \\\"scedilla\\\",\\n \\\"Cacute\\\",\\n \\\"cacute\\\",\\n \\\"Ccaron\\\",\\n \\\"ccaron\\\",\\n \\\"dcroat\\\"\\n ];\\n $f92906be28e61769$export$2e2bcd8739ae039 = class {\\n _getPath() {\\n return new (0, $f43aec954cdfdf21$export$2e2bcd8739ae039)();\\n }\\n _getCBox() {\\n return this.path.cbox;\\n }\\n _getBBox() {\\n return this.path.bbox;\\n }\\n _getTableMetrics(table) {\\n if (this.id < table.metrics.length) return table.metrics.get(this.id);\\n let metric = table.metrics.get(table.metrics.length - 1);\\n let res = {\\n advance: metric ? metric.advance : 0,\\n bearing: table.bearings.get(this.id - table.metrics.length) || 0\\n };\\n return res;\\n }\\n _getMetrics(cbox) {\\n if (this._metrics) return this._metrics;\\n let { advance: advanceWidth, bearing: leftBearing } = this._getTableMetrics(this._font.hmtx);\\n if (this._font.vmtx) var { advance: advanceHeight, bearing: topBearing } = this._getTableMetrics(this._font.vmtx);\\n else {\\n let os2;\\n if (typeof cbox === \\\"undefined\\\" || cbox === null) ({ cbox } = this);\\n if ((os2 = this._font[\\\"OS/2\\\"]) && os2.version > 0) {\\n var advanceHeight = Math.abs(os2.typoAscender - os2.typoDescender);\\n var topBearing = os2.typoAscender - cbox.maxY;\\n } else {\\n let { hhea } = this._font;\\n var advanceHeight = Math.abs(hhea.ascent - hhea.descent);\\n var topBearing = hhea.ascent - cbox.maxY;\\n }\\n }\\n if (this._font._variationProcessor && this._font.HVAR) advanceWidth += this._font._variationProcessor.getAdvanceAdjustment(this.id, this._font.HVAR);\\n return this._metrics = {\\n advanceWidth,\\n advanceHeight,\\n leftBearing,\\n topBearing\\n };\\n }\\n /**\\n * The glyph’s control box.\\n * This is often the same as the bounding box, but is faster to compute.\\n * Because of the way bezier curves are defined, some of the control points\\n * can be outside of the bounding box. Where `bbox` takes this into account,\\n * `cbox` does not. Thus, cbox is less accurate, but faster to compute.\\n * See [here](http://www.freetype.org/freetype2/docs/glyphs/glyphs-6.html#section-2)\\n * for a more detailed description.\\n *\\n * @type {BBox}\\n */\\n get cbox() {\\n return this._getCBox();\\n }\\n /**\\n * The glyph’s bounding box, i.e. the rectangle that encloses the\\n * glyph outline as tightly as possible.\\n * @type {BBox}\\n */\\n get bbox() {\\n return this._getBBox();\\n }\\n /**\\n * A vector Path object representing the glyph outline.\\n * @type {Path}\\n */\\n get path() {\\n return this._getPath();\\n }\\n /**\\n * Returns a path scaled to the given font size.\\n * @param {number} size\\n * @return {Path}\\n */\\n getScaledPath(size) {\\n let scale = 1 / this._font.unitsPerEm * size;\\n return this.path.scale(scale);\\n }\\n /**\\n * The glyph's advance width.\\n * @type {number}\\n */\\n get advanceWidth() {\\n return this._getMetrics().advanceWidth;\\n }\\n /**\\n * The glyph's advance height.\\n * @type {number}\\n */\\n get advanceHeight() {\\n return this._getMetrics().advanceHeight;\\n }\\n get ligatureCaretPositions() {\\n }\\n _getName() {\\n let { post } = this._font;\\n if (!post) return null;\\n switch (post.version) {\\n case 1:\\n return (0, $7713b9b7b438dff8$export$2e2bcd8739ae039)[this.id];\\n case 2:\\n let id = post.glyphNameIndex[this.id];\\n if (id < (0, $7713b9b7b438dff8$export$2e2bcd8739ae039).length) return (0, $7713b9b7b438dff8$export$2e2bcd8739ae039)[id];\\n return post.names[id - (0, $7713b9b7b438dff8$export$2e2bcd8739ae039).length];\\n case 2.5:\\n return (0, $7713b9b7b438dff8$export$2e2bcd8739ae039)[this.id + post.offsets[this.id]];\\n case 4:\\n return String.fromCharCode(post.map[this.id]);\\n }\\n }\\n /**\\n * The glyph's name\\n * @type {string}\\n */\\n get name() {\\n return this._getName();\\n }\\n /**\\n * Renders the glyph to the given graphics context, at the specified font size.\\n * @param {CanvasRenderingContext2d} ctx\\n * @param {number} size\\n */\\n render(ctx, size) {\\n ctx.save();\\n let scale = 1 / this._font.head.unitsPerEm * size;\\n ctx.scale(scale, scale);\\n let fn = this.path.toFunction();\\n fn(ctx);\\n ctx.fill();\\n ctx.restore();\\n }\\n constructor(id, codePoints, font) {\\n this.id = id;\\n this.codePoints = codePoints;\\n this._font = font;\\n this.isMark = this.codePoints.length > 0 && this.codePoints.every((0, $747425b437e121da$export$e33ad6871e762338));\\n this.isLigature = this.codePoints.length > 1;\\n }\\n };\\n (0, __decorate)([\\n (0, $e71565f2ce09cb6b$export$69a3209f1a06c04d)\\n ], $f92906be28e61769$export$2e2bcd8739ae039.prototype, \\\"cbox\\\", null);\\n (0, __decorate)([\\n (0, $e71565f2ce09cb6b$export$69a3209f1a06c04d)\\n ], $f92906be28e61769$export$2e2bcd8739ae039.prototype, \\\"bbox\\\", null);\\n (0, __decorate)([\\n (0, $e71565f2ce09cb6b$export$69a3209f1a06c04d)\\n ], $f92906be28e61769$export$2e2bcd8739ae039.prototype, \\\"path\\\", null);\\n (0, __decorate)([\\n (0, $e71565f2ce09cb6b$export$69a3209f1a06c04d)\\n ], $f92906be28e61769$export$2e2bcd8739ae039.prototype, \\\"advanceWidth\\\", null);\\n (0, __decorate)([\\n (0, $e71565f2ce09cb6b$export$69a3209f1a06c04d)\\n ], $f92906be28e61769$export$2e2bcd8739ae039.prototype, \\\"advanceHeight\\\", null);\\n (0, __decorate)([\\n (0, $e71565f2ce09cb6b$export$69a3209f1a06c04d)\\n ], $f92906be28e61769$export$2e2bcd8739ae039.prototype, \\\"name\\\", null);\\n $69aac16029968692$var$GlyfHeader = new Struct({\\n numberOfContours: int16,\\n xMin: int16,\\n yMin: int16,\\n xMax: int16,\\n yMax: int16\\n });\\n $69aac16029968692$var$ON_CURVE = 1;\\n $69aac16029968692$var$X_SHORT_VECTOR = 2;\\n $69aac16029968692$var$Y_SHORT_VECTOR = 4;\\n $69aac16029968692$var$REPEAT = 8;\\n $69aac16029968692$var$SAME_X = 16;\\n $69aac16029968692$var$SAME_Y = 32;\\n $69aac16029968692$var$ARG_1_AND_2_ARE_WORDS = 1;\\n $69aac16029968692$var$WE_HAVE_A_SCALE = 8;\\n $69aac16029968692$var$MORE_COMPONENTS = 32;\\n $69aac16029968692$var$WE_HAVE_AN_X_AND_Y_SCALE = 64;\\n $69aac16029968692$var$WE_HAVE_A_TWO_BY_TWO = 128;\\n $69aac16029968692$var$WE_HAVE_INSTRUCTIONS = 256;\\n $69aac16029968692$export$baf26146a414f24a = class _$69aac16029968692$export$baf26146a414f24a {\\n copy() {\\n return new _$69aac16029968692$export$baf26146a414f24a(this.onCurve, this.endContour, this.x, this.y);\\n }\\n constructor(onCurve, endContour, x = 0, y = 0) {\\n this.onCurve = onCurve;\\n this.endContour = endContour;\\n this.x = x;\\n this.y = y;\\n }\\n };\\n $69aac16029968692$var$Component = class {\\n constructor(glyphID, dx, dy) {\\n this.glyphID = glyphID;\\n this.dx = dx;\\n this.dy = dy;\\n this.pos = 0;\\n this.scaleX = this.scaleY = 1;\\n this.scale01 = this.scale10 = 0;\\n }\\n };\\n $69aac16029968692$export$2e2bcd8739ae039 = class extends (0, $f92906be28e61769$export$2e2bcd8739ae039) {\\n // Parses just the glyph header and returns the bounding box\\n _getCBox(internal) {\\n if (this._font._variationProcessor && !internal) return this.path.cbox;\\n let stream = this._font._getTableStream(\\\"glyf\\\");\\n stream.pos += this._font.loca.offsets[this.id];\\n let glyph = $69aac16029968692$var$GlyfHeader.decode(stream);\\n let cbox = new (0, $f34600ab9d7f70d8$export$2e2bcd8739ae039)(glyph.xMin, glyph.yMin, glyph.xMax, glyph.yMax);\\n return Object.freeze(cbox);\\n }\\n // Parses a single glyph coordinate\\n _parseGlyphCoord(stream, prev, short, same) {\\n if (short) {\\n var val = stream.readUInt8();\\n if (!same) val = -val;\\n val += prev;\\n } else if (same) var val = prev;\\n else var val = prev + stream.readInt16BE();\\n return val;\\n }\\n // Decodes the glyph data into points for simple glyphs,\\n // or components for composite glyphs\\n _decode() {\\n let glyfPos = this._font.loca.offsets[this.id];\\n let nextPos = this._font.loca.offsets[this.id + 1];\\n if (glyfPos === nextPos) return null;\\n let stream = this._font._getTableStream(\\\"glyf\\\");\\n stream.pos += glyfPos;\\n let startPos = stream.pos;\\n let glyph = $69aac16029968692$var$GlyfHeader.decode(stream);\\n if (glyph.numberOfContours > 0) this._decodeSimple(glyph, stream);\\n else if (glyph.numberOfContours < 0) this._decodeComposite(glyph, stream, startPos);\\n return glyph;\\n }\\n _decodeSimple(glyph, stream) {\\n glyph.points = [];\\n let endPtsOfContours = new ArrayT(uint16, glyph.numberOfContours).decode(stream);\\n glyph.instructions = new ArrayT(uint8, uint16).decode(stream);\\n let flags = [];\\n let numCoords = endPtsOfContours[endPtsOfContours.length - 1] + 1;\\n while (flags.length < numCoords) {\\n var flag = stream.readUInt8();\\n flags.push(flag);\\n if (flag & $69aac16029968692$var$REPEAT) {\\n let count = stream.readUInt8();\\n for (let j = 0; j < count; j++) flags.push(flag);\\n }\\n }\\n for (var i = 0; i < flags.length; i++) {\\n var flag = flags[i];\\n let point = new $69aac16029968692$export$baf26146a414f24a(!!(flag & $69aac16029968692$var$ON_CURVE), endPtsOfContours.indexOf(i) >= 0, 0, 0);\\n glyph.points.push(point);\\n }\\n let px = 0;\\n for (var i = 0; i < flags.length; i++) {\\n var flag = flags[i];\\n glyph.points[i].x = px = this._parseGlyphCoord(stream, px, flag & $69aac16029968692$var$X_SHORT_VECTOR, flag & $69aac16029968692$var$SAME_X);\\n }\\n let py = 0;\\n for (var i = 0; i < flags.length; i++) {\\n var flag = flags[i];\\n glyph.points[i].y = py = this._parseGlyphCoord(stream, py, flag & $69aac16029968692$var$Y_SHORT_VECTOR, flag & $69aac16029968692$var$SAME_Y);\\n }\\n if (this._font._variationProcessor) {\\n let points = glyph.points.slice();\\n points.push(...this._getPhantomPoints(glyph));\\n this._font._variationProcessor.transformPoints(this.id, points);\\n glyph.phantomPoints = points.slice(-4);\\n }\\n return;\\n }\\n _decodeComposite(glyph, stream, offset = 0) {\\n glyph.components = [];\\n let haveInstructions = false;\\n let flags = $69aac16029968692$var$MORE_COMPONENTS;\\n while (flags & $69aac16029968692$var$MORE_COMPONENTS) {\\n flags = stream.readUInt16BE();\\n let gPos = stream.pos - offset;\\n let glyphID = stream.readUInt16BE();\\n if (!haveInstructions) haveInstructions = (flags & $69aac16029968692$var$WE_HAVE_INSTRUCTIONS) !== 0;\\n if (flags & $69aac16029968692$var$ARG_1_AND_2_ARE_WORDS) {\\n var dx = stream.readInt16BE();\\n var dy = stream.readInt16BE();\\n } else {\\n var dx = stream.readInt8();\\n var dy = stream.readInt8();\\n }\\n var component = new $69aac16029968692$var$Component(glyphID, dx, dy);\\n component.pos = gPos;\\n if (flags & $69aac16029968692$var$WE_HAVE_A_SCALE)\\n component.scaleX = component.scaleY = (stream.readUInt8() << 24 | stream.readUInt8() << 16) / 1073741824;\\n else if (flags & $69aac16029968692$var$WE_HAVE_AN_X_AND_Y_SCALE) {\\n component.scaleX = (stream.readUInt8() << 24 | stream.readUInt8() << 16) / 1073741824;\\n component.scaleY = (stream.readUInt8() << 24 | stream.readUInt8() << 16) / 1073741824;\\n } else if (flags & $69aac16029968692$var$WE_HAVE_A_TWO_BY_TWO) {\\n component.scaleX = (stream.readUInt8() << 24 | stream.readUInt8() << 16) / 1073741824;\\n component.scale01 = (stream.readUInt8() << 24 | stream.readUInt8() << 16) / 1073741824;\\n component.scale10 = (stream.readUInt8() << 24 | stream.readUInt8() << 16) / 1073741824;\\n component.scaleY = (stream.readUInt8() << 24 | stream.readUInt8() << 16) / 1073741824;\\n }\\n glyph.components.push(component);\\n }\\n if (this._font._variationProcessor) {\\n let points = [];\\n for (let j = 0; j < glyph.components.length; j++) {\\n var component = glyph.components[j];\\n points.push(new $69aac16029968692$export$baf26146a414f24a(true, true, component.dx, component.dy));\\n }\\n points.push(...this._getPhantomPoints(glyph));\\n this._font._variationProcessor.transformPoints(this.id, points);\\n glyph.phantomPoints = points.splice(-4, 4);\\n for (let i = 0; i < points.length; i++) {\\n let point = points[i];\\n glyph.components[i].dx = point.x;\\n glyph.components[i].dy = point.y;\\n }\\n }\\n return haveInstructions;\\n }\\n _getPhantomPoints(glyph) {\\n let cbox = this._getCBox(true);\\n if (this._metrics == null) this._metrics = (0, $f92906be28e61769$export$2e2bcd8739ae039).prototype._getMetrics.call(this, cbox);\\n let { advanceWidth, advanceHeight, leftBearing, topBearing } = this._metrics;\\n return [\\n new $69aac16029968692$export$baf26146a414f24a(false, true, glyph.xMin - leftBearing, 0),\\n new $69aac16029968692$export$baf26146a414f24a(false, true, glyph.xMin - leftBearing + advanceWidth, 0),\\n new $69aac16029968692$export$baf26146a414f24a(false, true, 0, glyph.yMax + topBearing),\\n new $69aac16029968692$export$baf26146a414f24a(false, true, 0, glyph.yMax + topBearing + advanceHeight)\\n ];\\n }\\n // Decodes font data, resolves composite glyphs, and returns an array of contours\\n _getContours() {\\n let glyph = this._decode();\\n if (!glyph) return [];\\n let points = [];\\n if (glyph.numberOfContours < 0)\\n for (let component of glyph.components) {\\n let contours2 = this._font.getGlyph(component.glyphID)._getContours();\\n for (let i = 0; i < contours2.length; i++) {\\n let contour = contours2[i];\\n for (let j = 0; j < contour.length; j++) {\\n let point2 = contour[j];\\n let x = point2.x * component.scaleX + point2.y * component.scale01 + component.dx;\\n let y = point2.y * component.scaleY + point2.x * component.scale10 + component.dy;\\n points.push(new $69aac16029968692$export$baf26146a414f24a(point2.onCurve, point2.endContour, x, y));\\n }\\n }\\n }\\n else points = glyph.points || [];\\n if (glyph.phantomPoints && !this._font.directory.tables.HVAR) {\\n this._metrics.advanceWidth = glyph.phantomPoints[1].x - glyph.phantomPoints[0].x;\\n this._metrics.advanceHeight = glyph.phantomPoints[3].y - glyph.phantomPoints[2].y;\\n this._metrics.leftBearing = glyph.xMin - glyph.phantomPoints[0].x;\\n this._metrics.topBearing = glyph.phantomPoints[2].y - glyph.yMax;\\n }\\n let contours = [];\\n let cur = [];\\n for (let k = 0; k < points.length; k++) {\\n var point = points[k];\\n cur.push(point);\\n if (point.endContour) {\\n contours.push(cur);\\n cur = [];\\n }\\n }\\n return contours;\\n }\\n _getMetrics() {\\n if (this._metrics) return this._metrics;\\n let cbox = this._getCBox(true);\\n super._getMetrics(cbox);\\n if (this._font._variationProcessor && !this._font.HVAR)\\n this.path;\\n return this._metrics;\\n }\\n // Converts contours to a Path object that can be rendered\\n _getPath() {\\n let contours = this._getContours();\\n let path = new (0, $f43aec954cdfdf21$export$2e2bcd8739ae039)();\\n for (let i = 0; i < contours.length; i++) {\\n let contour = contours[i];\\n let firstPt = contour[0];\\n let lastPt = contour[contour.length - 1];\\n let start = 0;\\n if (firstPt.onCurve) {\\n var curvePt = null;\\n start = 1;\\n } else {\\n if (lastPt.onCurve)\\n firstPt = lastPt;\\n else\\n firstPt = new $69aac16029968692$export$baf26146a414f24a(false, false, (firstPt.x + lastPt.x) / 2, (firstPt.y + lastPt.y) / 2);\\n var curvePt = firstPt;\\n }\\n path.moveTo(firstPt.x, firstPt.y);\\n for (let j = start; j < contour.length; j++) {\\n let pt = contour[j];\\n let prevPt = j === 0 ? firstPt : contour[j - 1];\\n if (prevPt.onCurve && pt.onCurve) path.lineTo(pt.x, pt.y);\\n else if (prevPt.onCurve && !pt.onCurve) var curvePt = pt;\\n else if (!prevPt.onCurve && !pt.onCurve) {\\n let midX = (prevPt.x + pt.x) / 2;\\n let midY = (prevPt.y + pt.y) / 2;\\n path.quadraticCurveTo(prevPt.x, prevPt.y, midX, midY);\\n var curvePt = pt;\\n } else if (!prevPt.onCurve && pt.onCurve) {\\n path.quadraticCurveTo(curvePt.x, curvePt.y, pt.x, pt.y);\\n var curvePt = null;\\n } else throw new Error(\\\"Unknown TTF path state\\\");\\n }\\n if (curvePt) path.quadraticCurveTo(curvePt.x, curvePt.y, firstPt.x, firstPt.y);\\n path.closePath();\\n }\\n return path;\\n }\\n constructor(...args) {\\n super(...args);\\n (0, _define_property)(this, \\\"type\\\", \\\"TTF\\\");\\n }\\n };\\n $62cc5109c6101893$export$2e2bcd8739ae039 = class extends (0, $f92906be28e61769$export$2e2bcd8739ae039) {\\n _getName() {\\n if (this._font.CFF2) return super._getName();\\n return this._font[\\\"CFF \\\"].getGlyphName(this.id);\\n }\\n bias(s) {\\n if (s.length < 1240) return 107;\\n else if (s.length < 33900) return 1131;\\n else return 32768;\\n }\\n _getPath() {\\n let cff = this._font.CFF2 || this._font[\\\"CFF \\\"];\\n let { stream } = cff;\\n let str = cff.topDict.CharStrings[this.id];\\n let end = str.offset + str.length;\\n stream.pos = str.offset;\\n let path = new (0, $f43aec954cdfdf21$export$2e2bcd8739ae039)();\\n let stack = [];\\n let trans = [];\\n let width = null;\\n let nStems = 0;\\n let x = 0, y = 0;\\n let usedGsubrs;\\n let usedSubrs;\\n let open = false;\\n this._usedGsubrs = usedGsubrs = {};\\n this._usedSubrs = usedSubrs = {};\\n let gsubrs = cff.globalSubrIndex || [];\\n let gsubrsBias = this.bias(gsubrs);\\n let privateDict = cff.privateDictForGlyph(this.id) || {};\\n let subrs = privateDict.Subrs || [];\\n let subrsBias = this.bias(subrs);\\n let vstore = cff.topDict.vstore && cff.topDict.vstore.itemVariationStore;\\n let vsindex = privateDict.vsindex;\\n let variationProcessor = this._font._variationProcessor;\\n function checkWidth() {\\n if (width == null) width = stack.shift() + privateDict.nominalWidthX;\\n }\\n function parseStems() {\\n if (stack.length % 2 !== 0) checkWidth();\\n nStems += stack.length >> 1;\\n return stack.length = 0;\\n }\\n function moveTo(x2, y2) {\\n if (open) path.closePath();\\n path.moveTo(x2, y2);\\n open = true;\\n }\\n let parse = function() {\\n while (stream.pos < end) {\\n let op = stream.readUInt8();\\n if (op < 32) {\\n let index, subr, phase;\\n let c1x, c1y, c2x, c2y, c3x, c3y;\\n let c4x, c4y, c5x, c5y, c6x, c6y;\\n let pts;\\n switch (op) {\\n case 1:\\n case 3:\\n case 18:\\n case 23:\\n parseStems();\\n break;\\n case 4:\\n if (stack.length > 1) checkWidth();\\n y += stack.shift();\\n moveTo(x, y);\\n break;\\n case 5:\\n while (stack.length >= 2) {\\n x += stack.shift();\\n y += stack.shift();\\n path.lineTo(x, y);\\n }\\n break;\\n case 6:\\n case 7:\\n phase = op === 6;\\n while (stack.length >= 1) {\\n if (phase) x += stack.shift();\\n else y += stack.shift();\\n path.lineTo(x, y);\\n phase = !phase;\\n }\\n break;\\n case 8:\\n while (stack.length > 0) {\\n c1x = x + stack.shift();\\n c1y = y + stack.shift();\\n c2x = c1x + stack.shift();\\n c2y = c1y + stack.shift();\\n x = c2x + stack.shift();\\n y = c2y + stack.shift();\\n path.bezierCurveTo(c1x, c1y, c2x, c2y, x, y);\\n }\\n break;\\n case 10:\\n index = stack.pop() + subrsBias;\\n subr = subrs[index];\\n if (subr) {\\n usedSubrs[index] = true;\\n let p = stream.pos;\\n let e = end;\\n stream.pos = subr.offset;\\n end = subr.offset + subr.length;\\n parse();\\n stream.pos = p;\\n end = e;\\n }\\n break;\\n case 11:\\n if (cff.version >= 2) break;\\n return;\\n case 14:\\n if (cff.version >= 2) break;\\n if (stack.length > 0) checkWidth();\\n if (open) {\\n path.closePath();\\n open = false;\\n }\\n break;\\n case 15:\\n if (cff.version < 2) throw new Error(\\\"vsindex operator not supported in CFF v1\\\");\\n vsindex = stack.pop();\\n break;\\n case 16: {\\n if (cff.version < 2) throw new Error(\\\"blend operator not supported in CFF v1\\\");\\n if (!variationProcessor) throw new Error(\\\"blend operator in non-variation font\\\");\\n let blendVector = variationProcessor.getBlendVector(vstore, vsindex);\\n let numBlends = stack.pop();\\n let numOperands = numBlends * blendVector.length;\\n let delta = stack.length - numOperands;\\n let base = delta - numBlends;\\n for (let i = 0; i < numBlends; i++) {\\n let sum = stack[base + i];\\n for (let j = 0; j < blendVector.length; j++) sum += blendVector[j] * stack[delta++];\\n stack[base + i] = sum;\\n }\\n while (numOperands--) stack.pop();\\n break;\\n }\\n case 19:\\n case 20:\\n parseStems();\\n stream.pos += nStems + 7 >> 3;\\n break;\\n case 21:\\n if (stack.length > 2) checkWidth();\\n x += stack.shift();\\n y += stack.shift();\\n moveTo(x, y);\\n break;\\n case 22:\\n if (stack.length > 1) checkWidth();\\n x += stack.shift();\\n moveTo(x, y);\\n break;\\n case 24:\\n while (stack.length >= 8) {\\n c1x = x + stack.shift();\\n c1y = y + stack.shift();\\n c2x = c1x + stack.shift();\\n c2y = c1y + stack.shift();\\n x = c2x + stack.shift();\\n y = c2y + stack.shift();\\n path.bezierCurveTo(c1x, c1y, c2x, c2y, x, y);\\n }\\n x += stack.shift();\\n y += stack.shift();\\n path.lineTo(x, y);\\n break;\\n case 25:\\n while (stack.length >= 8) {\\n x += stack.shift();\\n y += stack.shift();\\n path.lineTo(x, y);\\n }\\n c1x = x + stack.shift();\\n c1y = y + stack.shift();\\n c2x = c1x + stack.shift();\\n c2y = c1y + stack.shift();\\n x = c2x + stack.shift();\\n y = c2y + stack.shift();\\n path.bezierCurveTo(c1x, c1y, c2x, c2y, x, y);\\n break;\\n case 26:\\n if (stack.length % 2) x += stack.shift();\\n while (stack.length >= 4) {\\n c1x = x;\\n c1y = y + stack.shift();\\n c2x = c1x + stack.shift();\\n c2y = c1y + stack.shift();\\n x = c2x;\\n y = c2y + stack.shift();\\n path.bezierCurveTo(c1x, c1y, c2x, c2y, x, y);\\n }\\n break;\\n case 27:\\n if (stack.length % 2) y += stack.shift();\\n while (stack.length >= 4) {\\n c1x = x + stack.shift();\\n c1y = y;\\n c2x = c1x + stack.shift();\\n c2y = c1y + stack.shift();\\n x = c2x + stack.shift();\\n y = c2y;\\n path.bezierCurveTo(c1x, c1y, c2x, c2y, x, y);\\n }\\n break;\\n case 28:\\n stack.push(stream.readInt16BE());\\n break;\\n case 29:\\n index = stack.pop() + gsubrsBias;\\n subr = gsubrs[index];\\n if (subr) {\\n usedGsubrs[index] = true;\\n let p = stream.pos;\\n let e = end;\\n stream.pos = subr.offset;\\n end = subr.offset + subr.length;\\n parse();\\n stream.pos = p;\\n end = e;\\n }\\n break;\\n case 30:\\n case 31:\\n phase = op === 31;\\n while (stack.length >= 4) {\\n if (phase) {\\n c1x = x + stack.shift();\\n c1y = y;\\n c2x = c1x + stack.shift();\\n c2y = c1y + stack.shift();\\n y = c2y + stack.shift();\\n x = c2x + (stack.length === 1 ? stack.shift() : 0);\\n } else {\\n c1x = x;\\n c1y = y + stack.shift();\\n c2x = c1x + stack.shift();\\n c2y = c1y + stack.shift();\\n x = c2x + stack.shift();\\n y = c2y + (stack.length === 1 ? stack.shift() : 0);\\n }\\n path.bezierCurveTo(c1x, c1y, c2x, c2y, x, y);\\n phase = !phase;\\n }\\n break;\\n case 12:\\n op = stream.readUInt8();\\n switch (op) {\\n case 3:\\n let a = stack.pop();\\n let b = stack.pop();\\n stack.push(a && b ? 1 : 0);\\n break;\\n case 4:\\n a = stack.pop();\\n b = stack.pop();\\n stack.push(a || b ? 1 : 0);\\n break;\\n case 5:\\n a = stack.pop();\\n stack.push(a ? 0 : 1);\\n break;\\n case 9:\\n a = stack.pop();\\n stack.push(Math.abs(a));\\n break;\\n case 10:\\n a = stack.pop();\\n b = stack.pop();\\n stack.push(a + b);\\n break;\\n case 11:\\n a = stack.pop();\\n b = stack.pop();\\n stack.push(a - b);\\n break;\\n case 12:\\n a = stack.pop();\\n b = stack.pop();\\n stack.push(a / b);\\n break;\\n case 14:\\n a = stack.pop();\\n stack.push(-a);\\n break;\\n case 15:\\n a = stack.pop();\\n b = stack.pop();\\n stack.push(a === b ? 1 : 0);\\n break;\\n case 18:\\n stack.pop();\\n break;\\n case 20:\\n let val = stack.pop();\\n let idx = stack.pop();\\n trans[idx] = val;\\n break;\\n case 21:\\n idx = stack.pop();\\n stack.push(trans[idx] || 0);\\n break;\\n case 22:\\n let s1 = stack.pop();\\n let s2 = stack.pop();\\n let v1 = stack.pop();\\n let v2 = stack.pop();\\n stack.push(v1 <= v2 ? s1 : s2);\\n break;\\n case 23:\\n stack.push(Math.random());\\n break;\\n case 24:\\n a = stack.pop();\\n b = stack.pop();\\n stack.push(a * b);\\n break;\\n case 26:\\n a = stack.pop();\\n stack.push(Math.sqrt(a));\\n break;\\n case 27:\\n a = stack.pop();\\n stack.push(a, a);\\n break;\\n case 28:\\n a = stack.pop();\\n b = stack.pop();\\n stack.push(b, a);\\n break;\\n case 29:\\n idx = stack.pop();\\n if (idx < 0) idx = 0;\\n else if (idx > stack.length - 1) idx = stack.length - 1;\\n stack.push(stack[idx]);\\n break;\\n case 30:\\n let n = stack.pop();\\n let j = stack.pop();\\n if (j >= 0) while (j > 0) {\\n var t = stack[n - 1];\\n for (let i = n - 2; i >= 0; i--) stack[i + 1] = stack[i];\\n stack[0] = t;\\n j--;\\n }\\n else while (j < 0) {\\n var t = stack[0];\\n for (let i = 0; i <= n; i++) stack[i] = stack[i + 1];\\n stack[n - 1] = t;\\n j++;\\n }\\n break;\\n case 34:\\n c1x = x + stack.shift();\\n c1y = y;\\n c2x = c1x + stack.shift();\\n c2y = c1y + stack.shift();\\n c3x = c2x + stack.shift();\\n c3y = c2y;\\n c4x = c3x + stack.shift();\\n c4y = c3y;\\n c5x = c4x + stack.shift();\\n c5y = c4y;\\n c6x = c5x + stack.shift();\\n c6y = c5y;\\n x = c6x;\\n y = c6y;\\n path.bezierCurveTo(c1x, c1y, c2x, c2y, c3x, c3y);\\n path.bezierCurveTo(c4x, c4y, c5x, c5y, c6x, c6y);\\n break;\\n case 35:\\n pts = [];\\n for (let i = 0; i <= 5; i++) {\\n x += stack.shift();\\n y += stack.shift();\\n pts.push(x, y);\\n }\\n path.bezierCurveTo(...pts.slice(0, 6));\\n path.bezierCurveTo(...pts.slice(6));\\n stack.shift();\\n break;\\n case 36:\\n c1x = x + stack.shift();\\n c1y = y + stack.shift();\\n c2x = c1x + stack.shift();\\n c2y = c1y + stack.shift();\\n c3x = c2x + stack.shift();\\n c3y = c2y;\\n c4x = c3x + stack.shift();\\n c4y = c3y;\\n c5x = c4x + stack.shift();\\n c5y = c4y + stack.shift();\\n c6x = c5x + stack.shift();\\n c6y = c5y;\\n x = c6x;\\n y = c6y;\\n path.bezierCurveTo(c1x, c1y, c2x, c2y, c3x, c3y);\\n path.bezierCurveTo(c4x, c4y, c5x, c5y, c6x, c6y);\\n break;\\n case 37:\\n let startx = x;\\n let starty = y;\\n pts = [];\\n for (let i = 0; i <= 4; i++) {\\n x += stack.shift();\\n y += stack.shift();\\n pts.push(x, y);\\n }\\n if (Math.abs(x - startx) > Math.abs(y - starty)) {\\n x += stack.shift();\\n y = starty;\\n } else {\\n x = startx;\\n y += stack.shift();\\n }\\n pts.push(x, y);\\n path.bezierCurveTo(...pts.slice(0, 6));\\n path.bezierCurveTo(...pts.slice(6));\\n break;\\n default:\\n throw new Error(`Unknown op: 12 ${op}`);\\n }\\n break;\\n default:\\n throw new Error(`Unknown op: ${op}`);\\n }\\n } else if (op < 247) stack.push(op - 139);\\n else if (op < 251) {\\n var b1 = stream.readUInt8();\\n stack.push((op - 247) * 256 + b1 + 108);\\n } else if (op < 255) {\\n var b1 = stream.readUInt8();\\n stack.push(-(op - 251) * 256 - b1 - 108);\\n } else stack.push(stream.readInt32BE() / 65536);\\n }\\n };\\n parse();\\n if (open) path.closePath();\\n return path;\\n }\\n constructor(...args) {\\n super(...args);\\n (0, _define_property)(this, \\\"type\\\", \\\"CFF\\\");\\n }\\n };\\n $25d8f049c222084c$var$SBIXImage = new Struct({\\n originX: uint16,\\n originY: uint16,\\n type: new StringT(4),\\n data: new BufferT((t) => t.parent.buflen - t._currentOffset)\\n });\\n $25d8f049c222084c$export$2e2bcd8739ae039 = class extends (0, $69aac16029968692$export$2e2bcd8739ae039) {\\n /**\\n * Returns an object representing a glyph image at the given point size.\\n * The object has a data property with a Buffer containing the actual image data,\\n * along with the image type, and origin.\\n *\\n * @param {number} size\\n * @return {object}\\n */\\n getImageForSize(size) {\\n for (let i = 0; i < this._font.sbix.imageTables.length; i++) {\\n var table = this._font.sbix.imageTables[i];\\n if (table.ppem >= size) break;\\n }\\n let offsets = table.imageOffsets;\\n let start = offsets[this.id];\\n let end = offsets[this.id + 1];\\n if (start === end) return null;\\n this._font.stream.pos = start;\\n return $25d8f049c222084c$var$SBIXImage.decode(this._font.stream, {\\n buflen: end - start\\n });\\n }\\n render(ctx, size) {\\n let img = this.getImageForSize(size);\\n if (img != null) {\\n let scale = size / this._font.unitsPerEm;\\n ctx.image(img.data, {\\n height: size,\\n x: img.originX,\\n y: (this.bbox.minY - img.originY) * scale\\n });\\n }\\n if (this._font.sbix.flags.renderOutlines) super.render(ctx, size);\\n }\\n constructor(...args) {\\n super(...args);\\n (0, _define_property)(this, \\\"type\\\", \\\"SBIX\\\");\\n }\\n };\\n $0d411f0165859681$var$COLRLayer = class {\\n constructor(glyph, color) {\\n this.glyph = glyph;\\n this.color = color;\\n }\\n };\\n $0d411f0165859681$export$2e2bcd8739ae039 = class extends (0, $f92906be28e61769$export$2e2bcd8739ae039) {\\n _getBBox() {\\n let bbox = new (0, $f34600ab9d7f70d8$export$2e2bcd8739ae039)();\\n for (let i = 0; i < this.layers.length; i++) {\\n let layer = this.layers[i];\\n let b = layer.glyph.bbox;\\n bbox.addPoint(b.minX, b.minY);\\n bbox.addPoint(b.maxX, b.maxY);\\n }\\n return bbox;\\n }\\n /**\\n * Returns an array of objects containing the glyph and color for\\n * each layer in the composite color glyph.\\n * @type {object[]}\\n */\\n get layers() {\\n let cpal = this._font.CPAL;\\n let colr = this._font.COLR;\\n let low = 0;\\n let high = colr.baseGlyphRecord.length - 1;\\n while (low <= high) {\\n let mid = low + high >> 1;\\n var rec = colr.baseGlyphRecord[mid];\\n if (this.id < rec.gid) high = mid - 1;\\n else if (this.id > rec.gid) low = mid + 1;\\n else {\\n var baseLayer = rec;\\n break;\\n }\\n }\\n if (baseLayer == null) {\\n var g = this._font._getBaseGlyph(this.id);\\n var color = {\\n red: 0,\\n green: 0,\\n blue: 0,\\n alpha: 255\\n };\\n return [\\n new $0d411f0165859681$var$COLRLayer(g, color)\\n ];\\n }\\n let layers = [];\\n for (let i = baseLayer.firstLayerIndex; i < baseLayer.firstLayerIndex + baseLayer.numLayers; i++) {\\n var rec = colr.layerRecords[i];\\n var color = cpal.colorRecords[rec.paletteIndex];\\n var g = this._font._getBaseGlyph(rec.gid);\\n layers.push(new $0d411f0165859681$var$COLRLayer(g, color));\\n }\\n return layers;\\n }\\n render(ctx, size) {\\n for (let { glyph, color } of this.layers) {\\n ctx.fillColor([\\n color.red,\\n color.green,\\n color.blue\\n ], color.alpha / 255 * 100);\\n glyph.render(ctx, size);\\n }\\n return;\\n }\\n constructor(...args) {\\n super(...args);\\n (0, _define_property)(this, \\\"type\\\", \\\"COLR\\\");\\n }\\n };\\n $0bb840cac04e911b$var$TUPLES_SHARE_POINT_NUMBERS = 32768;\\n $0bb840cac04e911b$var$TUPLE_COUNT_MASK = 4095;\\n $0bb840cac04e911b$var$EMBEDDED_TUPLE_COORD = 32768;\\n $0bb840cac04e911b$var$INTERMEDIATE_TUPLE = 16384;\\n $0bb840cac04e911b$var$PRIVATE_POINT_NUMBERS = 8192;\\n $0bb840cac04e911b$var$TUPLE_INDEX_MASK = 4095;\\n $0bb840cac04e911b$var$POINTS_ARE_WORDS = 128;\\n $0bb840cac04e911b$var$POINT_RUN_COUNT_MASK = 127;\\n $0bb840cac04e911b$var$DELTAS_ARE_ZERO = 128;\\n $0bb840cac04e911b$var$DELTAS_ARE_WORDS = 64;\\n $0bb840cac04e911b$var$DELTA_RUN_COUNT_MASK = 63;\\n $0bb840cac04e911b$export$2e2bcd8739ae039 = class {\\n normalizeCoords(coords) {\\n let normalized = [];\\n for (var i = 0; i < this.font.fvar.axis.length; i++) {\\n let axis = this.font.fvar.axis[i];\\n if (coords[i] < axis.defaultValue) normalized.push((coords[i] - axis.defaultValue + Number.EPSILON) / (axis.defaultValue - axis.minValue + Number.EPSILON));\\n else normalized.push((coords[i] - axis.defaultValue + Number.EPSILON) / (axis.maxValue - axis.defaultValue + Number.EPSILON));\\n }\\n if (this.font.avar) for (var i = 0; i < this.font.avar.segment.length; i++) {\\n let segment = this.font.avar.segment[i];\\n for (let j = 0; j < segment.correspondence.length; j++) {\\n let pair = segment.correspondence[j];\\n if (j >= 1 && normalized[i] < pair.fromCoord) {\\n let prev = segment.correspondence[j - 1];\\n normalized[i] = ((normalized[i] - prev.fromCoord) * (pair.toCoord - prev.toCoord) + Number.EPSILON) / (pair.fromCoord - prev.fromCoord + Number.EPSILON) + prev.toCoord;\\n break;\\n }\\n }\\n }\\n return normalized;\\n }\\n transformPoints(gid, glyphPoints) {\\n if (!this.font.fvar || !this.font.gvar) return;\\n let { gvar } = this.font;\\n if (gid >= gvar.glyphCount) return;\\n let offset = gvar.offsets[gid];\\n if (offset === gvar.offsets[gid + 1]) return;\\n let { stream } = this.font;\\n stream.pos = offset;\\n if (stream.pos >= stream.length) return;\\n let tupleCount = stream.readUInt16BE();\\n let offsetToData = offset + stream.readUInt16BE();\\n if (tupleCount & $0bb840cac04e911b$var$TUPLES_SHARE_POINT_NUMBERS) {\\n var here = stream.pos;\\n stream.pos = offsetToData;\\n var sharedPoints = this.decodePoints();\\n offsetToData = stream.pos;\\n stream.pos = here;\\n }\\n let origPoints = glyphPoints.map((pt) => pt.copy());\\n tupleCount &= $0bb840cac04e911b$var$TUPLE_COUNT_MASK;\\n for (let i = 0; i < tupleCount; i++) {\\n let tupleDataSize = stream.readUInt16BE();\\n let tupleIndex = stream.readUInt16BE();\\n if (tupleIndex & $0bb840cac04e911b$var$EMBEDDED_TUPLE_COORD) {\\n var tupleCoords = [];\\n for (let a = 0; a < gvar.axisCount; a++) tupleCoords.push(stream.readInt16BE() / 16384);\\n } else {\\n if ((tupleIndex & $0bb840cac04e911b$var$TUPLE_INDEX_MASK) >= gvar.globalCoordCount) throw new Error(\\\"Invalid gvar table\\\");\\n var tupleCoords = gvar.globalCoords[tupleIndex & $0bb840cac04e911b$var$TUPLE_INDEX_MASK];\\n }\\n if (tupleIndex & $0bb840cac04e911b$var$INTERMEDIATE_TUPLE) {\\n var startCoords = [];\\n for (let a = 0; a < gvar.axisCount; a++) startCoords.push(stream.readInt16BE() / 16384);\\n var endCoords = [];\\n for (let a = 0; a < gvar.axisCount; a++) endCoords.push(stream.readInt16BE() / 16384);\\n }\\n let factor = this.tupleFactor(tupleIndex, tupleCoords, startCoords, endCoords);\\n if (factor === 0) {\\n offsetToData += tupleDataSize;\\n continue;\\n }\\n var here = stream.pos;\\n stream.pos = offsetToData;\\n if (tupleIndex & $0bb840cac04e911b$var$PRIVATE_POINT_NUMBERS) var points = this.decodePoints();\\n else var points = sharedPoints;\\n let nPoints = points.length === 0 ? glyphPoints.length : points.length;\\n let xDeltas = this.decodeDeltas(nPoints);\\n let yDeltas = this.decodeDeltas(nPoints);\\n if (points.length === 0) for (let i2 = 0; i2 < glyphPoints.length; i2++) {\\n var point = glyphPoints[i2];\\n point.x += Math.round(xDeltas[i2] * factor);\\n point.y += Math.round(yDeltas[i2] * factor);\\n }\\n else {\\n let outPoints = origPoints.map((pt) => pt.copy());\\n let hasDelta = glyphPoints.map(() => false);\\n for (let i2 = 0; i2 < points.length; i2++) {\\n let idx = points[i2];\\n if (idx < glyphPoints.length) {\\n let point2 = outPoints[idx];\\n hasDelta[idx] = true;\\n point2.x += xDeltas[i2] * factor;\\n point2.y += yDeltas[i2] * factor;\\n }\\n }\\n this.interpolateMissingDeltas(outPoints, origPoints, hasDelta);\\n for (let i2 = 0; i2 < glyphPoints.length; i2++) {\\n let deltaX = outPoints[i2].x - origPoints[i2].x;\\n let deltaY = outPoints[i2].y - origPoints[i2].y;\\n glyphPoints[i2].x = Math.round(glyphPoints[i2].x + deltaX);\\n glyphPoints[i2].y = Math.round(glyphPoints[i2].y + deltaY);\\n }\\n }\\n offsetToData += tupleDataSize;\\n stream.pos = here;\\n }\\n }\\n decodePoints() {\\n let stream = this.font.stream;\\n let count = stream.readUInt8();\\n if (count & $0bb840cac04e911b$var$POINTS_ARE_WORDS) count = (count & $0bb840cac04e911b$var$POINT_RUN_COUNT_MASK) << 8 | stream.readUInt8();\\n let points = new Uint16Array(count);\\n let i = 0;\\n let point = 0;\\n while (i < count) {\\n let run = stream.readUInt8();\\n let runCount = (run & $0bb840cac04e911b$var$POINT_RUN_COUNT_MASK) + 1;\\n let fn = run & $0bb840cac04e911b$var$POINTS_ARE_WORDS ? stream.readUInt16 : stream.readUInt8;\\n for (let j = 0; j < runCount && i < count; j++) {\\n point += fn.call(stream);\\n points[i++] = point;\\n }\\n }\\n return points;\\n }\\n decodeDeltas(count) {\\n let stream = this.font.stream;\\n let i = 0;\\n let deltas = new Int16Array(count);\\n while (i < count) {\\n let run = stream.readUInt8();\\n let runCount = (run & $0bb840cac04e911b$var$DELTA_RUN_COUNT_MASK) + 1;\\n if (run & $0bb840cac04e911b$var$DELTAS_ARE_ZERO) i += runCount;\\n else {\\n let fn = run & $0bb840cac04e911b$var$DELTAS_ARE_WORDS ? stream.readInt16BE : stream.readInt8;\\n for (let j = 0; j < runCount && i < count; j++) deltas[i++] = fn.call(stream);\\n }\\n }\\n return deltas;\\n }\\n tupleFactor(tupleIndex, tupleCoords, startCoords, endCoords) {\\n let normalized = this.normalizedCoords;\\n let { gvar } = this.font;\\n let factor = 1;\\n for (let i = 0; i < gvar.axisCount; i++) {\\n if (tupleCoords[i] === 0) continue;\\n if (normalized[i] === 0) return 0;\\n if ((tupleIndex & $0bb840cac04e911b$var$INTERMEDIATE_TUPLE) === 0) {\\n if (normalized[i] < Math.min(0, tupleCoords[i]) || normalized[i] > Math.max(0, tupleCoords[i])) return 0;\\n factor = (factor * normalized[i] + Number.EPSILON) / (tupleCoords[i] + Number.EPSILON);\\n } else {\\n if (normalized[i] < startCoords[i] || normalized[i] > endCoords[i]) return 0;\\n else if (normalized[i] < tupleCoords[i]) factor = factor * (normalized[i] - startCoords[i] + Number.EPSILON) / (tupleCoords[i] - startCoords[i] + Number.EPSILON);\\n else factor = factor * (endCoords[i] - normalized[i] + Number.EPSILON) / (endCoords[i] - tupleCoords[i] + Number.EPSILON);\\n }\\n }\\n return factor;\\n }\\n // Interpolates points without delta values.\\n // Needed for the Ø and Q glyphs in Skia.\\n // Algorithm from Freetype.\\n interpolateMissingDeltas(points, inPoints, hasDelta) {\\n if (points.length === 0) return;\\n let point = 0;\\n while (point < points.length) {\\n let firstPoint = point;\\n let endPoint = point;\\n let pt = points[endPoint];\\n while (!pt.endContour) pt = points[++endPoint];\\n while (point <= endPoint && !hasDelta[point]) point++;\\n if (point > endPoint) continue;\\n let firstDelta = point;\\n let curDelta = point;\\n point++;\\n while (point <= endPoint) {\\n if (hasDelta[point]) {\\n this.deltaInterpolate(curDelta + 1, point - 1, curDelta, point, inPoints, points);\\n curDelta = point;\\n }\\n point++;\\n }\\n if (curDelta === firstDelta) this.deltaShift(firstPoint, endPoint, curDelta, inPoints, points);\\n else {\\n this.deltaInterpolate(curDelta + 1, endPoint, curDelta, firstDelta, inPoints, points);\\n if (firstDelta > 0) this.deltaInterpolate(firstPoint, firstDelta - 1, curDelta, firstDelta, inPoints, points);\\n }\\n point = endPoint + 1;\\n }\\n }\\n deltaInterpolate(p1, p2, ref1, ref2, inPoints, outPoints) {\\n if (p1 > p2) return;\\n let iterable = [\\n \\\"x\\\",\\n \\\"y\\\"\\n ];\\n for (let i = 0; i < iterable.length; i++) {\\n let k = iterable[i];\\n if (inPoints[ref1][k] > inPoints[ref2][k]) {\\n var p = ref1;\\n ref1 = ref2;\\n ref2 = p;\\n }\\n let in1 = inPoints[ref1][k];\\n let in2 = inPoints[ref2][k];\\n let out1 = outPoints[ref1][k];\\n let out2 = outPoints[ref2][k];\\n if (in1 !== in2 || out1 === out2) {\\n let scale = in1 === in2 ? 0 : (out2 - out1) / (in2 - in1);\\n for (let p3 = p1; p3 <= p2; p3++) {\\n let out = inPoints[p3][k];\\n if (out <= in1) out += out1 - in1;\\n else if (out >= in2) out += out2 - in2;\\n else out = out1 + (out - in1) * scale;\\n outPoints[p3][k] = out;\\n }\\n }\\n }\\n }\\n deltaShift(p1, p2, ref, inPoints, outPoints) {\\n let deltaX = outPoints[ref].x - inPoints[ref].x;\\n let deltaY = outPoints[ref].y - inPoints[ref].y;\\n if (deltaX === 0 && deltaY === 0) return;\\n for (let p = p1; p <= p2; p++) if (p !== ref) {\\n outPoints[p].x += deltaX;\\n outPoints[p].y += deltaY;\\n }\\n }\\n getAdvanceAdjustment(gid, table) {\\n let outerIndex, innerIndex;\\n if (table.advanceWidthMapping) {\\n let idx = gid;\\n if (idx >= table.advanceWidthMapping.mapCount) idx = table.advanceWidthMapping.mapCount - 1;\\n let entryFormat = table.advanceWidthMapping.entryFormat;\\n ({ outerIndex, innerIndex } = table.advanceWidthMapping.mapData[idx]);\\n } else {\\n outerIndex = 0;\\n innerIndex = gid;\\n }\\n return this.getDelta(table.itemVariationStore, outerIndex, innerIndex);\\n }\\n // See pseudo code from `Font Variations Overview'\\n // in the OpenType specification.\\n getDelta(itemStore, outerIndex, innerIndex) {\\n if (outerIndex >= itemStore.itemVariationData.length) return 0;\\n let varData = itemStore.itemVariationData[outerIndex];\\n if (innerIndex >= varData.deltaSets.length) return 0;\\n let deltaSet = varData.deltaSets[innerIndex];\\n let blendVector = this.getBlendVector(itemStore, outerIndex);\\n let netAdjustment = 0;\\n for (let master = 0; master < varData.regionIndexCount; master++) netAdjustment += deltaSet.deltas[master] * blendVector[master];\\n return netAdjustment;\\n }\\n getBlendVector(itemStore, outerIndex) {\\n let varData = itemStore.itemVariationData[outerIndex];\\n if (this.blendVectors.has(varData)) return this.blendVectors.get(varData);\\n let normalizedCoords = this.normalizedCoords;\\n let blendVector = [];\\n for (let master = 0; master < varData.regionIndexCount; master++) {\\n let scalar = 1;\\n let regionIndex = varData.regionIndexes[master];\\n let axes = itemStore.variationRegionList.variationRegions[regionIndex];\\n for (let j = 0; j < axes.length; j++) {\\n let axis = axes[j];\\n let axisScalar;\\n if (axis.startCoord > axis.peakCoord || axis.peakCoord > axis.endCoord) axisScalar = 1;\\n else if (axis.startCoord < 0 && axis.endCoord > 0 && axis.peakCoord !== 0) axisScalar = 1;\\n else if (axis.peakCoord === 0) axisScalar = 1;\\n else if (normalizedCoords[j] < axis.startCoord || normalizedCoords[j] > axis.endCoord) axisScalar = 0;\\n else {\\n if (normalizedCoords[j] === axis.peakCoord) axisScalar = 1;\\n else if (normalizedCoords[j] < axis.peakCoord) axisScalar = (normalizedCoords[j] - axis.startCoord + Number.EPSILON) / (axis.peakCoord - axis.startCoord + Number.EPSILON);\\n else axisScalar = (axis.endCoord - normalizedCoords[j] + Number.EPSILON) / (axis.endCoord - axis.peakCoord + Number.EPSILON);\\n }\\n scalar *= axisScalar;\\n }\\n blendVector[master] = scalar;\\n }\\n this.blendVectors.set(varData, blendVector);\\n return blendVector;\\n }\\n constructor(font, coords) {\\n this.font = font;\\n this.normalizedCoords = this.normalizeCoords(coords);\\n this.blendVectors = /* @__PURE__ */ new Map();\\n }\\n };\\n $5cc7476da92df375$var$resolved = Promise.resolve();\\n $5cc7476da92df375$export$2e2bcd8739ae039 = class {\\n includeGlyph(glyph) {\\n if (typeof glyph === \\\"object\\\") glyph = glyph.id;\\n if (this.mapping[glyph] == null) {\\n this.glyphs.push(glyph);\\n this.mapping[glyph] = this.glyphs.length - 1;\\n }\\n return this.mapping[glyph];\\n }\\n constructor(font) {\\n this.font = font;\\n this.glyphs = [];\\n this.mapping = {};\\n this.includeGlyph(0);\\n }\\n };\\n $807e58506be70005$var$ON_CURVE = 1;\\n $807e58506be70005$var$X_SHORT_VECTOR = 2;\\n $807e58506be70005$var$Y_SHORT_VECTOR = 4;\\n $807e58506be70005$var$REPEAT = 8;\\n $807e58506be70005$var$SAME_X = 16;\\n $807e58506be70005$var$SAME_Y = 32;\\n $807e58506be70005$var$Point = class {\\n static size(val) {\\n return val >= 0 && val <= 255 ? 1 : 2;\\n }\\n static encode(stream, value) {\\n if (value >= 0 && value <= 255) stream.writeUInt8(value);\\n else stream.writeInt16BE(value);\\n }\\n };\\n $807e58506be70005$var$Glyf = new Struct({\\n numberOfContours: int16,\\n xMin: int16,\\n yMin: int16,\\n xMax: int16,\\n yMax: int16,\\n endPtsOfContours: new ArrayT(uint16, \\\"numberOfContours\\\"),\\n instructions: new ArrayT(uint8, uint16),\\n flags: new ArrayT(uint8, 0),\\n xPoints: new ArrayT($807e58506be70005$var$Point, 0),\\n yPoints: new ArrayT($807e58506be70005$var$Point, 0)\\n });\\n $807e58506be70005$export$2e2bcd8739ae039 = class {\\n encodeSimple(path, instructions = []) {\\n let endPtsOfContours = [];\\n let xPoints = [];\\n let yPoints = [];\\n let flags = [];\\n let same = 0;\\n let lastX = 0, lastY = 0, lastFlag = 0;\\n let pointCount = 0;\\n for (let i = 0; i < path.commands.length; i++) {\\n let c = path.commands[i];\\n for (let j = 0; j < c.args.length; j += 2) {\\n let x = c.args[j];\\n let y = c.args[j + 1];\\n let flag = 0;\\n if (c.command === \\\"quadraticCurveTo\\\" && j === 2) {\\n let next = path.commands[i + 1];\\n if (next && next.command === \\\"quadraticCurveTo\\\") {\\n let midX = (lastX + next.args[0]) / 2;\\n let midY = (lastY + next.args[1]) / 2;\\n if (x === midX && y === midY) continue;\\n }\\n }\\n if (!(c.command === \\\"quadraticCurveTo\\\" && j === 0)) flag |= $807e58506be70005$var$ON_CURVE;\\n flag = this._encodePoint(x, lastX, xPoints, flag, $807e58506be70005$var$X_SHORT_VECTOR, $807e58506be70005$var$SAME_X);\\n flag = this._encodePoint(y, lastY, yPoints, flag, $807e58506be70005$var$Y_SHORT_VECTOR, $807e58506be70005$var$SAME_Y);\\n if (flag === lastFlag && same < 255) {\\n flags[flags.length - 1] |= $807e58506be70005$var$REPEAT;\\n same++;\\n } else {\\n if (same > 0) {\\n flags.push(same);\\n same = 0;\\n }\\n flags.push(flag);\\n lastFlag = flag;\\n }\\n lastX = x;\\n lastY = y;\\n pointCount++;\\n }\\n if (c.command === \\\"closePath\\\") endPtsOfContours.push(pointCount - 1);\\n }\\n if (path.commands.length > 1 && path.commands[path.commands.length - 1].command !== \\\"closePath\\\") endPtsOfContours.push(pointCount - 1);\\n let bbox = path.bbox;\\n let glyf = {\\n numberOfContours: endPtsOfContours.length,\\n xMin: bbox.minX,\\n yMin: bbox.minY,\\n xMax: bbox.maxX,\\n yMax: bbox.maxY,\\n endPtsOfContours,\\n instructions,\\n flags,\\n xPoints,\\n yPoints\\n };\\n let size = $807e58506be70005$var$Glyf.size(glyf);\\n let tail = 4 - size % 4;\\n let stream = new EncodeStream(size + tail);\\n $807e58506be70005$var$Glyf.encode(stream, glyf);\\n if (tail !== 0) stream.fill(0, tail);\\n return stream.buffer;\\n }\\n _encodePoint(value, last, points, flag, shortFlag, sameFlag) {\\n let diff = value - last;\\n if (value === last) flag |= sameFlag;\\n else {\\n if (-255 <= diff && diff <= 255) {\\n flag |= shortFlag;\\n if (diff < 0) diff = -diff;\\n else flag |= sameFlag;\\n }\\n points.push(diff);\\n }\\n return flag;\\n }\\n };\\n $4abbb6a5dbdc441a$export$2e2bcd8739ae039 = class extends (0, $5cc7476da92df375$export$2e2bcd8739ae039) {\\n _addGlyph(gid) {\\n let glyph = this.font.getGlyph(gid);\\n let glyf = glyph._decode();\\n let curOffset = this.font.loca.offsets[gid];\\n let nextOffset = this.font.loca.offsets[gid + 1];\\n let stream = this.font._getTableStream(\\\"glyf\\\");\\n stream.pos += curOffset;\\n let buffer = stream.readBuffer(nextOffset - curOffset);\\n if (glyf && glyf.numberOfContours < 0) {\\n buffer = new Uint8Array(buffer);\\n let view = new DataView(buffer.buffer);\\n for (let component of glyf.components) {\\n gid = this.includeGlyph(component.glyphID);\\n view.setUint16(component.pos, gid);\\n }\\n } else if (glyf && this.font._variationProcessor)\\n buffer = this.glyphEncoder.encodeSimple(glyph.path, glyf.instructions);\\n this.glyf.push(buffer);\\n this.loca.offsets.push(this.offset);\\n this.hmtx.metrics.push({\\n advance: glyph.advanceWidth,\\n bearing: glyph._getMetrics().leftBearing\\n });\\n this.offset += buffer.length;\\n return this.glyf.length - 1;\\n }\\n encode() {\\n this.glyf = [];\\n this.offset = 0;\\n this.loca = {\\n offsets: [],\\n version: this.font.loca.version\\n };\\n this.hmtx = {\\n metrics: [],\\n bearings: []\\n };\\n let i = 0;\\n while (i < this.glyphs.length) this._addGlyph(this.glyphs[i++]);\\n let maxp = (0, import_clone.default)(this.font.maxp);\\n maxp.numGlyphs = this.glyf.length;\\n this.loca.offsets.push(this.offset);\\n let head = (0, import_clone.default)(this.font.head);\\n head.indexToLocFormat = this.loca.version;\\n let hhea = (0, import_clone.default)(this.font.hhea);\\n hhea.numberOfMetrics = this.hmtx.metrics.length;\\n return (0, $816c07a04b6dba87$export$2e2bcd8739ae039).toBuffer({\\n tables: {\\n head,\\n hhea,\\n loca: this.loca,\\n maxp,\\n \\\"cvt \\\": this.font[\\\"cvt \\\"],\\n prep: this.font.prep,\\n glyf: this.glyf,\\n hmtx: this.hmtx,\\n fpgm: this.font.fpgm\\n }\\n });\\n }\\n constructor(font) {\\n super(font);\\n this.glyphEncoder = new (0, $807e58506be70005$export$2e2bcd8739ae039)();\\n }\\n };\\n $001d739428a71d5a$export$2e2bcd8739ae039 = class extends (0, $5cc7476da92df375$export$2e2bcd8739ae039) {\\n subsetCharstrings() {\\n this.charstrings = [];\\n let gsubrs = {};\\n for (let gid of this.glyphs) {\\n this.charstrings.push(this.cff.getCharString(gid));\\n let glyph = this.font.getGlyph(gid);\\n let path = glyph.path;\\n for (let subr in glyph._usedGsubrs) gsubrs[subr] = true;\\n }\\n this.gsubrs = this.subsetSubrs(this.cff.globalSubrIndex, gsubrs);\\n }\\n subsetSubrs(subrs, used) {\\n let res = [];\\n for (let i = 0; i < subrs.length; i++) {\\n let subr = subrs[i];\\n if (used[i]) {\\n this.cff.stream.pos = subr.offset;\\n res.push(this.cff.stream.readBuffer(subr.length));\\n } else res.push(new Uint8Array([\\n 11\\n ]));\\n }\\n return res;\\n }\\n subsetFontdict(topDict) {\\n topDict.FDArray = [];\\n topDict.FDSelect = {\\n version: 0,\\n fds: []\\n };\\n let used_fds = {};\\n let used_subrs = [];\\n let fd_select = {};\\n for (let gid of this.glyphs) {\\n let fd = this.cff.fdForGlyph(gid);\\n if (fd == null) continue;\\n if (!used_fds[fd]) {\\n topDict.FDArray.push(Object.assign({}, this.cff.topDict.FDArray[fd]));\\n used_subrs.push({});\\n fd_select[fd] = topDict.FDArray.length - 1;\\n }\\n used_fds[fd] = true;\\n topDict.FDSelect.fds.push(fd_select[fd]);\\n let glyph = this.font.getGlyph(gid);\\n let path = glyph.path;\\n for (let subr in glyph._usedSubrs) used_subrs[fd_select[fd]][subr] = true;\\n }\\n for (let i = 0; i < topDict.FDArray.length; i++) {\\n let dict = topDict.FDArray[i];\\n delete dict.FontName;\\n if (dict.Private && dict.Private.Subrs) {\\n dict.Private = Object.assign({}, dict.Private);\\n dict.Private.Subrs = this.subsetSubrs(dict.Private.Subrs, used_subrs[i]);\\n }\\n }\\n return;\\n }\\n createCIDFontdict(topDict) {\\n let used_subrs = {};\\n for (let gid of this.glyphs) {\\n let glyph = this.font.getGlyph(gid);\\n let path = glyph.path;\\n for (let subr in glyph._usedSubrs) used_subrs[subr] = true;\\n }\\n let privateDict = Object.assign({}, this.cff.topDict.Private);\\n if (this.cff.topDict.Private && this.cff.topDict.Private.Subrs) privateDict.Subrs = this.subsetSubrs(this.cff.topDict.Private.Subrs, used_subrs);\\n topDict.FDArray = [\\n {\\n Private: privateDict\\n }\\n ];\\n return topDict.FDSelect = {\\n version: 3,\\n nRanges: 1,\\n ranges: [\\n {\\n first: 0,\\n fd: 0\\n }\\n ],\\n sentinel: this.charstrings.length\\n };\\n }\\n addString(string) {\\n if (!string) return null;\\n if (!this.strings) this.strings = [];\\n this.strings.push(string);\\n return (0, $229224aec43783c5$export$2e2bcd8739ae039).length + this.strings.length - 1;\\n }\\n encode() {\\n this.subsetCharstrings();\\n let charset = {\\n version: this.charstrings.length > 255 ? 2 : 1,\\n ranges: [\\n {\\n first: 1,\\n nLeft: this.charstrings.length - 2\\n }\\n ]\\n };\\n let topDict = Object.assign({}, this.cff.topDict);\\n topDict.Private = null;\\n topDict.charset = charset;\\n topDict.Encoding = null;\\n topDict.CharStrings = this.charstrings;\\n for (let key of [\\n \\\"version\\\",\\n \\\"Notice\\\",\\n \\\"Copyright\\\",\\n \\\"FullName\\\",\\n \\\"FamilyName\\\",\\n \\\"Weight\\\",\\n \\\"PostScript\\\",\\n \\\"BaseFontName\\\",\\n \\\"FontName\\\"\\n ]) topDict[key] = this.addString(this.cff.string(topDict[key]));\\n topDict.ROS = [\\n this.addString(\\\"Adobe\\\"),\\n this.addString(\\\"Identity\\\"),\\n 0\\n ];\\n topDict.CIDCount = this.charstrings.length;\\n if (this.cff.isCIDFont) this.subsetFontdict(topDict);\\n else this.createCIDFontdict(topDict);\\n let top = {\\n version: 1,\\n hdrSize: this.cff.hdrSize,\\n offSize: 4,\\n header: this.cff.header,\\n nameIndex: [\\n this.cff.postscriptName\\n ],\\n topDictIndex: [\\n topDict\\n ],\\n stringIndex: this.strings,\\n globalSubrIndex: this.gsubrs\\n };\\n return (0, $b84fd3dd9d8eddb2$export$2e2bcd8739ae039).toBuffer(top);\\n }\\n constructor(font) {\\n super(font);\\n this.cff = this.font[\\\"CFF \\\"];\\n if (!this.cff) throw new Error(\\\"Not a CFF Font\\\");\\n }\\n };\\n $4c1709dee528ea76$export$2e2bcd8739ae039 = class _$4c1709dee528ea76$export$2e2bcd8739ae039 {\\n static probe(buffer) {\\n let format = (0, $12727730ddfc8bfe$export$3d28c1996ced1f14).decode(buffer.slice(0, 4));\\n return format === \\\"true\\\" || format === \\\"OTTO\\\" || format === String.fromCharCode(0, 1, 0, 0);\\n }\\n setDefaultLanguage(lang = null) {\\n this.defaultLanguage = lang;\\n }\\n _getTable(table) {\\n if (!(table.tag in this._tables)) try {\\n this._tables[table.tag] = this._decodeTable(table);\\n } catch (e) {\\n if ($d636bc798e7178db$export$bd5c5d8b8dcafd78) {\\n console.error(`Error decoding table ${table.tag}`);\\n console.error(e.stack);\\n }\\n }\\n return this._tables[table.tag];\\n }\\n _getTableStream(tag) {\\n let table = this.directory.tables[tag];\\n if (table) {\\n this.stream.pos = table.offset;\\n return this.stream;\\n }\\n return null;\\n }\\n _decodeDirectory() {\\n return this.directory = (0, $816c07a04b6dba87$export$2e2bcd8739ae039).decode(this.stream, {\\n _startOffset: 0\\n });\\n }\\n _decodeTable(table) {\\n let pos = this.stream.pos;\\n let stream = this._getTableStream(table.tag);\\n let result = (0, $c3395722bea751e2$export$2e2bcd8739ae039)[table.tag].decode(stream, this, table.length);\\n this.stream.pos = pos;\\n return result;\\n }\\n /**\\n * Gets a string from the font's `name` table\\n * `lang` is a BCP-47 language code.\\n * @return {string}\\n */\\n getName(key, lang = this.defaultLanguage || $d636bc798e7178db$export$42940898df819940) {\\n let record = this.name && this.name.records[key];\\n if (record)\\n return record[lang] || record[this.defaultLanguage] || record[$d636bc798e7178db$export$42940898df819940] || record[\\\"en\\\"] || record[Object.keys(record)[0]] || null;\\n return null;\\n }\\n /**\\n * The unique PostScript name for this font, e.g. \\\"Helvetica-Bold\\\"\\n * @type {string}\\n */\\n get postscriptName() {\\n return this.getName(\\\"postscriptName\\\");\\n }\\n /**\\n * The font's full name, e.g. \\\"Helvetica Bold\\\"\\n * @type {string}\\n */\\n get fullName() {\\n return this.getName(\\\"fullName\\\");\\n }\\n /**\\n * The font's family name, e.g. \\\"Helvetica\\\"\\n * @type {string}\\n */\\n get familyName() {\\n return this.getName(\\\"fontFamily\\\");\\n }\\n /**\\n * The font's sub-family, e.g. \\\"Bold\\\".\\n * @type {string}\\n */\\n get subfamilyName() {\\n return this.getName(\\\"fontSubfamily\\\");\\n }\\n /**\\n * The font's copyright information\\n * @type {string}\\n */\\n get copyright() {\\n return this.getName(\\\"copyright\\\");\\n }\\n /**\\n * The font's version number\\n * @type {string}\\n */\\n get version() {\\n return this.getName(\\\"version\\\");\\n }\\n /**\\n * The font’s [ascender](https://en.wikipedia.org/wiki/Ascender_(typography))\\n * @type {number}\\n */\\n get ascent() {\\n return this.hhea.ascent;\\n }\\n /**\\n * The font’s [descender](https://en.wikipedia.org/wiki/Descender)\\n * @type {number}\\n */\\n get descent() {\\n return this.hhea.descent;\\n }\\n /**\\n * The amount of space that should be included between lines\\n * @type {number}\\n */\\n get lineGap() {\\n return this.hhea.lineGap;\\n }\\n /**\\n * The offset from the normal underline position that should be used\\n * @type {number}\\n */\\n get underlinePosition() {\\n return this.post.underlinePosition;\\n }\\n /**\\n * The weight of the underline that should be used\\n * @type {number}\\n */\\n get underlineThickness() {\\n return this.post.underlineThickness;\\n }\\n /**\\n * If this is an italic font, the angle the cursor should be drawn at to match the font design\\n * @type {number}\\n */\\n get italicAngle() {\\n return this.post.italicAngle;\\n }\\n /**\\n * The height of capital letters above the baseline.\\n * See [here](https://en.wikipedia.org/wiki/Cap_height) for more details.\\n * @type {number}\\n */\\n get capHeight() {\\n let os2 = this[\\\"OS/2\\\"];\\n return os2 ? os2.capHeight : this.ascent;\\n }\\n /**\\n * The height of lower case letters in the font.\\n * See [here](https://en.wikipedia.org/wiki/X-height) for more details.\\n * @type {number}\\n */\\n get xHeight() {\\n let os2 = this[\\\"OS/2\\\"];\\n return os2 ? os2.xHeight : 0;\\n }\\n /**\\n * The number of glyphs in the font.\\n * @type {number}\\n */\\n get numGlyphs() {\\n return this.maxp.numGlyphs;\\n }\\n /**\\n * The size of the font’s internal coordinate grid\\n * @type {number}\\n */\\n get unitsPerEm() {\\n return this.head.unitsPerEm;\\n }\\n /**\\n * The font’s bounding box, i.e. the box that encloses all glyphs in the font.\\n * @type {BBox}\\n */\\n get bbox() {\\n return Object.freeze(new (0, $f34600ab9d7f70d8$export$2e2bcd8739ae039)(this.head.xMin, this.head.yMin, this.head.xMax, this.head.yMax));\\n }\\n get _cmapProcessor() {\\n return new (0, $f08dd41ef10b694c$export$2e2bcd8739ae039)(this.cmap);\\n }\\n /**\\n * An array of all of the unicode code points supported by the font.\\n * @type {number[]}\\n */\\n get characterSet() {\\n return this._cmapProcessor.getCharacterSet();\\n }\\n /**\\n * Returns whether there is glyph in the font for the given unicode code point.\\n *\\n * @param {number} codePoint\\n * @return {boolean}\\n */\\n hasGlyphForCodePoint(codePoint) {\\n return !!this._cmapProcessor.lookup(codePoint);\\n }\\n /**\\n * Maps a single unicode code point to a Glyph object.\\n * Does not perform any advanced substitutions (there is no context to do so).\\n *\\n * @param {number} codePoint\\n * @return {Glyph}\\n */\\n glyphForCodePoint(codePoint) {\\n return this.getGlyph(this._cmapProcessor.lookup(codePoint), [\\n codePoint\\n ]);\\n }\\n /**\\n * Returns an array of Glyph objects for the given string.\\n * This is only a one-to-one mapping from characters to glyphs.\\n * For most uses, you should use font.layout (described below), which\\n * provides a much more advanced mapping supporting AAT and OpenType shaping.\\n *\\n * @param {string} string\\n * @return {Glyph[]}\\n */\\n glyphsForString(string) {\\n let glyphs = [];\\n let len = string.length;\\n let idx = 0;\\n let last = -1;\\n let state = -1;\\n while (idx <= len) {\\n let code = 0;\\n let nextState = 0;\\n if (idx < len) {\\n code = string.charCodeAt(idx++);\\n if (55296 <= code && code <= 56319 && idx < len) {\\n let next = string.charCodeAt(idx);\\n if (56320 <= next && next <= 57343) {\\n idx++;\\n code = ((code & 1023) << 10) + (next & 1023) + 65536;\\n }\\n }\\n nextState = 65024 <= code && code <= 65039 || 917760 <= code && code <= 917999 ? 1 : 0;\\n } else idx++;\\n if (state === 0 && nextState === 1)\\n glyphs.push(this.getGlyph(this._cmapProcessor.lookup(last, code), [\\n last,\\n code\\n ]));\\n else if (state === 0 && nextState === 0)\\n glyphs.push(this.glyphForCodePoint(last));\\n last = code;\\n state = nextState;\\n }\\n return glyphs;\\n }\\n get _layoutEngine() {\\n return new (0, $4c0a7fa5df7a9ab1$export$2e2bcd8739ae039)(this);\\n }\\n /**\\n * Returns a GlyphRun object, which includes an array of Glyphs and GlyphPositions for the given string.\\n *\\n * @param {string} string\\n * @param {string[]} [userFeatures]\\n * @param {string} [script]\\n * @param {string} [language]\\n * @param {string} [direction]\\n * @return {GlyphRun}\\n */\\n layout(string, userFeatures, script, language, direction) {\\n return this._layoutEngine.layout(string, userFeatures, script, language, direction);\\n }\\n /**\\n * Returns an array of strings that map to the given glyph id.\\n * @param {number} gid - glyph id\\n */\\n stringsForGlyph(gid) {\\n return this._layoutEngine.stringsForGlyph(gid);\\n }\\n /**\\n * An array of all [OpenType feature tags](https://www.microsoft.com/typography/otspec/featuretags.htm)\\n * (or mapped AAT tags) supported by the font.\\n * The features parameter is an array of OpenType feature tags to be applied in addition to the default set.\\n * If this is an AAT font, the OpenType feature tags are mapped to AAT features.\\n *\\n * @type {string[]}\\n */\\n get availableFeatures() {\\n return this._layoutEngine.getAvailableFeatures();\\n }\\n getAvailableFeatures(script, language) {\\n return this._layoutEngine.getAvailableFeatures(script, language);\\n }\\n _getBaseGlyph(glyph, characters = []) {\\n if (!this._glyphs[glyph]) {\\n if (this.directory.tables.glyf) this._glyphs[glyph] = new (0, $69aac16029968692$export$2e2bcd8739ae039)(glyph, characters, this);\\n else if (this.directory.tables[\\\"CFF \\\"] || this.directory.tables.CFF2) this._glyphs[glyph] = new (0, $62cc5109c6101893$export$2e2bcd8739ae039)(glyph, characters, this);\\n }\\n return this._glyphs[glyph] || null;\\n }\\n /**\\n * Returns a glyph object for the given glyph id.\\n * You can pass the array of code points this glyph represents for\\n * your use later, and it will be stored in the glyph object.\\n *\\n * @param {number} glyph\\n * @param {number[]} characters\\n * @return {Glyph}\\n */\\n getGlyph(glyph, characters = []) {\\n if (!this._glyphs[glyph]) {\\n if (this.directory.tables.sbix) this._glyphs[glyph] = new (0, $25d8f049c222084c$export$2e2bcd8739ae039)(glyph, characters, this);\\n else if (this.directory.tables.COLR && this.directory.tables.CPAL) this._glyphs[glyph] = new (0, $0d411f0165859681$export$2e2bcd8739ae039)(glyph, characters, this);\\n else this._getBaseGlyph(glyph, characters);\\n }\\n return this._glyphs[glyph] || null;\\n }\\n /**\\n * Returns a Subset for this font.\\n * @return {Subset}\\n */\\n createSubset() {\\n if (this.directory.tables[\\\"CFF \\\"]) return new (0, $001d739428a71d5a$export$2e2bcd8739ae039)(this);\\n return new (0, $4abbb6a5dbdc441a$export$2e2bcd8739ae039)(this);\\n }\\n /**\\n * Returns an object describing the available variation axes\\n * that this font supports. Keys are setting tags, and values\\n * contain the axis name, range, and default value.\\n *\\n * @type {object}\\n */\\n get variationAxes() {\\n let res = {};\\n if (!this.fvar) return res;\\n for (let axis of this.fvar.axis) res[axis.axisTag.trim()] = {\\n name: axis.name.en,\\n min: axis.minValue,\\n default: axis.defaultValue,\\n max: axis.maxValue\\n };\\n return res;\\n }\\n /**\\n * Returns an object describing the named variation instances\\n * that the font designer has specified. Keys are variation names\\n * and values are the variation settings for this instance.\\n *\\n * @type {object}\\n */\\n get namedVariations() {\\n let res = {};\\n if (!this.fvar) return res;\\n for (let instance of this.fvar.instance) {\\n let settings = {};\\n for (let i = 0; i < this.fvar.axis.length; i++) {\\n let axis = this.fvar.axis[i];\\n settings[axis.axisTag.trim()] = instance.coord[i];\\n }\\n res[instance.name.en] = settings;\\n }\\n return res;\\n }\\n /**\\n * Returns a new font with the given variation settings applied.\\n * Settings can either be an instance name, or an object containing\\n * variation tags as specified by the `variationAxes` property.\\n *\\n * @param {object} settings\\n * @return {TTFFont}\\n */\\n getVariation(settings) {\\n if (!(this.directory.tables.fvar && (this.directory.tables.gvar && this.directory.tables.glyf || this.directory.tables.CFF2))) throw new Error(\\\"Variations require a font with the fvar, gvar and glyf, or CFF2 tables.\\\");\\n if (typeof settings === \\\"string\\\") settings = this.namedVariations[settings];\\n if (typeof settings !== \\\"object\\\") throw new Error(\\\"Variation settings must be either a variation name or settings object.\\\");\\n let coords = this.fvar.axis.map((axis, i) => {\\n let axisTag = axis.axisTag.trim();\\n if (axisTag in settings) return Math.max(axis.minValue, Math.min(axis.maxValue, settings[axisTag]));\\n else return axis.defaultValue;\\n });\\n let stream = new DecodeStream(this.stream.buffer);\\n stream.pos = this._directoryPos;\\n let font = new _$4c1709dee528ea76$export$2e2bcd8739ae039(stream, coords);\\n font._tables = this._tables;\\n return font;\\n }\\n get _variationProcessor() {\\n if (!this.fvar) return null;\\n let variationCoords = this.variationCoords;\\n if (!variationCoords && !this.CFF2) return null;\\n if (!variationCoords) variationCoords = this.fvar.axis.map((axis) => axis.defaultValue);\\n return new (0, $0bb840cac04e911b$export$2e2bcd8739ae039)(this, variationCoords);\\n }\\n // Standardized format plugin API\\n getFont(name) {\\n return this.getVariation(name);\\n }\\n constructor(stream, variationCoords = null) {\\n (0, _define_property)(this, \\\"type\\\", \\\"TTF\\\");\\n this.defaultLanguage = null;\\n this.stream = stream;\\n this.variationCoords = variationCoords;\\n this._directoryPos = this.stream.pos;\\n this._tables = {};\\n this._glyphs = {};\\n this._decodeDirectory();\\n for (let tag in this.directory.tables) {\\n let table = this.directory.tables[tag];\\n if ((0, $c3395722bea751e2$export$2e2bcd8739ae039)[tag] && table.length > 0) Object.defineProperty(this, tag, {\\n get: this._getTable.bind(this, table)\\n });\\n }\\n }\\n };\\n (0, __decorate)([\\n (0, $e71565f2ce09cb6b$export$69a3209f1a06c04d)\\n ], $4c1709dee528ea76$export$2e2bcd8739ae039.prototype, \\\"bbox\\\", null);\\n (0, __decorate)([\\n (0, $e71565f2ce09cb6b$export$69a3209f1a06c04d)\\n ], $4c1709dee528ea76$export$2e2bcd8739ae039.prototype, \\\"_cmapProcessor\\\", null);\\n (0, __decorate)([\\n (0, $e71565f2ce09cb6b$export$69a3209f1a06c04d)\\n ], $4c1709dee528ea76$export$2e2bcd8739ae039.prototype, \\\"characterSet\\\", null);\\n (0, __decorate)([\\n (0, $e71565f2ce09cb6b$export$69a3209f1a06c04d)\\n ], $4c1709dee528ea76$export$2e2bcd8739ae039.prototype, \\\"_layoutEngine\\\", null);\\n (0, __decorate)([\\n (0, $e71565f2ce09cb6b$export$69a3209f1a06c04d)\\n ], $4c1709dee528ea76$export$2e2bcd8739ae039.prototype, \\\"variationAxes\\\", null);\\n (0, __decorate)([\\n (0, $e71565f2ce09cb6b$export$69a3209f1a06c04d)\\n ], $4c1709dee528ea76$export$2e2bcd8739ae039.prototype, \\\"namedVariations\\\", null);\\n (0, __decorate)([\\n (0, $e71565f2ce09cb6b$export$69a3209f1a06c04d)\\n ], $4c1709dee528ea76$export$2e2bcd8739ae039.prototype, \\\"_variationProcessor\\\", null);\\n $c1726355ecc5b889$var$WOFFDirectoryEntry = new Struct({\\n tag: new StringT(4),\\n offset: new Pointer(uint32, \\\"void\\\", {\\n type: \\\"global\\\"\\n }),\\n compLength: uint32,\\n length: uint32,\\n origChecksum: uint32\\n });\\n $c1726355ecc5b889$var$WOFFDirectory = new Struct({\\n tag: new StringT(4),\\n flavor: uint32,\\n length: uint32,\\n numTables: uint16,\\n reserved: new Reserved(uint16),\\n totalSfntSize: uint32,\\n majorVersion: uint16,\\n minorVersion: uint16,\\n metaOffset: uint32,\\n metaLength: uint32,\\n metaOrigLength: uint32,\\n privOffset: uint32,\\n privLength: uint32,\\n tables: new ArrayT($c1726355ecc5b889$var$WOFFDirectoryEntry, \\\"numTables\\\")\\n });\\n $c1726355ecc5b889$var$WOFFDirectory.process = function() {\\n let tables = {};\\n for (let table of this.tables) tables[table.tag] = table;\\n this.tables = tables;\\n };\\n $c1726355ecc5b889$export$2e2bcd8739ae039 = $c1726355ecc5b889$var$WOFFDirectory;\\n $760785214b9fc52c$export$2e2bcd8739ae039 = class extends (0, $4c1709dee528ea76$export$2e2bcd8739ae039) {\\n static probe(buffer) {\\n return (0, $12727730ddfc8bfe$export$3d28c1996ced1f14).decode(buffer.slice(0, 4)) === \\\"wOFF\\\";\\n }\\n _decodeDirectory() {\\n this.directory = (0, $c1726355ecc5b889$export$2e2bcd8739ae039).decode(this.stream, {\\n _startOffset: 0\\n });\\n }\\n _getTableStream(tag) {\\n let table = this.directory.tables[tag];\\n if (table) {\\n this.stream.pos = table.offset;\\n if (table.compLength < table.length) {\\n this.stream.pos += 2;\\n let outBuffer = new Uint8Array(table.length);\\n let buf = (0, import_tiny_inflate.default)(this.stream.readBuffer(table.compLength - 2), outBuffer);\\n return new DecodeStream(buf);\\n } else return this.stream;\\n }\\n return null;\\n }\\n constructor(...args) {\\n super(...args);\\n (0, _define_property)(this, \\\"type\\\", \\\"WOFF\\\");\\n }\\n };\\n $8046190c9f1ad19e$export$2e2bcd8739ae039 = class extends (0, $69aac16029968692$export$2e2bcd8739ae039) {\\n _decode() {\\n return this._font._transformedGlyphs[this.id];\\n }\\n _getCBox() {\\n return this.path.bbox;\\n }\\n constructor(...args) {\\n super(...args);\\n (0, _define_property)(this, \\\"type\\\", \\\"WOFF2\\\");\\n }\\n };\\n $c28ec7bbb3b8de3a$var$Base128 = {\\n decode(stream) {\\n let result = 0;\\n let iterable = [\\n 0,\\n 1,\\n 2,\\n 3,\\n 4\\n ];\\n for (let j = 0; j < iterable.length; j++) {\\n let i = iterable[j];\\n let code = stream.readUInt8();\\n if (result & 3758096384) throw new Error(\\\"Overflow\\\");\\n result = result << 7 | code & 127;\\n if ((code & 128) === 0) return result;\\n }\\n throw new Error(\\\"Bad base 128 number\\\");\\n }\\n };\\n $c28ec7bbb3b8de3a$var$knownTags = [\\n \\\"cmap\\\",\\n \\\"head\\\",\\n \\\"hhea\\\",\\n \\\"hmtx\\\",\\n \\\"maxp\\\",\\n \\\"name\\\",\\n \\\"OS/2\\\",\\n \\\"post\\\",\\n \\\"cvt \\\",\\n \\\"fpgm\\\",\\n \\\"glyf\\\",\\n \\\"loca\\\",\\n \\\"prep\\\",\\n \\\"CFF \\\",\\n \\\"VORG\\\",\\n \\\"EBDT\\\",\\n \\\"EBLC\\\",\\n \\\"gasp\\\",\\n \\\"hdmx\\\",\\n \\\"kern\\\",\\n \\\"LTSH\\\",\\n \\\"PCLT\\\",\\n \\\"VDMX\\\",\\n \\\"vhea\\\",\\n \\\"vmtx\\\",\\n \\\"BASE\\\",\\n \\\"GDEF\\\",\\n \\\"GPOS\\\",\\n \\\"GSUB\\\",\\n \\\"EBSC\\\",\\n \\\"JSTF\\\",\\n \\\"MATH\\\",\\n \\\"CBDT\\\",\\n \\\"CBLC\\\",\\n \\\"COLR\\\",\\n \\\"CPAL\\\",\\n \\\"SVG \\\",\\n \\\"sbix\\\",\\n \\\"acnt\\\",\\n \\\"avar\\\",\\n \\\"bdat\\\",\\n \\\"bloc\\\",\\n \\\"bsln\\\",\\n \\\"cvar\\\",\\n \\\"fdsc\\\",\\n \\\"feat\\\",\\n \\\"fmtx\\\",\\n \\\"fvar\\\",\\n \\\"gvar\\\",\\n \\\"hsty\\\",\\n \\\"just\\\",\\n \\\"lcar\\\",\\n \\\"mort\\\",\\n \\\"morx\\\",\\n \\\"opbd\\\",\\n \\\"prop\\\",\\n \\\"trak\\\",\\n \\\"Zapf\\\",\\n \\\"Silf\\\",\\n \\\"Glat\\\",\\n \\\"Gloc\\\",\\n \\\"Feat\\\",\\n \\\"Sill\\\"\\n ];\\n $c28ec7bbb3b8de3a$var$WOFF2DirectoryEntry = new Struct({\\n flags: uint8,\\n customTag: new Optional(new StringT(4), (t) => (t.flags & 63) === 63),\\n tag: (t) => t.customTag || $c28ec7bbb3b8de3a$var$knownTags[t.flags & 63],\\n length: $c28ec7bbb3b8de3a$var$Base128,\\n transformVersion: (t) => t.flags >>> 6 & 3,\\n transformed: (t) => t.tag === \\\"glyf\\\" || t.tag === \\\"loca\\\" ? t.transformVersion === 0 : t.transformVersion !== 0,\\n transformLength: new Optional($c28ec7bbb3b8de3a$var$Base128, (t) => t.transformed)\\n });\\n $c28ec7bbb3b8de3a$var$WOFF2Directory = new Struct({\\n tag: new StringT(4),\\n flavor: uint32,\\n length: uint32,\\n numTables: uint16,\\n reserved: new Reserved(uint16),\\n totalSfntSize: uint32,\\n totalCompressedSize: uint32,\\n majorVersion: uint16,\\n minorVersion: uint16,\\n metaOffset: uint32,\\n metaLength: uint32,\\n metaOrigLength: uint32,\\n privOffset: uint32,\\n privLength: uint32,\\n tables: new ArrayT($c28ec7bbb3b8de3a$var$WOFF2DirectoryEntry, \\\"numTables\\\")\\n });\\n $c28ec7bbb3b8de3a$var$WOFF2Directory.process = function() {\\n let tables = {};\\n for (let i = 0; i < this.tables.length; i++) {\\n let table = this.tables[i];\\n tables[table.tag] = table;\\n }\\n return this.tables = tables;\\n };\\n $c28ec7bbb3b8de3a$export$2e2bcd8739ae039 = $c28ec7bbb3b8de3a$var$WOFF2Directory;\\n $21ee218f84ac7f32$export$2e2bcd8739ae039 = class extends (0, $4c1709dee528ea76$export$2e2bcd8739ae039) {\\n static probe(buffer) {\\n return (0, $12727730ddfc8bfe$export$3d28c1996ced1f14).decode(buffer.slice(0, 4)) === \\\"wOF2\\\";\\n }\\n _decodeDirectory() {\\n this.directory = (0, $c28ec7bbb3b8de3a$export$2e2bcd8739ae039).decode(this.stream);\\n this._dataPos = this.stream.pos;\\n }\\n _decompress() {\\n if (!this._decompressed) {\\n this.stream.pos = this._dataPos;\\n let buffer = this.stream.readBuffer(this.directory.totalCompressedSize);\\n let decompressedSize = 0;\\n for (let tag in this.directory.tables) {\\n let entry = this.directory.tables[tag];\\n entry.offset = decompressedSize;\\n decompressedSize += entry.transformLength != null ? entry.transformLength : entry.length;\\n }\\n let decompressed = (0, import_decompress.default)(buffer, decompressedSize);\\n if (!decompressed) throw new Error(\\\"Error decoding compressed data in WOFF2\\\");\\n this.stream = new DecodeStream(decompressed);\\n this._decompressed = true;\\n }\\n }\\n _decodeTable(table) {\\n this._decompress();\\n return super._decodeTable(table);\\n }\\n // Override this method to get a glyph and return our\\n // custom subclass if there is a glyf table.\\n _getBaseGlyph(glyph, characters = []) {\\n if (!this._glyphs[glyph]) {\\n if (this.directory.tables.glyf && this.directory.tables.glyf.transformed) {\\n if (!this._transformedGlyphs) this._transformGlyfTable();\\n return this._glyphs[glyph] = new (0, $8046190c9f1ad19e$export$2e2bcd8739ae039)(glyph, characters, this);\\n } else return super._getBaseGlyph(glyph, characters);\\n }\\n }\\n _transformGlyfTable() {\\n this._decompress();\\n this.stream.pos = this.directory.tables.glyf.offset;\\n let table = $21ee218f84ac7f32$var$GlyfTable.decode(this.stream);\\n let glyphs = [];\\n for (let index = 0; index < table.numGlyphs; index++) {\\n let glyph = {};\\n let nContours = table.nContours.readInt16BE();\\n glyph.numberOfContours = nContours;\\n if (nContours > 0) {\\n let nPoints = [];\\n let totalPoints = 0;\\n for (let i = 0; i < nContours; i++) {\\n let r = $21ee218f84ac7f32$var$read255UInt16(table.nPoints);\\n totalPoints += r;\\n nPoints.push(totalPoints);\\n }\\n glyph.points = $21ee218f84ac7f32$var$decodeTriplet(table.flags, table.glyphs, totalPoints);\\n for (let i = 0; i < nContours; i++) glyph.points[nPoints[i] - 1].endContour = true;\\n var instructionSize = $21ee218f84ac7f32$var$read255UInt16(table.glyphs);\\n } else if (nContours < 0) {\\n let haveInstructions = (0, $69aac16029968692$export$2e2bcd8739ae039).prototype._decodeComposite.call({\\n _font: this\\n }, glyph, table.composites);\\n if (haveInstructions) var instructionSize = $21ee218f84ac7f32$var$read255UInt16(table.glyphs);\\n }\\n glyphs.push(glyph);\\n }\\n this._transformedGlyphs = glyphs;\\n }\\n constructor(...args) {\\n super(...args);\\n (0, _define_property)(this, \\\"type\\\", \\\"WOFF2\\\");\\n }\\n };\\n $21ee218f84ac7f32$var$Substream = class {\\n decode(stream, parent) {\\n return new DecodeStream(this._buf.decode(stream, parent));\\n }\\n constructor(length) {\\n this.length = length;\\n this._buf = new BufferT(length);\\n }\\n };\\n $21ee218f84ac7f32$var$GlyfTable = new Struct({\\n version: uint32,\\n numGlyphs: uint16,\\n indexFormat: uint16,\\n nContourStreamSize: uint32,\\n nPointsStreamSize: uint32,\\n flagStreamSize: uint32,\\n glyphStreamSize: uint32,\\n compositeStreamSize: uint32,\\n bboxStreamSize: uint32,\\n instructionStreamSize: uint32,\\n nContours: new $21ee218f84ac7f32$var$Substream(\\\"nContourStreamSize\\\"),\\n nPoints: new $21ee218f84ac7f32$var$Substream(\\\"nPointsStreamSize\\\"),\\n flags: new $21ee218f84ac7f32$var$Substream(\\\"flagStreamSize\\\"),\\n glyphs: new $21ee218f84ac7f32$var$Substream(\\\"glyphStreamSize\\\"),\\n composites: new $21ee218f84ac7f32$var$Substream(\\\"compositeStreamSize\\\"),\\n bboxes: new $21ee218f84ac7f32$var$Substream(\\\"bboxStreamSize\\\"),\\n instructions: new $21ee218f84ac7f32$var$Substream(\\\"instructionStreamSize\\\")\\n });\\n $21ee218f84ac7f32$var$WORD_CODE = 253;\\n $21ee218f84ac7f32$var$ONE_MORE_BYTE_CODE2 = 254;\\n $21ee218f84ac7f32$var$ONE_MORE_BYTE_CODE1 = 255;\\n $21ee218f84ac7f32$var$LOWEST_U_CODE = 253;\\n $cd5853a56c68fec7$var$TTCHeader = new VersionedStruct(uint32, {\\n 65536: {\\n numFonts: uint32,\\n offsets: new ArrayT(uint32, \\\"numFonts\\\")\\n },\\n 131072: {\\n numFonts: uint32,\\n offsets: new ArrayT(uint32, \\\"numFonts\\\"),\\n dsigTag: uint32,\\n dsigLength: uint32,\\n dsigOffset: uint32\\n }\\n });\\n $cd5853a56c68fec7$export$2e2bcd8739ae039 = class {\\n static probe(buffer) {\\n return (0, $12727730ddfc8bfe$export$3d28c1996ced1f14).decode(buffer.slice(0, 4)) === \\\"ttcf\\\";\\n }\\n getFont(name) {\\n for (let offset of this.header.offsets) {\\n let stream = new DecodeStream(this.stream.buffer);\\n stream.pos = offset;\\n let font = new (0, $4c1709dee528ea76$export$2e2bcd8739ae039)(stream);\\n if (font.postscriptName === name || font.postscriptName instanceof Uint8Array && name instanceof Uint8Array && font.postscriptName.every((v, i) => name[i] === v)) return font;\\n }\\n return null;\\n }\\n get fonts() {\\n let fonts = [];\\n for (let offset of this.header.offsets) {\\n let stream = new DecodeStream(this.stream.buffer);\\n stream.pos = offset;\\n fonts.push(new (0, $4c1709dee528ea76$export$2e2bcd8739ae039)(stream));\\n }\\n return fonts;\\n }\\n constructor(stream) {\\n (0, _define_property)(this, \\\"type\\\", \\\"TTC\\\");\\n this.stream = stream;\\n if (stream.readString(4) !== \\\"ttcf\\\") throw new Error(\\\"Not a TrueType collection\\\");\\n this.header = $cd5853a56c68fec7$var$TTCHeader.decode(stream);\\n }\\n };\\n $05f49f930186144e$var$DFontName = new StringT(uint8);\\n $05f49f930186144e$var$DFontData = new Struct({\\n len: uint32,\\n buf: new BufferT(\\\"len\\\")\\n });\\n $05f49f930186144e$var$Ref = new Struct({\\n id: uint16,\\n nameOffset: int16,\\n attr: uint8,\\n dataOffset: uint24,\\n handle: uint32\\n });\\n $05f49f930186144e$var$Type = new Struct({\\n name: new StringT(4),\\n maxTypeIndex: uint16,\\n refList: new Pointer(uint16, new ArrayT($05f49f930186144e$var$Ref, (t) => t.maxTypeIndex + 1), {\\n type: \\\"parent\\\"\\n })\\n });\\n $05f49f930186144e$var$TypeList = new Struct({\\n length: uint16,\\n types: new ArrayT($05f49f930186144e$var$Type, (t) => t.length + 1)\\n });\\n $05f49f930186144e$var$DFontMap = new Struct({\\n reserved: new Reserved(uint8, 24),\\n typeList: new Pointer(uint16, $05f49f930186144e$var$TypeList),\\n nameListOffset: new Pointer(uint16, \\\"void\\\")\\n });\\n $05f49f930186144e$var$DFontHeader = new Struct({\\n dataOffset: uint32,\\n map: new Pointer(uint32, $05f49f930186144e$var$DFontMap),\\n dataLength: uint32,\\n mapLength: uint32\\n });\\n $05f49f930186144e$export$2e2bcd8739ae039 = class {\\n static probe(buffer) {\\n let stream = new DecodeStream(buffer);\\n try {\\n var header = $05f49f930186144e$var$DFontHeader.decode(stream);\\n } catch (e) {\\n return false;\\n }\\n for (let type of header.map.typeList.types) {\\n if (type.name === \\\"sfnt\\\") return true;\\n }\\n return false;\\n }\\n getFont(name) {\\n if (!this.sfnt) return null;\\n for (let ref of this.sfnt.refList) {\\n let pos = this.header.dataOffset + ref.dataOffset + 4;\\n let stream = new DecodeStream(this.stream.buffer.slice(pos));\\n let font = new (0, $4c1709dee528ea76$export$2e2bcd8739ae039)(stream);\\n if (font.postscriptName === name || font.postscriptName instanceof Uint8Array && name instanceof Uint8Array && font.postscriptName.every((v, i) => name[i] === v)) return font;\\n }\\n return null;\\n }\\n get fonts() {\\n let fonts = [];\\n for (let ref of this.sfnt.refList) {\\n let pos = this.header.dataOffset + ref.dataOffset + 4;\\n let stream = new DecodeStream(this.stream.buffer.slice(pos));\\n fonts.push(new (0, $4c1709dee528ea76$export$2e2bcd8739ae039)(stream));\\n }\\n return fonts;\\n }\\n constructor(stream) {\\n (0, _define_property)(this, \\\"type\\\", \\\"DFont\\\");\\n this.stream = stream;\\n this.header = $05f49f930186144e$var$DFontHeader.decode(this.stream);\\n for (let type of this.header.map.typeList.types) {\\n for (let ref of type.refList) if (ref.nameOffset >= 0) {\\n this.stream.pos = ref.nameOffset + this.header.map.nameListOffset;\\n ref.name = $05f49f930186144e$var$DFontName.decode(this.stream);\\n } else ref.name = null;\\n if (type.name === \\\"sfnt\\\") this.sfnt = type;\\n }\\n }\\n };\\n (0, $d636bc798e7178db$export$36b2f24e97d43be)((0, $4c1709dee528ea76$export$2e2bcd8739ae039));\\n (0, $d636bc798e7178db$export$36b2f24e97d43be)((0, $760785214b9fc52c$export$2e2bcd8739ae039));\\n (0, $d636bc798e7178db$export$36b2f24e97d43be)((0, $21ee218f84ac7f32$export$2e2bcd8739ae039));\\n (0, $d636bc798e7178db$export$36b2f24e97d43be)((0, $cd5853a56c68fec7$export$2e2bcd8739ae039));\\n (0, $d636bc798e7178db$export$36b2f24e97d43be)((0, $05f49f930186144e$export$2e2bcd8739ae039));\\n }\\n });\\n\\n // src/fonts/google-fonts.ts\\n var TSHIRT_FONTS = [\\n // Bold/Display Fonts - Perfect for statements and headlines (49 fonts)\\n {\\n name: \\\"Bebas Neue\\\",\\n category: \\\"display\\\",\\n weights: [400],\\n googleFont: true,\\n description: \\\"Modern condensed display\\\"\\n },\\n {\\n name: \\\"Bevan\\\",\\n category: \\\"display\\\",\\n weights: [400],\\n googleFont: true,\\n description: \\\"Bold slab serif display\\\"\\n },\\n {\\n name: \\\"Bigshot One\\\",\\n category: \\\"display\\\",\\n weights: [400],\\n googleFont: true,\\n description: \\\"Bold elegant display\\\"\\n },\\n {\\n name: \\\"Anton\\\",\\n category: \\\"display\\\",\\n weights: [400],\\n googleFont: true,\\n description: \\\"Super bold display font\\\"\\n },\\n {\\n name: \\\"Oswald\\\",\\n category: \\\"display\\\",\\n weights: [200, 300, 400, 500, 600, 700],\\n googleFont: true,\\n description: \\\"Condensed sans-serif\\\"\\n },\\n {\\n name: \\\"Archivo Black\\\",\\n category: \\\"display\\\",\\n weights: [400],\\n googleFont: true,\\n description: \\\"Heavy weight display\\\"\\n },\\n {\\n name: \\\"Alfa Slab One\\\",\\n category: \\\"display\\\",\\n weights: [400],\\n googleFont: true,\\n description: \\\"Bold slab serif, varsity style\\\"\\n },\\n {\\n name: \\\"Bowlby One SC\\\",\\n category: \\\"display\\\",\\n weights: [400],\\n googleFont: true,\\n description: \\\"Blocky display, sports style\\\"\\n },\\n {\\n name: \\\"Black Ops One\\\",\\n category: \\\"display\\\",\\n weights: [400],\\n googleFont: true,\\n description: \\\"Military/stencil style\\\"\\n },\\n {\\n name: \\\"Abril Fatface\\\",\\n category: \\\"display\\\",\\n weights: [400],\\n googleFont: true,\\n description: \\\"Bold high-contrast display\\\"\\n },\\n {\\n name: \\\"Bangers\\\",\\n category: \\\"display\\\",\\n weights: [400],\\n googleFont: true,\\n description: \\\"Comic book style\\\"\\n },\\n {\\n name: \\\"Titan One\\\",\\n category: \\\"display\\\",\\n weights: [400],\\n googleFont: true,\\n description: \\\"Heavy impactful display\\\"\\n },\\n {\\n name: \\\"Lilita One\\\",\\n category: \\\"display\\\",\\n weights: [400],\\n googleFont: true,\\n description: \\\"Rounded display font\\\"\\n },\\n {\\n name: \\\"Fugaz One\\\",\\n category: \\\"display\\\",\\n weights: [400],\\n googleFont: true,\\n description: \\\"Bold geometric display\\\"\\n },\\n {\\n name: \\\"Russo One\\\",\\n category: \\\"display\\\",\\n weights: [400],\\n googleFont: true,\\n description: \\\"Bold sans display\\\"\\n },\\n {\\n name: \\\"Passion One\\\",\\n category: \\\"display\\\",\\n weights: [400, 700, 900],\\n googleFont: true,\\n description: \\\"Condensed bold display\\\"\\n },\\n {\\n name: \\\"Righteous\\\",\\n category: \\\"display\\\",\\n weights: [400],\\n googleFont: true,\\n description: \\\"1980s-style display\\\"\\n },\\n {\\n name: \\\"Bungee\\\",\\n category: \\\"display\\\",\\n weights: [400],\\n googleFont: true,\\n description: \\\"Bold urban/street style\\\"\\n },\\n {\\n name: \\\"Barlow Condensed\\\",\\n category: \\\"display\\\",\\n weights: [100, 200, 300, 400, 500, 600, 700, 800, 900],\\n googleFont: true,\\n description: \\\"Condensed sans display\\\"\\n },\\n {\\n name: \\\"Staatliches\\\",\\n category: \\\"display\\\",\\n weights: [400],\\n googleFont: true,\\n description: \\\"Bold condensed display\\\"\\n },\\n {\\n name: \\\"Rubik Mono One\\\",\\n category: \\\"display\\\",\\n weights: [400],\\n googleFont: true,\\n description: \\\"Blocky monoline display\\\"\\n },\\n {\\n name: \\\"Ultra\\\",\\n category: \\\"display\\\",\\n weights: [400],\\n googleFont: true,\\n description: \\\"Ultra bold serif\\\"\\n },\\n {\\n name: \\\"Audiowide\\\",\\n category: \\\"display\\\",\\n weights: [400],\\n googleFont: true,\\n description: \\\"Tech/futuristic display\\\"\\n },\\n {\\n name: \\\"Changa One\\\",\\n category: \\\"display\\\",\\n weights: [400],\\n googleFont: true,\\n description: \\\"Rounded bold display\\\"\\n },\\n {\\n name: \\\"Lobster\\\",\\n category: \\\"display\\\",\\n weights: [400],\\n googleFont: true,\\n description: \\\"Bold script display\\\"\\n },\\n {\\n name: \\\"Coda\\\",\\n category: \\\"display\\\",\\n weights: [400, 800],\\n googleFont: true,\\n description: \\\"Bold humanist sans\\\"\\n },\\n {\\n name: \\\"Teko\\\",\\n category: \\\"display\\\",\\n weights: [300, 400, 500, 600, 700],\\n googleFont: true,\\n description: \\\"Narrow sans display\\\"\\n },\\n {\\n name: \\\"Fredoka One\\\",\\n category: \\\"display\\\",\\n weights: [400],\\n googleFont: true,\\n description: \\\"Rounded bold display\\\"\\n },\\n {\\n name: \\\"Caprasimo\\\",\\n category: \\\"display\\\",\\n weights: [400],\\n googleFont: true,\\n description: \\\"Retro rounded display\\\"\\n },\\n {\\n name: \\\"Fjalla One\\\",\\n category: \\\"display\\\",\\n weights: [400],\\n googleFont: true,\\n description: \\\"Bold condensed sans\\\"\\n },\\n {\\n name: \\\"Secular One\\\",\\n category: \\\"display\\\",\\n weights: [400],\\n googleFont: true,\\n description: \\\"Hebrew-inspired display\\\"\\n },\\n {\\n name: \\\"Saira\\\",\\n category: \\\"display\\\",\\n weights: [100, 200, 300, 400, 500, 600, 700, 800, 900],\\n googleFont: true,\\n description: \\\"Semi-condensed sans display\\\"\\n },\\n {\\n name: \\\"Barlow Semi Condensed\\\",\\n category: \\\"display\\\",\\n weights: [100, 200, 300, 400, 500, 600, 700, 800, 900],\\n googleFont: true,\\n description: \\\"Semi-condensed low-contrast\\\"\\n },\\n {\\n name: \\\"Exo\\\",\\n category: \\\"display\\\",\\n weights: [100, 200, 300, 400, 500, 600, 700, 800, 900],\\n googleFont: true,\\n description: \\\"Geometric technological display\\\"\\n },\\n {\\n name: \\\"Saira Condensed\\\",\\n category: \\\"display\\\",\\n weights: [100, 200, 300, 400, 500, 600, 700, 800, 900],\\n googleFont: true,\\n description: \\\"Condensed display font\\\"\\n },\\n {\\n name: \\\"Fredoka\\\",\\n category: \\\"display\\\",\\n weights: [300, 400, 500, 600, 700],\\n googleFont: true,\\n description: \\\"Rounded friendly display\\\"\\n },\\n {\\n name: \\\"Comfortaa\\\",\\n category: \\\"display\\\",\\n weights: [300, 400, 500, 600, 700],\\n googleFont: true,\\n description: \\\"Rounded geometric display\\\"\\n },\\n {\\n name: \\\"Questrial\\\",\\n category: \\\"display\\\",\\n weights: [400],\\n googleFont: true,\\n description: \\\"Simple sans-serif display\\\"\\n },\\n {\\n name: \\\"Lexend\\\",\\n category: \\\"display\\\",\\n weights: [100, 200, 300, 400, 500, 600, 700, 800, 900],\\n googleFont: true,\\n description: \\\"Variable sans for readability\\\"\\n },\\n {\\n name: \\\"Darker Grotesque\\\",\\n category: \\\"display\\\",\\n weights: [300, 400, 500, 600, 700, 800, 900],\\n googleFont: true,\\n description: \\\"Contemporary grotesque sans\\\"\\n },\\n {\\n name: \\\"Bakbak One\\\",\\n category: \\\"display\\\",\\n weights: [400],\\n googleFont: true,\\n description: \\\"Heavy condensed display\\\"\\n },\\n {\\n name: \\\"Turret Road\\\",\\n category: \\\"display\\\",\\n weights: [200, 300, 400, 500, 700, 800],\\n googleFont: true,\\n description: \\\"Geometric display font\\\"\\n },\\n {\\n name: \\\"Zilla Slab Highlight\\\",\\n category: \\\"display\\\",\\n weights: [400, 700],\\n googleFont: true,\\n description: \\\"Highlighted slab serif\\\"\\n },\\n {\\n name: \\\"Bree Serif\\\",\\n category: \\\"display\\\",\\n weights: [400],\\n googleFont: true,\\n description: \\\"Upright italic slab\\\"\\n },\\n {\\n name: \\\"Overpass\\\",\\n category: \\\"display\\\",\\n weights: [100, 200, 300, 400, 500, 600, 700, 800, 900],\\n googleFont: true,\\n description: \\\"Highway-inspired sans\\\"\\n },\\n {\\n name: \\\"Archivo\\\",\\n category: \\\"display\\\",\\n weights: [100, 200, 300, 400, 500, 600, 700, 800, 900],\\n googleFont: true,\\n description: \\\"Grotesque sans-serif\\\"\\n },\\n {\\n name: \\\"Chakra Petch\\\",\\n category: \\\"display\\\",\\n weights: [300, 400, 500, 600, 700],\\n googleFont: true,\\n description: \\\"Futuristic Thai-inspired\\\"\\n },\\n {\\n name: \\\"Concert One\\\",\\n category: \\\"display\\\",\\n weights: [400],\\n googleFont: true,\\n description: \\\"Rounded grotesque display\\\"\\n },\\n // Sans Serif - Modern and clean (44 fonts)\\n {\\n name: \\\"Roboto\\\",\\n category: \\\"sans-serif\\\",\\n weights: [100, 300, 400, 500, 700, 900],\\n googleFont: true,\\n description: \\\"Clean, modern sans-serif\\\"\\n },\\n {\\n name: \\\"Montserrat\\\",\\n category: \\\"sans-serif\\\",\\n weights: [100, 200, 300, 400, 500, 600, 700, 800, 900],\\n googleFont: true,\\n description: \\\"Geometric sans-serif\\\"\\n },\\n {\\n name: \\\"Open Sans\\\",\\n category: \\\"sans-serif\\\",\\n weights: [300, 400, 500, 600, 700, 800],\\n googleFont: true,\\n description: \\\"Highly readable\\\"\\n },\\n {\\n name: \\\"Poppins\\\",\\n category: \\\"sans-serif\\\",\\n weights: [100, 200, 300, 400, 500, 600, 700, 800, 900],\\n googleFont: true,\\n description: \\\"Geometric with personality\\\"\\n },\\n {\\n name: \\\"Work Sans\\\",\\n category: \\\"sans-serif\\\",\\n weights: [100, 200, 300, 400, 500, 600, 700, 800, 900],\\n googleFont: true,\\n description: \\\"Contemporary sans-serif\\\"\\n },\\n {\\n name: \\\"Raleway\\\",\\n category: \\\"sans-serif\\\",\\n weights: [100, 200, 300, 400, 500, 600, 700, 800, 900],\\n googleFont: true,\\n description: \\\"Elegant sans-serif\\\"\\n },\\n {\\n name: \\\"Lato\\\",\\n category: \\\"sans-serif\\\",\\n weights: [100, 300, 400, 700, 900],\\n googleFont: true,\\n description: \\\"Warm sans-serif\\\"\\n },\\n {\\n name: \\\"Nunito\\\",\\n category: \\\"sans-serif\\\",\\n weights: [200, 300, 400, 500, 600, 700, 800, 900],\\n googleFont: true,\\n description: \\\"Rounded sans-serif\\\"\\n },\\n {\\n name: \\\"Outfit\\\",\\n category: \\\"sans-serif\\\",\\n weights: [100, 200, 300, 400, 500, 600, 700, 800, 900],\\n googleFont: true,\\n description: \\\"Modern geometric sans\\\"\\n },\\n {\\n name: \\\"Inter\\\",\\n category: \\\"sans-serif\\\",\\n weights: [100, 200, 300, 400, 500, 600, 700, 800, 900],\\n googleFont: true,\\n description: \\\"Clean interface font\\\"\\n },\\n {\\n name: \\\"Quicksand\\\",\\n category: \\\"sans-serif\\\",\\n weights: [300, 400, 500, 600, 700],\\n googleFont: true,\\n description: \\\"Friendly rounded sans\\\"\\n },\\n {\\n name: \\\"Rubik\\\",\\n category: \\\"sans-serif\\\",\\n weights: [300, 400, 500, 600, 700, 800, 900],\\n googleFont: true,\\n description: \\\"Slightly rounded sans\\\"\\n },\\n {\\n name: \\\"Barlow\\\",\\n category: \\\"sans-serif\\\",\\n weights: [100, 200, 300, 400, 500, 600, 700, 800, 900],\\n googleFont: true,\\n description: \\\"Low-contrast sans\\\"\\n },\\n {\\n name: \\\"Josefin Sans\\\",\\n category: \\\"sans-serif\\\",\\n weights: [100, 200, 300, 400, 500, 600, 700],\\n googleFont: true,\\n description: \\\"Geometric vintage sans\\\"\\n },\\n {\\n name: \\\"Exo 2\\\",\\n category: \\\"sans-serif\\\",\\n weights: [100, 200, 300, 400, 500, 600, 700, 800, 900],\\n googleFont: true,\\n description: \\\"Contemporary geometric\\\"\\n },\\n {\\n name: \\\"Kanit\\\",\\n category: \\\"sans-serif\\\",\\n weights: [100, 200, 300, 400, 500, 600, 700, 800, 900],\\n googleFont: true,\\n description: \\\"Modern loopless Thai\\\"\\n },\\n {\\n name: \\\"Hind\\\",\\n category: \\\"sans-serif\\\",\\n weights: [300, 400, 500, 600, 700],\\n googleFont: true,\\n description: \\\"Clean humanist sans\\\"\\n },\\n {\\n name: \\\"Alata\\\",\\n category: \\\"sans-serif\\\",\\n weights: [400],\\n googleFont: true,\\n description: \\\"Geometric sans\\\"\\n },\\n {\\n name: \\\"Urbanist\\\",\\n category: \\\"sans-serif\\\",\\n weights: [100, 200, 300, 400, 500, 600, 700, 800, 900],\\n googleFont: true,\\n description: \\\"Geometric low-contrast\\\"\\n },\\n {\\n name: \\\"Manrope\\\",\\n category: \\\"sans-serif\\\",\\n weights: [200, 300, 400, 500, 600, 700, 800],\\n googleFont: true,\\n description: \\\"Modern geometric sans\\\"\\n },\\n {\\n name: \\\"Be Vietnam Pro\\\",\\n category: \\\"sans-serif\\\",\\n weights: [100, 200, 300, 400, 500, 600, 700, 800, 900],\\n googleFont: true,\\n description: \\\"Modern Vietnamese-optimized sans\\\"\\n },\\n {\\n name: \\\"Belanosima\\\",\\n category: \\\"sans-serif\\\",\\n weights: [400, 600, 700],\\n googleFont: true,\\n description: \\\"Contemporary sans-serif\\\"\\n },\\n {\\n name: \\\"DM Sans\\\",\\n category: \\\"sans-serif\\\",\\n weights: [100, 200, 300, 400, 500, 600, 700, 800, 900],\\n googleFont: true,\\n description: \\\"Low-contrast geometric sans\\\"\\n },\\n {\\n name: \\\"Source Sans 3\\\",\\n category: \\\"sans-serif\\\",\\n weights: [200, 300, 400, 500, 600, 700, 800, 900],\\n googleFont: true,\\n description: \\\"Adobe sans-serif family\\\"\\n },\\n {\\n name: \\\"Source Sans Pro\\\",\\n category: \\\"sans-serif\\\",\\n weights: [200, 300, 400, 600, 700, 900],\\n googleFont: true,\\n description: \\\"Adobe sans-serif (legacy)\\\"\\n },\\n {\\n name: \\\"IBM Plex Sans\\\",\\n category: \\\"sans-serif\\\",\\n weights: [100, 200, 300, 400, 500, 600, 700],\\n googleFont: true,\\n description: \\\"IBM corporate sans\\\"\\n },\\n {\\n name: \\\"Karla\\\",\\n category: \\\"sans-serif\\\",\\n weights: [200, 300, 400, 500, 600, 700, 800],\\n googleFont: true,\\n description: \\\"Grotesque sans-serif\\\"\\n },\\n {\\n name: \\\"PT Sans\\\",\\n category: \\\"sans-serif\\\",\\n weights: [400, 700],\\n googleFont: true,\\n description: \\\"Russian universal sans\\\"\\n },\\n {\\n name: \\\"Fira Sans\\\",\\n category: \\\"sans-serif\\\",\\n weights: [100, 200, 300, 400, 500, 600, 700, 800, 900],\\n googleFont: true,\\n description: \\\"Mozilla humanist sans\\\"\\n },\\n {\\n name: \\\"Space Grotesk\\\",\\n category: \\\"sans-serif\\\",\\n weights: [300, 400, 500, 600, 700],\\n googleFont: true,\\n description: \\\"Proportional space age sans\\\"\\n },\\n {\\n name: \\\"Syne\\\",\\n category: \\\"sans-serif\\\",\\n weights: [400, 500, 600, 700, 800],\\n googleFont: true,\\n description: \\\"Geometric variable sans\\\"\\n },\\n {\\n name: \\\"Libre Franklin\\\",\\n category: \\\"sans-serif\\\",\\n weights: [100, 200, 300, 400, 500, 600, 700, 800, 900],\\n googleFont: true,\\n description: \\\"Interpretation of Franklin Gothic\\\"\\n },\\n {\\n name: \\\"Alegreya Sans\\\",\\n category: \\\"sans-serif\\\",\\n weights: [100, 300, 400, 500, 700, 800, 900],\\n googleFont: true,\\n description: \\\"Humanist sans companion\\\"\\n },\\n {\\n name: \\\"Archivo Narrow\\\",\\n category: \\\"sans-serif\\\",\\n weights: [400, 500, 600, 700],\\n googleFont: true,\\n description: \\\"Narrow grotesque sans\\\"\\n },\\n {\\n name: \\\"Chivo\\\",\\n category: \\\"sans-serif\\\",\\n weights: [100, 200, 300, 400, 500, 600, 700, 800, 900],\\n googleFont: true,\\n description: \\\"Grotesque sans-serif\\\"\\n },\\n {\\n name: \\\"Neuton\\\",\\n category: \\\"sans-serif\\\",\\n weights: [200, 300, 400, 700, 800],\\n googleFont: true,\\n description: \\\"Serif-adjacent sans\\\"\\n },\\n {\\n name: \\\"Prompt\\\",\\n category: \\\"sans-serif\\\",\\n weights: [100, 200, 300, 400, 500, 600, 700, 800, 900],\\n googleFont: true,\\n description: \\\"Loopless Thai sans\\\"\\n },\\n {\\n name: \\\"Noto Sans\\\",\\n category: \\\"sans-serif\\\",\\n weights: [100, 200, 300, 400, 500, 600, 700, 800, 900],\\n googleFont: true,\\n description: \\\"Google universal sans\\\"\\n },\\n {\\n name: \\\"Nunito Sans\\\",\\n category: \\\"sans-serif\\\",\\n weights: [200, 300, 400, 600, 700, 800, 900],\\n googleFont: true,\\n description: \\\"Rounded sans-serif\\\"\\n },\\n {\\n name: \\\"Proza Libre\\\",\\n category: \\\"sans-serif\\\",\\n weights: [400, 500, 600, 700, 800],\\n googleFont: true,\\n description: \\\"Humanist sans-serif\\\"\\n },\\n {\\n name: \\\"Cabin\\\",\\n category: \\\"sans-serif\\\",\\n weights: [400, 500, 600, 700],\\n googleFont: true,\\n description: \\\"Humanist sans inspired by Edward Johnston\\\"\\n },\\n {\\n name: \\\"Signika\\\",\\n category: \\\"sans-serif\\\",\\n weights: [300, 400, 500, 600, 700],\\n googleFont: true,\\n description: \\\"Sans-serif for signage\\\"\\n },\\n {\\n name: \\\"Public Sans\\\",\\n category: \\\"sans-serif\\\",\\n weights: [100, 200, 300, 400, 500, 600, 700, 800, 900],\\n googleFont: true,\\n description: \\\"Strong neutral sans\\\"\\n },\\n {\\n name: \\\"Plus Jakarta Sans\\\",\\n category: \\\"sans-serif\\\",\\n weights: [200, 300, 400, 500, 600, 700, 800],\\n googleFont: true,\\n description: \\\"Geometric neo-grotesque\\\"\\n },\\n {\\n name: \\\"Red Hat Display\\\",\\n category: \\\"sans-serif\\\",\\n weights: [300, 400, 500, 600, 700, 800, 900],\\n googleFont: true,\\n description: \\\"Display variant of Red Hat sans\\\"\\n },\\n // Script/Handwritten - Personal and creative (26 fonts)\\n {\\n name: \\\"Pacifico\\\",\\n category: \\\"script\\\",\\n weights: [400],\\n googleFont: true,\\n description: \\\"Retro surf script\\\"\\n },\\n {\\n name: \\\"Dancing Script\\\",\\n category: \\\"script\\\",\\n weights: [400, 500, 600, 700],\\n googleFont: true,\\n description: \\\"Elegant handwriting\\\"\\n },\\n {\\n name: \\\"Satisfy\\\",\\n category: \\\"script\\\",\\n weights: [400],\\n googleFont: true,\\n description: \\\"Casual handwritten\\\"\\n },\\n {\\n name: \\\"Permanent Marker\\\",\\n category: \\\"script\\\",\\n weights: [400],\\n googleFont: true,\\n description: \\\"Bold marker style\\\"\\n },\\n {\\n name: \\\"Caveat\\\",\\n category: \\\"script\\\",\\n weights: [400, 500, 600, 700],\\n googleFont: true,\\n description: \\\"Modern handwritten\\\"\\n },\\n {\\n name: \\\"Shadows Into Light\\\",\\n category: \\\"script\\\",\\n weights: [400],\\n googleFont: true,\\n description: \\\"Friendly handwriting\\\"\\n },\\n {\\n name: \\\"Kaushan Script\\\",\\n category: \\\"script\\\",\\n weights: [400],\\n googleFont: true,\\n description: \\\"Bold script\\\"\\n },\\n {\\n name: \\\"Amatic SC\\\",\\n category: \\\"script\\\",\\n weights: [400, 700],\\n googleFont: true,\\n description: \\\"Hand-drawn style\\\"\\n },\\n {\\n name: \\\"Indie Flower\\\",\\n category: \\\"script\\\",\\n weights: [400],\\n googleFont: true,\\n description: \\\"Casual handwriting\\\"\\n },\\n {\\n name: \\\"Cookie\\\",\\n category: \\\"script\\\",\\n weights: [400],\\n googleFont: true,\\n description: \\\"Brush script\\\"\\n },\\n {\\n name: \\\"Sacramento\\\",\\n category: \\\"script\\\",\\n weights: [400],\\n googleFont: true,\\n description: \\\"Elegant script\\\"\\n },\\n {\\n name: \\\"Allura\\\",\\n category: \\\"script\\\",\\n weights: [400],\\n googleFont: true,\\n description: \\\"Formal script\\\"\\n },\\n {\\n name: \\\"Great Vibes\\\",\\n category: \\\"script\\\",\\n weights: [400],\\n googleFont: true,\\n description: \\\"Elegant calligraphy\\\"\\n },\\n {\\n name: \\\"Yellowtail\\\",\\n category: \\\"script\\\",\\n weights: [400],\\n googleFont: true,\\n description: \\\"Flat-nib script\\\"\\n },\\n {\\n name: \\\"Courgette\\\",\\n category: \\\"script\\\",\\n weights: [400],\\n googleFont: true,\\n description: \\\"Casual upright script\\\"\\n },\\n {\\n name: \\\"Beth Ellen\\\",\\n category: \\\"script\\\",\\n weights: [400],\\n googleFont: true,\\n description: \\\"Handwritten marker style\\\"\\n },\\n {\\n name: \\\"Covered By Your Grace\\\",\\n category: \\\"script\\\",\\n weights: [400],\\n googleFont: true,\\n description: \\\"Casual handwritten\\\"\\n },\\n {\\n name: \\\"Nothing You Could Do\\\",\\n category: \\\"script\\\",\\n weights: [400],\\n googleFont: true,\\n description: \\\"Hand-drawn lettering\\\"\\n },\\n {\\n name: \\\"Homemade Apple\\\",\\n category: \\\"script\\\",\\n weights: [400],\\n googleFont: true,\\n description: \\\"Thin marker handwriting\\\"\\n },\\n {\\n name: \\\"Reenie Beanie\\\",\\n category: \\\"script\\\",\\n weights: [400],\\n googleFont: true,\\n description: \\\"Casual handwritten note style\\\"\\n },\\n {\\n name: \\\"Patrick Hand\\\",\\n category: \\\"script\\\",\\n weights: [400],\\n googleFont: true,\\n description: \\\"Handwriting font\\\"\\n },\\n {\\n name: \\\"Architects Daughter\\\",\\n category: \\\"script\\\",\\n weights: [400],\\n googleFont: true,\\n description: \\\"Architect-style handwriting\\\"\\n },\\n {\\n name: \\\"Handlee\\\",\\n category: \\\"script\\\",\\n weights: [400],\\n googleFont: true,\\n description: \\\"Casual handwriting\\\"\\n },\\n {\\n name: \\\"Zeyada\\\",\\n category: \\\"script\\\",\\n weights: [400],\\n googleFont: true,\\n description: \\\"Bouncy handwritten script\\\"\\n },\\n {\\n name: \\\"Gloria Hallelujah\\\",\\n category: \\\"script\\\",\\n weights: [400],\\n googleFont: true,\\n description: \\\"Comic-style handwriting\\\"\\n },\\n {\\n name: \\\"Bad Script\\\",\\n category: \\\"script\\\",\\n weights: [400],\\n googleFont: true,\\n description: \\\"Casual Cyrillic script\\\"\\n },\\n // Serif - Classic and elegant (28 fonts)\\n {\\n name: \\\"Playfair Display\\\",\\n category: \\\"serif\\\",\\n weights: [400, 500, 600, 700, 800, 900],\\n googleFont: true,\\n description: \\\"High-contrast elegant\\\"\\n },\\n {\\n name: \\\"Merriweather\\\",\\n category: \\\"serif\\\",\\n weights: [300, 400, 700, 900],\\n googleFont: true,\\n description: \\\"Readable serif\\\"\\n },\\n {\\n name: \\\"Lora\\\",\\n category: \\\"serif\\\",\\n weights: [400, 500, 600, 700],\\n googleFont: true,\\n description: \\\"Contemporary serif\\\"\\n },\\n {\\n name: \\\"Crimson Text\\\",\\n category: \\\"serif\\\",\\n weights: [400, 600, 700],\\n googleFont: true,\\n description: \\\"Classic book typography\\\"\\n },\\n {\\n name: \\\"PT Serif\\\",\\n category: \\\"serif\\\",\\n weights: [400, 700],\\n googleFont: true,\\n description: \\\"Transitional serif\\\"\\n },\\n {\\n name: \\\"Libre Baskerville\\\",\\n category: \\\"serif\\\",\\n weights: [400, 700],\\n googleFont: true,\\n description: \\\"Classic serif\\\"\\n },\\n {\\n name: \\\"Bitter\\\",\\n category: \\\"serif\\\",\\n weights: [100, 200, 300, 400, 500, 600, 700, 800, 900],\\n googleFont: true,\\n description: \\\"Contemporary slab serif\\\"\\n },\\n {\\n name: \\\"Cormorant Garamond\\\",\\n category: \\\"serif\\\",\\n weights: [300, 400, 500, 600, 700],\\n googleFont: true,\\n description: \\\"Display serif\\\"\\n },\\n {\\n name: \\\"Cinzel\\\",\\n category: \\\"serif\\\",\\n weights: [400, 500, 600, 700, 800, 900],\\n googleFont: true,\\n description: \\\"Classical serif capitals\\\"\\n },\\n {\\n name: \\\"Zilla Slab\\\",\\n category: \\\"serif\\\",\\n weights: [300, 400, 500, 600, 700],\\n googleFont: true,\\n description: \\\"Contemporary slab serif\\\"\\n },\\n {\\n name: \\\"Cardo\\\",\\n category: \\\"serif\\\",\\n weights: [400, 700],\\n googleFont: true,\\n description: \\\"Large text serif\\\"\\n },\\n {\\n name: \\\"Spectral\\\",\\n category: \\\"serif\\\",\\n weights: [200, 300, 400, 500, 600, 700, 800],\\n googleFont: true,\\n description: \\\"Efficient serif\\\"\\n },\\n {\\n name: \\\"Literata\\\",\\n category: \\\"serif\\\",\\n weights: [200, 300, 400, 500, 600, 700, 800, 900],\\n googleFont: true,\\n description: \\\"Modern serif\\\"\\n },\\n {\\n name: \\\"Cantata One\\\",\\n category: \\\"serif\\\",\\n weights: [400],\\n googleFont: true,\\n description: \\\"Humanist slab serif\\\"\\n },\\n {\\n name: \\\"Bellefair\\\",\\n category: \\\"serif\\\",\\n weights: [400],\\n googleFont: true,\\n description: \\\"Elegant high-contrast serif\\\"\\n },\\n {\\n name: \\\"Source Serif Pro\\\",\\n category: \\\"serif\\\",\\n weights: [200, 300, 400, 600, 700, 900],\\n googleFont: true,\\n description: \\\"Adobe serif family\\\"\\n },\\n {\\n name: \\\"Cormorant\\\",\\n category: \\\"serif\\\",\\n weights: [300, 400, 500, 600, 700],\\n googleFont: true,\\n description: \\\"Display serif typeface\\\"\\n },\\n {\\n name: \\\"Eczar\\\",\\n category: \\\"serif\\\",\\n weights: [400, 500, 600, 700, 800],\\n googleFont: true,\\n description: \\\"Hybrid serif for screen\\\"\\n },\\n {\\n name: \\\"Alegreya\\\",\\n category: \\\"serif\\\",\\n weights: [400, 500, 600, 700, 800, 900],\\n googleFont: true,\\n description: \\\"Humanist serif\\\"\\n },\\n {\\n name: \\\"Fraunces\\\",\\n category: \\\"serif\\\",\\n weights: [100, 200, 300, 400, 500, 600, 700, 800, 900],\\n googleFont: true,\\n description: \\\"Variable display serif\\\"\\n },\\n {\\n name: \\\"Inknut Antiqua\\\",\\n category: \\\"serif\\\",\\n weights: [300, 400, 500, 600, 700, 800, 900],\\n googleFont: true,\\n description: \\\"Display serif\\\"\\n },\\n {\\n name: \\\"BioRhyme\\\",\\n category: \\\"serif\\\",\\n weights: [200, 300, 400, 700, 800],\\n googleFont: true,\\n description: \\\"Rounded slab serif\\\"\\n },\\n {\\n name: \\\"Slabo 27px\\\",\\n category: \\\"serif\\\",\\n weights: [400],\\n googleFont: true,\\n description: \\\"Display serif at 27px\\\"\\n },\\n {\\n name: \\\"Slabo 13px\\\",\\n category: \\\"serif\\\",\\n weights: [400],\\n googleFont: true,\\n description: \\\"Text serif at 13px\\\"\\n },\\n {\\n name: \\\"Crimson Pro\\\",\\n category: \\\"serif\\\",\\n weights: [200, 300, 400, 500, 600, 700, 800, 900],\\n googleFont: true,\\n description: \\\"Modern oldstyle serif\\\"\\n },\\n {\\n name: \\\"Noto Serif\\\",\\n category: \\\"serif\\\",\\n weights: [100, 200, 300, 400, 500, 600, 700, 800, 900],\\n googleFont: true,\\n description: \\\"Google universal serif\\\"\\n },\\n {\\n name: \\\"EB Garamond\\\",\\n category: \\\"serif\\\",\\n weights: [400, 500, 600, 700, 800],\\n googleFont: true,\\n description: \\\"Classical Garamond revival\\\"\\n },\\n {\\n name: \\\"Vollkorn\\\",\\n category: \\\"serif\\\",\\n weights: [400, 500, 600, 700, 800, 900],\\n googleFont: true,\\n description: \\\"Quiet, moderate serif\\\"\\n },\\n {\\n name: \\\"Young Serif\\\",\\n category: \\\"serif\\\",\\n weights: [400, 500, 600, 700],\\n googleFont: true,\\n description: \\\"Modern retro serif\\\"\\n },\\n // Vintage/Retro - Nostalgic and stylish (49 fonts)\\n // Art Deco & 1920s-30s Style\\n {\\n name: \\\"Monoton\\\",\\n category: \\\"vintage\\\",\\n weights: [400],\\n googleFont: true,\\n description: \\\"Art deco display\\\"\\n },\\n {\\n name: \\\"Limelight\\\",\\n category: \\\"vintage\\\",\\n weights: [400],\\n googleFont: true,\\n description: \\\"Art deco geometric sans\\\"\\n },\\n {\\n name: \\\"Poiret One\\\",\\n category: \\\"vintage\\\",\\n weights: [400],\\n googleFont: true,\\n description: \\\"Art deco constructivist\\\"\\n },\\n {\\n name: \\\"Italiana\\\",\\n category: \\\"vintage\\\",\\n weights: [400],\\n googleFont: true,\\n description: \\\"Art deco calligraphic\\\"\\n },\\n {\\n name: \\\"Federo\\\",\\n category: \\\"vintage\\\",\\n weights: [400],\\n googleFont: true,\\n description: \\\"Art nouveau geometric\\\"\\n },\\n {\\n name: \\\"Dorsa\\\",\\n category: \\\"vintage\\\",\\n weights: [400],\\n googleFont: true,\\n description: \\\"Art deco display\\\"\\n },\\n // Groovy/Psychedelic 60s-70s Style\\n {\\n name: \\\"Boogaloo\\\",\\n category: \\\"vintage\\\",\\n weights: [400],\\n googleFont: true,\\n description: \\\"Groovy rounded display\\\"\\n },\\n {\\n name: \\\"Gorditas\\\",\\n category: \\\"vintage\\\",\\n weights: [400, 700],\\n googleFont: true,\\n description: \\\"Bubble slab with hearts\\\"\\n },\\n {\\n name: \\\"Shrikhand\\\",\\n category: \\\"vintage\\\",\\n weights: [400],\\n googleFont: true,\\n description: \\\"Retro curved display\\\"\\n },\\n {\\n name: \\\"Kumar One\\\",\\n category: \\\"vintage\\\",\\n weights: [400],\\n googleFont: true,\\n description: \\\"Rounded bubble display\\\"\\n },\\n {\\n name: \\\"Chicle\\\",\\n category: \\\"vintage\\\",\\n weights: [400],\\n googleFont: true,\\n description: \\\"Bubble gum style\\\"\\n },\\n {\\n name: \\\"Flavors\\\",\\n category: \\\"vintage\\\",\\n weights: [400],\\n googleFont: true,\\n description: \\\"Retro bubble font\\\"\\n },\\n {\\n name: \\\"Chango\\\",\\n category: \\\"vintage\\\",\\n weights: [400],\\n googleFont: true,\\n description: \\\"Groovy rounded bold\\\"\\n },\\n {\\n name: \\\"Purple Purse\\\",\\n category: \\\"vintage\\\",\\n weights: [400],\\n googleFont: true,\\n description: \\\"Hippie funky casual\\\"\\n },\\n {\\n name: \\\"Super Dream\\\",\\n category: \\\"vintage\\\",\\n weights: [400],\\n googleFont: false,\\n description: \\\"70s groovy bubble font\\\"\\n },\\n // Retro Script & Sign Painting\\n {\\n name: \\\"Yesteryear\\\",\\n category: \\\"vintage\\\",\\n weights: [400],\\n googleFont: true,\\n description: \\\"Vintage cursive script\\\"\\n },\\n {\\n name: \\\"Mrs Sheppards\\\",\\n category: \\\"vintage\\\",\\n weights: [400],\\n googleFont: true,\\n description: \\\"Old American script\\\"\\n },\\n {\\n name: \\\"Condiment\\\",\\n category: \\\"vintage\\\",\\n weights: [400],\\n googleFont: true,\\n description: \\\"Vintage sign design\\\"\\n },\\n // Western/Cowboy Style\\n {\\n name: \\\"Rye\\\",\\n category: \\\"vintage\\\",\\n weights: [400],\\n googleFont: true,\\n description: \\\"Western Victorian\\\"\\n },\\n {\\n name: \\\"Sancreek\\\",\\n category: \\\"vintage\\\",\\n weights: [400],\\n googleFont: true,\\n description: \\\"Western slab serif\\\"\\n },\\n {\\n name: \\\"Smokum\\\",\\n category: \\\"vintage\\\",\\n weights: [400],\\n googleFont: true,\\n description: \\\"Western playful slab\\\"\\n },\\n {\\n name: \\\"Diplomata\\\",\\n category: \\\"vintage\\\",\\n weights: [400],\\n googleFont: true,\\n description: \\\"Bold western display\\\"\\n },\\n {\\n name: \\\"Ewert\\\",\\n category: \\\"vintage\\\",\\n weights: [400],\\n googleFont: true,\\n description: \\\"Ornamental wood type\\\"\\n },\\n {\\n name: \\\"Macondo\\\",\\n category: \\\"vintage\\\",\\n weights: [400],\\n googleFont: true,\\n description: \\\"Western carnival style\\\"\\n },\\n {\\n name: \\\"Wellfleet\\\",\\n category: \\\"vintage\\\",\\n weights: [400],\\n googleFont: true,\\n description: \\\"Vintage slab serif\\\"\\n },\\n {\\n name: \\\"Ranchers\\\",\\n category: \\\"vintage\\\",\\n weights: [400],\\n googleFont: true,\\n description: \\\"Western slab serif\\\"\\n },\\n // Circus/Carnival/Theater\\n {\\n name: \\\"Bungee Shade\\\",\\n category: \\\"vintage\\\",\\n weights: [400],\\n googleFont: true,\\n description: \\\"Layered circus display\\\"\\n },\\n {\\n name: \\\"Peralta\\\",\\n category: \\\"vintage\\\",\\n weights: [400],\\n googleFont: true,\\n description: \\\"Rounded circus style\\\"\\n },\\n {\\n name: \\\"Kelly Slab\\\",\\n category: \\\"vintage\\\",\\n weights: [400],\\n googleFont: true,\\n description: \\\"Retro slab serif\\\"\\n },\\n {\\n name: \\\"Snippet\\\",\\n category: \\\"vintage\\\",\\n weights: [400],\\n googleFont: true,\\n description: \\\"Vintage condensed\\\"\\n },\\n // Retro Gaming & Tech\\n {\\n name: \\\"Press Start 2P\\\",\\n category: \\\"vintage\\\",\\n weights: [400],\\n googleFont: true,\\n description: \\\"8-bit retro gaming\\\"\\n },\\n {\\n name: \\\"VT323\\\",\\n category: \\\"vintage\\\",\\n weights: [400],\\n googleFont: true,\\n description: \\\"Terminal monospace\\\"\\n },\\n // Victorian/Gothic/Medieval\\n {\\n name: \\\"UnifrakturCook\\\",\\n category: \\\"vintage\\\",\\n weights: [700],\\n googleFont: true,\\n description: \\\"Gothic blackletter\\\"\\n },\\n {\\n name: \\\"Sevillana\\\",\\n category: \\\"vintage\\\",\\n weights: [400],\\n googleFont: true,\\n description: \\\"Victorian ornate\\\"\\n },\\n {\\n name: \\\"Uncial Antiqua\\\",\\n category: \\\"vintage\\\",\\n weights: [400],\\n googleFont: true,\\n description: \\\"Medieval uncial\\\"\\n },\\n {\\n name: \\\"Piedra\\\",\\n category: \\\"vintage\\\",\\n weights: [400],\\n googleFont: true,\\n description: \\\"Stone carved display\\\"\\n },\\n // Horror/Heavy Metal\\n {\\n name: \\\"Creepster\\\",\\n category: \\\"vintage\\\",\\n weights: [400],\\n googleFont: true,\\n description: \\\"Horror Halloween style\\\"\\n },\\n {\\n name: \\\"Nosifer\\\",\\n category: \\\"vintage\\\",\\n weights: [400],\\n googleFont: true,\\n description: \\\"Horror dripping\\\"\\n },\\n {\\n name: \\\"Eater\\\",\\n category: \\\"vintage\\\",\\n weights: [400],\\n googleFont: true,\\n description: \\\"Zombie horror\\\"\\n },\\n {\\n name: \\\"Metal Mania\\\",\\n category: \\\"vintage\\\",\\n weights: [400],\\n googleFont: true,\\n description: \\\"Heavy metal style\\\"\\n },\\n {\\n name: \\\"Butcherman\\\",\\n category: \\\"vintage\\\",\\n weights: [400],\\n googleFont: true,\\n description: \\\"Zombified horror\\\"\\n },\\n // Typewriter & Classic\\n {\\n name: \\\"Special Elite\\\",\\n category: \\\"vintage\\\",\\n weights: [400],\\n googleFont: true,\\n description: \\\"Typewriter style\\\"\\n },\\n // Soviet/Constructivist\\n {\\n name: \\\"Stalinist One\\\",\\n category: \\\"vintage\\\",\\n weights: [400],\\n googleFont: true,\\n description: \\\"Soviet constructivist\\\"\\n },\\n {\\n name: \\\"Ruslan Display\\\",\\n category: \\\"vintage\\\",\\n weights: [400],\\n googleFont: true,\\n description: \\\"Russian display style\\\"\\n },\\n // Additional Retro Display\\n {\\n name: \\\"Corben\\\",\\n category: \\\"vintage\\\",\\n weights: [400, 700],\\n googleFont: true,\\n description: \\\"Mid-century rounded\\\"\\n },\\n {\\n name: \\\"Kranky\\\",\\n category: \\\"vintage\\\",\\n weights: [400],\\n googleFont: true,\\n description: \\\"Quirky handwritten retro\\\"\\n },\\n // Decorative/Unique (10+ fonts)\\n {\\n name: \\\"Orbitron\\\",\\n category: \\\"decorative\\\",\\n weights: [400, 500, 600, 700, 800, 900],\\n googleFont: true,\\n description: \\\"Futuristic geometric\\\"\\n },\\n {\\n name: \\\"Playball\\\",\\n category: \\\"decorative\\\",\\n weights: [400],\\n googleFont: true,\\n description: \\\"Baseball script\\\"\\n },\\n {\\n name: \\\"Sedgwick Ave Display\\\",\\n category: \\\"decorative\\\",\\n weights: [400],\\n googleFont: true,\\n description: \\\"Graffiti style\\\"\\n },\\n {\\n name: \\\"Modak\\\",\\n category: \\\"decorative\\\",\\n weights: [400],\\n googleFont: true,\\n description: \\\"Rounded heavy display\\\"\\n },\\n {\\n name: \\\"Fascinate\\\",\\n category: \\\"decorative\\\",\\n weights: [400],\\n googleFont: true,\\n description: \\\"Broadway/theater\\\"\\n },\\n {\\n name: \\\"Bungee Inline\\\",\\n category: \\\"decorative\\\",\\n weights: [400],\\n googleFont: true,\\n description: \\\"Inline display\\\"\\n },\\n {\\n name: \\\"Emblema One\\\",\\n category: \\\"decorative\\\",\\n weights: [400],\\n googleFont: true,\\n description: \\\"Decorative caps\\\"\\n },\\n {\\n name: \\\"Fascinate Inline\\\",\\n category: \\\"decorative\\\",\\n weights: [400],\\n googleFont: true,\\n description: \\\"Inline Broadway\\\"\\n },\\n {\\n name: \\\"New Rocker\\\",\\n category: \\\"decorative\\\",\\n weights: [400],\\n googleFont: true,\\n description: \\\"Rock and roll\\\"\\n },\\n {\\n name: \\\"Bigelow Rules\\\",\\n category: \\\"decorative\\\",\\n weights: [400],\\n googleFont: true,\\n description: \\\"Playful cursive display\\\"\\n },\\n // Monospace (useful for tech designs)\\n {\\n name: \\\"Roboto Mono\\\",\\n category: \\\"monospace\\\",\\n weights: [100, 200, 300, 400, 500, 600, 700],\\n googleFont: true,\\n description: \\\"Modern monospace\\\"\\n },\\n {\\n name: \\\"Courier Prime\\\",\\n category: \\\"monospace\\\",\\n weights: [400, 700],\\n googleFont: true,\\n description: \\\"Typewriter monospace\\\"\\n },\\n {\\n name: \\\"Space Mono\\\",\\n category: \\\"monospace\\\",\\n weights: [400, 700],\\n googleFont: true,\\n description: \\\"Retro-futuristic mono\\\"\\n },\\n {\\n name: \\\"Inconsolata\\\",\\n category: \\\"monospace\\\",\\n weights: [200, 300, 400, 500, 600, 700, 800, 900],\\n googleFont: true,\\n description: \\\"Humanist monospace\\\"\\n }\\n ];\\n function getFontNames() {\\n return TSHIRT_FONTS.map((f) => f.name);\\n }\\n\\n // src/constants.ts\\n var FONT_FAMILIES = getFontNames();\\n var HORIZONTAL_PADDING = 0;\\n var LINE_HEIGHT_MULTIPLIER = 1.2;\\n var SYSTEM_FONTS = /* @__PURE__ */ new Set([\\n \\\"Arial\\\",\\n \\\"Arial Black\\\",\\n \\\"Verdana\\\",\\n \\\"Tahoma\\\",\\n \\\"Trebuchet MS\\\",\\n \\\"Impact\\\",\\n \\\"Times New Roman\\\",\\n \\\"Georgia\\\",\\n \\\"Garamond\\\",\\n \\\"Courier New\\\",\\n \\\"Brush Script MT\\\",\\n \\\"Palatino\\\",\\n \\\"Baskerville\\\",\\n \\\"Helvetica\\\",\\n \\\"Helvetica Neue\\\",\\n \\\"Comic Sans MS\\\",\\n \\\"Lucida Console\\\",\\n \\\"Monaco\\\",\\n \\\"Consolas\\\",\\n \\\"Courier\\\"\\n ]);\\n var WAVE_SKEW_FACTOR = 0.3;\\n\\n // src/types/index.ts\\n var RichText = class _RichText {\\n constructor(spans = []) {\\n this.spans = spans.length > 0 ? spans : [{ text: \\\"\\\", style: {} }];\\n this.normalize();\\n }\\n /**\\n * Create RichText from plain text string (no special formatting)\\n */\\n static fromPlainText(text, style = {}) {\\n return new _RichText([{ text, style }]);\\n }\\n /**\\n * Get the full text content (all spans concatenated)\\n */\\n getText() {\\n return this.spans.map((s) => s.text).join(\\\"\\\");\\n }\\n /**\\n * Get the total character count\\n */\\n getLength() {\\n return this.getText().length;\\n }\\n /**\\n * Get the style at a specific character index\\n * @param charIndex Character index (0-based)\\n * @returns The style object for the span containing this character\\n */\\n getStyleAt(charIndex) {\\n if (this.spans.length === 0) return {};\\n if (charIndex < 0) return this.spans[0].style;\\n let currentIndex = 0;\\n for (const span of this.spans) {\\n if (charIndex < currentIndex + span.text.length) {\\n return span.style;\\n }\\n currentIndex += span.text.length;\\n }\\n return this.spans[this.spans.length - 1].style;\\n }\\n /**\\n * Apply a style to a character range\\n * @param start Start index (inclusive)\\n * @param end End index (exclusive)\\n * @param style Style to apply (merged with existing styles)\\n */\\n applyStyle(start, end, style) {\\n if (start >= end || start < 0 || end > this.getLength()) {\\n return;\\n }\\n const newSpans = [];\\n let currentIndex = 0;\\n for (const span of this.spans) {\\n const spanStart = currentIndex;\\n const spanEnd = currentIndex + span.text.length;\\n if (spanEnd <= start) {\\n newSpans.push(span);\\n currentIndex = spanEnd;\\n continue;\\n }\\n if (spanStart >= end) {\\n newSpans.push(span);\\n currentIndex = spanEnd;\\n continue;\\n }\\n const overlapStart = Math.max(start, spanStart);\\n const overlapEnd = Math.min(end, spanEnd);\\n if (overlapStart > spanStart) {\\n newSpans.push({\\n text: span.text.substring(0, overlapStart - spanStart),\\n style: span.style\\n });\\n }\\n newSpans.push({\\n text: span.text.substring(overlapStart - spanStart, overlapEnd - spanStart),\\n style: { ...span.style, ...style }\\n });\\n if (overlapEnd < spanEnd) {\\n newSpans.push({\\n text: span.text.substring(overlapEnd - spanStart),\\n style: span.style\\n });\\n }\\n currentIndex = spanEnd;\\n }\\n this.spans = newSpans;\\n this.normalize();\\n }\\n /**\\n * Insert text at a specific position with a given style\\n * @param index Character index to insert at\\n * @param text Text to insert\\n * @param style Style for the inserted text\\n */\\n insert(index, text, style) {\\n if (text.length === 0) return;\\n const newSpans = [];\\n let currentIndex = 0;\\n for (const span of this.spans) {\\n const spanStart = currentIndex;\\n const spanEnd = currentIndex + span.text.length;\\n if (index <= spanStart && newSpans.length === 0) {\\n newSpans.push({ text, style });\\n }\\n if (index > spanStart && index <= spanEnd) {\\n const offset = index - spanStart;\\n newSpans.push({\\n text: span.text.substring(0, offset),\\n style: span.style\\n });\\n newSpans.push({ text, style });\\n newSpans.push({\\n text: span.text.substring(offset),\\n style: span.style\\n });\\n currentIndex = spanEnd;\\n continue;\\n }\\n newSpans.push(span);\\n currentIndex = spanEnd;\\n }\\n if (index >= this.getLength() && !newSpans.some((s) => s.text === text)) {\\n newSpans.push({ text, style });\\n }\\n this.spans = newSpans;\\n this.normalize();\\n }\\n /**\\n * Delete text in a character range\\n * @param start Start index (inclusive)\\n * @param end End index (exclusive)\\n */\\n delete(start, end) {\\n const length = this.getLength();\\n start = Math.max(0, Math.min(start, length));\\n end = Math.max(0, Math.min(end, length));\\n if (start >= end) {\\n return;\\n }\\n const newSpans = [];\\n let currentIndex = 0;\\n for (const span of this.spans) {\\n const spanStart = currentIndex;\\n const spanEnd = currentIndex + span.text.length;\\n if (spanEnd <= start) {\\n newSpans.push(span);\\n currentIndex = spanEnd;\\n continue;\\n }\\n if (spanStart >= end) {\\n newSpans.push(span);\\n currentIndex = spanEnd;\\n continue;\\n }\\n const deleteStart = Math.max(start, spanStart);\\n const deleteEnd = Math.min(end, spanEnd);\\n if (deleteStart > spanStart) {\\n newSpans.push({\\n text: span.text.substring(0, deleteStart - spanStart),\\n style: span.style\\n });\\n }\\n if (deleteEnd < spanEnd) {\\n newSpans.push({\\n text: span.text.substring(deleteEnd - spanStart),\\n style: span.style\\n });\\n }\\n currentIndex = spanEnd;\\n }\\n this.spans = newSpans.length > 0 ? newSpans : [{ text: \\\"\\\", style: {} }];\\n this.normalize();\\n }\\n /**\\n * Normalize spans by:\\n * 1. Removing empty spans\\n * 2. Merging adjacent spans with identical styles\\n * This prevents fragmentation and improves performance\\n */\\n normalize() {\\n this.spans = this.spans.filter((s) => s.text !== \\\"\\\");\\n if (this.spans.length === 0) {\\n this.spans = [{ text: \\\"\\\", style: {} }];\\n return;\\n }\\n if (this.spans.length <= 1) return;\\n const merged = [];\\n let current = this.spans[0];\\n for (let i = 1; i < this.spans.length; i++) {\\n const next = this.spans[i];\\n if (this.stylesEqual(current.style, next.style)) {\\n current = {\\n text: current.text + next.text,\\n style: current.style\\n };\\n } else {\\n merged.push(current);\\n current = next;\\n }\\n }\\n merged.push(current);\\n this.spans = merged;\\n }\\n /**\\n * Check if two styles are equal\\n */\\n stylesEqual(a, b) {\\n return a.color === b.color && a.fontFamily === b.fontFamily && a.fontSize === b.fontSize && a.bold === b.bold && a.italic === b.italic && a.underline === b.underline && a.strikethrough === b.strikethrough;\\n }\\n /**\\n * Clone this RichText instance\\n */\\n clone() {\\n return new _RichText(\\n this.spans.map((span) => ({\\n text: span.text,\\n style: { ...span.style }\\n }))\\n );\\n }\\n /**\\n * Clear a specific style property from all spans.\\n * Used when element-level property changes should override character-level.\\n * After clearing, spans will inherit the property from element defaults.\\n * @param property The style property to clear (e.g., 'fontFamily', 'bold')\\n */\\n clearStyleProperty(property) {\\n for (const span of this.spans) {\\n if (span.style[property] !== void 0) {\\n delete span.style[property];\\n }\\n }\\n this.normalize();\\n }\\n /**\\n * Serialize to JSON\\n */\\n toJSON() {\\n return { spans: this.spans };\\n }\\n /**\\n * Deserialize from JSON\\n */\\n static fromJSON(json) {\\n return new _RichText(json.spans);\\n }\\n };\\n\\n // src/rendering/transform-renderer.ts\\n function createOffscreenCanvas(width, height) {\\n if (typeof OffscreenCanvas !== \\\"undefined\\\") {\\n return new OffscreenCanvas(width, height);\\n }\\n const canvas = document.createElement(\\\"canvas\\\");\\n canvas.width = width;\\n canvas.height = height;\\n return canvas;\\n }\\n function applyStrokeToChar(ctx, char, stroke) {\\n if (!stroke?.enabled) return;\\n ctx.strokeStyle = stroke.color;\\n ctx.lineWidth = stroke.width;\\n ctx.lineCap = stroke.lineCap || \\\"round\\\";\\n ctx.lineJoin = stroke.lineJoin || \\\"round\\\";\\n if (stroke.miterLimit !== void 0) ctx.miterLimit = stroke.miterLimit;\\n if (stroke.opacity !== void 0) {\\n const prevAlpha = ctx.globalAlpha;\\n ctx.globalAlpha = stroke.opacity;\\n ctx.strokeText(char, 0, 0);\\n ctx.globalAlpha = prevAlpha;\\n } else {\\n ctx.strokeText(char, 0, 0);\\n }\\n }\\n function renderTransformWithOffscreenStroke(ctx, elementData, renderFn) {\\n const stroke = elementData.stroke;\\n const strokeOpacity = stroke?.opacity ?? 1;\\n const elementAlpha = ctx.globalAlpha;\\n const hasStrokeOpacity = stroke?.enabled && strokeOpacity < 1;\\n const hasElementOpacity = stroke?.enabled && elementAlpha < 1;\\n const needsOffscreen = hasStrokeOpacity || hasElementOpacity;\\n if (!needsOffscreen) {\\n renderFn(ctx, elementData);\\n return;\\n }\\n const fontSize = elementData.fontSize || 24;\\n const strokeWidth = stroke.width || 0;\\n const td = elementData.transformData;\\n const textEstimate = fontSize * elementData.text.length * 0.7;\\n const containerSpan = td.width ?? (td.radius ? td.radius * 2 : 0);\\n const estimatedSpan = Math.max(containerSpan, textEstimate);\\n const featherPad = (stroke.feather || 0) * 2;\\n const padding = strokeWidth * 4 + featherPad + fontSize + 40;\\n const estWidth = estimatedSpan + padding;\\n const archExtra = td.archHeight ? Math.abs(td.archHeight) * fontSize * 2 : 0;\\n const radiusExtra = td.radius ? td.radius : 0;\\n const estHeight = fontSize * 3 + padding + archExtra + radiusExtra;\\n const transform = ctx.getTransform();\\n const scale = Math.max(Math.abs(transform.a), Math.abs(transform.d), 1);\\n const offW = Math.ceil(estWidth * scale / 2) * 2;\\n const offH = Math.ceil(estHeight * scale / 2) * 2;\\n if (offW <= 0 || offH <= 0) {\\n renderFn(ctx, elementData);\\n return;\\n }\\n const offCanvas = createOffscreenCanvas(offW, offH);\\n const offCtx = offCanvas.getContext(\\\"2d\\\");\\n if (!offCtx) {\\n renderFn(ctx, elementData);\\n return;\\n }\\n const elemX = elementData.x || 0;\\n const elemY = elementData.y || 0;\\n const centerPixelX = transform.a * elemX + transform.c * elemY + transform.e;\\n const centerPixelY = transform.b * elemX + transform.d * elemY + transform.f;\\n const drawBackX = Math.round(centerPixelX - offW / 2);\\n const drawBackY = Math.round(centerPixelY - offH / 2);\\n offCtx.setTransform(\\n transform.a,\\n transform.b,\\n transform.c,\\n transform.d,\\n offW / 2 - centerPixelX + transform.e,\\n offH / 2 - centerPixelY + transform.f\\n );\\n if (hasElementOpacity) {\\n offCtx.globalAlpha = 1;\\n const savedStrokeOpa = stroke.opacity;\\n if (hasStrokeOpacity) stroke.opacity = 1;\\n renderFn(offCtx, elementData);\\n if (hasStrokeOpacity) stroke.opacity = savedStrokeOpa;\\n ctx.save();\\n ctx.resetTransform();\\n ctx.globalAlpha = elementAlpha;\\n ctx.drawImage(offCanvas, drawBackX, drawBackY);\\n ctx.restore();\\n return;\\n }\\n const savedOpacity = stroke.opacity;\\n stroke.opacity = 1;\\n renderFn(offCtx, elementData);\\n stroke.opacity = savedOpacity;\\n const savedEnabled = stroke.enabled;\\n stroke.enabled = false;\\n renderFn(ctx, elementData);\\n stroke.enabled = savedEnabled;\\n ctx.save();\\n ctx.resetTransform();\\n ctx.globalAlpha = strokeOpacity;\\n ctx.drawImage(\\n offCanvas,\\n drawBackX,\\n drawBackY\\n );\\n ctx.restore();\\n }\\n function renderCircleTransform(ctx, elementData) {\\n renderTransformWithOffscreenStroke(ctx, elementData, renderCircleTransformDirect);\\n }\\n function renderCircleTransformDirect(ctx, elementData) {\\n const transformData = elementData.transformData;\\n ctx.save();\\n ctx.translate(elementData.x, elementData.y);\\n ctx.rotate(-elementData.rotation * Math.PI / 180);\\n ctx.scale(transformData.scale, transformData.scale);\\n const weight = elementData.bold ? \\\"bold\\\" : \\\"normal\\\";\\n const style = elementData.italic ? \\\"italic\\\" : \\\"normal\\\";\\n ctx.font = `${style} ${weight} ${elementData.fontSize}px ${elementData.fontFamily}`;\\n ctx.fillStyle = elementData.color;\\n ctx.textAlign = \\\"center\\\";\\n ctx.textBaseline = \\\"middle\\\";\\n const chars = elementData.text.split(\\\"\\\");\\n const charWidths = chars.map((char) => ctx.measureText(char).width);\\n const totalWidth = charWidths.reduce((sum, w) => sum + w, 0);\\n if (transformData.reverse) {\\n let currentAngle = Math.PI / 2 + totalWidth / (2 * transformData.radius);\\n chars.forEach((char, i) => {\\n const charWidth = charWidths[i];\\n const angleStep = charWidth / transformData.radius;\\n const x = Math.cos(currentAngle - angleStep / 2) * transformData.radius;\\n const y = Math.sin(currentAngle - angleStep / 2) * transformData.radius;\\n ctx.save();\\n ctx.translate(x, y);\\n ctx.rotate(currentAngle - angleStep / 2 - Math.PI / 2);\\n applyStrokeToChar(ctx, char, elementData.stroke);\\n ctx.fillText(char, 0, 0);\\n ctx.restore();\\n currentAngle -= angleStep;\\n });\\n } else {\\n let currentAngle = -Math.PI / 2 - totalWidth / (2 * transformData.radius);\\n chars.forEach((char, i) => {\\n const charWidth = charWidths[i];\\n const angleStep = charWidth / transformData.radius;\\n const x = Math.cos(currentAngle + angleStep / 2) * transformData.radius;\\n const y = Math.sin(currentAngle + angleStep / 2) * transformData.radius;\\n ctx.save();\\n ctx.translate(x, y);\\n ctx.rotate(currentAngle + angleStep / 2 + Math.PI / 2);\\n applyStrokeToChar(ctx, char, elementData.stroke);\\n ctx.fillText(char, 0, 0);\\n ctx.restore();\\n currentAngle += angleStep;\\n });\\n }\\n ctx.restore();\\n }\\n function renderWaveTransform(ctx, elementData) {\\n renderTransformWithOffscreenStroke(ctx, elementData, renderWaveTransformDirect);\\n }\\n function renderWaveTransformDirect(ctx, elementData) {\\n const transformData = elementData.transformData;\\n ctx.save();\\n ctx.translate(elementData.x, elementData.y);\\n ctx.rotate(-elementData.rotation * Math.PI / 180);\\n ctx.font = buildFontString(elementData.fontSize, elementData.fontFamily, elementData.bold, elementData.italic);\\n ctx.fillStyle = elementData.color;\\n ctx.textAlign = \\\"center\\\";\\n ctx.textBaseline = \\\"middle\\\";\\n const chars = elementData.text.split(\\\"\\\");\\n const totalWidth = chars.reduce((sum, char) => sum + ctx.measureText(char).width, 0);\\n let currentX = -totalWidth / 2;\\n chars.forEach((char) => {\\n const charWidth = ctx.measureText(char).width;\\n const x = currentX + charWidth / 2;\\n const normalizedX = x / (transformData.width / 2);\\n const y = transformData.amplitude * elementData.fontSize * Math.sin(transformData.frequency * Math.PI * normalizedX);\\n const slope = transformData.amplitude * transformData.frequency * Math.PI * Math.cos(transformData.frequency * Math.PI * normalizedX);\\n ctx.save();\\n ctx.translate(x, y);\\n ctx.transform(1, slope * WAVE_SKEW_FACTOR, 0, 1, 0, 0);\\n applyStrokeToChar(ctx, char, elementData.stroke);\\n ctx.fillText(char, 0, 0);\\n ctx.restore();\\n currentX += charWidth;\\n });\\n ctx.restore();\\n }\\n function renderArchTransform(ctx, elementData) {\\n renderTransformWithOffscreenStroke(ctx, elementData, renderArchTransformDirect);\\n }\\n function renderArchTransformDirect(ctx, elementData) {\\n const transformData = elementData.transformData;\\n ctx.save();\\n ctx.translate(elementData.x, elementData.y);\\n ctx.rotate(-elementData.rotation * Math.PI / 180);\\n ctx.font = buildFontString(elementData.fontSize, elementData.fontFamily, elementData.bold, elementData.italic);\\n ctx.fillStyle = elementData.color;\\n ctx.textAlign = \\\"center\\\";\\n ctx.textBaseline = \\\"middle\\\";\\n const chars = elementData.text.split(\\\"\\\");\\n const totalWidth = chars.reduce((sum, char) => sum + ctx.measureText(char).width, 0);\\n const radius = transformData.width / 2;\\n let currentX = -totalWidth / 2;\\n chars.forEach((char) => {\\n const charWidth = ctx.measureText(char).width;\\n const x = currentX + charWidth / 2;\\n const normalizedX = x / radius;\\n const y = (Math.pow(normalizedX, 2) - 1) * transformData.archHeight * elementData.fontSize;\\n const slope = 2 * normalizedX * transformData.archHeight;\\n ctx.save();\\n ctx.translate(x, y);\\n const skewFactor = 0.3;\\n ctx.transform(1, slope * skewFactor, 0, 1, 0, 0);\\n applyStrokeToChar(ctx, char, elementData.stroke);\\n ctx.fillText(char, 0, 0);\\n ctx.restore();\\n currentX += charWidth;\\n });\\n ctx.restore();\\n }\\n function renderAscendTransform(ctx, elementData) {\\n renderTransformWithOffscreenStroke(ctx, elementData, renderAscendTransformDirect);\\n }\\n function renderAscendTransformDirect(ctx, elementData) {\\n const transformData = elementData.transformData;\\n ctx.save();\\n ctx.translate(elementData.x, elementData.y);\\n ctx.rotate(-elementData.rotation * Math.PI / 180);\\n ctx.font = buildFontString(elementData.fontSize, elementData.fontFamily, elementData.bold, elementData.italic);\\n ctx.fillStyle = elementData.color;\\n ctx.textAlign = \\\"center\\\";\\n ctx.textBaseline = \\\"middle\\\";\\n const chars = elementData.text.split(\\\"\\\");\\n const totalWidth = chars.reduce((sum, char) => sum + ctx.measureText(char).width, 0);\\n const angleRad = transformData.ascendAngle * Math.PI / 180;\\n let currentX = -totalWidth / 2;\\n chars.forEach((char) => {\\n const charWidth = ctx.measureText(char).width;\\n const x = currentX + charWidth / 2;\\n const y = x * Math.tan(angleRad);\\n const slope = Math.tan(angleRad);\\n ctx.save();\\n ctx.translate(x, y);\\n const skewFactor = 1;\\n ctx.transform(1, slope * skewFactor, 0, 1, 0, 0);\\n applyStrokeToChar(ctx, char, elementData.stroke);\\n ctx.fillText(char, 0, 0);\\n ctx.restore();\\n currentX += charWidth;\\n });\\n ctx.restore();\\n }\\n function renderLeanTransform(ctx, elementData) {\\n renderTransformWithOffscreenStroke(ctx, elementData, renderLeanTransformDirect);\\n }\\n function renderLeanTransformDirect(ctx, elementData) {\\n const transformData = elementData.transformData;\\n ctx.save();\\n ctx.translate(elementData.x, elementData.y);\\n ctx.rotate(-elementData.rotation * Math.PI / 180);\\n const skewAngle = -transformData.leanAmount * Math.PI / 4;\\n ctx.transform(1, 0, Math.tan(skewAngle), 1, 0, 0);\\n ctx.font = buildFontString(elementData.fontSize, elementData.fontFamily, elementData.bold, elementData.italic);\\n ctx.fillStyle = elementData.color;\\n ctx.textAlign = \\\"center\\\";\\n ctx.textBaseline = \\\"middle\\\";\\n if (elementData.stroke?.enabled) {\\n ctx.save();\\n ctx.strokeStyle = elementData.stroke.color;\\n ctx.lineWidth = elementData.stroke.width;\\n ctx.lineCap = elementData.stroke.lineCap || \\\"round\\\";\\n ctx.lineJoin = elementData.stroke.lineJoin || \\\"round\\\";\\n if (elementData.stroke.opacity !== void 0) ctx.globalAlpha = elementData.stroke.opacity;\\n ctx.strokeText(elementData.text, 0, 0);\\n ctx.restore();\\n }\\n ctx.fillText(elementData.text, 0, 0);\\n ctx.restore();\\n }\\n function renderFlagTransform(ctx, elementData) {\\n renderTransformWithOffscreenStroke(ctx, elementData, renderFlagTransformDirect);\\n }\\n function renderFlagTransformDirect(ctx, elementData) {\\n const transformData = elementData.transformData;\\n ctx.save();\\n ctx.translate(elementData.x, elementData.y);\\n ctx.rotate(-elementData.rotation * Math.PI / 180);\\n ctx.font = buildFontString(elementData.fontSize, elementData.fontFamily, elementData.bold, elementData.italic);\\n ctx.fillStyle = elementData.color;\\n ctx.textAlign = \\\"center\\\";\\n ctx.textBaseline = \\\"middle\\\";\\n const chars = elementData.text.split(\\\"\\\");\\n const totalWidth = chars.reduce((sum, char) => sum + ctx.measureText(char).width, 0);\\n let currentX = -totalWidth / 2;\\n chars.forEach((char) => {\\n const charWidth = ctx.measureText(char).width;\\n const x = currentX + charWidth / 2;\\n const normalizedX = x / (transformData.width / 2);\\n const distanceFromCenter = Math.abs(normalizedX);\\n const flagAmplitude = transformData.amplitude * distanceFromCenter;\\n const y = flagAmplitude * elementData.fontSize * Math.sin(transformData.frequency * Math.PI * normalizedX);\\n const cosComponent = flagAmplitude * transformData.frequency * Math.PI * Math.cos(transformData.frequency * Math.PI * normalizedX);\\n const sinComponent = transformData.amplitude * Math.sign(normalizedX) * Math.sin(transformData.frequency * Math.PI * normalizedX);\\n const slope = cosComponent + sinComponent;\\n ctx.save();\\n ctx.translate(x, y);\\n const skewFactor = 0.3;\\n ctx.transform(1, slope * skewFactor, 0, 1, 0, 0);\\n applyStrokeToChar(ctx, char, elementData.stroke);\\n ctx.fillText(char, 0, 0);\\n ctx.restore();\\n currentX += charWidth;\\n });\\n ctx.restore();\\n }\\n\\n // src/core/TextMetrics.ts\\n var _measureCanvas = null;\\n function getMeasureCanvas() {\\n if (!_measureCanvas) {\\n if (typeof document !== \\\"undefined\\\") {\\n _measureCanvas = document.createElement(\\\"canvas\\\");\\n } else if (typeof OffscreenCanvas !== \\\"undefined\\\") {\\n _measureCanvas = new OffscreenCanvas(1, 1);\\n } else {\\n throw new Error(\\\"No canvas available for text measurement\\\");\\n }\\n }\\n return _measureCanvas;\\n }\\n function buildFontString2(fontSize, fontFamily, bold = false, italic = false) {\\n const parts = [];\\n if (italic) {\\n parts.push(\\\"italic\\\");\\n }\\n if (bold) {\\n parts.push(\\\"bold\\\");\\n }\\n parts.push(`${fontSize}px`);\\n parts.push(fontFamily);\\n return parts.join(\\\" \\\");\\n }\\n function wrapText(text, maxWidth, fontSize, fontFamily, bold = false, italic = false, lockedLineCount, strict = false) {\\n const canvas = getMeasureCanvas();\\n const ctx = canvas.getContext(\\\"2d\\\");\\n ctx.font = buildFontString2(fontSize, fontFamily, bold, italic);\\n if (text.trim().length === 0) {\\n return [text];\\n }\\n if (text.includes(\\\"\\\\n\\\")) {\\n const explicitLines = text.split(\\\"\\\\n\\\");\\n const allWrappedLines = [];\\n for (let i = 0; i < explicitLines.length; i++) {\\n const line = explicitLines[i];\\n const wrappedLine = wrapText(line, maxWidth, fontSize, fontFamily, bold, italic, void 0, strict);\\n allWrappedLines.push(...wrappedLine);\\n }\\n return allWrappedLines;\\n }\\n const leadingSpacesMatch = text.match(/^\\\\s*/);\\n const trailingSpacesMatch = text.match(/\\\\s*$/);\\n const leadingSpaces = leadingSpacesMatch ? leadingSpacesMatch[0] : \\\"\\\";\\n const trailingSpaces = trailingSpacesMatch ? trailingSpacesMatch[0] : \\\"\\\";\\n const trimmedText = text.substring(leadingSpaces.length, text.length - trailingSpaces.length);\\n const words = trimmedText.split(\\\" \\\");\\n if (lockedLineCount !== void 0 && lockedLineCount > 0) {\\n if (lockedLineCount === 1) {\\n return [leadingSpaces + words.join(\\\" \\\") + trailingSpaces];\\n }\\n const lines2 = [];\\n const wordsPerLine = Math.ceil(words.length / lockedLineCount);\\n for (let i = 0; i < words.length; i += wordsPerLine) {\\n const lineWords = words.slice(i, i + wordsPerLine);\\n lines2.push(lineWords.join(\\\" \\\"));\\n }\\n if (lines2.length > 0) {\\n lines2[0] = leadingSpaces + lines2[0];\\n lines2[lines2.length - 1] = lines2[lines2.length - 1] + trailingSpaces;\\n }\\n return lines2;\\n }\\n const allText = words.join(\\\" \\\");\\n const allTextWithSpaces = leadingSpaces + allText + trailingSpaces;\\n const allTextWidth = ctx.measureText(allTextWithSpaces).width;\\n const isSmallSize = maxWidth < 200;\\n const wrapTolerancePercent = strict ? 0 : isSmallSize ? 0.08 : 0.05;\\n const wrapTolerance = strict ? 0 : Math.max(20, maxWidth * wrapTolerancePercent);\\n if (allTextWidth <= maxWidth + wrapTolerance) {\\n return [allTextWithSpaces];\\n }\\n const lines = [];\\n let currentLine = \\\"\\\";\\n const lineTolerancePercent = strict ? 0 : isSmallSize ? 0.05 : 0.03;\\n const lineTolerance = strict ? 0 : Math.max(15, maxWidth * lineTolerancePercent);\\n for (let i = 0; i < words.length; i++) {\\n const word = words[i];\\n const wordWidth = ctx.measureText(word).width;\\n if (wordWidth > maxWidth + lineTolerance) {\\n if (currentLine.length > 0) {\\n lines.push(currentLine);\\n currentLine = \\\"\\\";\\n }\\n const chars = Array.from(word);\\n let charBuffer = \\\"\\\";\\n for (const char of chars) {\\n const testBuffer = charBuffer + char;\\n const bufferWidth = ctx.measureText(testBuffer).width;\\n if (bufferWidth > maxWidth + lineTolerance && charBuffer.length > 0) {\\n lines.push(charBuffer);\\n charBuffer = char;\\n } else {\\n charBuffer = testBuffer;\\n }\\n }\\n currentLine = charBuffer;\\n } else {\\n const testLine = currentLine.length > 0 ? currentLine + \\\" \\\" + word : word;\\n const metrics = ctx.measureText(testLine);\\n if (metrics.width > maxWidth + lineTolerance && currentLine.length > 0) {\\n lines.push(currentLine);\\n currentLine = word;\\n } else {\\n currentLine = testLine;\\n }\\n }\\n }\\n if (currentLine.length > 0) {\\n lines.push(currentLine);\\n }\\n if (lines.length > 0) {\\n if (leadingSpaces.length > 0) {\\n const firstLineWithSpace = leadingSpaces + lines[0];\\n const firstLineWidth = ctx.measureText(firstLineWithSpace).width;\\n if (firstLineWidth > maxWidth + lineTolerance) {\\n lines.unshift(leadingSpaces);\\n } else {\\n lines[0] = firstLineWithSpace;\\n }\\n }\\n if (trailingSpaces.length > 0) {\\n const lastIdx = lines.length - 1;\\n const lastLineWithSpace = lines[lastIdx] + trailingSpaces;\\n const lastLineWidth = ctx.measureText(lastLineWithSpace).width;\\n if (lastLineWidth > maxWidth + lineTolerance) {\\n lines.push(trailingSpaces);\\n } else {\\n lines[lastIdx] = lastLineWithSpace;\\n }\\n }\\n }\\n return lines;\\n }\\n function getFontMetrics(fontSize, fontFamily, bold = false, italic = false) {\\n const canvas = getMeasureCanvas();\\n const ctx = canvas.getContext(\\\"2d\\\");\\n ctx.font = buildFontString2(fontSize, fontFamily, bold, italic);\\n const sampleText = \\\"\\\\xC1\\\\xC9\\\\xCDgjpqy\\\";\\n const metrics = ctx.measureText(sampleText);\\n const ascent = metrics.actualBoundingBoxAscent || fontSize * 0.8;\\n const descent = metrics.actualBoundingBoxDescent || fontSize * 0.2;\\n const height = ascent + descent;\\n return { ascent, descent, height };\\n }\\n function calculateVisualBoundsWithSpaceCollapsing(text, maxWidth, fontSize, fontFamily, bold = false, italic = false, lockedLineCount, strict = false) {\\n const lines = wrapText(text, maxWidth, fontSize, fontFamily, bold, italic, lockedLineCount, strict);\\n const hasExplicitNewlines = text.includes(\\\"\\\\n\\\");\\n const paragraphMetadata = lines.map((_, index) => ({\\n isParagraphStart: !hasExplicitNewlines && index === 0,\\n isParagraphEnd: !hasExplicitNewlines && index === lines.length - 1\\n }));\\n const canvas = getMeasureCanvas();\\n const ctx = canvas.getContext(\\\"2d\\\");\\n ctx.font = buildFontString2(fontSize, fontFamily, bold, italic);\\n let maxLineWidth = 0;\\n const fontMetrics = getFontMetrics(fontSize, fontFamily, bold, italic);\\n const visibleLines = [];\\n let totalLineCount = 0;\\n lines.forEach((line, index) => {\\n const isParagraphStart = paragraphMetadata[index].isParagraphStart;\\n const isParagraphEnd = paragraphMetadata[index].isParagraphEnd;\\n let visibleText = line;\\n if (!isParagraphStart) {\\n const leadingSpacesMatch = line.match(/^ +/);\\n const leadingSpacesCount = leadingSpacesMatch ? leadingSpacesMatch[0].length : 0;\\n if (leadingSpacesCount > 0) {\\n visibleText = visibleText.substring(leadingSpacesCount);\\n }\\n }\\n if (!isParagraphEnd) {\\n const trailingSpacesMatch = visibleText.match(/ +$/);\\n const trailingSpacesCount = trailingSpacesMatch ? trailingSpacesMatch[0].length : 0;\\n if (trailingSpacesCount > 0) {\\n visibleText = visibleText.substring(0, visibleText.length - trailingSpacesCount);\\n }\\n }\\n totalLineCount++;\\n if (visibleText.length > 0) {\\n visibleLines.push(visibleText);\\n const lineWidth = ctx.measureText(visibleText).width;\\n maxLineWidth = Math.max(maxLineWidth, lineWidth);\\n }\\n });\\n let height;\\n const lineHeight = LINE_HEIGHT_MULTIPLIER;\\n if (totalLineCount === 1) {\\n height = fontMetrics.height;\\n } else if (totalLineCount === 0) {\\n height = 0;\\n } else {\\n const lineSpacing = fontSize * lineHeight;\\n height = (totalLineCount - 1) * lineSpacing + fontMetrics.height;\\n }\\n return {\\n width: maxLineWidth,\\n height,\\n lines\\n };\\n }\\n\\n // src/rendering/stroke-utils.ts\\n function createImagePath(ctx, element) {\\n if (!element.transformData) return;\\n const { borderRadius = 0 } = element.transformData;\\n const width = element.transformData.width ?? 100;\\n const height = element.transformData.height ?? 100;\\n ctx.translate(element.x || 0, element.y || 0);\\n ctx.rotate(-(element.rotation || 0) * Math.PI / 180);\\n ctx.beginPath();\\n if (borderRadius > 0) {\\n const maxRadius = Math.min(width, height) / 2;\\n const radius = Math.min(borderRadius, maxRadius);\\n const x = -width / 2;\\n const y = -height / 2;\\n ctx.moveTo(x + radius, y);\\n ctx.lineTo(x + width - radius, y);\\n ctx.arcTo(x + width, y, x + width, y + radius, radius);\\n ctx.lineTo(x + width, y + height - radius);\\n ctx.arcTo(x + width, y + height, x + width - radius, y + height, radius);\\n ctx.lineTo(x + radius, y + height);\\n ctx.arcTo(x, y + height, x, y + height - radius, radius);\\n ctx.lineTo(x, y + radius);\\n ctx.arcTo(x, y, x + radius, y, radius);\\n ctx.closePath();\\n } else {\\n ctx.rect(-width / 2, -height / 2, width, height);\\n }\\n }\\n\\n // src/rendering/StrokeRenderer.ts\\n function applyStrokeStyle(ctx, stroke) {\\n ctx.strokeStyle = stroke.color;\\n ctx.lineWidth = stroke.width;\\n ctx.lineCap = stroke.lineCap || \\\"butt\\\";\\n ctx.lineJoin = stroke.lineJoin || \\\"miter\\\";\\n if (stroke.miterLimit !== void 0) {\\n ctx.miterLimit = stroke.miterLimit;\\n }\\n if (stroke.dashArray && stroke.dashArray.length > 0) {\\n ctx.setLineDash(stroke.dashArray);\\n } else {\\n ctx.setLineDash([]);\\n }\\n if (stroke.opacity !== void 0) {\\n ctx.globalAlpha = stroke.opacity;\\n }\\n }\\n function createOffscreenCanvas2(width, height) {\\n if (typeof OffscreenCanvas !== \\\"undefined\\\") {\\n return new OffscreenCanvas(width, height);\\n }\\n const canvas = document.createElement(\\\"canvas\\\");\\n canvas.width = width;\\n canvas.height = height;\\n return canvas;\\n }\\n function renderTextStroke(ctx, element, renderingContext) {\\n if (!element.stroke?.enabled) return;\\n const textElement = element;\\n const text = textElement.text || \\\"\\\";\\n if (!text) return;\\n const isKnockoutRender = renderingContext?.isKnockout === true;\\n const strokeOpacity = element.stroke.opacity ?? 1;\\n const needsOffscreen = !isKnockoutRender && strokeOpacity < 1;\\n if (needsOffscreen) {\\n try {\\n renderTextStrokeViaOffscreen(ctx, element, textElement, renderingContext, strokeOpacity);\\n } catch {\\n renderTextStrokeDirect(ctx, element, textElement, renderingContext, false);\\n }\\n } else {\\n renderTextStrokeDirect(ctx, element, textElement, renderingContext, isKnockoutRender);\\n }\\n }\\n function renderTextStrokeViaOffscreen(ctx, element, textElement, renderingContext, strokeOpacity) {\\n const text = textElement.text || \\\"\\\";\\n const fontSize = textElement.fontSize || 24;\\n const strokeWidth = element.stroke.width;\\n const feather = element.stroke.feather || 0;\\n const isCustomTransform = element.transformType === \\\"custom\\\" && element.transformData?.width;\\n const customWidth = isCustomTransform ? element.transformData?.width ?? 200 : 0;\\n const estWidth = isCustomTransform ? customWidth + strokeWidth * 2 + feather * 2 + 40 : fontSize * text.length * 0.7 + strokeWidth * 2 + feather * 2 + 40;\\n const estHeight = fontSize * 3 + strokeWidth * 2 + feather * 2 + 40;\\n const transform = ctx.getTransform();\\n const scale = Math.max(Math.abs(transform.a), Math.abs(transform.d), 1);\\n const offW = Math.ceil(estWidth * scale / 2) * 2;\\n const offH = Math.ceil(estHeight * scale / 2) * 2;\\n if (offW <= 0 || offH <= 0) {\\n renderTextStrokeDirect(ctx, element, textElement, renderingContext, false);\\n return;\\n }\\n const offCanvas = createOffscreenCanvas2(offW, offH);\\n const offCtx = offCanvas.getContext(\\\"2d\\\");\\n if (!offCtx) {\\n renderTextStrokeDirect(ctx, element, textElement, renderingContext, false);\\n return;\\n }\\n const elemX = element.x || 0;\\n const elemY = element.y || 0;\\n const centerPixelX = transform.a * elemX + transform.c * elemY + transform.e;\\n const centerPixelY = transform.b * elemX + transform.d * elemY + transform.f;\\n offCtx.setTransform(\\n transform.a,\\n transform.b,\\n transform.c,\\n transform.d,\\n offW / 2 - centerPixelX + transform.e,\\n offH / 2 - centerPixelY + transform.f\\n );\\n const originalOpacity = element.stroke.opacity;\\n element.stroke.opacity = 1;\\n renderTextStrokeDirect(offCtx, element, textElement, renderingContext, false);\\n element.stroke.opacity = originalOpacity;\\n ctx.save();\\n ctx.resetTransform();\\n ctx.globalAlpha = strokeOpacity;\\n ctx.drawImage(\\n offCanvas,\\n Math.round(centerPixelX - offW / 2),\\n Math.round(centerPixelY - offH / 2)\\n );\\n ctx.restore();\\n }\\n function renderTextStrokeDirect(ctx, element, textElement, renderingContext, isKnockoutRender) {\\n const text = textElement.text || \\\"\\\";\\n ctx.save();\\n if (!renderingContext?.positionApplied) {\\n ctx.translate(element.x || 0, element.y || 0);\\n ctx.rotate(-(element.rotation || 0) * Math.PI / 180);\\n }\\n const fontSize = textElement.fontSize || 24;\\n const fontFamily = textElement.fontFamily || \\\"Arial\\\";\\n const bold = textElement.bold || false;\\n const italic = textElement.italic || false;\\n const textAlign = textElement.textAlign || \\\"center\\\";\\n ctx.font = `${italic ? \\\"italic \\\" : \\\"\\\"}${bold ? \\\"bold \\\" : \\\"\\\"}${fontSize}px ${fontFamily}`;\\n ctx.textAlign = textAlign;\\n ctx.textBaseline = \\\"alphabetic\\\";\\n if (isKnockoutRender) {\\n ctx.strokeStyle = \\\"#000000\\\";\\n ctx.globalAlpha = 1;\\n } else {\\n ctx.strokeStyle = element.stroke.color;\\n if (element.stroke.opacity !== void 0) {\\n ctx.globalAlpha = element.stroke.opacity;\\n }\\n }\\n ctx.lineWidth = element.stroke.width;\\n ctx.lineCap = element.stroke.lineCap || \\\"round\\\";\\n ctx.lineJoin = element.stroke.lineJoin || \\\"round\\\";\\n if (element.stroke.miterLimit !== void 0) {\\n ctx.miterLimit = element.stroke.miterLimit;\\n }\\n if (!isKnockoutRender && element.stroke.feather && element.stroke.feather > 0) {\\n if (\\\"filter\\\" in ctx) {\\n ctx.filter = `blur(${element.stroke.feather}px)`;\\n }\\n }\\n const fontMetrics = getFontMetrics(fontSize, fontFamily, bold, italic);\\n const isCustomTransform = element.transformType === \\\"custom\\\" && element.transformData?.width;\\n if (isCustomTransform) {\\n const transformData = element.transformData;\\n const width = transformData?.width ?? 200;\\n const availableWidth = width - HORIZONTAL_PADDING * 2;\\n const { lines, height: visualHeight } = calculateVisualBoundsWithSpaceCollapsing(\\n text,\\n availableWidth,\\n fontSize,\\n fontFamily,\\n bold,\\n italic,\\n void 0,\\n // No locked line count for stroke\\n true\\n // strict: wrap exactly at maxWidth\\n );\\n const topLeftX = -width / 2;\\n const topLeftY = -visualHeight / 2;\\n const lineSpacing = fontSize * LINE_HEIGHT_MULTIPLIER;\\n lines.forEach((line, index) => {\\n const isParagraphStart = index === 0;\\n const isParagraphEnd = index === lines.length - 1;\\n let visibleText = line;\\n if (!isParagraphStart) {\\n const leadingSpacesMatch = line.match(/^ +/);\\n const leadingSpacesCount = leadingSpacesMatch ? leadingSpacesMatch[0].length : 0;\\n if (leadingSpacesCount > 0) {\\n visibleText = visibleText.substring(leadingSpacesCount);\\n }\\n }\\n if (!isParagraphEnd) {\\n const trailingSpacesMatch = visibleText.match(/ +$/);\\n const trailingSpacesCount = trailingSpacesMatch ? trailingSpacesMatch[0].length : 0;\\n if (trailingSpacesCount > 0) {\\n visibleText = visibleText.substring(0, visibleText.length - trailingSpacesCount);\\n }\\n }\\n let xPos = topLeftX + HORIZONTAL_PADDING;\\n if (textAlign === \\\"center\\\") {\\n xPos = topLeftX + width / 2;\\n } else if (textAlign === \\\"right\\\") {\\n xPos = topLeftX + width - HORIZONTAL_PADDING;\\n }\\n const yPos = topLeftY + fontMetrics.ascent + index * lineSpacing;\\n ctx.strokeText(visibleText, xPos, yPos);\\n });\\n } else {\\n const visualHeight = fontMetrics.height;\\n const topLeftY = -visualHeight / 2;\\n const yPos = topLeftY + fontMetrics.ascent;\\n ctx.strokeText(text, 0, yPos);\\n }\\n ctx.restore();\\n }\\n function renderImageStroke(ctx, element, renderingContext) {\\n if (!element.stroke?.enabled) return;\\n if (!element.transformData) return;\\n const isKnockoutRender = renderingContext?.isKnockout === true;\\n ctx.save();\\n if (isKnockoutRender) {\\n ctx.strokeStyle = \\\"#000000\\\";\\n ctx.lineWidth = element.stroke.width;\\n ctx.lineCap = element.stroke.lineCap || \\\"butt\\\";\\n ctx.lineJoin = element.stroke.lineJoin || \\\"miter\\\";\\n ctx.globalAlpha = 1;\\n if (element.stroke.miterLimit !== void 0) {\\n ctx.miterLimit = element.stroke.miterLimit;\\n }\\n } else {\\n applyStrokeStyle(ctx, element.stroke);\\n }\\n if (!isKnockoutRender && element.stroke.feather && element.stroke.feather > 0) {\\n if (\\\"filter\\\" in ctx) {\\n ctx.filter = `blur(${element.stroke.feather}px)`;\\n }\\n }\\n createImagePath(ctx, element);\\n ctx.stroke();\\n ctx.restore();\\n }\\n\\n // src/utils/logger.ts\\n var Logger = class {\\n constructor() {\\n this.level = 0 /* DEBUG */;\\n this.enabled = typeof process !== \\\"undefined\\\" && false;\\n }\\n // Only enabled in development by default\\n /**\\n * Set the minimum log level to display\\n */\\n setLevel(level) {\\n this.level = level;\\n }\\n /**\\n * Enable or disable logging globally\\n */\\n setEnabled(enabled) {\\n this.enabled = enabled;\\n }\\n /**\\n * Get current log level\\n */\\n getLevel() {\\n return this.level;\\n }\\n /**\\n * Check if logging is enabled\\n */\\n isEnabled() {\\n return this.enabled;\\n }\\n /**\\n * Log debug message (verbose, development only)\\n */\\n debug(_message, ..._args) {\\n }\\n /**\\n * Log info message (general information)\\n */\\n info(message, ...args) {\\n if (this.enabled && this.level <= 1 /* INFO */) {\\n console.info(`[INFO] ${message}`, ...args);\\n }\\n }\\n /**\\n * Log warning message (potential issues)\\n */\\n warn(message, ...args) {\\n if (this.enabled && this.level <= 2 /* WARN */) {\\n console.warn(`[WARN] ${message}`, ...args);\\n }\\n }\\n /**\\n * Log error message (critical issues)\\n */\\n error(message, ...args) {\\n if (this.enabled && this.level <= 3 /* ERROR */) {\\n console.error(`[ERROR] ${message}`, ...args);\\n }\\n }\\n /**\\n * Create a scoped logger with a prefix for a specific module\\n */\\n scope(scopeName) {\\n return new ScopedLogger(this, scopeName);\\n }\\n };\\n var ScopedLogger = class {\\n constructor(logger5, scopeName) {\\n this.logger = logger5;\\n this.scopeName = scopeName;\\n }\\n debug(message, ...args) {\\n this.logger.debug(`[${this.scopeName}] ${message}`, ...args);\\n }\\n info(message, ...args) {\\n this.logger.info(`[${this.scopeName}] ${message}`, ...args);\\n }\\n warn(message, ...args) {\\n this.logger.warn(`[${this.scopeName}] ${message}`, ...args);\\n }\\n error(message, ...args) {\\n this.logger.error(`[${this.scopeName}] ${message}`, ...args);\\n }\\n };\\n var logger = new Logger();\\n var createLogger = (scopeName) => {\\n return logger.scope(scopeName);\\n };\\n\\n // src/utils/FontAnalyzer.ts\\n var log = createLogger(\\\"FontAnalyzer\\\");\\n var fontkitModule = null;\\n async function getFontkit() {\\n if (!fontkitModule) {\\n fontkitModule = await Promise.resolve().then(() => (init_browser_module(), browser_module_exports));\\n }\\n return fontkitModule;\\n }\\n var FontAnalyzerService = class {\\n constructor() {\\n this.fontCache = /* @__PURE__ */ new Map();\\n this.failedFonts = /* @__PURE__ */ new Set();\\n // Track fonts that failed to load (CORS, network errors)\\n this.CACHE_DURATION = 1e3 * 60 * 30;\\n // 30 minutes\\n this.MAX_CACHE_SIZE = 5;\\n }\\n // Limit cache to prevent iOS Safari memory crashes\\n /**\\n * Evict the oldest font from cache if over the limit\\n * Uses LRU (Least Recently Used) strategy based on timestamp\\n */\\n evictOldestFont() {\\n if (this.fontCache.size <= this.MAX_CACHE_SIZE) return;\\n let oldestKey = null;\\n let oldestTime = Date.now();\\n this.fontCache.forEach((entry, key) => {\\n if (entry.timestamp < oldestTime) {\\n oldestTime = entry.timestamp;\\n oldestKey = key;\\n }\\n });\\n if (oldestKey) {\\n this.fontCache.delete(oldestKey);\\n }\\n }\\n /**\\n * Check if a font is a system font\\n */\\n isSystemFont(fontFamily) {\\n return SYSTEM_FONTS.has(fontFamily);\\n }\\n /**\\n * Get Google Fonts API URL for a specific font family\\n */\\n getGoogleFontUrl(fontFamily, weight = 400) {\\n const formattedFamily = fontFamily.replace(/\\\\s+/g, \\\"+\\\");\\n return `https://fonts.googleapis.com/css2?family=${formattedFamily}:wght@${weight}&display=swap`;\\n }\\n /**\\n * Extract actual font file URL from Google Fonts CSS\\n */\\n async extractFontFileUrl(fontFamily, weight = 400) {\\n try {\\n const cssUrl = this.getGoogleFontUrl(fontFamily, weight);\\n const response = await fetch(cssUrl);\\n const css = await response.text();\\n const fontFaceRegex = /@font-face\\\\s*{([^}]*)}/g;\\n const fontFaces = Array.from(css.matchAll(fontFaceRegex));\\n if (fontFaces.length === 0) {\\n log.warn(\\\"No @font-face found in CSS\\\");\\n return null;\\n }\\n let bestUrl = null;\\n let bestScore = -1;\\n for (let i = 0; i < fontFaces.length; i++) {\\n const fontFaceContent = fontFaces[i][1];\\n const urlMatch = fontFaceContent.match(/url\\\\((https:\\\\/\\\\/fonts\\\\.gstatic\\\\.com\\\\/[^)]+)\\\\)/);\\n const hasUnicodeRange = fontFaceContent.includes(\\\"unicode-range\\\");\\n const unicodeRangeMatch = fontFaceContent.match(/unicode-range:\\\\s*([^;]+);/);\\n if (!urlMatch) continue;\\n const url = urlMatch[1];\\n let score = 0;\\n if (!hasUnicodeRange) {\\n score = 1e3;\\n } else if (unicodeRangeMatch) {\\n const rangeContent = unicodeRangeMatch[1];\\n score = (rangeContent.match(/U\\\\+/g) || []).length;\\n }\\n if (score > bestScore) {\\n bestScore = score;\\n bestUrl = url;\\n }\\n }\\n if (bestUrl) {\\n return bestUrl;\\n }\\n log.warn(\\\"No font URL found in CSS for\\\", fontFamily);\\n return null;\\n } catch (error) {\\n log.error(\\\"Error extracting font file URL:\\\", error);\\n return null;\\n }\\n }\\n /**\\n * Load and parse a font file\\n */\\n async loadFont(fontFamily, weight = 400) {\\n if (this.isSystemFont(fontFamily)) {\\n return null;\\n }\\n const cacheKey = `${fontFamily}-${weight}`;\\n if (this.failedFonts.has(cacheKey)) {\\n return null;\\n }\\n const cached = this.fontCache.get(cacheKey);\\n if (cached && Date.now() - cached.timestamp < this.CACHE_DURATION) {\\n cached.timestamp = Date.now();\\n return cached.font;\\n }\\n try {\\n const fontUrl = await this.extractFontFileUrl(fontFamily, weight);\\n if (!fontUrl) {\\n this.failedFonts.add(cacheKey);\\n return null;\\n }\\n const response = await fetch(fontUrl);\\n if (!response.ok) {\\n log.error(`Font fetch failed: ${response.status} ${response.statusText}`);\\n this.failedFonts.add(cacheKey);\\n return null;\\n }\\n const arrayBuffer = await response.arrayBuffer();\\n const buffer = new Uint8Array(arrayBuffer);\\n const fontkit = await getFontkit();\\n const fontOrCollection = fontkit.create(buffer);\\n const font = \\\"fonts\\\" in fontOrCollection ? fontOrCollection.fonts[0] : fontOrCollection;\\n this.fontCache.set(cacheKey, {\\n font,\\n url: fontUrl,\\n timestamp: Date.now()\\n });\\n this.evictOldestFont();\\n return font;\\n } catch (error) {\\n log.error(`Error loading font ${fontFamily}:`, error);\\n this.failedFonts.add(cacheKey);\\n return null;\\n }\\n }\\n /**\\n * Get font from cache synchronously (for rendering)\\n * Returns null if font is not cached - font should be pre-loaded before rendering\\n */\\n getFontSync(fontFamily, weight = 400) {\\n const cacheKey = `${fontFamily}-${weight}`;\\n const cached = this.fontCache.get(cacheKey);\\n if (cached && Date.now() - cached.timestamp < this.CACHE_DURATION) {\\n cached.timestamp = Date.now();\\n return cached.font;\\n }\\n return null;\\n }\\n /**\\n * Clear font cache (useful for debugging or forcing reload)\\n * Also clears failed fonts to allow retry\\n */\\n clearCache(fontFamily, weight) {\\n if (fontFamily) {\\n const cacheKey = `${fontFamily}-${weight || 400}`;\\n this.fontCache.delete(cacheKey);\\n this.failedFonts.delete(cacheKey);\\n } else {\\n this.fontCache.clear();\\n this.failedFonts.clear();\\n }\\n }\\n /**\\n * Get all glyphs in a font (for browsing)\\n */\\n async getAllGlyphs(fontFamily, weight = 400, limit = 1500) {\\n if (this.isSystemFont(fontFamily)) {\\n return [];\\n }\\n const font = await this.loadFont(fontFamily, weight);\\n if (!font) {\\n return [];\\n }\\n const glyphs = [];\\n const maxGlyphs = Math.min(font.numGlyphs, limit);\\n for (let glyphId = 0; glyphId < maxGlyphs; glyphId++) {\\n try {\\n const glyph = font.getGlyph(glyphId);\\n if (!glyph || !glyph.name) continue;\\n if (glyph.name === \\\".notdef\\\" || glyph.name.startsWith(\\\".null\\\")) {\\n continue;\\n }\\n const codePoints = glyph.codePoints || [];\\n let unicode = codePoints.length > 0 ? String.fromCodePoint(codePoints[0]) : \\\"\\\";\\n if (!unicode || unicode.length === 0) {\\n const baseCharMatch = glyph.name.match(/^([A-Za-z0-9])[._]/);\\n if (baseCharMatch) {\\n unicode = baseCharMatch[1];\\n }\\n }\\n let friendlyName = glyph.name;\\n if (unicode && unicode.length > 0 && /\\\\S/.test(unicode)) {\\n if (glyph.name.includes(\\\".swash\\\")) {\\n friendlyName = `${unicode} Swash`;\\n } else if (glyph.name.match(/\\\\.alt(\\\\d+)?/)) {\\n const num = glyph.name.match(/\\\\.alt(\\\\d+)/)?.[1] || \\\"\\\";\\n friendlyName = `${unicode} Alternate${num ? \\\" \\\" + num : \\\"\\\"}`;\\n } else if (glyph.name.match(/\\\\.ss(\\\\d+)/)) {\\n const num = glyph.name.match(/\\\\.ss(\\\\d+)/)?.[1];\\n friendlyName = `${unicode} Stylistic Set ${num}`;\\n } else {\\n friendlyName = `${unicode} - ${glyph.name}`;\\n }\\n }\\n let category = \\\"default\\\";\\n const nameLower = glyph.name.toLowerCase();\\n if (nameLower.includes(\\\"swash\\\") || nameLower.includes(\\\"cswh\\\")) {\\n category = \\\"swash\\\";\\n } else if (glyph.name.match(/\\\\.(alt|ss\\\\d+|cv\\\\d+|salt|ornament)/)) {\\n category = \\\"stylistic\\\";\\n } else if (glyph.name.match(/_\\\\d+$/)) {\\n category = \\\"stylistic\\\";\\n } else if (nameLower.match(/liga|dlig/)) {\\n category = \\\"ligature\\\";\\n }\\n if (category === \\\"default\\\") {\\n continue;\\n }\\n if (unicode && unicode.length > 0) {\\n glyphs.push({\\n glyphIndex: glyph.id,\\n unicode,\\n name: friendlyName,\\n category,\\n previewDataUrl: this.generateGlyphPreview(font, glyph.id, 80)\\n });\\n }\\n } catch (e) {\\n }\\n }\\n return glyphs;\\n }\\n /**\\n * Get glyph alternates for a specific character\\n */\\n async getGlyphAlternates(fontFamily, character, weight = 400) {\\n const font = await this.loadFont(fontFamily, weight);\\n if (!font) {\\n return [];\\n }\\n const alternates = [];\\n const codePoint = character.codePointAt(0);\\n if (codePoint === void 0) {\\n return [];\\n }\\n const defaultGlyph = font.glyphForCodePoint(codePoint);\\n if (defaultGlyph) {\\n alternates.push({\\n glyphIndex: defaultGlyph.id,\\n unicode: character,\\n name: defaultGlyph.name || \\\"Default\\\",\\n category: \\\"default\\\",\\n previewDataUrl: this.generateGlyphPreview(font, defaultGlyph.id, 80)\\n });\\n }\\n const baseName = defaultGlyph?.name;\\n if (baseName) {\\n let foundCount = 0;\\n for (let glyphId = 0; glyphId < font.numGlyphs; glyphId++) {\\n try {\\n const glyph = font.getGlyph(glyphId);\\n if (!glyph || !glyph.name) continue;\\n const namePatterns = [\\n new RegExp(`^${baseName}\\\\\\\\.(swash|alt|ss\\\\\\\\d+|salt|ornament)`, \\\"i\\\"),\\n new RegExp(`^${baseName}_\\\\\\\\d+$`, \\\"i\\\"),\\n new RegExp(`^${baseName}\\\\\\\\.\\\\\\\\d+$`, \\\"i\\\")\\n ];\\n const isVariant = namePatterns.some((pattern) => pattern.test(glyph.name));\\n if (isVariant && glyph.id !== defaultGlyph.id) {\\n foundCount++;\\n let friendlyName = glyph.name;\\n if (glyph.name.includes(\\\".swash\\\")) {\\n friendlyName = `${character} Swash`;\\n } else if (glyph.name.match(/\\\\.alt(\\\\d+)?/)) {\\n const num = glyph.name.match(/\\\\.alt(\\\\d+)/)?.[1] || \\\"\\\";\\n friendlyName = `${character} Alternate${num ? \\\" \\\" + num : \\\"\\\"}`;\\n } else if (glyph.name.match(/\\\\.ss(\\\\d+)/)) {\\n const num = glyph.name.match(/\\\\.ss(\\\\d+)/)?.[1];\\n friendlyName = `${character} Stylistic Set ${num}`;\\n }\\n alternates.push({\\n glyphIndex: glyph.id,\\n unicode: character,\\n name: friendlyName,\\n category: \\\"stylistic\\\",\\n previewDataUrl: this.generateGlyphPreview(font, glyph.id, 80)\\n });\\n }\\n } catch (e) {\\n }\\n }\\n }\\n if (font.GSUB) {\\n const gsub = font.GSUB;\\n if (gsub.featureList) {\\n for (const feature of gsub.featureList) {\\n const tag = feature.tag;\\n if (!this.isRelevantFeature(tag)) {\\n continue;\\n }\\n if (feature.feature && feature.feature.lookupListIndexes) {\\n for (const lookupIndex of feature.feature.lookupListIndexes) {\\n const lookup = gsub.lookupList?.lookups?.[lookupIndex];\\n if (!lookup) continue;\\n if (lookup.lookupType === 1) {\\n for (const subtable of lookup.subtables || []) {\\n const coverage = subtable.coverage;\\n if (!coverage) continue;\\n const coverageIndex = this.getCoverageIndex(coverage, defaultGlyph.id);\\n if (coverageIndex !== -1) {\\n const substituteGlyphIndex = this.getSubstituteGlyph(subtable, defaultGlyph.id);\\n if (substituteGlyphIndex !== null) {\\n alternates.push({\\n glyphIndex: substituteGlyphIndex,\\n unicode: character,\\n name: `${character} (${tag})`,\\n category: this.categorizeFeature(tag),\\n previewDataUrl: this.generateGlyphPreview(font, substituteGlyphIndex, 80)\\n });\\n }\\n }\\n }\\n } else if (lookup.lookupType === 3) {\\n for (const subtable of lookup.subtables || []) {\\n const coverage = subtable.coverage;\\n if (!coverage) continue;\\n const coverageIndex = this.getCoverageIndex(coverage, defaultGlyph.id);\\n const altSubtable = subtable;\\n if (coverageIndex !== -1 && altSubtable.alternateSets) {\\n const alternateSet = altSubtable.alternateSets[coverageIndex];\\n if (alternateSet) {\\n for (const altGlyphIndex of alternateSet) {\\n alternates.push({\\n glyphIndex: altGlyphIndex,\\n unicode: character,\\n name: `${character} (${tag} alt)`,\\n category: this.categorizeFeature(tag),\\n previewDataUrl: this.generateGlyphPreview(font, altGlyphIndex, 80)\\n });\\n }\\n }\\n }\\n }\\n }\\n }\\n }\\n }\\n }\\n }\\n return alternates;\\n }\\n /**\\n * Get available OpenType features for a font\\n */\\n async getAvailableFeatures(fontFamily, weight = 400) {\\n const font = await this.loadFont(fontFamily, weight);\\n if (!font) {\\n log.warn(`Font ${fontFamily} failed to load`);\\n return [];\\n }\\n try {\\n const features = [];\\n if (font.GSUB && font.GSUB.featureList) {\\n const uniqueFeatures = /* @__PURE__ */ new Set();\\n for (const feature of font.GSUB.featureList) {\\n if (feature.tag) {\\n uniqueFeatures.add(feature.tag);\\n }\\n }\\n features.push(...Array.from(uniqueFeatures));\\n }\\n if (font.GPOS && font.GPOS.featureList) {\\n const uniqueFeatures = /* @__PURE__ */ new Set();\\n for (const feature of font.GPOS.featureList) {\\n if (feature.tag) {\\n uniqueFeatures.add(feature.tag);\\n }\\n }\\n features.push(...Array.from(uniqueFeatures));\\n }\\n return features;\\n } catch (error) {\\n log.error(`Error getting features for ${fontFamily}:`, error);\\n return [];\\n }\\n }\\n /**\\n * Generate a preview image for a glyph\\n */\\n generateGlyphPreview(font, glyphIndex, size = 80) {\\n const canvas = document.createElement(\\\"canvas\\\");\\n canvas.width = size;\\n canvas.height = size;\\n const ctx = canvas.getContext(\\\"2d\\\");\\n if (!ctx) {\\n return \\\"\\\";\\n }\\n try {\\n const glyph = font.getGlyph(glyphIndex);\\n if (!glyph) {\\n return \\\"\\\";\\n }\\n ctx.clearRect(0, 0, size, size);\\n const bbox = glyph.bbox;\\n if (!bbox) {\\n return \\\"\\\";\\n }\\n const glyphWidth = bbox.maxX - bbox.minX;\\n const glyphHeight = bbox.maxY - bbox.minY;\\n if (glyphWidth === 0 || glyphHeight === 0) {\\n return \\\"\\\";\\n }\\n const padding = 0.6;\\n const scale = Math.min(size / glyphWidth, size / glyphHeight) * padding;\\n const glyphCenterX = (bbox.minX + bbox.maxX) / 2;\\n const glyphCenterY = (bbox.minY + bbox.maxY) / 2;\\n const canvasCenterX = size / 2;\\n const canvasCenterY = size / 2;\\n const svgPath = glyph.path.toSVG();\\n if (!svgPath) {\\n return \\\"\\\";\\n }\\n const path2D = new Path2D(svgPath);\\n ctx.save();\\n ctx.translate(canvasCenterX, canvasCenterY);\\n ctx.scale(scale, -scale);\\n ctx.translate(-glyphCenterX, -glyphCenterY);\\n ctx.fillStyle = \\\"#000000\\\";\\n ctx.fill(path2D);\\n ctx.restore();\\n return canvas.toDataURL(\\\"image/png\\\");\\n } catch (error) {\\n log.error(\\\"Error generating glyph preview:\\\", error);\\n return \\\"\\\";\\n }\\n }\\n /**\\n * Check if a feature tag is relevant for glyph alternates\\n */\\n isRelevantFeature(tag) {\\n const relevantFeatures = [\\n \\\"swsh\\\",\\n \\\"cswh\\\",\\n \\\"salt\\\",\\n \\\"ss01\\\",\\n \\\"ss02\\\",\\n \\\"ss03\\\",\\n \\\"ss04\\\",\\n \\\"ss05\\\",\\n \\\"ss06\\\",\\n \\\"ss07\\\",\\n \\\"ss08\\\",\\n \\\"ss09\\\",\\n \\\"ss10\\\",\\n \\\"ss11\\\",\\n \\\"ss12\\\",\\n \\\"ss13\\\",\\n \\\"ss14\\\",\\n \\\"ss15\\\",\\n \\\"ss16\\\",\\n \\\"ss17\\\",\\n \\\"ss18\\\",\\n \\\"ss19\\\",\\n \\\"ss20\\\",\\n \\\"cv01\\\",\\n \\\"cv02\\\",\\n \\\"cv03\\\",\\n \\\"cv04\\\",\\n \\\"cv05\\\",\\n \\\"cv06\\\",\\n \\\"cv07\\\",\\n \\\"cv08\\\",\\n \\\"cv09\\\",\\n \\\"cv10\\\",\\n \\\"aalt\\\",\\n \\\"dlig\\\",\\n \\\"liga\\\"\\n ];\\n return relevantFeatures.includes(tag);\\n }\\n /**\\n * Categorize a feature tag\\n */\\n categorizeFeature(tag) {\\n if (tag.startsWith(\\\"swsh\\\") || tag === \\\"cswh\\\") return \\\"swash\\\";\\n if (tag.startsWith(\\\"ss\\\") || tag.startsWith(\\\"cv\\\") || tag === \\\"salt\\\") return \\\"stylistic\\\";\\n if (tag === \\\"liga\\\" || tag === \\\"dlig\\\") return \\\"ligature\\\";\\n if (tag === \\\"calt\\\") return \\\"contextual\\\";\\n return \\\"stylistic\\\";\\n }\\n /**\\n * Get coverage index for a glyph\\n */\\n getCoverageIndex(coverage, glyphIndex) {\\n if (!coverage) return -1;\\n if (coverage.format === 1 && coverage.glyphs) {\\n return coverage.glyphs.indexOf(glyphIndex);\\n }\\n if (coverage.format === 2 && coverage.ranges) {\\n const ranges = coverage.ranges;\\n for (let i = 0; i < ranges.length; i++) {\\n const range = ranges[i];\\n if (glyphIndex >= range.start && glyphIndex <= range.end) {\\n return range.index + (glyphIndex - range.start);\\n }\\n }\\n }\\n return -1;\\n }\\n /**\\n * Get substitute glyph from a single substitution subtable\\n */\\n getSubstituteGlyph(subtable, glyphIndex) {\\n if (!subtable) return null;\\n if (subtable.substFormat === 1 && typeof subtable.deltaGlyphId === \\\"number\\\") {\\n return glyphIndex + subtable.deltaGlyphId;\\n }\\n if (subtable.substFormat === 2 && subtable.substitute) {\\n const coverageIndex = this.getCoverageIndex(subtable.coverage, glyphIndex);\\n const substitute = subtable.substitute;\\n if (coverageIndex !== -1 && substitute[coverageIndex] !== void 0) {\\n return substitute[coverageIndex];\\n }\\n }\\n return null;\\n }\\n /**\\n * Get the count of alternate glyphs in a font (fast - no preview generation)\\n */\\n async getAlternateGlyphCount(fontFamily, weight = 400) {\\n const font = await this.loadFont(fontFamily, weight);\\n if (!font) {\\n return 0;\\n }\\n let count = 0;\\n const maxGlyphs = Math.min(font.numGlyphs, 1500);\\n for (let glyphId = 0; glyphId < maxGlyphs; glyphId++) {\\n try {\\n const glyph = font.getGlyph(glyphId);\\n if (!glyph || !glyph.name) continue;\\n if (glyph.name === \\\".notdef\\\" || glyph.name.startsWith(\\\".null\\\")) {\\n continue;\\n }\\n const codePoints = glyph.codePoints || [];\\n let unicode = codePoints.length > 0 ? String.fromCodePoint(codePoints[0]) : \\\"\\\";\\n if (!unicode || unicode.length === 0) {\\n const baseCharMatch = glyph.name.match(/^([A-Za-z0-9])[._]/);\\n if (baseCharMatch) {\\n unicode = baseCharMatch[1];\\n }\\n }\\n let category = \\\"default\\\";\\n const nameLower = glyph.name.toLowerCase();\\n if (nameLower.includes(\\\"swash\\\") || nameLower.includes(\\\"cswh\\\")) {\\n category = \\\"swash\\\";\\n } else if (glyph.name.match(/\\\\.(alt|ss\\\\d+|cv\\\\d+|salt|ornament)/)) {\\n category = \\\"stylistic\\\";\\n } else if (glyph.name.match(/_\\\\d+$/)) {\\n category = \\\"stylistic\\\";\\n } else if (nameLower.match(/liga|dlig/)) {\\n category = \\\"ligature\\\";\\n }\\n if (category !== \\\"default\\\" && unicode && unicode.length > 0) {\\n count++;\\n }\\n } catch (e) {\\n }\\n }\\n return count;\\n }\\n /**\\n * Get cache statistics\\n */\\n getCacheStats() {\\n return {\\n size: this.fontCache.size,\\n entries: Array.from(this.fontCache.keys())\\n };\\n }\\n };\\n var FontAnalyzer = new FontAnalyzerService();\\n\\n // src/utils/GlyphRenderer.ts\\n var logger2 = createLogger(\\\"GlyphRenderer\\\");\\n\\n // src/rendering/rich-text-renderer.ts\\n function wrapRichTextSpans(spans, maxWidth, element) {\\n const ctx = getMeasureContext();\\n const lines = [];\\n const measureText = (text, style) => {\\n const fontSize = style.fontSize || element.fontSize;\\n const fontFamily = style.fontFamily || element.fontFamily;\\n const bold = style.bold !== void 0 ? style.bold : element.bold || false;\\n const italic = style.italic !== void 0 ? style.italic : element.italic || false;\\n ctx.font = buildFontString(fontSize, fontFamily, bold, italic);\\n return ctx.measureText(text).width;\\n };\\n const stylesMatch = (s1, s2) => {\\n return s1.fontSize === s2.fontSize && s1.fontFamily === s2.fontFamily && s1.color === s2.color && s1.bold === s2.bold && s1.italic === s2.italic && s1.underline === s2.underline && s1.strikethrough === s2.strikethrough;\\n };\\n const mergedSpans = [];\\n spans.forEach((span) => {\\n if (mergedSpans.length > 0 && stylesMatch(mergedSpans[mergedSpans.length - 1].style, span.style)) {\\n mergedSpans[mergedSpans.length - 1].text += span.text;\\n } else {\\n mergedSpans.push({ text: span.text, style: span.style });\\n }\\n });\\n let fullText = \\\"\\\";\\n const charToSpan = [];\\n mergedSpans.forEach((span, spanIndex) => {\\n for (let i = 0; i < span.text.length; i++) {\\n fullText += span.text[i];\\n charToSpan.push(spanIndex);\\n }\\n });\\n const words = [];\\n let currentWord = \\\"\\\";\\n let wordStart = 0;\\n for (let i = 0; i < fullText.length; i++) {\\n const char = fullText[i];\\n if (char === \\\" \\\") {\\n if (currentWord.length > 0) {\\n words.push({ text: currentWord, startIdx: wordStart, endIdx: i - 1 });\\n currentWord = \\\"\\\";\\n }\\n words.push({ text: \\\" \\\", startIdx: i, endIdx: i });\\n } else {\\n if (currentWord.length === 0) {\\n wordStart = i;\\n }\\n currentWord += char;\\n }\\n }\\n if (currentWord.length > 0) {\\n words.push({ text: currentWord, startIdx: wordStart, endIdx: fullText.length - 1 });\\n }\\n let currentLine = [];\\n let currentLineWidth = 0;\\n const finishLine = () => {\\n if (currentLine.length > 0) {\\n lines.push(currentLine);\\n currentLine = [];\\n currentLineWidth = 0;\\n }\\n };\\n words.forEach((word, _wordIdx) => {\\n const wordSpans = [];\\n let currentSpanIdx = charToSpan[word.startIdx];\\n let currentText = \\\"\\\";\\n for (let charIdx = word.startIdx; charIdx <= word.endIdx; charIdx++) {\\n const spanIdx = charToSpan[charIdx];\\n if (spanIdx !== currentSpanIdx) {\\n wordSpans.push({ text: currentText, style: mergedSpans[currentSpanIdx].style });\\n currentText = fullText[charIdx];\\n currentSpanIdx = spanIdx;\\n } else {\\n currentText += fullText[charIdx];\\n }\\n }\\n if (currentText.length > 0) {\\n wordSpans.push({ text: currentText, style: mergedSpans[currentSpanIdx].style });\\n }\\n const wordWidth = wordSpans.reduce((sum, span) => sum + measureText(span.text, span.style), 0);\\n if (word.text === \\\" \\\") {\\n if (currentLine.length > 0) {\\n const lastSpan = currentLine[currentLine.length - 1];\\n if (stylesMatch(lastSpan.style, wordSpans[0].style)) {\\n lastSpan.text += \\\" \\\";\\n } else {\\n currentLine.push({ text: \\\" \\\", style: wordSpans[0].style });\\n }\\n } else {\\n currentLine.push({ text: \\\" \\\", style: wordSpans[0].style });\\n }\\n currentLineWidth += wordWidth;\\n } else {\\n if (wordWidth > maxWidth) {\\n if (currentLine.length > 0) {\\n finishLine();\\n }\\n for (const span of wordSpans) {\\n const chars = Array.from(span.text);\\n let charBuffer = \\\"\\\";\\n for (const char of chars) {\\n const charWidth = measureText(char, span.style);\\n if (currentLineWidth + charWidth > maxWidth && currentLineWidth > 0) {\\n if (charBuffer.length > 0) {\\n if (currentLine.length > 0) {\\n const lastSpan = currentLine[currentLine.length - 1];\\n if (stylesMatch(lastSpan.style, span.style)) {\\n lastSpan.text += charBuffer;\\n } else {\\n currentLine.push({ text: charBuffer, style: span.style });\\n }\\n } else {\\n currentLine.push({ text: charBuffer, style: span.style });\\n }\\n charBuffer = \\\"\\\";\\n }\\n finishLine();\\n }\\n charBuffer += char;\\n currentLineWidth += charWidth;\\n }\\n if (charBuffer.length > 0) {\\n if (currentLine.length > 0) {\\n const lastSpan = currentLine[currentLine.length - 1];\\n if (stylesMatch(lastSpan.style, span.style)) {\\n lastSpan.text += charBuffer;\\n } else {\\n currentLine.push({ text: charBuffer, style: span.style });\\n }\\n } else {\\n currentLine.push({ text: charBuffer, style: span.style });\\n }\\n }\\n }\\n } else {\\n if (currentLineWidth + wordWidth > maxWidth && currentLine.length > 0) {\\n finishLine();\\n }\\n wordSpans.forEach((span) => {\\n if (currentLine.length > 0) {\\n const lastSpan = currentLine[currentLine.length - 1];\\n if (stylesMatch(lastSpan.style, span.style)) {\\n lastSpan.text += span.text;\\n } else {\\n currentLine.push({ ...span });\\n }\\n } else {\\n currentLine.push({ ...span });\\n }\\n });\\n currentLineWidth += wordWidth;\\n }\\n }\\n });\\n finishLine();\\n if (lines.length === 0) {\\n lines.push([]);\\n }\\n return lines;\\n }\\n function splitRichTextIntoLines(richText) {\\n const lines = [];\\n let currentLine = [];\\n richText.spans.forEach((span) => {\\n const parts = span.text.split(\\\"\\\\n\\\");\\n parts.forEach((part, i) => {\\n if (part.length > 0) {\\n currentLine.push({ text: part, style: span.style });\\n }\\n if (i < parts.length - 1) {\\n lines.push(currentLine);\\n currentLine = [];\\n }\\n });\\n });\\n if (currentLine.length > 0) {\\n lines.push(currentLine);\\n }\\n if (lines.length === 0) {\\n lines.push([]);\\n }\\n return lines;\\n }\\n function renderRichTextFillOnly(ctx, richText, element, maxWidth, lockedLineCount) {\\n ctx.fillStyle = element.color;\\n const textAlign = element.textAlign || \\\"center\\\";\\n const explicitLines = splitRichTextIntoLines(richText);\\n let lines;\\n let paragraphMetadata;\\n if (maxWidth !== void 0 && maxWidth > 0 && !lockedLineCount) {\\n lines = [];\\n paragraphMetadata = [];\\n explicitLines.forEach((lineSpans) => {\\n const wrappedLines = wrapRichTextSpans(lineSpans, maxWidth, element);\\n wrappedLines.forEach((wrappedLine, idx) => {\\n lines.push(wrappedLine);\\n paragraphMetadata.push({\\n isParagraphStart: idx === 0,\\n isParagraphEnd: idx === wrappedLines.length - 1\\n });\\n });\\n });\\n } else {\\n lines = explicitLines;\\n paragraphMetadata = explicitLines.map(() => ({\\n isParagraphStart: true,\\n isParagraphEnd: true\\n }));\\n }\\n const lineMetrics = [];\\n let maxLineHeight = 0;\\n lines.forEach((lineSpans, lineIndex) => {\\n let lineWidth = 0;\\n const spanWidths = [];\\n let lineHeight = 0;\\n let lineAscent = 0;\\n const isParagraphStart = paragraphMetadata[lineIndex].isParagraphStart;\\n const isParagraphEnd = paragraphMetadata[lineIndex].isParagraphEnd;\\n lineSpans.forEach((span) => {\\n const fontSize = span.style.fontSize !== void 0 ? span.style.fontSize : element.fontSize;\\n const fontFamily = span.style.fontFamily !== void 0 ? span.style.fontFamily : element.fontFamily;\\n const bold = span.style.bold !== void 0 ? span.style.bold : element.bold || false;\\n const italic = span.style.italic !== void 0 ? span.style.italic : element.italic || false;\\n ctx.font = buildFontString(fontSize, fontFamily, bold, italic);\\n const width = ctx.measureText(span.text).width;\\n spanWidths.push(width);\\n lineWidth += width;\\n const metrics = getFontMetrics2(fontSize, fontFamily, bold, italic);\\n lineHeight = Math.max(lineHeight, metrics.height);\\n lineAscent = Math.max(lineAscent, metrics.ascent);\\n });\\n const fullLineText = lineSpans.map((span) => span.text).join(\\\"\\\");\\n const leadingSpacesMatch = fullLineText.match(/^ +/);\\n const trailingSpacesMatch = fullLineText.match(/ +$/);\\n const leadingSpacesCount = leadingSpacesMatch ? leadingSpacesMatch[0].length : 0;\\n const trailingSpacesCount = trailingSpacesMatch ? trailingSpacesMatch[0].length : 0;\\n let adjustedLineWidth = 0;\\n let charIndexInLine = 0;\\n lineSpans.forEach((span) => {\\n const fontSize = span.style.fontSize !== void 0 ? span.style.fontSize : element.fontSize;\\n const fontFamily = span.style.fontFamily !== void 0 ? span.style.fontFamily : element.fontFamily;\\n const bold = span.style.bold !== void 0 ? span.style.bold : element.bold || false;\\n const italic = span.style.italic !== void 0 ? span.style.italic : element.italic || false;\\n let visibleText = span.text;\\n const spanStartIndex = charIndexInLine;\\n const spanEndIndex = charIndexInLine + span.text.length;\\n if (!isParagraphStart && leadingSpacesCount > 0 && spanStartIndex < leadingSpacesCount) {\\n const hiddenCharsInSpan = Math.min(leadingSpacesCount - spanStartIndex, span.text.length);\\n visibleText = visibleText.substring(hiddenCharsInSpan);\\n }\\n if (!isParagraphEnd && trailingSpacesCount > 0) {\\n const trailingSpaceStartIndex = fullLineText.length - trailingSpacesCount;\\n if (spanEndIndex > trailingSpaceStartIndex) {\\n const leadingTrimAmount = !isParagraphStart && leadingSpacesCount > 0 && spanStartIndex < leadingSpacesCount ? Math.min(leadingSpacesCount - spanStartIndex, span.text.length) : 0;\\n const visibleCharsInSpan = Math.max(0, trailingSpaceStartIndex - spanStartIndex - leadingTrimAmount);\\n visibleText = visibleText.substring(0, visibleCharsInSpan);\\n }\\n }\\n charIndexInLine += span.text.length;\\n if (visibleText.length > 0) {\\n ctx.save();\\n ctx.font = buildFontString(fontSize, fontFamily, bold, italic);\\n adjustedLineWidth += ctx.measureText(visibleText).width;\\n ctx.restore();\\n }\\n });\\n lineMetrics.push({\\n spans: lineSpans,\\n width: adjustedLineWidth,\\n // Use adjusted width for alignment (may be 0 for empty lines)\\n height: lineHeight,\\n ascent: lineAscent,\\n spanWidths,\\n isParagraphStart,\\n // Store metadata with line\\n isParagraphEnd\\n });\\n maxLineHeight = Math.max(maxLineHeight, lineHeight);\\n });\\n const elementFontMetrics = getFontMetrics2(element.fontSize, element.fontFamily, element.bold, element.italic);\\n const lineSpacing = element.fontSize * LINE_HEIGHT_MULTIPLIER;\\n let totalHeight;\\n if (lineMetrics.length === 0) {\\n totalHeight = 0;\\n } else if (lineMetrics.length === 1) {\\n totalHeight = elementFontMetrics.height;\\n } else {\\n totalHeight = (lineMetrics.length - 1) * lineSpacing + elementFontMetrics.height;\\n }\\n const topLeftY = -totalHeight / 2;\\n lineMetrics.forEach((lineData, lineIndex) => {\\n const { spans, width: lineWidth, isParagraphStart, isParagraphEnd } = lineData;\\n let currentX;\\n if (textAlign === \\\"center\\\") {\\n currentX = -lineWidth / 2;\\n } else if (textAlign === \\\"right\\\") {\\n currentX = maxWidth !== void 0 ? maxWidth / 2 - lineWidth : -lineWidth;\\n } else {\\n currentX = maxWidth !== void 0 ? -maxWidth / 2 : 0;\\n }\\n const baselineY = topLeftY + elementFontMetrics.ascent + lineIndex * lineSpacing;\\n const fullLineText = spans.map((s) => s.text).join(\\\"\\\");\\n const leadingSpacesMatch = fullLineText.match(/^ +/);\\n const trailingSpacesMatch = fullLineText.match(/ +$/);\\n const leadingSpacesCount = leadingSpacesMatch ? leadingSpacesMatch[0].length : 0;\\n const trailingSpacesCount = trailingSpacesMatch ? trailingSpacesMatch[0].length : 0;\\n let charIndexInLine = 0;\\n spans.forEach((span) => {\\n const fontSize = span.style.fontSize !== void 0 ? span.style.fontSize : element.fontSize;\\n const fontFamily = span.style.fontFamily !== void 0 ? span.style.fontFamily : element.fontFamily;\\n const color = span.style.color !== void 0 ? span.style.color : element.color;\\n const bold = span.style.bold !== void 0 ? span.style.bold : element.bold || false;\\n const italic = span.style.italic !== void 0 ? span.style.italic : element.italic || false;\\n const underline = span.style.underline !== void 0 ? span.style.underline : element.underline || false;\\n const strikethrough = span.style.strikethrough !== void 0 ? span.style.strikethrough : element.strikethrough || false;\\n let renderText = span.text;\\n let spanStartIndex = charIndexInLine;\\n let spanEndIndex = charIndexInLine + span.text.length;\\n if (!isParagraphStart && leadingSpacesCount > 0 && spanStartIndex < leadingSpacesCount) {\\n const hiddenCharsInSpan = Math.min(leadingSpacesCount - spanStartIndex, span.text.length);\\n renderText = renderText.substring(hiddenCharsInSpan);\\n }\\n if (!isParagraphEnd && trailingSpacesCount > 0) {\\n const trailingSpaceStartIndex = fullLineText.length - trailingSpacesCount;\\n if (spanEndIndex > trailingSpaceStartIndex) {\\n const leadingTrimAmount = !isParagraphStart && leadingSpacesCount > 0 && spanStartIndex < leadingSpacesCount ? Math.min(leadingSpacesCount - spanStartIndex, span.text.length) : 0;\\n const visibleCharsInSpan = Math.max(0, trailingSpaceStartIndex - spanStartIndex - leadingTrimAmount);\\n renderText = renderText.substring(0, visibleCharsInSpan);\\n }\\n }\\n charIndexInLine += span.text.length;\\n if (renderText.length > 0) {\\n ctx.font = buildFontString(fontSize, fontFamily, bold, italic);\\n ctx.fillStyle = color;\\n ctx.textBaseline = \\\"alphabetic\\\";\\n ctx.textAlign = \\\"left\\\";\\n ctx.fillText(renderText, currentX, baselineY);\\n const renderedWidth = ctx.measureText(renderText).width;\\n if (underline) {\\n const underlineY = baselineY + fontSize * 0.1;\\n ctx.beginPath();\\n ctx.moveTo(currentX, underlineY);\\n ctx.lineTo(currentX + renderedWidth, underlineY);\\n ctx.lineWidth = Math.max(1, fontSize * 0.05);\\n ctx.strokeStyle = color;\\n ctx.stroke();\\n }\\n if (strikethrough) {\\n const strikethroughY = baselineY - fontSize * 0.25;\\n ctx.beginPath();\\n ctx.moveTo(currentX, strikethroughY);\\n ctx.lineTo(currentX + renderedWidth, strikethroughY);\\n ctx.lineWidth = Math.max(1, fontSize * 0.05);\\n ctx.strokeStyle = color;\\n ctx.stroke();\\n }\\n currentX += renderedWidth;\\n }\\n });\\n });\\n }\\n var _measureCtx = null;\\n function getMeasureContext() {\\n if (!_measureCtx) {\\n if (typeof OffscreenCanvas !== \\\"undefined\\\") {\\n const canvas = new OffscreenCanvas(1, 1);\\n _measureCtx = canvas.getContext(\\\"2d\\\");\\n } else if (typeof document !== \\\"undefined\\\") {\\n const canvas = document.createElement(\\\"canvas\\\");\\n _measureCtx = canvas.getContext(\\\"2d\\\");\\n } else {\\n throw new Error(\\\"No canvas context available\\\");\\n }\\n }\\n return _measureCtx;\\n }\\n\\n // src/rendering/text-renderer.ts\\n var logger3 = createLogger(\\\"canvas-renderer\\\");\\n var _measureCtx2 = null;\\n function getMeasureContext2() {\\n if (!_measureCtx2) {\\n if (typeof OffscreenCanvas !== \\\"undefined\\\") {\\n const canvas = new OffscreenCanvas(1, 1);\\n _measureCtx2 = canvas.getContext(\\\"2d\\\");\\n } else if (typeof document !== \\\"undefined\\\") {\\n const canvas = document.createElement(\\\"canvas\\\");\\n _measureCtx2 = canvas.getContext(\\\"2d\\\");\\n } else {\\n throw new Error(\\\"No canvas context available\\\");\\n }\\n }\\n return _measureCtx2;\\n }\\n function buildFontString(fontSize, fontFamily, bold = false, italic = false) {\\n const parts = [];\\n if (italic) {\\n parts.push(\\\"italic\\\");\\n }\\n if (bold) {\\n parts.push(\\\"bold\\\");\\n }\\n parts.push(`${fontSize}px`);\\n parts.push(fontFamily);\\n return parts.join(\\\" \\\");\\n }\\n function getFontMetrics2(fontSize, fontFamily, bold = false, italic = false) {\\n const ctx = getMeasureContext2();\\n ctx.font = buildFontString(fontSize, fontFamily, bold, italic);\\n const sampleText = \\\"\\\\xC1\\\\xC9\\\\xCDgjpqy\\\";\\n const metrics = ctx.measureText(sampleText);\\n const ascent = metrics.actualBoundingBoxAscent || fontSize * 0.8;\\n const descent = metrics.actualBoundingBoxDescent || fontSize * 0.2;\\n const height = ascent + descent;\\n return { ascent, descent, height };\\n }\\n function renderTextFillOnly(ctx, element) {\\n const fontSize = element.fontSize;\\n const fontFamily = element.fontFamily;\\n const bold = element.bold || false;\\n const italic = element.italic || false;\\n const textAlign = element.textAlign || \\\"center\\\";\\n const text = element.text;\\n ctx.font = buildFontString(fontSize, fontFamily, bold, italic);\\n ctx.textAlign = textAlign;\\n ctx.textBaseline = \\\"alphabetic\\\";\\n ctx.fillStyle = element.color;\\n const fontMetrics = getFontMetrics2(fontSize, fontFamily, bold, italic);\\n const visualHeight = fontMetrics.height;\\n const topLeftY = -visualHeight / 2;\\n const yPos = topLeftY + fontMetrics.ascent;\\n ctx.fillText(text, 0, yPos);\\n }\\n function renderCustomTransform(ctx, elementData) {\\n renderCustomTransformNormal(ctx, elementData);\\n }\\n function renderCustomTransformNormal(ctx, elementData) {\\n if (elementData.stroke?.enabled) {\\n renderTextStroke(ctx, elementData);\\n }\\n ctx.save();\\n ctx.translate(elementData.x, elementData.y);\\n ctx.rotate(-elementData.rotation * Math.PI / 180);\\n const transformData = elementData.transformData;\\n const availableWidth = (transformData?.width ?? 100) - HORIZONTAL_PADDING * 2;\\n if (elementData.richText) {\\n const richText = RichText.fromJSON(elementData.richText);\\n ctx.save();\\n ctx.translate(0, 0);\\n const lockedLineCount = elementData._lockedLineCount;\\n renderRichTextFillOnly(\\n ctx,\\n richText,\\n {\\n fontSize: elementData.fontSize,\\n fontFamily: elementData.fontFamily,\\n color: elementData.color,\\n bold: elementData.bold,\\n italic: elementData.italic,\\n underline: elementData.underline,\\n strikethrough: elementData.strikethrough,\\n textAlign: elementData.textAlign\\n },\\n availableWidth,\\n lockedLineCount\\n );\\n ctx.restore();\\n } else {\\n if (elementData.text) {\\n ctx.fillStyle = elementData.color;\\n const lockedLineCount = elementData._lockedLineCount;\\n const { lines, height: visualHeight } = calculateVisualBoundsWithSpaceCollapsing(\\n elementData.text,\\n availableWidth,\\n elementData.fontSize,\\n elementData.fontFamily,\\n elementData.bold,\\n elementData.italic,\\n lockedLineCount,\\n true\\n // strict: true\\n );\\n const fontMetrics = getFontMetrics2(\\n elementData.fontSize,\\n elementData.fontFamily,\\n elementData.bold,\\n elementData.italic\\n );\\n const topLeftX = -(transformData?.width ?? 100) / 2;\\n const topLeftY = -visualHeight / 2;\\n const lineSpacing = elementData.fontSize * LINE_HEIGHT_MULTIPLIER;\\n ctx.font = `${elementData.italic ? \\\"italic \\\" : \\\"\\\"}${elementData.bold ? \\\"bold \\\" : \\\"\\\"}${elementData.fontSize}px ${elementData.fontFamily}`;\\n ctx.textBaseline = \\\"alphabetic\\\";\\n ctx.textAlign = elementData.textAlign;\\n lines.forEach((line, index) => {\\n const isParagraphStart = index === 0;\\n const isParagraphEnd = index === lines.length - 1;\\n let visibleText = line;\\n if (!isParagraphStart) {\\n const leadingSpacesMatch = line.match(/^ +/);\\n const leadingSpacesCount = leadingSpacesMatch ? leadingSpacesMatch[0].length : 0;\\n if (leadingSpacesCount > 0) {\\n visibleText = visibleText.substring(leadingSpacesCount);\\n }\\n }\\n if (!isParagraphEnd) {\\n const trailingSpacesMatch = visibleText.match(/ +$/);\\n const trailingSpacesCount = trailingSpacesMatch ? trailingSpacesMatch[0].length : 0;\\n if (trailingSpacesCount > 0) {\\n visibleText = visibleText.substring(0, visibleText.length - trailingSpacesCount);\\n }\\n }\\n let xPos = topLeftX + HORIZONTAL_PADDING;\\n if (elementData.textAlign === \\\"center\\\") {\\n xPos = topLeftX + (transformData?.width ?? 100) / 2;\\n } else if (elementData.textAlign === \\\"right\\\") {\\n xPos = topLeftX + (transformData?.width ?? 100) - HORIZONTAL_PADDING;\\n }\\n const yPos = topLeftY + fontMetrics.ascent + index * lineSpacing;\\n ctx.fillText(visibleText, xPos, yPos);\\n if (visibleText.length > 0) {\\n const lineWidth = ctx.measureText(visibleText).width;\\n let decorationX = xPos;\\n if (elementData.textAlign === \\\"center\\\") decorationX -= lineWidth / 2;\\n else if (elementData.textAlign === \\\"right\\\") decorationX -= lineWidth;\\n if (elementData.underline) {\\n const underlineY = yPos + elementData.fontSize * 0.1;\\n ctx.fillRect(decorationX, underlineY, lineWidth, Math.max(1, elementData.fontSize * 0.05));\\n }\\n if (elementData.strikethrough) {\\n const strikeY = yPos - fontMetrics.ascent * 0.4;\\n ctx.fillRect(decorationX, strikeY, lineWidth, Math.max(1, elementData.fontSize * 0.05));\\n }\\n }\\n });\\n }\\n }\\n ctx.restore();\\n }\\n function renderTextElement(ctx, elementData) {\\n const elementOpacity = elementData.opacity ?? 1;\\n const hasStroke = !!elementData.stroke?.enabled;\\n const isCustomTransform = elementData.type === \\\"custom\\\";\\n if (elementOpacity < 1 && hasStroke && isCustomTransform) {\\n renderTextElementWithOffscreen(ctx, elementData, elementOpacity);\\n return;\\n }\\n const previousAlpha = ctx.globalAlpha;\\n if (elementOpacity !== 1) {\\n ctx.globalAlpha = elementOpacity;\\n }\\n renderTextElementInner(ctx, elementData);\\n ctx.globalAlpha = previousAlpha;\\n }\\n function renderTextElementWithOffscreen(ctx, elementData, elementOpacity) {\\n const td = elementData.transformData;\\n const fontSize = elementData.fontSize || 24;\\n const strokeWidth = elementData.stroke?.width || 0;\\n const estWidth = (td?.width ?? fontSize * elementData.text.length * 0.7) + strokeWidth * 2 + 40;\\n const estHeight = fontSize * 3 + strokeWidth * 2 + 40;\\n const transform = ctx.getTransform();\\n const scale = Math.max(Math.abs(transform.a), Math.abs(transform.d), 1);\\n const offW = Math.ceil(estWidth * scale);\\n const offH = Math.ceil(estHeight * scale);\\n let offCanvas;\\n if (typeof OffscreenCanvas !== \\\"undefined\\\") {\\n offCanvas = new OffscreenCanvas(offW, offH);\\n } else {\\n offCanvas = document.createElement(\\\"canvas\\\");\\n offCanvas.width = offW;\\n offCanvas.height = offH;\\n }\\n const offCtx = offCanvas.getContext(\\\"2d\\\");\\n if (!offCtx) {\\n const prev = ctx.globalAlpha;\\n ctx.globalAlpha = elementOpacity;\\n renderTextElementInner(ctx, elementData);\\n ctx.globalAlpha = prev;\\n return;\\n }\\n const centerPixelX = transform.a * elementData.x + transform.e;\\n const centerPixelY = transform.d * elementData.y + transform.f;\\n offCtx.setTransform(\\n transform.a,\\n transform.b,\\n transform.c,\\n transform.d,\\n transform.e - centerPixelX + offW / 2,\\n transform.f - centerPixelY + offH / 2\\n );\\n renderTextElementInner(offCtx, elementData);\\n ctx.save();\\n ctx.setTransform(1, 0, 0, 1, 0, 0);\\n ctx.globalAlpha = elementOpacity;\\n ctx.drawImage(offCanvas, centerPixelX - offW / 2, centerPixelY - offH / 2);\\n ctx.restore();\\n }\\n function renderTextElementInner(ctx, elementData) {\\n switch (elementData.type) {\\n case \\\"custom\\\":\\n renderCustomTransform(ctx, elementData);\\n break;\\n case \\\"circle\\\":\\n renderCircleTransform(ctx, elementData);\\n break;\\n case \\\"wave\\\":\\n renderWaveTransform(ctx, elementData);\\n break;\\n case \\\"arch\\\":\\n renderArchTransform(ctx, elementData);\\n break;\\n case \\\"ascend\\\":\\n renderAscendTransform(ctx, elementData);\\n break;\\n case \\\"lean\\\":\\n renderLeanTransform(ctx, elementData);\\n break;\\n case \\\"flag\\\":\\n renderFlagTransform(ctx, elementData);\\n break;\\n default:\\n logger3.warn(`[canvas-renderer] Unsupported transform type: ${elementData.type}`);\\n renderCustomTransform(ctx, elementData);\\n }\\n }\\n\\n // src/rendering/image-renderer.ts\\n function renderImageElement(ctx, elementData, imageBitmap) {\\n ctx.save();\\n ctx.translate(elementData.x, elementData.y);\\n if (elementData.rotation) {\\n ctx.rotate(-elementData.rotation * Math.PI / 180);\\n }\\n let scaleX = 1;\\n let scaleY = 1;\\n if (elementData.flipHorizontal) scaleX = -1;\\n if (elementData.flipVertical) scaleY = -1;\\n if (scaleX !== 1 || scaleY !== 1) {\\n ctx.scale(scaleX, scaleY);\\n }\\n if (elementData.opacity !== void 0 && elementData.opacity !== 1) {\\n ctx.globalAlpha = elementData.opacity;\\n }\\n if (elementData.borderRadius && elementData.borderRadius > 0) {\\n const radius = Math.min(\\n elementData.borderRadius / 100 * Math.min(elementData.width, elementData.height),\\n elementData.width / 2,\\n elementData.height / 2\\n );\\n ctx.beginPath();\\n const x = -elementData.width / 2;\\n const y = -elementData.height / 2;\\n const w = elementData.width;\\n const h = elementData.height;\\n ctx.moveTo(x + radius, y);\\n ctx.lineTo(x + w - radius, y);\\n ctx.arcTo(x + w, y, x + w, y + radius, radius);\\n ctx.lineTo(x + w, y + h - radius);\\n ctx.arcTo(x + w, y + h, x + w - radius, y + h, radius);\\n ctx.lineTo(x + radius, y + h);\\n ctx.arcTo(x, y + h, x, y + h - radius, radius);\\n ctx.lineTo(x, y + radius);\\n ctx.arcTo(x, y, x + radius, y, radius);\\n ctx.closePath();\\n ctx.clip();\\n }\\n if (elementData.cropX !== void 0 && elementData.cropWidth !== void 0) {\\n ctx.drawImage(\\n imageBitmap,\\n elementData.cropX,\\n elementData.cropY || 0,\\n elementData.cropWidth,\\n elementData.cropHeight || imageBitmap.height,\\n -elementData.width / 2,\\n -elementData.height / 2,\\n elementData.width,\\n elementData.height\\n );\\n } else {\\n ctx.drawImage(imageBitmap, -elementData.width / 2, -elementData.height / 2, elementData.width, elementData.height);\\n }\\n ctx.restore();\\n if (elementData.stroke?.enabled) {\\n const hasKnockoutStroke = elementData.knockoutParts?.stroke === true;\\n const imageConfig = {\\n transformType: \\\"image\\\",\\n x: elementData.x,\\n y: elementData.y,\\n rotation: elementData.rotation,\\n stroke: elementData.stroke,\\n knockoutParts: elementData.knockoutParts,\\n transformData: {\\n type: \\\"image\\\",\\n width: elementData.width,\\n height: elementData.height,\\n borderRadius: elementData.borderRadius || 0\\n }\\n };\\n if (hasKnockoutStroke) {\\n const canvas = ctx.canvas;\\n let offscreen;\\n if (typeof OffscreenCanvas !== \\\"undefined\\\") {\\n offscreen = new OffscreenCanvas(canvas.width, canvas.height);\\n } else if (typeof document !== \\\"undefined\\\") {\\n offscreen = document.createElement(\\\"canvas\\\");\\n offscreen.width = canvas.width;\\n offscreen.height = canvas.height;\\n } else {\\n renderImageStroke(ctx, imageConfig);\\n return;\\n }\\n const offCtx = offscreen.getContext(\\\"2d\\\");\\n if (!offCtx) {\\n renderImageStroke(ctx, imageConfig);\\n return;\\n }\\n renderImageStroke(offCtx, imageConfig, { isKnockout: true });\\n ctx.save();\\n ctx.globalCompositeOperation = \\\"destination-out\\\";\\n ctx.drawImage(offscreen, 0, 0);\\n ctx.restore();\\n } else {\\n renderImageStroke(ctx, imageConfig);\\n }\\n }\\n }\\n\\n // src/rendering/shape-renderer.ts\\n function createTempCanvas(width, height) {\\n if (typeof OffscreenCanvas !== \\\"undefined\\\") {\\n return new OffscreenCanvas(width, height);\\n }\\n const canvas = document.createElement(\\\"canvas\\\");\\n canvas.width = width;\\n canvas.height = height;\\n return canvas;\\n }\\n function renderShapeElement(ctx, elementData) {\\n const elementOpacity = elementData.opacity ?? 1;\\n const hasStroke = !!elementData.stroke?.enabled;\\n const needsOffscreen = elementOpacity < 1 && hasStroke;\\n if (needsOffscreen) {\\n renderShapeWithOffscreen(ctx, elementData, elementOpacity);\\n } else {\\n renderShapeDirect(ctx, elementData, elementOpacity);\\n }\\n }\\n function renderShapeWithOffscreen(ctx, elementData, elementOpacity) {\\n const td = elementData.transformData;\\n const strokeWidth = elementData.stroke?.width || 2;\\n const padding = strokeWidth + 2;\\n const offW = Math.ceil(td.width + padding * 2);\\n const offH = Math.ceil(td.height + padding * 2);\\n const offCanvas = createTempCanvas(offW, offH);\\n const offCtx = offCanvas.getContext(\\\"2d\\\");\\n if (!offCtx) {\\n renderShapeDirect(ctx, elementData, elementOpacity);\\n return;\\n }\\n const tempData = {\\n ...elementData,\\n x: offW / 2,\\n y: offH / 2,\\n opacity: 1\\n };\\n renderShapeDirect(offCtx, tempData, 1);\\n ctx.save();\\n ctx.translate(elementData.x, elementData.y);\\n if (elementData.rotation) {\\n ctx.rotate(-elementData.rotation * Math.PI / 180);\\n }\\n ctx.globalAlpha = elementOpacity;\\n ctx.drawImage(offCanvas, -offW / 2, -offH / 2);\\n ctx.restore();\\n }\\n function renderShapeDirect(ctx, elementData, elementOpacity) {\\n const transformData = elementData.transformData;\\n const fillOpacity = transformData.fillOpacity ?? 1;\\n ctx.save();\\n ctx.translate(elementData.x, elementData.y);\\n if (elementData.rotation) {\\n ctx.rotate(-elementData.rotation * Math.PI / 180);\\n }\\n ctx.globalAlpha = elementOpacity * fillOpacity;\\n ctx.fillStyle = transformData.fillColor || \\\"#3b82f6\\\";\\n ctx.beginPath();\\n traceShapePath(ctx, transformData);\\n ctx.fill();\\n ctx.restore();\\n if (elementData.stroke?.enabled) {\\n ctx.save();\\n ctx.translate(elementData.x, elementData.y);\\n if (elementData.rotation) {\\n ctx.rotate(-elementData.rotation * Math.PI / 180);\\n }\\n const stroke = elementData.stroke;\\n ctx.globalAlpha = elementOpacity * (stroke.opacity ?? 1);\\n ctx.strokeStyle = stroke.color || \\\"#000000\\\";\\n ctx.lineWidth = stroke.width || 2;\\n ctx.lineCap = stroke.lineCap || \\\"round\\\";\\n ctx.lineJoin = stroke.lineJoin || \\\"round\\\";\\n ctx.beginPath();\\n traceShapePath(ctx, transformData);\\n ctx.stroke();\\n ctx.restore();\\n }\\n }\\n function traceShapePath(ctx, transformData) {\\n const { shapeType, width, height } = transformData;\\n switch (shapeType) {\\n case \\\"rectangle\\\": {\\n const borderRadius = transformData.borderRadius || 0;\\n const x = -width / 2;\\n const y = -height / 2;\\n if (borderRadius > 0) {\\n const radius = Math.min(borderRadius / 100 * Math.min(width, height), width / 2, height / 2);\\n ctx.roundRect(x, y, width, height, radius);\\n } else {\\n ctx.rect(x, y, width, height);\\n }\\n break;\\n }\\n case \\\"circle\\\": {\\n const radius = Math.min(width, height) / 2;\\n ctx.arc(0, 0, radius, 0, Math.PI * 2);\\n break;\\n }\\n case \\\"ellipse\\\": {\\n ctx.ellipse(0, 0, width / 2, height / 2, 0, 0, Math.PI * 2);\\n break;\\n }\\n case \\\"triangle\\\": {\\n const halfWidth = width / 2;\\n const halfHeight = height / 2;\\n ctx.moveTo(0, -halfHeight);\\n ctx.lineTo(halfWidth, halfHeight);\\n ctx.lineTo(-halfWidth, halfHeight);\\n ctx.closePath();\\n break;\\n }\\n case \\\"polygon\\\": {\\n const sides = transformData.sides || 5;\\n const radius = Math.min(width, height) / 2;\\n for (let i = 0; i < sides; i++) {\\n const angle = i * 2 * Math.PI / sides - Math.PI / 2;\\n const px = radius * Math.cos(angle);\\n const py = radius * Math.sin(angle);\\n if (i === 0) {\\n ctx.moveTo(px, py);\\n } else {\\n ctx.lineTo(px, py);\\n }\\n }\\n ctx.closePath();\\n break;\\n }\\n case \\\"star\\\": {\\n const points = transformData.points || 5;\\n const outerRadius = Math.min(width, height) / 2;\\n const innerRadius = outerRadius * (transformData.innerRadius || 0.4);\\n for (let i = 0; i < points * 2; i++) {\\n const angle = i * Math.PI / points - Math.PI / 2;\\n const r = i % 2 === 0 ? outerRadius : innerRadius;\\n const px = r * Math.cos(angle);\\n const py = r * Math.sin(angle);\\n if (i === 0) {\\n ctx.moveTo(px, py);\\n } else {\\n ctx.lineTo(px, py);\\n }\\n }\\n ctx.closePath();\\n break;\\n }\\n case \\\"line\\\": {\\n const halfWidth = width / 2;\\n const halfHeight = height / 2;\\n ctx.rect(-halfWidth, -halfHeight, width, height);\\n break;\\n }\\n default:\\n ctx.rect(-width / 2, -height / 2, width, height);\\n }\\n }\\n\\n // src/rendering/ElementRenderUtils.ts\\n function renderElement(ctx, element, options = {}) {\\n const mode = options.mode || \\\"both\\\";\\n ctx.save();\\n ctx.translate(element.x || 0, element.y || 0);\\n ctx.rotate(-(element.rotation || 0) * Math.PI / 180);\\n switch (element.transformType) {\\n case \\\"image\\\":\\n renderImageElement2(ctx, element, mode, options);\\n break;\\n case \\\"shape\\\":\\n renderShapeElement2(ctx, element, mode, options);\\n break;\\n case \\\"group\\\":\\n break;\\n default:\\n renderTextElement2(ctx, element, mode, options);\\n break;\\n }\\n ctx.restore();\\n }\\n function renderTextElement2(ctx, element, mode, options) {\\n const textElement = element;\\n const text = textElement.text || \\\"\\\";\\n if (!text) return;\\n if ((mode === \\\"stroke\\\" || mode === \\\"both\\\") && element.stroke?.enabled) {\\n ctx.save();\\n renderTextStroke(ctx, element, { ...options.renderingContext, positionApplied: true });\\n ctx.restore();\\n }\\n if (mode === \\\"fill\\\" || mode === \\\"both\\\") {\\n ctx.save();\\n renderTextFillOnly(ctx, {\\n text,\\n fontSize: textElement.fontSize || 24,\\n fontFamily: textElement.fontFamily || \\\"Arial\\\",\\n bold: textElement.bold || false,\\n italic: textElement.italic || false,\\n textAlign: textElement.textAlign || \\\"center\\\",\\n color: textElement.color || \\\"#000000\\\"\\n });\\n ctx.restore();\\n }\\n }\\n function renderImageElement2(ctx, element, mode, options) {\\n if (!element.transformData) return;\\n const transformData = element.transformData;\\n if (mode === \\\"fill\\\" || mode === \\\"both\\\") {\\n createImagePath2(ctx, element);\\n if (options.loadedImage) {\\n ctx.save();\\n ctx.clip();\\n const flipH = transformData.flipHorizontal ? -1 : 1;\\n const flipV = transformData.flipVertical ? -1 : 1;\\n ctx.scale(flipH, flipV);\\n const width = transformData.width ?? 100;\\n const height = transformData.height ?? 100;\\n ctx.drawImage(options.loadedImage, -width / 2, -height / 2, width, height);\\n ctx.restore();\\n } else {\\n ctx.fillStyle = \\\"#cccccc\\\";\\n ctx.fill();\\n }\\n }\\n if ((mode === \\\"stroke\\\" || mode === \\\"both\\\") && element.stroke?.enabled) {\\n ctx.save();\\n renderImageStroke(ctx, element, options.renderingContext);\\n ctx.restore();\\n }\\n }\\n function renderShapeElement2(ctx, element, mode, options) {\\n if (!element.transformData) return;\\n const transformData = element.transformData;\\n const isKnockoutRender = options.renderingContext?.isKnockout === true;\\n ctx.beginPath();\\n renderShapePath(ctx, transformData);\\n if (mode === \\\"fill\\\" || mode === \\\"both\\\") {\\n ctx.fillStyle = isKnockoutRender ? \\\"#000000\\\" : transformData.fillColor || \\\"#3b82f6\\\";\\n ctx.globalAlpha = isKnockoutRender ? 1 : transformData.fillOpacity ?? 1;\\n ctx.fill();\\n }\\n if ((mode === \\\"stroke\\\" || mode === \\\"both\\\") && element.stroke?.enabled) {\\n ctx.save();\\n renderShapeStroke(ctx, element, options.renderingContext);\\n ctx.restore();\\n }\\n }\\n function renderShapePath(ctx, transformData) {\\n const { shapeType } = transformData;\\n const width = transformData.width ?? 100;\\n const height = transformData.height ?? 100;\\n switch (shapeType) {\\n case \\\"rectangle\\\":\\n renderRectanglePath(ctx, transformData, width, height);\\n break;\\n case \\\"circle\\\":\\n renderCirclePath(ctx, Math.min(width, height) / 2);\\n break;\\n case \\\"ellipse\\\":\\n renderEllipsePath(ctx, width / 2, height / 2);\\n break;\\n case \\\"star\\\":\\n renderStarPath(ctx, transformData, Math.min(width, height) / 2);\\n break;\\n default:\\n renderRectanglePath(ctx, transformData, width, height);\\n }\\n }\\n function renderRectanglePath(ctx, transformData, width, height) {\\n const borderRadius = transformData.borderRadius || 0;\\n const x = -width / 2;\\n const y = -height / 2;\\n if (borderRadius > 0) {\\n const radius = Math.min(borderRadius / 100 * Math.min(width, height), width / 2, height / 2);\\n ctx.roundRect(x, y, width, height, radius);\\n } else {\\n ctx.rect(x, y, width, height);\\n }\\n }\\n function renderCirclePath(ctx, radius) {\\n ctx.arc(0, 0, radius, 0, Math.PI * 2);\\n }\\n function renderEllipsePath(ctx, radiusX, radiusY) {\\n ctx.ellipse(0, 0, radiusX, radiusY, 0, 0, Math.PI * 2);\\n }\\n function renderStarPath(ctx, transformData, outerRadius) {\\n const points = Math.max(3, Math.min(20, transformData.points || 5));\\n const innerRadiusRatio = Math.max(0.1, Math.min(0.9, transformData.innerRadius || 0.4));\\n const innerRadius = outerRadius * innerRadiusRatio;\\n const angleStep = Math.PI / points;\\n const startAngle = -Math.PI / 2;\\n for (let i = 0; i < points * 2; i++) {\\n const angle = startAngle + angleStep * i;\\n const radius = i % 2 === 0 ? outerRadius : innerRadius;\\n const x = Math.cos(angle) * radius;\\n const y = Math.sin(angle) * radius;\\n if (i === 0) {\\n ctx.moveTo(x, y);\\n } else {\\n ctx.lineTo(x, y);\\n }\\n }\\n ctx.closePath();\\n }\\n function renderShapeStroke(ctx, element, renderingContext) {\\n if (!element.stroke?.enabled || !element.transformData) return;\\n const isKnockoutRender = renderingContext?.isKnockout === true;\\n ctx.save();\\n if (isKnockoutRender) {\\n ctx.strokeStyle = \\\"#000000\\\";\\n ctx.lineWidth = element.stroke.width;\\n ctx.lineCap = element.stroke.lineCap || \\\"butt\\\";\\n ctx.lineJoin = element.stroke.lineJoin || \\\"miter\\\";\\n ctx.globalAlpha = 1;\\n } else {\\n ctx.strokeStyle = element.stroke.color;\\n ctx.lineWidth = element.stroke.width;\\n ctx.lineCap = element.stroke.lineCap || \\\"butt\\\";\\n ctx.lineJoin = element.stroke.lineJoin || \\\"miter\\\";\\n if (element.stroke.opacity !== void 0) {\\n ctx.globalAlpha = element.stroke.opacity;\\n }\\n }\\n if (element.stroke.miterLimit !== void 0) {\\n ctx.miterLimit = element.stroke.miterLimit;\\n }\\n if (element.stroke.dashArray && element.stroke.dashArray.length > 0) {\\n ctx.setLineDash(element.stroke.dashArray);\\n }\\n if (!isKnockoutRender && element.stroke.feather && element.stroke.feather > 0) {\\n if (\\\"filter\\\" in ctx) {\\n ctx.filter = `blur(${element.stroke.feather}px)`;\\n }\\n }\\n ctx.beginPath();\\n renderShapePath(ctx, element.transformData);\\n ctx.stroke();\\n ctx.restore();\\n }\\n function createImagePath2(ctx, element) {\\n if (!element.transformData) return;\\n const { borderRadius } = element.transformData;\\n const width = element.transformData.width ?? 100;\\n const height = element.transformData.height ?? 100;\\n const x = -width / 2;\\n const y = -height / 2;\\n ctx.beginPath();\\n if (borderRadius && borderRadius > 0) {\\n const radius = Math.min(borderRadius / 100 * Math.min(width, height), width / 2, height / 2);\\n ctx.roundRect(x, y, width, height, radius);\\n } else {\\n ctx.rect(x, y, width, height);\\n }\\n }\\n\\n // src/rendering/CompositingRenderer.ts\\n function renderWithCompositing(ctx, compositingElement, allElements, renderElementFn, artboardBackgroundColor, artboard, compositeOp = \\\"destination-out\\\") {\\n if (!compositingElement.knockoutParts) return;\\n const hasAnyParts = compositingElement.knockoutParts.fill || compositingElement.knockoutParts.stroke;\\n if (!hasAnyParts) {\\n renderElementFn(ctx, compositingElement);\\n return;\\n }\\n const savedTransform = ctx.getTransform();\\n ctx.save();\\n const scope = compositingElement.knockoutParts.scope || \\\"group\\\";\\n const affectedElements = getAffectedElements(compositingElement, scope, allElements);\\n if (affectedElements.length === 0 && scope === \\\"artboard\\\") {\\n renderNonCompositingParts(ctx, compositingElement, renderElementFn);\\n ctx.restore();\\n return;\\n }\\n if (affectedElements.length === 0) {\\n renderElementFn(ctx, compositingElement);\\n ctx.restore();\\n return;\\n }\\n const canvas = ctx.canvas;\\n const mainTransform = ctx.getTransform();\\n const dpr = mainTransform.a;\\n const offscreen = createOffscreenCanvas3(canvas.width, canvas.height);\\n const offCtx = offscreen.getContext(\\\"2d\\\");\\n if (!offCtx) return;\\n offCtx.scale(dpr, dpr);\\n if (artboardBackgroundColor && artboard) {\\n offCtx.fillStyle = artboardBackgroundColor;\\n offCtx.fillRect(artboard.x, artboard.y, artboard.width, artboard.height);\\n }\\n for (const element of affectedElements) {\\n renderElementFn(offCtx, element);\\n }\\n if (compositingElement.knockoutParts.fill && !compositingElement.knockoutParts.stroke && compositingElement.stroke?.enabled) {\\n offCtx.save();\\n renderElementStroke(offCtx, compositingElement);\\n offCtx.restore();\\n }\\n offCtx.save();\\n offCtx.globalCompositeOperation = compositeOp;\\n if (compositingElement.knockoutParts.fill) {\\n renderElementFill(offCtx, compositingElement, renderElementFn);\\n }\\n if (compositingElement.knockoutParts.stroke) {\\n renderElementStroke(offCtx, compositingElement);\\n }\\n offCtx.restore();\\n if (!compositingElement.knockoutParts.fill) {\\n offCtx.save();\\n renderElementFill(offCtx, compositingElement, renderElementFn);\\n offCtx.restore();\\n }\\n const logicalWidth = canvas.width / dpr;\\n const logicalHeight = canvas.height / dpr;\\n ctx.drawImage(offscreen, 0, 0, logicalWidth, logicalHeight);\\n ctx.restore();\\n const afterRestore = ctx.getTransform();\\n if (Math.abs(afterRestore.a - savedTransform.a) > 1e-3 || Math.abs(afterRestore.d - savedTransform.d) > 1e-3 || Math.abs(afterRestore.e - savedTransform.e) > 1e-3 || Math.abs(afterRestore.f - savedTransform.f) > 1e-3) {\\n ctx.setTransform(\\n savedTransform.a,\\n savedTransform.b,\\n savedTransform.c,\\n savedTransform.d,\\n savedTransform.e,\\n savedTransform.f\\n );\\n }\\n }\\n function getAffectedElements(knockoutElement, scope, allElements) {\\n if (scope === \\\"artboard\\\") {\\n return getAllElementsBelow(knockoutElement, allElements);\\n } else {\\n return getGroupSiblings(knockoutElement, allElements);\\n }\\n }\\n function getAllElementsBelow(knockoutElement, allElements) {\\n const knockoutIndex = allElements.findIndex((el) => el.id === knockoutElement.id);\\n if (knockoutIndex === -1) return [];\\n return allElements.slice(0, knockoutIndex);\\n }\\n function getGroupSiblings(knockoutElement, allElements) {\\n const parentGroup = findParentGroup(knockoutElement, allElements);\\n if (!parentGroup) {\\n return getAllElementsBelow(knockoutElement, allElements);\\n }\\n if (parentGroup.transformType !== \\\"group\\\" || !parentGroup.children) {\\n return [];\\n }\\n const knockoutIndex = parentGroup.children.findIndex((child) => child.id === knockoutElement.id);\\n if (knockoutIndex === -1) return [];\\n return parentGroup.children.slice(0, knockoutIndex);\\n }\\n function findParentGroup(element, allElements) {\\n for (const candidate of allElements) {\\n if (candidate.transformType === \\\"group\\\" && candidate.children) {\\n if (candidate.children.some((child) => child.id === element.id)) {\\n return candidate;\\n }\\n const nestedParent = findParentGroup(element, candidate.children);\\n if (nestedParent) {\\n return nestedParent;\\n }\\n }\\n }\\n return null;\\n }\\n function renderElementFill(ctx, element, _renderFn) {\\n renderElement(ctx, element, {\\n mode: \\\"fill\\\",\\n renderingContext: { isKnockout: true }\\n });\\n }\\n function renderElementStroke(ctx, element) {\\n if (!element.stroke?.enabled) return;\\n renderElement(ctx, element, {\\n mode: \\\"stroke\\\",\\n renderingContext: { isKnockout: true }\\n });\\n }\\n function renderNonCompositingParts(ctx, element, renderFn) {\\n const knockoutParts = element.knockoutParts;\\n if (!knockoutParts) {\\n renderFn(ctx, element);\\n return;\\n }\\n if (!knockoutParts.fill) {\\n ctx.save();\\n renderElementFill(ctx, element, renderFn);\\n ctx.restore();\\n }\\n if (!knockoutParts.stroke && element.stroke?.enabled) {\\n ctx.save();\\n renderElementStroke(ctx, element);\\n ctx.restore();\\n }\\n }\\n function createOffscreenCanvas3(width, height) {\\n if (typeof OffscreenCanvas !== \\\"undefined\\\") {\\n return new OffscreenCanvas(width, height);\\n } else if (typeof document !== \\\"undefined\\\") {\\n const canvas = document.createElement(\\\"canvas\\\");\\n canvas.width = width;\\n canvas.height = height;\\n return canvas;\\n }\\n throw new Error(\\\"No canvas context available\\\");\\n }\\n\\n // src/effects/DistressGenerator.ts\\n var SimplexNoise = class {\\n constructor(seed = Math.random()) {\\n this.perm = [];\\n for (let i = 0; i < 256; i++) {\\n this.perm[i] = i;\\n }\\n const random = this.seededRandom(seed);\\n for (let i = 255; i > 0; i--) {\\n const j = Math.floor(random() * (i + 1));\\n [this.perm[i], this.perm[j]] = [this.perm[j], this.perm[i]];\\n }\\n for (let i = 0; i < 256; i++) {\\n this.perm[256 + i] = this.perm[i];\\n }\\n }\\n seededRandom(seed) {\\n let x = Math.sin(seed++) * 1e4;\\n return () => {\\n x = Math.sin(seed++) * 1e4;\\n return x - Math.floor(x);\\n };\\n }\\n fade(t) {\\n return t * t * t * (t * (t * 6 - 15) + 10);\\n }\\n lerp(t, a, b) {\\n return a + t * (b - a);\\n }\\n grad(hash, x, y) {\\n const h = hash & 15;\\n const u = h < 8 ? x : y;\\n const v = h < 4 ? y : h === 12 || h === 14 ? x : 0;\\n return ((h & 1) === 0 ? u : -u) + ((h & 2) === 0 ? v : -v);\\n }\\n noise(x, y) {\\n const X = Math.floor(x) & 255;\\n const Y = Math.floor(y) & 255;\\n x -= Math.floor(x);\\n y -= Math.floor(y);\\n const u = this.fade(x);\\n const v = this.fade(y);\\n const a = this.perm[X] + Y;\\n const b = this.perm[X + 1] + Y;\\n return this.lerp(\\n v,\\n this.lerp(u, this.grad(this.perm[a], x, y), this.grad(this.perm[b], x - 1, y)),\\n this.lerp(u, this.grad(this.perm[a + 1], x, y - 1), this.grad(this.perm[b + 1], x - 1, y - 1))\\n );\\n }\\n };\\n function generateWornEffect(width, height, intensity, seed = Date.now()) {\\n const canvas = createCanvas(width, height);\\n const ctx = canvas.getContext(\\\"2d\\\");\\n const imageData = ctx.createImageData(width, height);\\n const data = imageData.data;\\n const noise = new SimplexNoise(seed);\\n const scale = 0.02;\\n const threshold = 1 - intensity / 100;\\n for (let y = 0; y < height; y++) {\\n for (let x = 0; x < width; x++) {\\n const idx = (y * width + x) * 4;\\n let value = 0;\\n value += noise.noise(x * scale, y * scale) * 0.5;\\n value += noise.noise(x * scale * 2, y * scale * 2) * 0.25;\\n value += noise.noise(x * scale * 4, y * scale * 4) * 0.125;\\n value = (value + 1) / 2;\\n const edgeX = Math.min(x / width, (width - x) / width) * 2;\\n const edgeY = Math.min(y / height, (height - y) / height) * 2;\\n const edgeFactor = Math.min(edgeX, edgeY);\\n value *= 0.7 + edgeFactor * 0.3;\\n const alpha = value > threshold ? 255 : 0;\\n data[idx] = 255;\\n data[idx + 1] = 255;\\n data[idx + 2] = 255;\\n data[idx + 3] = alpha;\\n }\\n }\\n return imageData;\\n }\\n function generateCrackedEffect(width, height, intensity, seed = Date.now()) {\\n const canvas = createCanvas(width, height);\\n const ctx = canvas.getContext(\\\"2d\\\");\\n ctx.clearRect(0, 0, width, height);\\n ctx.strokeStyle = \\\"#000000\\\";\\n ctx.lineWidth = 1 + intensity / 50;\\n ctx.lineCap = \\\"round\\\";\\n const random = seededRandom(seed);\\n const numCracks = Math.floor(intensity / 100 * 30 + 5);\\n for (let i = 0; i < numCracks; i++) {\\n const startX = random() * width;\\n const startY = random() * height;\\n drawCrackBranch(ctx, startX, startY, random() * Math.PI * 2, 50 + random() * 100, random, 0);\\n }\\n return ctx.getImageData(0, 0, width, height);\\n }\\n function drawCrackBranch(ctx, x, y, angle, length, random, depth) {\\n if (depth > 3 || length < 10) return;\\n const endX = x + Math.cos(angle) * length;\\n const endY = y + Math.sin(angle) * length;\\n ctx.beginPath();\\n ctx.moveTo(x, y);\\n ctx.lineTo(endX, endY);\\n ctx.stroke();\\n if (random() > 0.5) {\\n const branchAngle = angle + (random() - 0.5) * Math.PI / 2;\\n drawCrackBranch(ctx, endX, endY, branchAngle, length * 0.6, random, depth + 1);\\n }\\n if (random() > 0.7) {\\n const branchAngle = angle - (random() - 0.5) * Math.PI / 2;\\n drawCrackBranch(ctx, endX, endY, branchAngle, length * 0.6, random, depth + 1);\\n }\\n }\\n function generateGrungeEffect(width, height, intensity, seed = Date.now()) {\\n const canvas = createCanvas(width, height);\\n const ctx = canvas.getContext(\\\"2d\\\");\\n const imageData = ctx.createImageData(width, height);\\n const data = imageData.data;\\n const random = seededRandom(seed);\\n const density = intensity / 100 * 0.5;\\n for (let y = 0; y < height; y++) {\\n for (let x = 0; x < width; x++) {\\n const idx = (y * width + x) * 4;\\n const value = random();\\n const alpha = value < density ? 255 : 0;\\n data[idx] = 0;\\n data[idx + 1] = 0;\\n data[idx + 2] = 0;\\n data[idx + 3] = alpha;\\n }\\n }\\n return imageData;\\n }\\n function generateRetroEffect(width, height, intensity, seed = Date.now()) {\\n const canvas = createCanvas(width, height);\\n const ctx = canvas.getContext(\\\"2d\\\");\\n ctx.fillStyle = \\\"#000000\\\";\\n const random = seededRandom(seed);\\n const dotSize = 4 + intensity / 100 * 6;\\n const spacing = dotSize * 2;\\n for (let y = 0; y < height; y += spacing) {\\n for (let x = 0; x < width; x += spacing) {\\n if (random() < intensity / 100) {\\n const size = dotSize * (0.5 + random() * 0.5);\\n ctx.beginPath();\\n ctx.arc(x, y, size / 2, 0, Math.PI * 2);\\n ctx.fill();\\n }\\n }\\n }\\n return ctx.getImageData(0, 0, width, height);\\n }\\n function createCanvas(width, height) {\\n if (typeof OffscreenCanvas !== \\\"undefined\\\") {\\n return new OffscreenCanvas(width, height);\\n } else if (typeof document !== \\\"undefined\\\") {\\n const canvas = document.createElement(\\\"canvas\\\");\\n canvas.width = width;\\n canvas.height = height;\\n return canvas;\\n }\\n throw new Error(\\\"No canvas context available\\\");\\n }\\n function seededRandom(seed) {\\n let x = Math.sin(seed++) * 1e4;\\n return () => {\\n x = Math.sin(seed++) * 1e4;\\n return x - Math.floor(x);\\n };\\n }\\n\\n // src/effects/distress-textures.ts\\n var BUILTIN_SEED = 42;\\n var TEX_SIZE = 512;\\n var THUMB_SIZE = 64;\\n function toAlphaMask(imageData) {\\n const data = imageData.data;\\n for (let i = 0; i < data.length; i += 4) {\\n data[i] = 255;\\n data[i + 1] = 255;\\n data[i + 2] = 255;\\n }\\n return imageData;\\n }\\n function layerAlpha(a, b) {\\n const data = a.data;\\n const bData = b.data;\\n for (let i = 0; i < data.length; i += 4) {\\n data[i] = 255;\\n data[i + 1] = 255;\\n data[i + 2] = 255;\\n data[i + 3] = Math.min(255, data[i + 3] + bData[i + 3]);\\n }\\n return a;\\n }\\n var DISTRESS_TEXTURE_PRESETS = [\\n {\\n id: \\\"grunge-heavy\\\",\\n name: \\\"Heavy Grunge\\\",\\n textureUrl: \\\"builtin:grunge-heavy\\\",\\n thumbnailUrl: \\\"\\\",\\n description: \\\"Dense random splatters\\\",\\n generate: (w, h) => generateGrungeEffect(w, h, 80, BUILTIN_SEED)\\n },\\n {\\n id: \\\"grunge-fine\\\",\\n name: \\\"Fine Grunge\\\",\\n textureUrl: \\\"builtin:grunge-fine\\\",\\n thumbnailUrl: \\\"\\\",\\n description: \\\"Sparse fine grain\\\",\\n generate: (w, h) => generateGrungeEffect(w, h, 25, BUILTIN_SEED + 1)\\n },\\n {\\n id: \\\"concrete\\\",\\n name: \\\"Concrete\\\",\\n textureUrl: \\\"builtin:concrete\\\",\\n thumbnailUrl: \\\"\\\",\\n description: \\\"Rough surface via Perlin noise\\\",\\n generate: (w, h) => generateWornEffect(w, h, 55, BUILTIN_SEED + 2)\\n },\\n {\\n id: \\\"paper\\\",\\n name: \\\"Old Paper\\\",\\n textureUrl: \\\"builtin:paper\\\",\\n thumbnailUrl: \\\"\\\",\\n description: \\\"Subtle aging\\\",\\n generate: (w, h) => generateWornEffect(w, h, 20, BUILTIN_SEED + 3)\\n },\\n {\\n id: \\\"rust\\\",\\n name: \\\"Rust\\\",\\n textureUrl: \\\"builtin:rust\\\",\\n thumbnailUrl: \\\"\\\",\\n description: \\\"Noise + splatter combined\\\",\\n generate: (w, h) => {\\n const worn = generateWornEffect(w, h, 45, BUILTIN_SEED + 4);\\n const grunge = generateGrungeEffect(w, h, 35, BUILTIN_SEED + 5);\\n return layerAlpha(toAlphaMask(worn), toAlphaMask(grunge));\\n }\\n },\\n {\\n id: \\\"scratches\\\",\\n name: \\\"Scratches\\\",\\n textureUrl: \\\"builtin:scratches\\\",\\n thumbnailUrl: \\\"\\\",\\n description: \\\"Branching crack lines\\\",\\n generate: (w, h) => generateCrackedEffect(w, h, 55, BUILTIN_SEED + 6)\\n },\\n {\\n id: \\\"halftone\\\",\\n name: \\\"Halftone\\\",\\n textureUrl: \\\"builtin:halftone\\\",\\n thumbnailUrl: \\\"\\\",\\n description: \\\"Dot grid pattern\\\",\\n generate: (w, h) => generateRetroEffect(w, h, 55, BUILTIN_SEED + 7)\\n },\\n {\\n id: \\\"spray\\\",\\n name: \\\"Spray Paint\\\",\\n textureUrl: \\\"builtin:spray\\\",\\n thumbnailUrl: \\\"\\\",\\n description: \\\"Medium random splatter\\\",\\n generate: (w, h) => generateGrungeEffect(w, h, 55, BUILTIN_SEED + 8)\\n }\\n ];\\n var initialized = false;\\n function createCanvas2(width, height) {\\n if (typeof OffscreenCanvas !== \\\"undefined\\\") {\\n return new OffscreenCanvas(width, height);\\n }\\n const canvas = document.createElement(\\\"canvas\\\");\\n canvas.width = width;\\n canvas.height = height;\\n return canvas;\\n }\\n function createDOMCanvas(width, height) {\\n if (typeof document === \\\"undefined\\\") return null;\\n const canvas = document.createElement(\\\"canvas\\\");\\n canvas.width = width;\\n canvas.height = height;\\n return canvas;\\n }\\n function generateThumbnailDataUrl(imageData) {\\n const fullCanvas = createDOMCanvas(imageData.width, imageData.height);\\n if (!fullCanvas) return \\\"\\\";\\n const fullCtx = fullCanvas.getContext(\\\"2d\\\");\\n if (!fullCtx) return \\\"\\\";\\n fullCtx.putImageData(imageData, 0, 0);\\n const canvas = createDOMCanvas(THUMB_SIZE, THUMB_SIZE);\\n if (!canvas) return \\\"\\\";\\n const ctx = canvas.getContext(\\\"2d\\\");\\n if (!ctx) return \\\"\\\";\\n ctx.drawImage(fullCanvas, 0, 0, imageData.width, imageData.height, 0, 0, THUMB_SIZE, THUMB_SIZE);\\n const thumbData = ctx.getImageData(0, 0, THUMB_SIZE, THUMB_SIZE);\\n const pixels = thumbData.data;\\n for (let i = 0; i < pixels.length; i += 4) {\\n const a = pixels[i + 3];\\n const gray = 255 - Math.round(a / 255 * 195);\\n pixels[i] = gray;\\n pixels[i + 1] = gray;\\n pixels[i + 2] = gray;\\n pixels[i + 3] = 255;\\n }\\n ctx.putImageData(thumbData, 0, 0);\\n return canvas.toDataURL(\\\"image/png\\\");\\n }\\n function ensureBuiltinTexturesReady() {\\n if (initialized) return;\\n initialized = true;\\n for (const preset of DISTRESS_TEXTURE_PRESETS) {\\n const imageData = preset.generate(TEX_SIZE, TEX_SIZE);\\n toAlphaMask(imageData);\\n const maskCanvas = createCanvas2(TEX_SIZE, TEX_SIZE);\\n const maskCtx = maskCanvas.getContext(\\\"2d\\\");\\n if (maskCtx) {\\n maskCtx.putImageData(imageData, 0, 0);\\n registerAlphaMask(preset.textureUrl, maskCanvas, TEX_SIZE, TEX_SIZE);\\n }\\n if (typeof document !== \\\"undefined\\\") {\\n preset.thumbnailUrl = generateThumbnailDataUrl(imageData);\\n }\\n }\\n }\\n\\n // src/effects/DistressTextureCache.ts\\n var loadingUrls = /* @__PURE__ */ new Set();\\n var cache = /* @__PURE__ */ new Map();\\n var pendingCallbacks = /* @__PURE__ */ new Map();\\n function createCanvas3(width, height) {\\n if (typeof OffscreenCanvas !== \\\"undefined\\\") {\\n return new OffscreenCanvas(width, height);\\n }\\n const canvas = document.createElement(\\\"canvas\\\");\\n canvas.width = width;\\n canvas.height = height;\\n return canvas;\\n }\\n function getContext(canvas) {\\n return canvas.getContext(\\\"2d\\\");\\n }\\n function convertToAlphaMask(source) {\\n const { width, height } = source;\\n const tempCanvas = createCanvas3(width, height);\\n const tempCtx = getContext(tempCanvas);\\n if (!tempCtx) throw new Error(\\\"Failed to get 2d context for temp canvas\\\");\\n tempCtx.drawImage(source, 0, 0);\\n const imageData = tempCtx.getImageData(0, 0, width, height);\\n const data = imageData.data;\\n for (let i = 0; i < data.length; i += 4) {\\n const r = data[i];\\n const g = data[i + 1];\\n const b = data[i + 2];\\n const luma = 0.299 * r + 0.587 * g + 0.114 * b;\\n const alpha = 255 - luma;\\n data[i] = 255;\\n data[i + 1] = 255;\\n data[i + 2] = 255;\\n data[i + 3] = alpha;\\n }\\n const maskCanvas = createCanvas3(width, height);\\n const maskCtx = getContext(maskCanvas);\\n if (!maskCtx) throw new Error(\\\"Failed to get 2d context for mask canvas\\\");\\n maskCtx.putImageData(imageData, 0, 0);\\n return { alphaMask: maskCanvas, width, height };\\n }\\n function getAlphaMask(url) {\\n const cached = cache.get(url);\\n if (cached) return cached;\\n if (url.startsWith(\\\"builtin:\\\")) {\\n ensureBuiltinTexturesReady();\\n const post = cache.get(url);\\n if (post) return post;\\n return null;\\n }\\n if (loadingUrls.has(url)) return null;\\n loadingUrls.add(url);\\n loadTexture(url);\\n return null;\\n }\\n function preloadTexture(url) {\\n if (cache.has(url)) return Promise.resolve();\\n return new Promise((resolve) => {\\n if (cache.has(url)) {\\n resolve();\\n return;\\n }\\n const callbacks = pendingCallbacks.get(url) || [];\\n callbacks.push(resolve);\\n pendingCallbacks.set(url, callbacks);\\n if (!loadingUrls.has(url)) {\\n loadingUrls.add(url);\\n loadTexture(url);\\n }\\n });\\n }\\n function registerAlphaMask(key, canvas, width, height) {\\n if (cache.has(key)) return;\\n cache.set(key, { alphaMask: canvas, width, height });\\n notifyPending(key);\\n }\\n function notifyPending(url) {\\n const callbacks = pendingCallbacks.get(url);\\n if (callbacks) {\\n callbacks.forEach((cb) => cb());\\n pendingCallbacks.delete(url);\\n }\\n }\\n function loadTexture(url) {\\n if (typeof document !== \\\"undefined\\\") {\\n const img = new Image();\\n img.crossOrigin = \\\"anonymous\\\";\\n img.onload = () => {\\n const entry = convertToAlphaMask(img);\\n cache.set(url, entry);\\n loadingUrls.delete(url);\\n notifyPending(url);\\n };\\n img.onerror = () => {\\n loadingUrls.delete(url);\\n notifyPending(url);\\n };\\n img.src = url;\\n } else {\\n fetch(url).then((res) => res.blob()).then((blob) => createImageBitmap(blob)).then((bitmap) => {\\n const entry = convertToAlphaMask(bitmap);\\n cache.set(url, entry);\\n loadingUrls.delete(url);\\n notifyPending(url);\\n }).catch(() => {\\n loadingUrls.delete(url);\\n notifyPending(url);\\n });\\n }\\n }\\n\\n // src/rendering/DistressTextureRenderer.ts\\n function createOffscreenCanvas4(width, height) {\\n if (typeof OffscreenCanvas !== \\\"undefined\\\") {\\n return new OffscreenCanvas(width, height);\\n }\\n const canvas = document.createElement(\\\"canvas\\\");\\n canvas.width = width;\\n canvas.height = height;\\n return canvas;\\n }\\n function applyArtboardDistressTexture(ctx, config, artboard, artboardBackgroundColor) {\\n if (!config.enabled || !config.textureUrl || config.intensity <= 0) return;\\n const mask = getAlphaMask(config.textureUrl);\\n if (!mask) return;\\n const { x, y, width, height } = artboard;\\n const transform = ctx.getTransform();\\n const pixelX = transform.a * x + transform.e;\\n const pixelY = transform.d * y + transform.f;\\n const pixelWidth = transform.a * width;\\n const pixelHeight = transform.d * height;\\n const offWidth = Math.ceil(pixelWidth);\\n const offHeight = Math.ceil(pixelHeight);\\n if (offWidth <= 0 || offHeight <= 0) return;\\n const offCanvas = createOffscreenCanvas4(offWidth, offHeight);\\n const offCtx = offCanvas.getContext(\\\"2d\\\");\\n if (!offCtx) return;\\n offCtx.drawImage(\\n ctx.canvas,\\n pixelX,\\n pixelY,\\n pixelWidth,\\n pixelHeight,\\n 0,\\n 0,\\n offWidth,\\n offHeight\\n );\\n const artMaskCtx = mask.alphaMask.getContext(\\\"2d\\\");\\n if (artMaskCtx) {\\n const artIntensity = config.intensity / 100;\\n const mData = artMaskCtx.getImageData(0, 0, mask.width, mask.height).data;\\n const mW = mask.width;\\n const mH = mask.height;\\n const content = offCtx.getImageData(0, 0, offWidth, offHeight);\\n const cData = content.data;\\n for (let y2 = 0; y2 < offHeight; y2++) {\\n const my = Math.floor(y2 / offHeight * mH);\\n for (let x2 = 0; x2 < offWidth; x2++) {\\n const mx = Math.floor(x2 / offWidth * mW);\\n const maskAlpha = mData[(my * mW + mx) * 4 + 3] / 255;\\n const ci = (y2 * offWidth + x2) * 4;\\n cData[ci + 3] = Math.round(cData[ci + 3] * (1 - maskAlpha * artIntensity));\\n }\\n }\\n offCtx.putImageData(content, 0, 0);\\n } else {\\n offCtx.globalCompositeOperation = \\\"destination-out\\\";\\n offCtx.globalAlpha = config.intensity / 100;\\n offCtx.drawImage(mask.alphaMask, 0, 0, offWidth, offHeight);\\n offCtx.globalCompositeOperation = \\\"source-over\\\";\\n }\\n offCtx.globalAlpha = 1;\\n ctx.save();\\n ctx.setTransform(1, 0, 0, 1, 0, 0);\\n ctx.clearRect(pixelX, pixelY, pixelWidth, pixelHeight);\\n if (artboardBackgroundColor) {\\n ctx.fillStyle = artboardBackgroundColor;\\n ctx.fillRect(pixelX, pixelY, pixelWidth, pixelHeight);\\n }\\n ctx.drawImage(offCanvas, pixelX, pixelY);\\n ctx.restore();\\n }\\n function applyElementDistressTexture(ctx, distress, elementBounds, renderFn) {\\n if (!distress.enabled || distress.style !== \\\"custom\\\" || !distress.textureUrl) return;\\n const mask = getAlphaMask(distress.textureUrl);\\n if (!mask) {\\n renderFn(ctx);\\n return;\\n }\\n const intensity = distress.textureOpacity ?? distress.intensity / 100;\\n const transform = ctx.getTransform();\\n const diagonal = Math.sqrt(elementBounds.width ** 2 + elementBounds.height ** 2);\\n const extraW = (diagonal - elementBounds.width) / 2;\\n const extraH = (diagonal - elementBounds.height) / 2;\\n const strokePad = 20;\\n const padX = extraW + strokePad;\\n const padY = extraH + strokePad;\\n const paddedBounds = {\\n x: elementBounds.x - padX,\\n y: elementBounds.y - padY,\\n width: elementBounds.width + padX * 2,\\n height: elementBounds.height + padY * 2\\n };\\n const pixelX = transform.a * paddedBounds.x + transform.e;\\n const pixelY = transform.d * paddedBounds.y + transform.f;\\n const pixelWidth = transform.a * paddedBounds.width;\\n const pixelHeight = transform.d * paddedBounds.height;\\n const offWidth = Math.ceil(pixelWidth);\\n const offHeight = Math.ceil(pixelHeight);\\n if (offWidth <= 0 || offHeight <= 0) {\\n renderFn(ctx);\\n return;\\n }\\n const offCanvas = createOffscreenCanvas4(offWidth, offHeight);\\n const offCtx = offCanvas.getContext(\\\"2d\\\");\\n if (!offCtx) {\\n renderFn(ctx);\\n return;\\n }\\n offCtx.setTransform(\\n transform.a,\\n transform.b,\\n transform.c,\\n transform.d,\\n transform.e - pixelX,\\n transform.f - pixelY\\n );\\n renderFn(offCtx);\\n offCtx.setTransform(1, 0, 0, 1, 0, 0);\\n const maskCtx = mask.alphaMask.getContext(\\\"2d\\\");\\n if (maskCtx) {\\n const mData = maskCtx.getImageData(0, 0, mask.width, mask.height).data;\\n const mW = mask.width;\\n const mH = mask.height;\\n const content = offCtx.getImageData(0, 0, offWidth, offHeight);\\n const cData = content.data;\\n for (let y = 0; y < offHeight; y++) {\\n const my = Math.floor(y / offHeight * mH);\\n for (let x = 0; x < offWidth; x++) {\\n const mx = Math.floor(x / offWidth * mW);\\n const maskAlpha = mData[(my * mW + mx) * 4 + 3] / 255;\\n const ci = (y * offWidth + x) * 4;\\n cData[ci + 3] = Math.round(cData[ci + 3] * (1 - maskAlpha * intensity));\\n }\\n }\\n offCtx.putImageData(content, 0, 0);\\n } else {\\n offCtx.globalCompositeOperation = \\\"destination-out\\\";\\n offCtx.globalAlpha = intensity;\\n offCtx.drawImage(mask.alphaMask, 0, 0, offWidth, offHeight);\\n offCtx.globalCompositeOperation = \\\"source-over\\\";\\n offCtx.globalAlpha = 1;\\n }\\n ctx.save();\\n ctx.setTransform(1, 0, 0, 1, 0, 0);\\n ctx.drawImage(offCanvas, pixelX, pixelY);\\n ctx.restore();\\n }\\n\\n // src/core/ImageCache.ts\\n var ImageCache = class _ImageCache {\\n constructor() {\\n this.cache = /* @__PURE__ */ new Map();\\n }\\n /**\\n * Get the singleton ImageCache instance.\\n */\\n static getInstance() {\\n if (!_ImageCache.instance) {\\n _ImageCache.instance = new _ImageCache();\\n }\\n return _ImageCache.instance;\\n }\\n /**\\n * Acquire an HTMLImageElement for the given URL.\\n * If the URL is already cached, increments the reference count and returns the existing element.\\n * If not cached, creates a new HTMLImageElement, starts loading, and caches it.\\n *\\n * @param url - The image URL to load\\n * @returns The cached or newly created HTMLImageElement\\n */\\n acquire(url) {\\n const existing = this.cache.get(url);\\n if (existing) {\\n existing.refCount++;\\n return existing.image;\\n }\\n const img = new Image();\\n img.crossOrigin = \\\"anonymous\\\";\\n const entry = {\\n image: img,\\n refCount: 1,\\n loaded: false\\n };\\n img.onload = () => {\\n entry.loaded = true;\\n };\\n img.onerror = () => {\\n entry.loaded = true;\\n };\\n this.cache.set(url, entry);\\n if (!url.includes(\\\":\\\") || /^https?:\\\\/\\\\/|^data:|^blob:/.test(url)) {\\n img.src = url;\\n }\\n return img;\\n }\\n /**\\n * Release a reference to a cached image.\\n * When the reference count reaches zero, the entry is evicted from the cache.\\n *\\n * @param url - The image URL to release\\n */\\n release(url) {\\n const entry = this.cache.get(url);\\n if (!entry) return;\\n entry.refCount--;\\n if (entry.refCount <= 0) {\\n this.cache.delete(url);\\n }\\n }\\n /**\\n * Get a cached HTMLImageElement without incrementing the reference count.\\n * Returns undefined if the URL is not in the cache.\\n *\\n * @param url - The image URL to look up\\n */\\n get(url) {\\n return this.cache.get(url)?.image;\\n }\\n /**\\n * Check if a URL is in the cache.\\n *\\n * @param url - The image URL to check\\n */\\n has(url) {\\n return this.cache.has(url);\\n }\\n /**\\n * Get cache statistics.\\n *\\n * @returns Object with entry count and total reference count across all entries\\n */\\n getStats() {\\n let totalRefs = 0;\\n for (const entry of this.cache.values()) {\\n totalRefs += entry.refCount;\\n }\\n return { entries: this.cache.size, totalRefs };\\n }\\n /**\\n * Clear the entire cache.\\n * Primarily for testing -- removes all entries regardless of reference count.\\n */\\n clear() {\\n this.cache.clear();\\n }\\n };\\n\\n // src/rendering/mask-utils.ts\\n function computeMaskCoverDimensions(parentW, parentH, maskNaturalW, maskNaturalH, oversize = 0) {\\n if (maskNaturalW <= 0 || maskNaturalH <= 0 || parentW <= 0 || parentH <= 0) {\\n return { width: parentW + oversize, height: parentH + oversize };\\n }\\n const maskAspect = maskNaturalW / maskNaturalH;\\n const parentAspect = parentW / parentH;\\n let fitW;\\n let fitH;\\n if (parentAspect > maskAspect) {\\n fitH = parentH;\\n fitW = parentH * maskAspect;\\n } else {\\n fitW = parentW;\\n fitH = parentW / maskAspect;\\n }\\n return {\\n width: fitW + oversize,\\n height: fitH + oversize\\n };\\n }\\n\\n // src/effects/mask-presets.ts\\n var THUMB_SIZE2 = 64;\\n var MASK_SIZE = 512;\\n function drawCircle(ctx, size) {\\n ctx.beginPath();\\n ctx.arc(size / 2, size / 2, size * 0.45, 0, Math.PI * 2);\\n ctx.fill();\\n }\\n function drawStar(ctx, size) {\\n const cx = size / 2, cy = size / 2;\\n const outerR = size * 0.45, innerR = outerR * 0.4;\\n const points = 5;\\n ctx.beginPath();\\n for (let i = 0; i < points * 2; i++) {\\n const angle = -Math.PI / 2 + Math.PI / points * i;\\n const r = i % 2 === 0 ? outerR : innerR;\\n const x = cx + Math.cos(angle) * r;\\n const y = cy + Math.sin(angle) * r;\\n if (i === 0) ctx.moveTo(x, y);\\n else ctx.lineTo(x, y);\\n }\\n ctx.closePath();\\n ctx.fill();\\n }\\n function drawHeart(ctx, size) {\\n const cx = size / 2, s = size * 0.42;\\n ctx.beginPath();\\n ctx.moveTo(cx, size * 0.82);\\n ctx.bezierCurveTo(cx - s * 1.1, size * 0.6, cx - s * 1.3, size * 0.2, cx, size * 0.35);\\n ctx.bezierCurveTo(cx + s * 1.3, size * 0.2, cx + s * 1.1, size * 0.6, cx, size * 0.82);\\n ctx.closePath();\\n ctx.fill();\\n }\\n function drawDiamond(ctx, size) {\\n const cx = size / 2, cy = size / 2;\\n const rx = size * 0.4, ry = size * 0.48;\\n ctx.beginPath();\\n ctx.moveTo(cx, cy - ry);\\n ctx.lineTo(cx + rx, cy);\\n ctx.lineTo(cx, cy + ry);\\n ctx.lineTo(cx - rx, cy);\\n ctx.closePath();\\n ctx.fill();\\n }\\n function drawHexagon(ctx, size) {\\n const cx = size / 2, cy = size / 2, r = size * 0.44;\\n ctx.beginPath();\\n for (let i = 0; i < 6; i++) {\\n const angle = -Math.PI / 2 + Math.PI / 3 * i;\\n const x = cx + Math.cos(angle) * r;\\n const y = cy + Math.sin(angle) * r;\\n if (i === 0) ctx.moveTo(x, y);\\n else ctx.lineTo(x, y);\\n }\\n ctx.closePath();\\n ctx.fill();\\n }\\n function drawShield(ctx, size) {\\n const cx = size / 2, w = size * 0.4, top = size * 0.12;\\n ctx.beginPath();\\n ctx.moveTo(cx, top);\\n ctx.lineTo(cx + w, size * 0.25);\\n ctx.lineTo(cx + w, size * 0.55);\\n ctx.quadraticCurveTo(cx + w * 0.3, size * 0.8, cx, size * 0.9);\\n ctx.quadraticCurveTo(cx - w * 0.3, size * 0.8, cx - w, size * 0.55);\\n ctx.lineTo(cx - w, size * 0.25);\\n ctx.closePath();\\n ctx.fill();\\n }\\n function drawSplatter(ctx, size) {\\n const cx = size / 2, cy = size / 2;\\n let seed = 42;\\n const rand = () => {\\n seed = (seed * 16807 + 0) % 2147483647;\\n return seed / 2147483647;\\n };\\n ctx.beginPath();\\n ctx.arc(cx, cy, size * 0.28, 0, Math.PI * 2);\\n ctx.fill();\\n for (let i = 0; i < 30; i++) {\\n const angle = rand() * Math.PI * 2;\\n const dist = size * 0.15 + rand() * size * 0.3;\\n const r = size * 0.02 + rand() * size * 0.06;\\n ctx.beginPath();\\n ctx.arc(cx + Math.cos(angle) * dist, cy + Math.sin(angle) * dist, r, 0, Math.PI * 2);\\n ctx.fill();\\n }\\n }\\n function drawTornEdge(ctx, size) {\\n let seed = 123;\\n const rand = () => {\\n seed = (seed * 16807 + 0) % 2147483647;\\n return seed / 2147483647;\\n };\\n const margin = size * 0.08;\\n const steps = 40;\\n ctx.beginPath();\\n ctx.moveTo(margin, margin);\\n for (let i = 1; i <= steps; i++) {\\n const x = margin + (size - 2 * margin) * (i / steps);\\n const y = margin + (rand() - 0.5) * size * 0.08;\\n ctx.lineTo(x, y);\\n }\\n for (let i = 1; i <= steps; i++) {\\n const x = size - margin + (rand() - 0.5) * size * 0.08;\\n const y = margin + (size - 2 * margin) * (i / steps);\\n ctx.lineTo(x, y);\\n }\\n for (let i = steps; i >= 0; i--) {\\n const x = margin + (size - 2 * margin) * (i / steps);\\n const y = size - margin + (rand() - 0.5) * size * 0.08;\\n ctx.lineTo(x, y);\\n }\\n for (let i = steps; i >= 0; i--) {\\n const x = margin + (rand() - 0.5) * size * 0.08;\\n const y = margin + (size - 2 * margin) * (i / steps);\\n ctx.lineTo(x, y);\\n }\\n ctx.closePath();\\n ctx.fill();\\n }\\n function drawPaintStroke(ctx, size) {\\n let seed = 77;\\n const rand = () => {\\n seed = (seed * 16807 + 0) % 2147483647;\\n return seed / 2147483647;\\n };\\n const y0 = size * 0.25, y1 = size * 0.75;\\n const margin = size * 0.1;\\n ctx.beginPath();\\n ctx.moveTo(margin, y0 + rand() * size * 0.05);\\n for (let i = 1; i <= 10; i++) {\\n const x = margin + (size - 2 * margin) * (i / 10);\\n const y = y0 + (rand() - 0.5) * size * 0.1;\\n ctx.lineTo(x, y);\\n }\\n for (let i = 10; i >= 0; i--) {\\n const x = margin + (size - 2 * margin) * (i / 10);\\n const y = y1 + (rand() - 0.5) * size * 0.1;\\n ctx.lineTo(x, y);\\n }\\n ctx.closePath();\\n ctx.fill();\\n }\\n function drawCloud(ctx, size) {\\n const cx = size / 2, cy = size * 0.55;\\n ctx.beginPath();\\n ctx.arc(cx, cy, size * 0.2, 0, Math.PI * 2);\\n ctx.fill();\\n ctx.beginPath();\\n ctx.arc(cx - size * 0.18, cy + size * 0.02, size * 0.15, 0, Math.PI * 2);\\n ctx.fill();\\n ctx.beginPath();\\n ctx.arc(cx + size * 0.18, cy + size * 0.02, size * 0.16, 0, Math.PI * 2);\\n ctx.fill();\\n ctx.beginPath();\\n ctx.arc(cx - size * 0.06, cy - size * 0.14, size * 0.14, 0, Math.PI * 2);\\n ctx.fill();\\n ctx.beginPath();\\n ctx.arc(cx + size * 0.1, cy - size * 0.12, size * 0.12, 0, Math.PI * 2);\\n ctx.fill();\\n }\\n var MASK_IMAGE_PRESETS = [\\n // Geometric\\n { id: \\\"circle\\\", name: \\\"Circle\\\", description: \\\"Perfect circle\\\", imageUrl: \\\"builtin-mask:circle\\\", thumbnailUrl: \\\"\\\", category: \\\"geometric\\\", draw: drawCircle },\\n { id: \\\"star\\\", name: \\\"Star\\\", description: \\\"5-pointed star\\\", imageUrl: \\\"builtin-mask:star\\\", thumbnailUrl: \\\"\\\", category: \\\"geometric\\\", draw: drawStar },\\n { id: \\\"heart\\\", name: \\\"Heart\\\", description: \\\"Heart shape\\\", imageUrl: \\\"builtin-mask:heart\\\", thumbnailUrl: \\\"\\\", category: \\\"geometric\\\", draw: drawHeart },\\n { id: \\\"diamond\\\", name: \\\"Diamond\\\", description: \\\"Diamond/rhombus\\\", imageUrl: \\\"builtin-mask:diamond\\\", thumbnailUrl: \\\"\\\", category: \\\"geometric\\\", draw: drawDiamond },\\n { id: \\\"hexagon\\\", name: \\\"Hexagon\\\", description: \\\"Regular hexagon\\\", imageUrl: \\\"builtin-mask:hexagon\\\", thumbnailUrl: \\\"\\\", category: \\\"geometric\\\", draw: drawHexagon },\\n { id: \\\"shield\\\", name: \\\"Shield\\\", description: \\\"Shield/crest shape\\\", imageUrl: \\\"builtin-mask:shield\\\", thumbnailUrl: \\\"\\\", category: \\\"geometric\\\", draw: drawShield },\\n // Organic\\n { id: \\\"splatter\\\", name: \\\"Splatter\\\", description: \\\"Ink splatter\\\", imageUrl: \\\"builtin-mask:splatter\\\", thumbnailUrl: \\\"\\\", category: \\\"organic\\\", draw: drawSplatter },\\n { id: \\\"torn-edge\\\", name: \\\"Torn Edge\\\", description: \\\"Rough torn paper edge\\\", imageUrl: \\\"builtin-mask:torn-edge\\\", thumbnailUrl: \\\"\\\", category: \\\"organic\\\", draw: drawTornEdge },\\n { id: \\\"paint-stroke\\\", name: \\\"Paint Stroke\\\", description: \\\"Horizontal brush stroke\\\", imageUrl: \\\"builtin-mask:paint-stroke\\\", thumbnailUrl: \\\"\\\", category: \\\"organic\\\", draw: drawPaintStroke },\\n { id: \\\"cloud\\\", name: \\\"Cloud\\\", description: \\\"Soft cloud shape\\\", imageUrl: \\\"builtin-mask:cloud\\\", thumbnailUrl: \\\"\\\", category: \\\"organic\\\", draw: drawCloud }\\n ];\\n var initialized2 = false;\\n function createDOMCanvas2(width, height) {\\n if (typeof document === \\\"undefined\\\") return null;\\n const canvas = document.createElement(\\\"canvas\\\");\\n canvas.width = width;\\n canvas.height = height;\\n return canvas;\\n }\\n function ensureMaskPresetsReady() {\\n if (typeof document === \\\"undefined\\\") return;\\n if (initialized2) return;\\n initialized2 = true;\\n const cache2 = ImageCache.getInstance();\\n for (const preset of MASK_IMAGE_PRESETS) {\\n const maskCanvas = createDOMCanvas2(MASK_SIZE, MASK_SIZE);\\n if (!maskCanvas) continue;\\n const maskCtx = maskCanvas.getContext(\\\"2d\\\");\\n if (!maskCtx) continue;\\n maskCtx.fillStyle = \\\"white\\\";\\n preset.draw(maskCtx, MASK_SIZE);\\n const dataUrl = maskCanvas.toDataURL(\\\"image/png\\\");\\n const img = cache2.acquire(preset.imageUrl);\\n img.crossOrigin = \\\"anonymous\\\";\\n img.src = dataUrl;\\n const thumbCanvas = createDOMCanvas2(THUMB_SIZE2, THUMB_SIZE2);\\n if (thumbCanvas) {\\n const thumbCtx = thumbCanvas.getContext(\\\"2d\\\");\\n if (thumbCtx) {\\n thumbCtx.fillStyle = \\\"#1a1a2e\\\";\\n thumbCtx.fillRect(0, 0, THUMB_SIZE2, THUMB_SIZE2);\\n thumbCtx.fillStyle = \\\"white\\\";\\n preset.draw(thumbCtx, THUMB_SIZE2);\\n preset.thumbnailUrl = thumbCanvas.toDataURL(\\\"image/png\\\");\\n }\\n }\\n }\\n }\\n function generateMaskBitmap(builtinUrl) {\\n if (!builtinUrl.startsWith(\\\"builtin-mask:\\\")) return null;\\n if (typeof OffscreenCanvas === \\\"undefined\\\") return null;\\n const id = builtinUrl.replace(\\\"builtin-mask:\\\", \\\"\\\");\\n const preset = MASK_IMAGE_PRESETS.find((p) => p.id === id);\\n if (!preset) return null;\\n const canvas = new OffscreenCanvas(MASK_SIZE, MASK_SIZE);\\n const ctx = canvas.getContext(\\\"2d\\\");\\n if (!ctx) return null;\\n ctx.fillStyle = \\\"white\\\";\\n preset.draw(ctx, MASK_SIZE);\\n return canvas.transferToImageBitmap();\\n }\\n\\n // src/rendering/MaskRenderer.ts\\n var logger4 = createLogger(\\\"MaskRenderer\\\");\\n var workerMaskBitmaps = /* @__PURE__ */ new Map();\\n function registerMaskBitmap(imageUrl, bitmap) {\\n workerMaskBitmaps.set(imageUrl, bitmap);\\n }\\n function clearMaskBitmaps() {\\n workerMaskBitmaps.clear();\\n }\\n function renderWithMasks(ctx, element, renderFn) {\\n if (!element.masks || element.masks.length === 0) {\\n renderFn(ctx);\\n return;\\n }\\n const canvas = ctx.canvas;\\n const offscreen = createOffscreenCanvas5(canvas.width, canvas.height);\\n const offCtx = offscreen.getContext(\\\"2d\\\");\\n if (!offCtx) {\\n logger4.error(\\\"[renderWithMasks] Failed to get offscreen context\\\");\\n return;\\n }\\n const transform = ctx.getTransform();\\n offCtx.setTransform(transform);\\n renderFn(offCtx);\\n for (const mask of element.masks) {\\n applyMask(offCtx, mask, element);\\n }\\n ctx.save();\\n ctx.setTransform(1, 0, 0, 1, 0, 0);\\n ctx.drawImage(offscreen, 0, 0);\\n ctx.restore();\\n }\\n function applyMask(ctx, mask, parentElement) {\\n switch (mask.type) {\\n case \\\"clip\\\":\\n applyClipMask(ctx, mask, parentElement);\\n break;\\n case \\\"alpha\\\":\\n applyAlphaMask(ctx, mask, parentElement);\\n break;\\n case \\\"luma\\\":\\n applyLumaMask(ctx, mask, parentElement);\\n break;\\n case \\\"distress\\\":\\n applyDistressMask(ctx, mask, parentElement);\\n break;\\n }\\n }\\n function applyClipMask(ctx, mask, parentElement) {\\n ctx.save();\\n ctx.globalCompositeOperation = mask.inverted ? \\\"destination-out\\\" : \\\"destination-in\\\";\\n if (mask.opacity !== void 0) {\\n ctx.globalAlpha = mask.opacity;\\n }\\n renderMaskElement(ctx, mask.maskElement, parentElement);\\n ctx.restore();\\n }\\n function applyAlphaMask(ctx, mask, parentElement) {\\n ctx.save();\\n ctx.globalCompositeOperation = mask.inverted ? \\\"destination-out\\\" : \\\"destination-in\\\";\\n if (mask.opacity !== void 0) {\\n ctx.globalAlpha = mask.opacity;\\n }\\n renderMaskElement(ctx, mask.maskElement, parentElement);\\n if (mask.feather && mask.feather > 0) {\\n applyFeathering(ctx, mask.feather);\\n }\\n ctx.restore();\\n }\\n function applyLumaMask(ctx, mask, parentElement) {\\n const maskCanvas = createOffscreenCanvas5(ctx.canvas.width, ctx.canvas.height);\\n const maskCtx = maskCanvas.getContext(\\\"2d\\\");\\n if (!maskCtx) return;\\n renderMaskElement(maskCtx, mask.maskElement, parentElement);\\n const imageData = maskCtx.getImageData(0, 0, maskCanvas.width, maskCanvas.height);\\n const data = imageData.data;\\n for (let i = 0; i < data.length; i += 4) {\\n const r = data[i];\\n const g = data[i + 1];\\n const b = data[i + 2];\\n const luma = 0.299 * r + 0.587 * g + 0.114 * b;\\n data[i + 3] = mask.inverted ? 255 - luma : luma;\\n }\\n maskCtx.putImageData(imageData, 0, 0);\\n ctx.save();\\n ctx.globalCompositeOperation = \\\"destination-in\\\";\\n if (mask.opacity !== void 0) {\\n ctx.globalAlpha = mask.opacity;\\n }\\n ctx.drawImage(maskCanvas, 0, 0);\\n ctx.restore();\\n }\\n function applyDistressMask(ctx, mask, parentElement) {\\n ctx.save();\\n ctx.globalCompositeOperation = mask.inverted ? \\\"destination-in\\\" : \\\"destination-out\\\";\\n if (mask.opacity !== void 0) {\\n ctx.globalAlpha = mask.opacity;\\n }\\n renderMaskElement(ctx, mask.maskElement, parentElement);\\n if (mask.feather && mask.feather > 0) {\\n applyFeathering(ctx, mask.feather);\\n }\\n ctx.restore();\\n }\\n function renderMaskElement(ctx, maskElement, parentElement) {\\n const parentX = parentElement.x || 0;\\n const parentY = parentElement.y || 0;\\n const maskX = maskElement.x || 0;\\n const maskY = maskElement.y || 0;\\n const absoluteMaskElement = {\\n ...maskElement,\\n x: parentX + maskX,\\n y: parentY + maskY,\\n // Inherit parent rotation so mask rotates with the element\\n rotation: (maskElement.rotation || 0) + (parentElement.rotation || 0)\\n };\\n const MASK_OVERSIZE = 4;\\n const parentTd = parentElement.transformData;\\n const parentAny = parentElement;\\n const parentW = parentTd?.width || parentAny.width || 0;\\n const parentH = parentTd?.height || parentAny.height || 0;\\n const maskTd = maskElement.transformData;\\n if (parentW && parentH && maskTd) {\\n absoluteMaskElement.transformData = {\\n ...maskTd,\\n width: parentW + MASK_OVERSIZE,\\n height: parentH + MASK_OVERSIZE\\n };\\n }\\n let loadedImage;\\n let loadedBitmap;\\n if (maskElement.transformType === \\\"image\\\") {\\n const imageConfig = maskElement;\\n if (imageConfig.imageUrl) {\\n if (typeof document !== \\\"undefined\\\") {\\n if (imageConfig.imageUrl.startsWith(\\\"builtin-mask:\\\")) {\\n ensureMaskPresetsReady();\\n }\\n const cache2 = ImageCache.getInstance();\\n const img = cache2.acquire(imageConfig.imageUrl);\\n if (img.complete && img.naturalWidth > 0) {\\n loadedImage = img;\\n }\\n cache2.release(imageConfig.imageUrl);\\n } else {\\n loadedBitmap = workerMaskBitmaps.get(imageConfig.imageUrl);\\n }\\n }\\n }\\n const resolvedTd = absoluteMaskElement.transformData;\\n const maskNaturalW = maskTd?.width || 0;\\n const maskNaturalH = maskTd?.height || 0;\\n const needsContainScaling = maskNaturalW > 0 && maskNaturalH > 0 && parentW > 0 && parentH > 0 && Math.abs(maskNaturalW / maskNaturalH - parentW / parentH) > 1e-3;\\n if (loadedBitmap) {\\n ctx.save();\\n const w = resolvedTd?.width || loadedBitmap.width;\\n const h = resolvedTd?.height || loadedBitmap.height;\\n ctx.translate(absoluteMaskElement.x || 0, absoluteMaskElement.y || 0);\\n ctx.rotate(-(absoluteMaskElement.rotation || 0) * Math.PI / 180);\\n if (needsContainScaling) {\\n const contain = computeMaskCoverDimensions(\\n w,\\n h,\\n maskNaturalW,\\n maskNaturalH,\\n 0\\n );\\n ctx.drawImage(loadedBitmap, -contain.width / 2, -contain.height / 2, contain.width, contain.height);\\n } else {\\n ctx.drawImage(loadedBitmap, -w / 2, -h / 2, w, h);\\n }\\n ctx.restore();\\n } else if (needsContainScaling && loadedImage) {\\n const w = resolvedTd?.width || parentW;\\n const h = resolvedTd?.height || parentH;\\n const contain = computeMaskCoverDimensions(\\n w,\\n h,\\n maskNaturalW,\\n maskNaturalH,\\n 0\\n );\\n ctx.save();\\n ctx.translate(absoluteMaskElement.x || 0, absoluteMaskElement.y || 0);\\n ctx.rotate(-(absoluteMaskElement.rotation || 0) * Math.PI / 180);\\n ctx.drawImage(loadedImage, -contain.width / 2, -contain.height / 2, contain.width, contain.height);\\n ctx.restore();\\n } else {\\n renderElement(ctx, absoluteMaskElement, { mode: \\\"both\\\", loadedImage });\\n }\\n }\\n function applyFeathering(ctx, featherRadius) {\\n if (\\\"filter\\\" in ctx) {\\n ctx.filter = `blur(${featherRadius}px)`;\\n }\\n }\\n function createOffscreenCanvas5(width, height) {\\n if (typeof OffscreenCanvas !== \\\"undefined\\\") {\\n return new OffscreenCanvas(width, height);\\n } else if (typeof document !== \\\"undefined\\\") {\\n const canvas = document.createElement(\\\"canvas\\\");\\n canvas.width = width;\\n canvas.height = height;\\n return canvas;\\n }\\n throw new Error(\\\"No canvas context available\\\");\\n }\\n\\n // src/utils/google-fonts-loader.ts\\n var WEIGHTS_TO_REQUEST = [400, 700];\\n function buildGoogleFontUrl(family, weight) {\\n const fontName = family.replace(/ /g, \\\"+\\\");\\n return `https://fonts.googleapis.com/css2?family=${fontName}:wght@${weight}&display=swap`;\\n }\\n async function fetchGoogleFontCss(family, fetchImpl = fetch) {\\n const cssParts = await Promise.all(\\n WEIGHTS_TO_REQUEST.map((weight) => fetchOneWeightCss(family, weight, fetchImpl))\\n );\\n return cssParts.join(\\\"\\\\n\\\");\\n }\\n async function fetchOneWeightCss(family, weight, fetchImpl) {\\n const url = buildGoogleFontUrl(family, weight);\\n try {\\n const response = await fetchImpl(url);\\n if (!response.ok) return \\\"\\\";\\n return await response.text();\\n } catch {\\n return \\\"\\\";\\n }\\n }\\n function parseFontFaces(css) {\\n const fontFaceRegex = /@font-face\\\\s*{([^}]*)}/g;\\n const urlRegex = /url\\\\(([^)]+)\\\\)/;\\n const out = [];\\n let match;\\n while ((match = fontFaceRegex.exec(css)) !== null) {\\n const block = match[1];\\n const urlMatch = block.match(urlRegex);\\n if (!urlMatch) continue;\\n const fontFileUrl = urlMatch[1].replace(/['\\\"]/g, \\\"\\\");\\n const weightMatch = block.match(/font-weight:\\\\s*(\\\\d+)/);\\n const styleMatch = block.match(/font-style:\\\\s*(\\\\w+)/);\\n const rangeMatch = block.match(/unicode-range:\\\\s*([^;]+)/);\\n const descriptors = {\\n weight: weightMatch ? weightMatch[1] : \\\"400\\\",\\n style: styleMatch ? styleMatch[1] : \\\"normal\\\"\\n };\\n if (rangeMatch) descriptors.unicodeRange = rangeMatch[1].trim();\\n out.push({ fontFileUrl, descriptors });\\n }\\n return out;\\n }\\n async function loadFontFaceFromUrl(family, parsed, fetchImpl = fetch) {\\n try {\\n const response = await fetchImpl(parsed.fontFileUrl, { mode: \\\"cors\\\" });\\n if (!response.ok) return null;\\n const buffer = await response.arrayBuffer();\\n const fontFace = new FontFace(family, buffer, parsed.descriptors);\\n await fontFace.load();\\n return fontFace;\\n } catch {\\n return null;\\n }\\n }\\n\\n // src/workers/export-worker.ts\\n var MAX_BITMAP_CACHE_SIZE = 50;\\n var workerBitmapCache = /* @__PURE__ */ new Map();\\n function evictLRUBitmap() {\\n if (workerBitmapCache.size <= MAX_BITMAP_CACHE_SIZE) return;\\n let oldestKey = null;\\n let oldestTime = Infinity;\\n workerBitmapCache.forEach((entry, key) => {\\n if (entry.lastAccessed < oldestTime) {\\n oldestTime = entry.lastAccessed;\\n oldestKey = key;\\n }\\n });\\n if (oldestKey) {\\n const evicted = workerBitmapCache.get(oldestKey);\\n if (evicted) {\\n evicted.bitmap.close();\\n }\\n workerBitmapCache.delete(oldestKey);\\n }\\n }\\n function getCachedBitmap(cacheKey) {\\n const entry = workerBitmapCache.get(cacheKey);\\n if (entry) {\\n entry.lastAccessed = Date.now();\\n return entry.bitmap;\\n }\\n return void 0;\\n }\\n function handleRegisterBitmap(message) {\\n const { cacheKey, bitmap } = message;\\n const existing = workerBitmapCache.get(cacheKey);\\n if (existing) {\\n existing.bitmap.close();\\n }\\n workerBitmapCache.set(cacheKey, {\\n bitmap,\\n lastAccessed: Date.now()\\n });\\n evictLRUBitmap();\\n }\\n function handleClearBitmap(message) {\\n const { elementId } = message;\\n for (const [key, entry] of workerBitmapCache.entries()) {\\n if (key.startsWith(`${elementId}:`)) {\\n entry.bitmap.close();\\n workerBitmapCache.delete(key);\\n }\\n }\\n }\\n function handleClearAllBitmaps() {\\n for (const entry of workerBitmapCache.values()) {\\n entry.bitmap.close();\\n }\\n workerBitmapCache.clear();\\n }\\n var loadedFonts = /* @__PURE__ */ new Set();\\n var failedFonts = /* @__PURE__ */ new Set();\\n async function loadFonts(fontFamilies) {\\n if (!fontFamilies || fontFamilies.length === 0) return;\\n const loadPromises = fontFamilies.map(async (fontFamily) => {\\n if (loadedFonts.has(fontFamily) || failedFonts.has(fontFamily)) return;\\n if (SYSTEM_FONTS.has(fontFamily)) {\\n loadedFonts.add(fontFamily);\\n return;\\n }\\n try {\\n const css = await fetchGoogleFontCss(fontFamily);\\n if (!css.trim()) {\\n failedFonts.add(fontFamily);\\n return;\\n }\\n const parsedFaces = parseFontFaces(css);\\n const loadedFaces = await Promise.all(\\n parsedFaces.map((parsed) => loadFontFaceFromUrl(fontFamily, parsed))\\n );\\n for (const face of loadedFaces) {\\n if (face) self.fonts.add(face);\\n }\\n if (self.fonts && self.fonts.ready) {\\n await Promise.race([\\n self.fonts.ready,\\n new Promise((resolve) => setTimeout(resolve, 250))\\n ]);\\n }\\n void FontAnalyzer.loadFont(fontFamily, 400).catch(() => {\\n });\\n void FontAnalyzer.loadFont(fontFamily, 700).catch(() => {\\n });\\n loadedFonts.add(fontFamily);\\n } catch {\\n failedFonts.add(fontFamily);\\n }\\n });\\n await Promise.all(loadPromises);\\n }\\n var readyMessage = {\\n type: \\\"ready\\\",\\n timestamp: Date.now()\\n };\\n self.postMessage(readyMessage);\\n self.onmessage = async (event) => {\\n const message = event.data;\\n try {\\n switch (message.type) {\\n case \\\"export\\\":\\n await handleExportRequest(message);\\n break;\\n case \\\"register-bitmap\\\":\\n handleRegisterBitmap(message);\\n break;\\n case \\\"clear-bitmap\\\":\\n handleClearBitmap(message);\\n break;\\n case \\\"clear-all-bitmaps\\\":\\n handleClearAllBitmaps();\\n break;\\n case \\\"init\\\":\\n break;\\n case \\\"terminate\\\":\\n handleClearAllBitmaps();\\n self.close();\\n break;\\n default:\\n console.warn(\\\"[Export Worker] Unknown message type:\\\", message);\\n }\\n } catch (error) {\\n console.error(\\\"[Export Worker] Error handling message:\\\", error);\\n if (\\\"requestId\\\" in message) {\\n const errorResponse = {\\n type: \\\"exportError\\\",\\n requestId: message.requestId,\\n artboardId: \\\"artboardData\\\" in message ? message.artboardData.id : \\\"unknown\\\",\\n error: error instanceof Error ? error.message : String(error),\\n stack: error instanceof Error ? error.stack : void 0\\n };\\n self.postMessage(errorResponse);\\n }\\n }\\n };\\n async function handleExportRequest(request) {\\n const startTime = performance.now();\\n const {\\n requestId,\\n artboardData,\\n elements = [],\\n fonts = [],\\n scale = 1,\\n format = \\\"png\\\",\\n quality = 0.95,\\n returnFormat = \\\"dataUrl\\\"\\n } = request;\\n try {\\n if (fonts && fonts.length > 0) {\\n await loadFonts(fonts);\\n }\\n const width = artboardData.width * scale;\\n const height = artboardData.height * scale;\\n const canvas = new OffscreenCanvas(width, height);\\n const ctx = canvas.getContext(\\\"2d\\\");\\n if (!ctx) {\\n throw new Error(\\\"Failed to get 2D context from OffscreenCanvas\\\");\\n }\\n if (scale !== 1) {\\n ctx.scale(scale, scale);\\n }\\n if (artboardData.exportBackground) {\\n ctx.fillStyle = artboardData.backgroundColor || \\\"#ffffff\\\";\\n ctx.fillRect(0, 0, artboardData.width, artboardData.height);\\n }\\n await preloadDistressTextures(elements, artboardData);\\n await preloadMaskImages(elements);\\n const renderStartTime = performance.now();\\n await renderElements(ctx, elements, artboardData);\\n if (artboardData.distressTexture?.enabled) {\\n applyArtboardDistressTexture(ctx, artboardData.distressTexture, {\\n x: 0,\\n y: 0,\\n width: artboardData.width,\\n height: artboardData.height\\n });\\n }\\n if (artboardData.imageMask?.enabled) {\\n await applyWorkerArtboardImageMask(ctx, artboardData.imageMask, {\\n width: artboardData.width,\\n height: artboardData.height\\n });\\n }\\n const renderEndTime = performance.now();\\n const renderTime = renderEndTime - renderStartTime;\\n const blobStartTime = performance.now();\\n const mimeType = format === \\\"png\\\" ? \\\"image/png\\\" : format === \\\"webp\\\" ? \\\"image/webp\\\" : \\\"image/jpeg\\\";\\n const blob = await canvas.convertToBlob({\\n type: mimeType,\\n quality: format !== \\\"png\\\" ? quality : void 0\\n });\\n const blobEndTime = performance.now();\\n void (blobEndTime - blobStartTime);\\n if (returnFormat === \\\"blob\\\") {\\n const arrayBuffer = await blob.arrayBuffer();\\n const endTime = performance.now();\\n const totalTime = endTime - startTime;\\n const response = {\\n type: \\\"exportBlobComplete\\\",\\n requestId,\\n artboardId: artboardData.id,\\n artboardName: artboardData.name,\\n blobData: arrayBuffer,\\n mimeType,\\n renderTime,\\n totalTime\\n };\\n self.postMessage(response, { transfer: [arrayBuffer] });\\n } else {\\n const dataUrl = await blobToDataURL(blob);\\n const endTime = performance.now();\\n const totalTime = endTime - startTime;\\n const response = {\\n type: \\\"exportComplete\\\",\\n requestId,\\n artboardId: artboardData.id,\\n artboardName: artboardData.name,\\n dataUrl,\\n renderTime,\\n totalTime\\n };\\n self.postMessage(response);\\n }\\n } catch (error) {\\n console.error(\\\"[Export Worker] Export failed:\\\", error);\\n const errorResponse = {\\n type: \\\"exportError\\\",\\n requestId,\\n artboardId: artboardData.id,\\n error: error instanceof Error ? error.message : String(error),\\n stack: error instanceof Error ? error.stack : void 0\\n };\\n self.postMessage(errorResponse);\\n }\\n }\\n function renderSingleElement(ctx, element, artboardX, artboardY) {\\n if (element.type === \\\"text\\\" || element.type === \\\"custom\\\" || element.type === \\\"circle\\\" || element.type === \\\"wave\\\" || element.type === \\\"arch\\\" || element.type === \\\"ascend\\\" || element.type === \\\"lean\\\" || element.type === \\\"flag\\\") {\\n const adjustedElement = {\\n ...element,\\n x: element.x - artboardX,\\n y: element.y - artboardY\\n };\\n renderTextElement(ctx, adjustedElement);\\n } else if (element.type === \\\"image\\\") {\\n const imageElement = element;\\n const bitmap = getCachedBitmap(imageElement.bitmapCacheKey);\\n if (bitmap) {\\n const adjustedElement = {\\n ...imageElement,\\n x: imageElement.x - artboardX,\\n y: imageElement.y - artboardY\\n };\\n renderImageElement(ctx, adjustedElement, bitmap);\\n } else {\\n console.error(\\n `[Export Worker] Missing ImageBitmap for image: ${element.id} (cacheKey: ${imageElement.bitmapCacheKey})`\\n );\\n }\\n } else if (element.type === \\\"shape\\\") {\\n const shapeElement = element;\\n const adjustedElement = {\\n ...shapeElement,\\n x: shapeElement.x - artboardX,\\n y: shapeElement.y - artboardY\\n };\\n renderShapeElement(ctx, adjustedElement);\\n } else if (element.type === \\\"group\\\") {\\n console.warn(`[Export Worker] Group rendering not yet implemented: ${element.id}`);\\n } else {\\n console.warn(`[Export Worker] Unknown element type: ${element.type}`);\\n }\\n }\\n function renderSingleElementWithEffects(ctx, element, artboardX, artboardY) {\\n const hasDistress = element.distressEffect?.enabled && element.distressEffect.style === \\\"custom\\\" && element.distressEffect.textureUrl;\\n const hasMasks = element.masks && element.masks.length > 0;\\n if (!hasDistress && !hasMasks) {\\n renderSingleElement(ctx, element, artboardX, artboardY);\\n return;\\n }\\n const adjustedConfig = {\\n ...element,\\n transformType: element.type || element.transformType,\\n x: element.x - artboardX,\\n y: element.y - artboardY\\n };\\n let elementBounds;\\n if (element._boundingBox) {\\n const bbox = element._boundingBox;\\n elementBounds = {\\n x: bbox.x - artboardX,\\n y: bbox.y - artboardY,\\n width: bbox.width,\\n height: bbox.height\\n };\\n } else {\\n const td = element.transformData || {};\\n let width;\\n let height;\\n if (element.type === \\\"shape\\\" || element.type === \\\"image\\\") {\\n width = td.width || 100;\\n height = td.height || 100;\\n } else {\\n const fontSize = element.fontSize || 24;\\n const measureCanvas = new OffscreenCanvas(1, 1);\\n const measureCtx = measureCanvas.getContext(\\\"2d\\\");\\n const bold = element.bold ? \\\"bold \\\" : \\\"\\\";\\n const italic = element.italic ? \\\"italic \\\" : \\\"\\\";\\n measureCtx.font = `${italic}${bold}${fontSize}px ${element.fontFamily || \\\"Arial\\\"}`;\\n const textMetrics = measureCtx.measureText(element.text || \\\"\\\");\\n width = td.width || textMetrics.width + fontSize;\\n const ascent = textMetrics.actualBoundingBoxAscent || fontSize * 0.8;\\n const descent = textMetrics.actualBoundingBoxDescent || fontSize * 0.2;\\n height = ascent + descent + fontSize * 0.5;\\n }\\n elementBounds = {\\n x: (adjustedConfig.x || 0) - width / 2,\\n y: (adjustedConfig.y || 0) - height / 2,\\n width,\\n height\\n };\\n }\\n const baseRenderFn = (renderCtx) => {\\n renderSingleElement(renderCtx, element, artboardX, artboardY);\\n };\\n if (hasMasks && hasDistress) {\\n renderWithMasks(ctx, adjustedConfig, (maskCtx) => {\\n applyElementDistressTexture(\\n maskCtx,\\n element.distressEffect,\\n elementBounds,\\n baseRenderFn\\n );\\n });\\n } else if (hasMasks) {\\n renderWithMasks(ctx, adjustedConfig, baseRenderFn);\\n } else if (hasDistress) {\\n applyElementDistressTexture(\\n ctx,\\n element.distressEffect,\\n elementBounds,\\n baseRenderFn\\n );\\n }\\n }\\n async function renderElements(ctx, elements, artboardData) {\\n const artboardX = artboardData.x || 0;\\n const artboardY = artboardData.y || 0;\\n const allElementConfigs = elements.map((el) => ({\\n ...el,\\n transformType: el.type || el.transformType,\\n x: el.x - artboardX,\\n y: el.y - artboardY\\n }));\\n const renderElementForCompositing = (renderCtx, config) => {\\n const originalElement = elements.find((el) => el.id === config.id);\\n if (originalElement) {\\n renderSingleElement(renderCtx, originalElement, artboardX, artboardY);\\n } else {\\n renderElement(renderCtx, config);\\n }\\n };\\n const knockoutRenderedIds = /* @__PURE__ */ new Set();\\n for (let i = 0; i < elements.length; i++) {\\n const element = elements[i];\\n if (element.blendMode === \\\"knockout\\\" || element.blendMode === \\\"clip\\\") {\\n const elementConfig = allElementConfigs[i];\\n const compositeOp = element.blendMode === \\\"knockout\\\" ? \\\"destination-out\\\" : \\\"destination-in\\\";\\n const scope = elementConfig.knockoutParts?.scope || \\\"group\\\";\\n if (scope === \\\"artboard\\\") {\\n for (let j = 0; j < i; j++) {\\n const id = allElementConfigs[j].id;\\n if (id) knockoutRenderedIds.add(id);\\n }\\n }\\n renderWithCompositing(\\n ctx,\\n elementConfig,\\n allElementConfigs,\\n renderElementForCompositing,\\n artboardData.exportBackground ? artboardData.backgroundColor : void 0,\\n { x: 0, y: 0, width: artboardData.width, height: artboardData.height },\\n compositeOp\\n );\\n knockoutRenderedIds.add(element.id);\\n }\\n }\\n for (const element of elements) {\\n if (!knockoutRenderedIds.has(element.id)) {\\n try {\\n renderSingleElementWithEffects(ctx, element, artboardX, artboardY);\\n } catch (error) {\\n console.error(`[Export Worker] Failed to render element ${element.id}:`, error);\\n }\\n }\\n }\\n }\\n async function preloadDistressTextures(elements, artboardData) {\\n const textureUrls = /* @__PURE__ */ new Set();\\n let hasBuiltinTextures = false;\\n if (artboardData.distressTexture?.enabled && artboardData.distressTexture.textureUrl) {\\n const url = artboardData.distressTexture.textureUrl;\\n if (url.startsWith(\\\"builtin:\\\")) {\\n hasBuiltinTextures = true;\\n } else {\\n textureUrls.add(url);\\n }\\n }\\n for (const element of elements) {\\n if (element.distressEffect?.enabled && element.distressEffect.style === \\\"custom\\\" && element.distressEffect.textureUrl) {\\n const url = element.distressEffect.textureUrl;\\n if (url.startsWith(\\\"builtin:\\\")) {\\n hasBuiltinTextures = true;\\n } else {\\n textureUrls.add(url);\\n }\\n }\\n }\\n if (hasBuiltinTextures) {\\n ensureBuiltinTexturesReady();\\n }\\n if (textureUrls.size > 0) {\\n await Promise.all(Array.from(textureUrls).map((url) => preloadTexture(url)));\\n }\\n }\\n async function preloadMaskImages(elements) {\\n const builtinUrls = /* @__PURE__ */ new Set();\\n const externalUrls = /* @__PURE__ */ new Set();\\n for (const element of elements) {\\n if (!element.masks || !Array.isArray(element.masks)) continue;\\n for (const mask of element.masks) {\\n if (mask.maskElement?.transformType === \\\"image\\\" && mask.maskElement.imageUrl) {\\n const url = mask.maskElement.imageUrl;\\n if (url.startsWith(\\\"builtin-mask:\\\")) {\\n builtinUrls.add(url);\\n } else {\\n externalUrls.add(url);\\n }\\n }\\n }\\n }\\n if (builtinUrls.size === 0 && externalUrls.size === 0) return;\\n clearMaskBitmaps();\\n for (const url of builtinUrls) {\\n const bitmap = generateMaskBitmap(url);\\n if (bitmap) {\\n registerMaskBitmap(url, bitmap);\\n } else {\\n console.error(`[Export Worker] Failed to generate builtin mask: ${url}`);\\n }\\n }\\n if (externalUrls.size > 0) {\\n await Promise.all(\\n Array.from(externalUrls).map(async (url) => {\\n try {\\n const response = await fetch(url);\\n const blob = await response.blob();\\n const bitmap = await createImageBitmap(blob);\\n registerMaskBitmap(url, bitmap);\\n } catch (error) {\\n console.error(`[Export Worker] Failed to preload mask image: ${url}`, error);\\n }\\n })\\n );\\n }\\n }\\n async function applyWorkerArtboardImageMask(ctx, config, artboard) {\\n if (!config.enabled || !config.imageUrl || config.opacity <= 0) return;\\n try {\\n const response = await fetch(config.imageUrl);\\n const blob = await response.blob();\\n const img = await createImageBitmap(blob);\\n const transform = ctx.getTransform();\\n const pixelWidth = transform.a * artboard.width;\\n const pixelHeight = transform.d * artboard.height;\\n const pixelX = transform.e;\\n const pixelY = transform.f;\\n const offWidth = Math.ceil(pixelWidth);\\n const offHeight = Math.ceil(pixelHeight);\\n if (offWidth <= 0 || offHeight <= 0) return;\\n const offCanvas = new OffscreenCanvas(offWidth, offHeight);\\n const offCtx = offCanvas.getContext(\\\"2d\\\");\\n offCtx.drawImage(\\n ctx.canvas,\\n pixelX,\\n pixelY,\\n pixelWidth,\\n pixelHeight,\\n 0,\\n 0,\\n offWidth,\\n offHeight\\n );\\n const compositeOp = config.inverted ? \\\"destination-out\\\" : \\\"destination-in\\\";\\n if (config.maskType === \\\"luma\\\") {\\n const lumaCanvas = new OffscreenCanvas(offWidth, offHeight);\\n const lumaCtx = lumaCanvas.getContext(\\\"2d\\\");\\n lumaCtx.drawImage(img, 0, 0, offWidth, offHeight);\\n const imageData = lumaCtx.getImageData(0, 0, offWidth, offHeight);\\n const data = imageData.data;\\n for (let i = 0; i < data.length; i += 4) {\\n const luma = 0.299 * data[i] + 0.587 * data[i + 1] + 0.114 * data[i + 2];\\n data[i + 3] = config.inverted ? 255 - luma : luma;\\n }\\n lumaCtx.putImageData(imageData, 0, 0);\\n offCtx.globalCompositeOperation = \\\"destination-in\\\";\\n offCtx.globalAlpha = config.opacity / 100;\\n offCtx.drawImage(lumaCanvas, 0, 0);\\n } else {\\n offCtx.globalCompositeOperation = compositeOp;\\n offCtx.globalAlpha = config.opacity / 100;\\n offCtx.drawImage(img, 0, 0, offWidth, offHeight);\\n }\\n offCtx.globalCompositeOperation = \\\"source-over\\\";\\n offCtx.globalAlpha = 1;\\n ctx.save();\\n ctx.setTransform(1, 0, 0, 1, 0, 0);\\n ctx.clearRect(pixelX, pixelY, pixelWidth, pixelHeight);\\n ctx.drawImage(offCanvas, pixelX, pixelY);\\n ctx.restore();\\n img.close();\\n } catch (error) {\\n console.error(\\\"[Export Worker] Failed to apply artboard image mask:\\\", error);\\n }\\n }\\n function blobToDataURL(blob) {\\n return new Promise((resolve, reject) => {\\n const reader = new FileReader();\\n reader.onloadend = () => {\\n if (typeof reader.result === \\\"string\\\") {\\n resolve(reader.result);\\n } else {\\n reject(new Error(\\\"FileReader result is not a string\\\"));\\n }\\n };\\n reader.onerror = () => {\\n reject(new Error(\\\"Failed to read blob as data URL\\\"));\\n };\\n reader.readAsDataURL(blob);\\n });\\n }\\n self.onerror = (error) => {\\n console.error(\\\"[Export Worker] Uncaught error:\\\", error);\\n };\\n self.onunhandledrejection = (event) => {\\n console.error(\\\"[Export Worker] Unhandled promise rejection:\\\", event.reason);\\n };\\n})();\\n\";\n","/**\n * Worker Export Manager - Non-blocking artboard export via Web Workers.\n *\n * Manages the lifecycle of a dedicated Web Worker that uses `OffscreenCanvas`\n * to render artboard exports without blocking the main thread. Falls back to\n * main-thread rendering when `OffscreenCanvas` is not available.\n *\n * Provides a Promise-based API for requesting exports (as data URLs or Blobs),\n * queues concurrent requests, manages bitmap caching in the worker, and\n * automatically recovers from worker crashes.\n *\n * For most use cases, use `ExportManager` (which delegates to this internally)\n * or the `useExport` hook. Access `WorkerExportManager` directly only when you\n * need fine-grained control over the worker lifecycle or bitmap cache.\n *\n * @example\n * ```ts\n * import { getSharedWorkerExportManager } from '@snowcone-app/canvas';\n *\n * const manager = getSharedWorkerExportManager();\n * const result = await manager.exportToDataUrl(artboard, elements, config);\n * console.log(result.dataUrl, result.renderTime);\n * ```\n *\n * @module\n */\n\nimport type {\n WorkerResponse,\n ExportRequestMessage,\n ExportSuccessResponse,\n ExportBlobSuccessResponse,\n ExportErrorResponse,\n ExportConfig,\n RegisterBitmapMessage,\n ClearBitmapMessage,\n ClearAllBitmapsMessage,\n} from '../workers/export-protocol';\nimport type { ArtboardElement } from '../core/ArtboardElement';\nimport type { BaseElement } from '../core/BaseElement';\nimport {\n serializeForWorkerExport,\n clearRegisteredBitmapKeys,\n unregisterElementBitmaps,\n registerWorkerCacheCallbacks,\n unregisterWorkerCacheCallbacks,\n type NewBitmapRegistration,\n} from '../rendering/element-serializer.js';\n// Import bundled worker code as a string. The sibling\n// `export-worker.bundle.string.js` module is auto-generated alongside\n// `export-worker.bundle.js` by `scripts/bundle-worker.js` and exports the\n// bundle source as a plain JS string constant. Going through a normal ESM\n// `export default` (instead of Vite's `?raw` query) keeps the same code\n// path working across Vite, Webpack, and Turbopack — no special asset rule\n// required, no risk of an HMR shim injecting `import.meta` into the blob.\nimport workerCode from '../workers/export-worker.bundle.string.js';\nimport { createLogger } from './logger.js';\n\nconst log = createLogger('WorkerExport');\n\n// ============================================================================\n// Types\n// ============================================================================\n\ninterface PendingExportRequest {\n requestId: string;\n resolve: (response: ExportSuccessResponse) => void;\n reject: (error: Error) => void;\n startTime: number;\n returnFormat: 'dataUrl';\n}\n\ninterface PendingBlobExportRequest {\n requestId: string;\n resolve: (response: ExportBlobSuccessResponse) => void;\n reject: (error: Error) => void;\n startTime: number;\n returnFormat: 'blob';\n}\n\ntype AnyPendingExportRequest = PendingExportRequest | PendingBlobExportRequest;\n\ninterface QueuedExportRequest {\n artboard: ArtboardElement;\n elements: BaseElement[];\n config: ExportConfig;\n resolve: (result: WorkerExportResult) => void;\n reject: (error: Error) => void;\n}\n\ninterface QueuedBlobExportRequest {\n artboard: ArtboardElement;\n elements: BaseElement[];\n config: ExportConfig;\n resolve: (result: WorkerBlobExportResult) => void;\n reject: (error: Error) => void;\n}\n\n/** Result of a worker export operation returning a data URL string. */\nexport interface WorkerExportResult {\n /** Base64-encoded data URL of the exported image. */\n dataUrl: string;\n artboardId: string;\n artboardName: string;\n /** Time spent rendering in the worker (ms). */\n renderTime: number;\n /** Total round-trip time including serialization and messaging (ms). */\n totalTime: number;\n /** Time the main thread was blocked during the export (should be near 0ms). */\n mainThreadBlockTime: number;\n}\n\n/** Result of a worker export operation returning a Blob. More efficient for API uploads. */\nexport interface WorkerBlobExportResult {\n /** Binary Blob of the exported image. */\n blob: Blob;\n artboardId: string;\n artboardName: string;\n /** Time spent rendering in the worker (ms). */\n renderTime: number;\n /** Total round-trip time including serialization and messaging (ms). */\n totalTime: number;\n /** Time the main thread was blocked during the export (should be near 0ms). */\n mainThreadBlockTime: number;\n}\n\nexport interface ProgressEvent {\n requestId: string;\n progress: number; // 0-1\n message: string;\n}\n\nexport type ProgressListener = (event: ProgressEvent) => void;\n\n// ============================================================================\n// Worker Export Manager\n// ============================================================================\n\n/**\n * Manages a Web Worker for non-blocking artboard export using OffscreenCanvas.\n *\n * Features:\n * - Promise-based export API (data URL and Blob)\n * - Request queuing for concurrent export operations\n * - Bitmap caching in the worker (reduces main-thread memory by ~50%)\n * - Automatic crash recovery with fallback to main-thread rendering\n * - Idle timeout for worker cleanup (30s default)\n * - Progress reporting via listeners\n */\nexport class WorkerExportManager {\n private worker: Worker | null = null;\n private workerBlobUrl: string | null = null; // Track worker blob URL for cleanup\n private pendingRequests: Map<string, AnyPendingExportRequest> = new Map();\n private requestQueue: QueuedExportRequest[] = [];\n private blobRequestQueue: QueuedBlobExportRequest[] = [];\n private isProcessingQueue = false;\n private isReady = false;\n private readyPromise: Promise<void> | null = null;\n private requestIdCounter = 0;\n\n // Worker crash tracking\n private workerCrashCount = 0;\n private readonly MAX_CRASHES_BEFORE_FALLBACK = 3;\n private lastCrashTime = 0;\n private readonly CRASH_RESET_TIMEOUT = 60000; // Reset crash count after 1 minute\n\n // Progress reporting\n private progressListeners: Set<ProgressListener> = new Set();\n\n // Idle timeout for worker cleanup\n private idleTimeout: number | null = null;\n private readonly IDLE_TIMEOUT_MS = 30000; // 30 seconds\n\n /**\n * Add progress listener\n */\n onProgress(listener: ProgressListener): () => void {\n this.progressListeners.add(listener);\n // Return unsubscribe function\n return () => {\n this.progressListeners.delete(listener);\n };\n }\n\n /**\n * Remove progress listener\n */\n offProgress(listener: ProgressListener): void {\n this.progressListeners.delete(listener);\n }\n\n /**\n * Emit progress event to all listeners\n */\n private emitProgress(event: ProgressEvent): void {\n for (const listener of this.progressListeners) {\n try {\n listener(event);\n } catch (error) {\n log.error('Error in progress listener:', error);\n }\n }\n }\n\n /**\n * Reset idle timer\n */\n private resetIdleTimer(): void {\n if (this.idleTimeout) {\n clearTimeout(this.idleTimeout);\n }\n\n this.idleTimeout = window.setTimeout(() => {\n this.terminate();\n }, this.IDLE_TIMEOUT_MS) as unknown as number;\n }\n\n // ============================================================================\n // Worker Bitmap Cache Management\n // ============================================================================\n\n /**\n * Register bitmaps with the worker's cache.\n * This transfers the bitmaps to the worker (zero-copy) where they are cached.\n */\n private registerBitmapsWithWorker(bitmaps: NewBitmapRegistration[]): void {\n if (!this.worker || bitmaps.length === 0) {\n return;\n }\n\n for (const { cacheKey, bitmap } of bitmaps) {\n const message: RegisterBitmapMessage = {\n type: 'register-bitmap',\n cacheKey,\n bitmap,\n };\n\n // Transfer the bitmap (zero-copy!)\n this.worker.postMessage(message, [bitmap]);\n }\n }\n\n /**\n * Clear all bitmaps from the worker's cache.\n * Also clears the main thread's registration tracking.\n * Call this when exiting editor mode to free memory.\n */\n clearWorkerBitmapCache(): void {\n // Clear main thread tracking\n clearRegisteredBitmapKeys();\n\n // Tell worker to clear its cache\n if (this.worker && this.isReady) {\n const message: ClearAllBitmapsMessage = {\n type: 'clear-all-bitmaps',\n };\n this.worker.postMessage(message);\n }\n }\n\n /**\n * Clear a specific element's bitmaps from the worker's cache.\n * Call this when an element is removed or its image source changes.\n */\n clearWorkerBitmap(elementId: string): void {\n // Clear main thread tracking\n unregisterElementBitmaps(elementId);\n\n // Tell worker to clear this element's bitmaps\n if (this.worker && this.isReady) {\n const message: ClearBitmapMessage = {\n type: 'clear-bitmap',\n elementId,\n };\n this.worker.postMessage(message);\n }\n }\n\n\n /**\n * Check if browser supports OffscreenCanvas and Web Workers\n */\n static supportsWorkerExport(): boolean {\n try {\n // Check for OffscreenCanvas support\n if (typeof OffscreenCanvas === 'undefined') {\n log.warn('OffscreenCanvas not supported');\n return false;\n }\n\n // Check for Worker support\n if (typeof Worker === 'undefined') {\n log.warn('Web Workers not supported');\n return false;\n }\n\n // Check if OffscreenCanvas has getContext method\n const canvas = new OffscreenCanvas(1, 1);\n const ctx = canvas.getContext('2d');\n if (!ctx) {\n log.warn('OffscreenCanvas 2D context not supported');\n return false;\n }\n\n return true;\n } catch (error) {\n log.warn('Feature detection failed:', error);\n return false;\n }\n }\n\n /**\n * Initialize the worker\n */\n async initialize(): Promise<void> {\n if (this.worker) {\n return this.readyPromise || Promise.resolve();\n }\n\n if (!WorkerExportManager.supportsWorkerExport()) {\n throw new Error('Browser does not support OffscreenCanvas or Web Workers');\n }\n\n\n // Create promise that resolves when worker is ready\n this.readyPromise = new Promise((resolve, reject) => {\n try {\n // Try multiple strategies to load the worker\n // Strategy 1: Native URL approach (works in Vite dev mode)\n // Strategy 2: Blob URL from inlined data (works in bundled builds)\n let workerUrl: string | URL;\n\n try {\n // SOLUTION: Use pre-bundled worker code loaded as raw text at build time\n // This avoids Vite/webpack URL handling issues entirely\n // The worker is bundled separately via esbuild as a self-contained IIFE\n\n // Create a Blob from the worker code\n const blob = new Blob([workerCode], { type: 'application/javascript' });\n workerUrl = URL.createObjectURL(blob);\n\n // Store blob URL for cleanup on terminate()\n // This prevents memory leaks on iOS Safari which has stricter limits\n this.workerBlobUrl = workerUrl;\n\n } catch (urlError) {\n log.error('Failed to create worker blob:', urlError);\n reject(new Error(`Worker creation failed: ${urlError instanceof Error ? urlError.message : String(urlError)}`));\n return;\n }\n\n // CRITICAL: Use classic worker type, not module\n // Module workers with inlined imports don't work in Next.js\n this.worker = new Worker(workerUrl, { type: 'classic' });\n\n // Set up message handler\n this.worker.onmessage = (event: MessageEvent<WorkerResponse>) => {\n this.handleWorkerMessage(event.data);\n };\n\n // Set up error handler\n this.worker.onerror = (error) => {\n log.error('Worker error:', error);\n this.handleWorkerError(error);\n };\n\n // Wait for ready message with timeout. 15s rather than 5s because\n // iOS Safari on real phones is materially slower to compile + spawn\n // a ~1MB classic Worker than desktop Chrome — 5s was borderline and\n // a couple of recent worker-bundle additions (per-weight Google\n // Fonts loader, builtin texture preset generators) pushed it over\n // on iPhones. Chrome desktop resolves in <100ms regardless, so the\n // longer ceiling only ever fires when the worker is actually wedged.\n const timeout = setTimeout(() => {\n reject(new Error('Worker initialization timeout'));\n }, 15000);\n\n // Listen for ready message\n const readyHandler = (event: MessageEvent<WorkerResponse>) => {\n if (event.data.type === 'ready') {\n clearTimeout(timeout);\n this.isReady = true;\n\n // Register callbacks so legacy API (clearImageBitmapCache) can clear worker cache\n registerWorkerCacheCallbacks(\n () => this.clearWorkerBitmapCache(),\n (elementId) => this.clearWorkerBitmap(elementId)\n );\n\n resolve();\n }\n };\n\n this.worker.addEventListener('message', readyHandler, { once: true });\n } catch (error) {\n log.error('Failed to create worker:', error);\n reject(error);\n }\n });\n\n return this.readyPromise;\n }\n\n /**\n * Restart worker after crash\n */\n private async restartWorker(): Promise<void> {\n const now = Date.now();\n\n // Reset crash count if enough time has passed since last crash\n if (now - this.lastCrashTime > this.CRASH_RESET_TIMEOUT) {\n this.workerCrashCount = 0;\n }\n\n this.workerCrashCount++;\n this.lastCrashTime = now;\n\n log.warn(`Worker crashed (${this.workerCrashCount}/${this.MAX_CRASHES_BEFORE_FALLBACK})`);\n\n if (this.workerCrashCount >= this.MAX_CRASHES_BEFORE_FALLBACK) {\n log.error('Worker crashed too many times, giving up');\n throw new Error('Worker has crashed too many times. Please refresh the page or use main thread export.');\n }\n\n // Terminate old worker and clean up resources\n if (this.worker) {\n this.worker.terminate();\n this.worker = null;\n this.isReady = false;\n this.readyPromise = null;\n\n // Revoke old worker blob URL to free memory\n if (this.workerBlobUrl) {\n URL.revokeObjectURL(this.workerBlobUrl);\n this.workerBlobUrl = null;\n }\n }\n\n // Wait a bit before restarting (exponential backoff)\n const backoffDelay = Math.min(1000 * Math.pow(2, this.workerCrashCount - 1), 5000);\n await new Promise((resolve) => setTimeout(resolve, backoffDelay));\n\n // Restart worker\n await this.initialize();\n }\n\n /**\n * Export artboard to data URL using worker\n * Uses request queue for concurrent exports\n */\n async exportArtboardToDataURL(\n artboard: ArtboardElement,\n elements: BaseElement[],\n config: ExportConfig = {}\n ): Promise<WorkerExportResult> {\n // Reset idle timer\n this.resetIdleTimer();\n\n // Add to queue and return promise\n return new Promise<WorkerExportResult>((resolve, reject) => {\n this.requestQueue.push({\n artboard,\n elements,\n config: { ...config, returnFormat: 'dataUrl' },\n resolve,\n reject,\n });\n\n // Start processing queue if not already processing\n this.processQueue();\n });\n }\n\n /**\n * Export artboard to Blob using worker\n * Returns a Blob directly - more efficient for API uploads\n * Uses request queue for concurrent exports\n */\n async exportArtboardToBlob(\n artboard: ArtboardElement,\n elements: BaseElement[],\n config: ExportConfig = {}\n ): Promise<WorkerBlobExportResult> {\n // Reset idle timer\n this.resetIdleTimer();\n\n // Add to blob queue and return promise\n return new Promise<WorkerBlobExportResult>((resolve, reject) => {\n this.blobRequestQueue.push({\n artboard,\n elements,\n config: { ...config, returnFormat: 'blob' },\n resolve,\n reject,\n });\n\n // Start processing queue if not already processing\n this.processBlobQueue();\n });\n }\n\n /**\n * Process the request queue\n */\n private async processQueue(): Promise<void> {\n // If already processing or queue is empty, return\n if (this.isProcessingQueue || this.requestQueue.length === 0) {\n return;\n }\n\n this.isProcessingQueue = true;\n\n while (this.requestQueue.length > 0) {\n const request = this.requestQueue.shift()!;\n\n try {\n const result = await this.executeExportRequest(request);\n request.resolve(result);\n } catch (error) {\n request.reject(error instanceof Error ? error : new Error(String(error)));\n }\n }\n\n this.isProcessingQueue = false;\n }\n\n /**\n * Execute a single export request\n */\n private async executeExportRequest(request: QueuedExportRequest): Promise<WorkerExportResult> {\n const { artboard, elements, config } = request;\n\n // Ensure worker is initialized\n if (!this.worker || !this.isReady) {\n await this.initialize();\n }\n\n if (!this.worker) {\n throw new Error('Worker is not initialized');\n }\n\n // Generate unique request ID\n const requestId = `export-${++this.requestIdCounter}-${Date.now()}`;\n const mainThreadStartTime = performance.now();\n\n // Serialize artboard and elements\n // This returns new bitmaps that need to be registered with the worker\n const { data: serializedData, newBitmaps } = await serializeForWorkerExport(artboard, elements);\n\n // Register any new bitmaps with the worker BEFORE sending export request\n // The worker will cache these and look them up by bitmapCacheKey during export\n if (newBitmaps.length > 0) {\n this.registerBitmapsWithWorker(newBitmaps);\n }\n\n // Create export request message\n // Note: Images are now referenced by bitmapCacheKey, not transferred inline\n const exportRequest: ExportRequestMessage = {\n type: 'export',\n requestId,\n artboardData: serializedData.artboard,\n elements: serializedData.elements,\n fonts: serializedData.fonts,\n scale: config.scale || 1,\n format: config.format || 'png',\n quality: config.quality || 0.95,\n };\n\n // Create promise for this request\n const resultPromise = new Promise<ExportSuccessResponse>((resolve, reject) => {\n this.pendingRequests.set(requestId, {\n requestId,\n resolve,\n reject,\n startTime: mainThreadStartTime,\n returnFormat: 'dataUrl',\n });\n\n // Set timeout for request (30 seconds)\n setTimeout(() => {\n if (this.pendingRequests.has(requestId)) {\n this.pendingRequests.delete(requestId);\n reject(new Error('Export request timeout'));\n }\n }, 30000);\n });\n\n // Send export request to worker (no transferables needed - just JSON)\n this.worker.postMessage(exportRequest);\n\n // Wait for response\n const response = await resultPromise;\n const mainThreadEndTime = performance.now();\n\n // Calculate main thread blocking time (should be minimal, just serialization)\n const mainThreadBlockTime = mainThreadEndTime - mainThreadStartTime;\n\n\n return {\n dataUrl: response.dataUrl,\n artboardId: response.artboardId,\n artboardName: response.artboardName,\n renderTime: response.renderTime,\n totalTime: response.totalTime,\n mainThreadBlockTime,\n };\n }\n\n /**\n * Process the blob request queue\n */\n private async processBlobQueue(): Promise<void> {\n // If already processing or queue is empty, return\n if (this.isProcessingQueue || this.blobRequestQueue.length === 0) {\n return;\n }\n\n this.isProcessingQueue = true;\n\n while (this.blobRequestQueue.length > 0) {\n const request = this.blobRequestQueue.shift()!;\n\n try {\n const result = await this.executeBlobExportRequest(request);\n request.resolve(result);\n } catch (error) {\n request.reject(error instanceof Error ? error : new Error(String(error)));\n }\n }\n\n this.isProcessingQueue = false;\n }\n\n /**\n * Execute a single blob export request\n */\n private async executeBlobExportRequest(request: QueuedBlobExportRequest): Promise<WorkerBlobExportResult> {\n const { artboard, elements, config } = request;\n\n // Ensure worker is initialized\n if (!this.worker || !this.isReady) {\n await this.initialize();\n }\n\n if (!this.worker) {\n throw new Error('Worker is not initialized');\n }\n\n // Generate unique request ID\n const requestId = `export-blob-${++this.requestIdCounter}-${Date.now()}`;\n const mainThreadStartTime = performance.now();\n\n // Serialize artboard and elements\n // This returns new bitmaps that need to be registered with the worker\n const { data: serializedData, newBitmaps } = await serializeForWorkerExport(artboard, elements);\n\n // Register any new bitmaps with the worker BEFORE sending export request\n // The worker will cache these and look them up by bitmapCacheKey during export\n if (newBitmaps.length > 0) {\n this.registerBitmapsWithWorker(newBitmaps);\n }\n\n // Create export request message with blob return format\n // Note: Images are now referenced by bitmapCacheKey, not transferred inline\n const exportRequest: ExportRequestMessage = {\n type: 'export',\n requestId,\n artboardData: serializedData.artboard,\n elements: serializedData.elements,\n fonts: serializedData.fonts,\n scale: config.scale || 1,\n format: config.format || 'png',\n quality: config.quality || 0.95,\n returnFormat: 'blob',\n };\n\n // Create promise for this request\n const resultPromise = new Promise<ExportBlobSuccessResponse>((resolve, reject) => {\n this.pendingRequests.set(requestId, {\n requestId,\n resolve,\n reject,\n startTime: mainThreadStartTime,\n returnFormat: 'blob',\n });\n\n // Set timeout for request (30 seconds)\n setTimeout(() => {\n if (this.pendingRequests.has(requestId)) {\n this.pendingRequests.delete(requestId);\n reject(new Error('Export request timeout'));\n }\n }, 30000);\n });\n\n // Send export request to worker (no transferables needed - just JSON)\n this.worker.postMessage(exportRequest);\n\n // Wait for response\n const response = await resultPromise;\n const mainThreadEndTime = performance.now();\n\n // Calculate main thread blocking time (should be minimal, just serialization)\n const mainThreadBlockTime = mainThreadEndTime - mainThreadStartTime;\n\n // Convert ArrayBuffer back to Blob\n const blob = new Blob([response.blobData], { type: response.mimeType });\n\n\n return {\n blob,\n artboardId: response.artboardId,\n artboardName: response.artboardName,\n renderTime: response.renderTime,\n totalTime: response.totalTime,\n mainThreadBlockTime,\n };\n }\n\n /**\n * Handle messages from worker\n */\n private handleWorkerMessage(message: WorkerResponse): void {\n switch (message.type) {\n case 'exportComplete':\n this.handleExportComplete(message);\n break;\n\n case 'exportBlobComplete':\n this.handleBlobExportComplete(message);\n break;\n\n case 'exportError':\n this.handleExportError(message);\n break;\n\n case 'exportProgress':\n // Emit progress event to listeners\n this.emitProgress({\n requestId: message.requestId,\n progress: message.progress,\n message: message.message,\n });\n break;\n\n case 'ready':\n // Handled in initialize()\n break;\n\n default:\n log.warn('Unknown message type:', message);\n }\n }\n\n /**\n * Handle successful export completion (dataUrl)\n */\n private handleExportComplete(response: ExportSuccessResponse): void {\n const pending = this.pendingRequests.get(response.requestId);\n if (pending && pending.returnFormat === 'dataUrl') {\n pending.resolve(response);\n this.pendingRequests.delete(response.requestId);\n } else if (pending) {\n log.warn('Received dataUrl response for blob request:', response.requestId);\n pending.reject(new Error('Received dataUrl response when expecting blob'));\n this.pendingRequests.delete(response.requestId);\n } else {\n log.warn('Received response for unknown request:', response.requestId);\n }\n }\n\n /**\n * Handle successful blob export completion\n */\n private handleBlobExportComplete(response: ExportBlobSuccessResponse): void {\n const pending = this.pendingRequests.get(response.requestId);\n if (pending && pending.returnFormat === 'blob') {\n pending.resolve(response);\n this.pendingRequests.delete(response.requestId);\n } else if (pending) {\n log.warn('Received blob response for dataUrl request:', response.requestId);\n pending.reject(new Error('Received blob response when expecting dataUrl'));\n this.pendingRequests.delete(response.requestId);\n } else {\n log.warn('Received blob response for unknown request:', response.requestId);\n }\n }\n\n /**\n * Handle export error\n */\n private handleExportError(response: ExportErrorResponse): void {\n const pending = this.pendingRequests.get(response.requestId);\n if (pending) {\n const error = new Error(response.error);\n if (response.stack) {\n error.stack = response.stack;\n }\n pending.reject(error);\n this.pendingRequests.delete(response.requestId);\n } else {\n log.warn('Received error for unknown request:', response.requestId);\n }\n }\n\n /**\n * Handle worker errors\n */\n private async handleWorkerError(error: ErrorEvent): Promise<void> {\n log.error('Worker error:', error);\n\n // Reject all pending requests\n const failedRequests = Array.from(this.pendingRequests.values());\n for (const [requestId, _pending] of this.pendingRequests.entries()) {\n this.pendingRequests.delete(requestId);\n }\n\n // Reset worker state\n this.isReady = false;\n\n // Attempt to restart worker\n try {\n await this.restartWorker();\n\n // If restart succeeded, we can let queued requests retry automatically\n } catch (restartError) {\n log.error('Failed to restart worker:', restartError);\n\n // Reject failed requests since we can't recover\n for (const pending of failedRequests) {\n pending.reject(new Error(`Worker crashed and could not be restarted: ${error.message}`));\n }\n\n // Also reject all queued requests\n while (this.requestQueue.length > 0) {\n const request = this.requestQueue.shift()!;\n request.reject(new Error('Worker crashed and could not be restarted'));\n }\n }\n }\n\n /**\n * Terminate the worker\n */\n terminate(): void {\n // Clear idle timeout\n if (this.idleTimeout) {\n clearTimeout(this.idleTimeout);\n this.idleTimeout = null;\n }\n\n if (this.worker) {\n\n // Reject all pending requests\n for (const [requestId, pending] of this.pendingRequests.entries()) {\n pending.reject(new Error('Worker terminated'));\n this.pendingRequests.delete(requestId);\n }\n\n // Reject all queued requests\n while (this.requestQueue.length > 0) {\n const request = this.requestQueue.shift()!;\n request.reject(new Error('Worker terminated'));\n }\n\n this.worker.terminate();\n this.worker = null;\n this.isReady = false;\n this.readyPromise = null;\n\n // Clear bitmap registration tracking\n // The worker's cache is gone when it terminates, so our tracking should reset too\n clearRegisteredBitmapKeys();\n\n // Unregister callbacks so legacy API doesn't try to talk to dead worker\n unregisterWorkerCacheCallbacks();\n\n // Revoke worker blob URL to free memory\n // This is especially important on iOS Safari which has stricter memory limits\n if (this.workerBlobUrl) {\n URL.revokeObjectURL(this.workerBlobUrl);\n this.workerBlobUrl = null;\n }\n }\n }\n\n /**\n * Get worker status\n */\n getStatus(): {\n isReady: boolean;\n pendingRequests: number;\n queuedRequests: number;\n crashCount: number;\n } {\n return {\n isReady: this.isReady,\n pendingRequests: this.pendingRequests.size,\n queuedRequests: this.requestQueue.length,\n crashCount: this.workerCrashCount,\n };\n }\n}\n\n// ============================================================================\n// Singleton Instance (Optional)\n// ============================================================================\n\nlet sharedInstance: WorkerExportManager | null = null;\n\n/**\n * Get the shared singleton `WorkerExportManager` instance.\n *\n * Creates the instance on first call. The shared instance is used internally\n * by `ExportManager` and is the recommended way to access the worker for\n * advanced cache control (e.g., `getSharedWorkerExportManager().clearWorkerBitmapCache()`).\n *\n * @returns The shared WorkerExportManager instance\n */\nexport function getSharedWorkerExportManager(): WorkerExportManager {\n if (!sharedInstance) {\n sharedInstance = new WorkerExportManager();\n }\n return sharedInstance;\n}\n\n/**\n * Terminate the shared `WorkerExportManager` instance and release its Web Worker.\n *\n * Call this during app cleanup to free worker resources. The next call to\n * `getSharedWorkerExportManager()` will create a fresh instance.\n */\nexport function terminateSharedWorkerExportManager(): void {\n if (sharedInstance) {\n sharedInstance.terminate();\n sharedInstance = null;\n }\n}\n","/**\n * ExportManager - High-level API for workspace and artboard export.\n *\n * Provides static methods for:\n * - **JSON export/import** of the entire workspace (artboards + elements)\n * - **Image export** of individual artboards as data URL, Blob, or downloadable file\n * - **Worker-accelerated export** via OffscreenCanvas (non-blocking, auto-fallback)\n *\n * For React components, prefer the `useExport` hook which wraps this class\n * with React state management. Use `ExportManager` directly in non-React code\n * or for advanced export workflows.\n *\n * @example\n * ```ts\n * import { ExportManager } from '@snowcone-app/canvas';\n *\n * // Export artboard as data URL\n * const dataUrl = await ExportManager.exportArtboardToDataURL(\n * artboard, elements, canvasEl, { scale: 3, format: 'png' }\n * );\n *\n * // Export entire workspace as JSON\n * ExportManager.exportWorkspace(artboardManager, elements);\n * ```\n *\n * @module\n */\n\nimport type { ArtboardElement } from '../core/ArtboardElement.js';\nimport type { TextElement } from '../core/TextElement.js';\nimport type { ImageElement } from '../core/ImageElement.js';\nimport type { GroupElement } from '../core/GroupElement.js';\nimport type { ShapeElement } from '../core/ShapeElement.js';\nimport type { PathElement } from '../core/PathElement.js';\nimport type { ArtboardManager } from '../core/ArtboardManager.js';\nimport type { AnyElementConfig } from '../types/index.js';\n\n/** Union of all element types supported by export */\ntype ExportElement = TextElement | ImageElement | GroupElement | ShapeElement | PathElement;\nimport { WorkerExportManager } from './WorkerExportManager.js';\nimport { renderWithCompositing } from '../rendering/CompositingRenderer.js';\nimport type { CompositeOp } from '../rendering/CompositingRenderer.js';\nimport { applyArtboardDistressTexture, applyElementDistressTexture } from '../rendering/DistressTextureRenderer.js';\nimport { applyArtboardImageMask, renderWithMasks } from '../rendering/MaskRenderer.js';\nimport { TextureManager } from './TextureManager.js';\nimport { createLogger } from './logger.js';\n\nconst log = createLogger('Export');\n\n/**\n * Recursively collect every fontFamily referenced by an element (and its\n * group children / mask children / rich-text spans). Used by the main-thread\n * export fallback to pre-load fonts before rendering — without this, a\n * freshly-created detached `<canvas>` on iOS Safari renders with the serif\n * fallback even when the on-screen canvas paints the same font correctly.\n */\nfunction collectElementFontFamilies(\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n el: any,\n out: Set<string>\n): void {\n if (!el || typeof el !== 'object') return;\n if (typeof el.fontFamily === 'string' && el.fontFamily.trim()) {\n out.add(el.fontFamily);\n }\n // Rich-text spans may carry per-character font families\n if (el.richText && Array.isArray(el.richText.spans)) {\n for (const span of el.richText.spans) {\n if (span?.style?.fontFamily && typeof span.style.fontFamily === 'string') {\n out.add(span.style.fontFamily);\n }\n }\n }\n // Group children\n if (Array.isArray(el.children)) {\n for (const child of el.children) collectElementFontFamilies(child, out);\n }\n // Mask elements\n if (Array.isArray(el.masks)) {\n for (const m of el.masks) {\n if (m?.maskElement) collectElementFontFamilies(m.maskElement, out);\n }\n }\n}\n\n/**\n * Pre-load every font used by `elements` and wait for activation.\n *\n * iOS Safari quirk: a `<canvas>` created via `document.createElement('canvas')`\n * (used by `mainThreadExportToBlob`) is *detached* — never inserted into the\n * DOM. Safari activates fonts lazily on first DOM-attached use, so the\n * detached canvas's first `fillText(\"...\", ...)` paints with the fallback\n * even when the on-screen canvas is rendering the same family correctly.\n *\n * Calling `document.fonts.load(\"size family\")` for each (size, family) pair\n * forces Safari to activate the fontface for that specifier, then awaiting\n * `document.fonts.ready` flushes any in-flight activation work. Safe on every\n * other browser since `load()` resolves immediately for already-loaded fonts.\n */\nasync function ensureFontsLoadedForExport(\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n elements: any[]\n): Promise<void> {\n if (typeof document === 'undefined' || !document.fonts) return;\n const families = new Set<string>();\n for (const el of elements) collectElementFontFamilies(el, families);\n if (families.size === 0) return;\n const loadPromises: Promise<unknown>[] = [];\n for (const family of families) {\n // 16px is enough — once the font file is in the FontFaceSet it serves all sizes.\n loadPromises.push(document.fonts.load(`16px \"${family}\"`).catch(() => undefined));\n }\n await Promise.all(loadPromises);\n if (document.fonts.ready) await document.fonts.ready;\n}\n\n/** Serialized workspace document for JSON import/export. */\nexport interface CanvasDocument {\n metadata: {\n version: string;\n timestamp: string;\n appVersion?: string;\n };\n artboards: Array<{\n id: string;\n name: string;\n x: number;\n y: number;\n width: number;\n height: number;\n backgroundColor: string;\n elements: AnyElementConfig[];\n }>;\n activeArtboardId: string | null;\n}\n\n/** Options for image export operations. */\nexport interface ExportImageOptions {\n /** Image format. Default: `'png'`. */\n format?: 'png' | 'jpg' | 'jpeg' | 'webp';\n /** Compression quality for JPEG/WebP (0-1). Ignored for PNG. Default: 0.92. */\n quality?: number;\n /** Resolution multiplier (1x, 2x, 3x). Default: 3. */\n scale?: number;\n /** Export with transparent background. Should be `true` for print-on-demand designs. Default: true. */\n transparentBackground?: boolean;\n /** Background color when `transparentBackground` is false. */\n backgroundColor?: string;\n /** Suggested filename for downloads. */\n filename?: string;\n /** Force main-thread rendering (skip Web Worker). Useful for debugging. */\n forceMainThread?: boolean;\n // CRITICAL: Preview backgrounds (artboard.previewBackgroundColor) are NEVER exported\n // This is handled automatically - only artboard.backgroundColor is used\n}\n\n/**\n * Static utility class for exporting workspace data and artboard images.\n *\n * All methods are static -- there is no need to instantiate this class.\n * Internally delegates to {@link WorkerExportManager} for non-blocking\n * image exports when the browser supports `OffscreenCanvas`.\n */\nexport class ExportManager {\n private static readonly CURRENT_VERSION = '2.0.0'; // Version 2 includes artboards\n\n // Worker export manager (lazily initialized)\n private static workerManager: WorkerExportManager | null = null;\n private static workerInitPromise: Promise<void> | null = null;\n\n /**\n * Check if worker export is supported in this browser\n */\n static supportsWorkerExport(): boolean {\n return WorkerExportManager.supportsWorkerExport();\n }\n\n /**\n * Get or initialize the worker manager\n */\n private static async getWorkerManager(): Promise<WorkerExportManager | null> {\n if (!this.supportsWorkerExport()) {\n return null;\n }\n\n if (this.workerManager) {\n return this.workerManager;\n }\n\n // If initialization is already in progress, wait for it\n if (this.workerInitPromise) {\n await this.workerInitPromise;\n return this.workerManager;\n }\n\n // Initialize worker\n this.workerInitPromise = (async () => {\n try {\n this.workerManager = new WorkerExportManager();\n await this.workerManager.initialize();\n } catch (error) {\n log.error('Failed to initialize worker:', error);\n this.workerManager = null;\n }\n })();\n\n await this.workerInitPromise;\n this.workerInitPromise = null;\n\n return this.workerManager;\n }\n\n /**\n * Terminate the worker (for cleanup)\n */\n static terminateWorker(): void {\n if (this.workerManager) {\n this.workerManager.terminate();\n this.workerManager = null;\n }\n }\n\n /**\n * Export entire workspace to JSON\n */\n static exportToJSON(\n artboards: ArtboardElement[],\n elements: ExportElement[],\n artboardManager: ArtboardManager,\n filename?: string\n ): void {\n // Create document structure\n const document: CanvasDocument = {\n metadata: {\n version: this.CURRENT_VERSION,\n timestamp: new Date().toISOString(),\n appVersion: '1.0.0',\n },\n artboards: artboards.map((artboard) => {\n // Get elements for this artboard\n // PERFORMANCE: Use Set for O(1) lookup instead of O(n) includes()\n const elementIds = new Set(artboard.getElementIds());\n const artboardElements = elements.filter((e) => elementIds.has(e.id));\n\n return {\n id: artboard.id,\n name: artboard.name,\n x: artboard.x,\n y: artboard.y,\n width: artboard.width,\n height: artboard.height,\n backgroundColor: artboard.backgroundColor,\n elements: artboardElements.map((e) => e.toJSON()) as AnyElementConfig[],\n };\n }),\n activeArtboardId: artboardManager.getActiveArtboardId(),\n };\n\n // Convert to JSON string\n const jsonString = JSON.stringify(document, null, 2);\n\n // Create blob\n const blob = new Blob([jsonString], { type: 'application/json' });\n\n // Generate filename\n const timestamp = new Date().toISOString().replace(/[:.]/g, '-').split('T')[0];\n const finalFilename = filename || `canvas-${timestamp}.json`;\n\n // Trigger download\n this.downloadBlob(blob, finalFilename);\n }\n\n /**\n * Export artboard to image\n * Uses worker if supported, falls back to main thread\n */\n static async exportArtboardToImage(\n artboard: ArtboardElement,\n elements: ExportElement[],\n canvasElement: HTMLCanvasElement,\n options: ExportImageOptions = {}\n ): Promise<void> {\n const {\n format = 'png',\n quality = 0.95,\n scale = 1,\n transparentBackground = false,\n backgroundColor = artboard.backgroundColor,\n filename,\n forceMainThread = false,\n } = options;\n\n // Export to data URL using worker or main thread\n const dataUrl = await this.exportArtboardToDataURL(artboard, elements, canvasElement, {\n format,\n quality,\n scale,\n transparentBackground,\n backgroundColor,\n forceMainThread,\n });\n\n // Convert to blob and download\n const blob = await this.dataUrlToBlob(dataUrl);\n const timestamp = new Date().toISOString().replace(/[:.]/g, '-').split('T')[0];\n const finalFilename = filename || `${artboard.name}-${timestamp}.${format}`;\n\n this.downloadBlob(blob, finalFilename);\n }\n\n /**\n * Export artboard to data URL (for preview/testing)\n * Uses worker if supported, falls back to main thread\n */\n static async exportArtboardToDataURL(\n artboard: ArtboardElement,\n elements: ExportElement[],\n canvasElement: HTMLCanvasElement,\n options: ExportImageOptions = {}\n ): Promise<string> {\n const {\n format = 'png',\n quality = 0.95,\n scale = 1,\n transparentBackground = false,\n backgroundColor = artboard.backgroundColor,\n forceMainThread = false,\n } = options;\n\n // Try worker export first (unless forced to use main thread)\n if (!forceMainThread && this.supportsWorkerExport()) {\n try {\n const workerManager = await this.getWorkerManager();\n\n if (workerManager) {\n\n // Get elements for this artboard\n const artboardElementIds = new Set(artboard.getElementIds());\n const artboardElements = elements.filter((e) => artboardElementIds.has(e.id));\n\n const result = await workerManager.exportArtboardToDataURL(artboard, artboardElements, {\n scale,\n format: format === 'jpg' ? 'jpeg' : format,\n quality,\n });\n\n return result.dataUrl;\n }\n } catch (error) {\n log.warn('Worker export failed, falling back to main thread:', error);\n // Fall through to main thread export\n }\n }\n\n // Fallback: Main thread export\n return this.mainThreadExportToDataURL(artboard, elements, canvasElement, {\n format,\n quality,\n scale,\n transparentBackground,\n backgroundColor,\n });\n }\n\n /**\n * Export artboard as Blob (more efficient for API uploads)\n * Returns a Blob instead of data URL - smaller payload, faster for network operations\n * Uses worker if supported, falls back to main thread\n */\n static async exportArtboardToBlob(\n artboard: ArtboardElement,\n elements: ExportElement[],\n canvasElement: HTMLCanvasElement,\n options: ExportImageOptions = {}\n ): Promise<Blob> {\n const {\n format = 'png',\n quality = 0.95,\n scale = 1,\n transparentBackground = false,\n backgroundColor = artboard.backgroundColor,\n forceMainThread = false,\n } = options;\n\n // Try worker export first (unless forced to use main thread)\n if (!forceMainThread && this.supportsWorkerExport()) {\n try {\n const workerManager = await this.getWorkerManager();\n\n if (workerManager) {\n const artboardElementIds = new Set(artboard.getElementIds());\n const artboardElements = elements.filter((e) => artboardElementIds.has(e.id));\n\n const result = await workerManager.exportArtboardToBlob(artboard, artboardElements, {\n scale,\n format: format === 'jpg' ? 'jpeg' : format,\n quality,\n });\n\n return result.blob;\n }\n } catch (error) {\n log.warn('Worker blob export failed, falling back to main thread:', error);\n }\n }\n\n // Fallback: Main thread export\n return this.mainThreadExportToBlob(artboard, elements, canvasElement, {\n format,\n quality,\n scale,\n transparentBackground,\n backgroundColor,\n });\n }\n\n /**\n * Main thread export to Blob (fallback/legacy method).\n *\n * On iOS WebKit this is also the *primary* path (`isIOSWebKit()` skips the\n * worker), so font readiness matters here even when no fallback occurred.\n */\n private static async mainThreadExportToBlob(\n artboard: ArtboardElement,\n elements: ExportElement[],\n _canvasElement: HTMLCanvasElement,\n options: ExportImageOptions = {}\n ): Promise<Blob> {\n const {\n format = 'png',\n quality = 0.95,\n scale = 1,\n transparentBackground = false,\n backgroundColor = artboard.backgroundColor,\n } = options;\n\n // CRITICAL: Pre-load every font referenced by the elements before rendering.\n // The detached `<canvas>` we create below is never DOM-attached; iOS Safari\n // activates fonts lazily on first DOM use, so without this the offscreen\n // canvas paints text with the serif fallback even when the on-screen\n // canvas is rendering the same family correctly. See\n // `ensureFontsLoadedForExport` for the full reasoning.\n await ensureFontsLoadedForExport(elements);\n\n // Create offscreen canvas at artboard dimensions\n const offscreenCanvas = document.createElement('canvas');\n const width = artboard.width * scale;\n const height = artboard.height * scale;\n offscreenCanvas.width = width;\n offscreenCanvas.height = height;\n\n const ctx = offscreenCanvas.getContext('2d')!;\n ctx.scale(scale, scale);\n\n // Draw background if not transparent AND exportBackground is enabled\n if (!transparentBackground && artboard.exportBackground) {\n ctx.save();\n this.applyExportBackgroundClipPath(ctx, artboard);\n\n if (artboard.backgroundType === 'texture' && artboard.backgroundTexture) {\n const presetColor = TextureManager.getTexturePresetColor(artboard.backgroundTexture);\n ctx.fillStyle = presetColor;\n ctx.fillRect(0, 0, artboard.width, artboard.height);\n\n const texture = TextureManager.getTexture(artboard.backgroundTexture);\n if (texture && texture.complete) {\n ctx.drawImage(texture, 0, 0, artboard.width, artboard.height);\n }\n } else {\n ctx.fillStyle = backgroundColor || artboard.backgroundColor;\n ctx.fillRect(0, 0, artboard.width, artboard.height);\n }\n\n ctx.restore();\n }\n\n // Translate to artboard origin\n ctx.save();\n ctx.translate(-artboard.x, -artboard.y);\n\n // Clip to artboard bounds (respecting clipShape)\n this.applyExportClipPath(ctx, artboard);\n\n // Get elements for this artboard\n const artboardElementIds = new Set(artboard.getElementIds());\n const artboardElements = elements.filter((e) => artboardElementIds.has(e.id));\n\n // Create a map from element ID to actual element instance\n const elementMap = new Map<string, ExportElement>();\n artboardElements.forEach((el) => elementMap.set(el.id, el));\n\n // Helper to render actual element instance\n const renderElement = (\n ctx: CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D,\n config: AnyElementConfig\n ) => {\n if (!config.id) return;\n const actualElement = elementMap.get(config.id);\n if (actualElement) {\n actualElement.render(ctx as CanvasRenderingContext2D, false);\n }\n };\n\n // Convert all elements to JSON for compositing processing\n const allElementConfigs = artboardElements.map((e) => e.toJSON()) as AnyElementConfig[];\n const knockoutRenderedIds = new Set<string>();\n\n // First pass: render compositing elements (knockout and clip)\n artboardElements.forEach((element, index) => {\n if (element.blendMode === 'knockout' || element.blendMode === 'clip') {\n const elementConfig = allElementConfigs[index];\n const compositeOp: CompositeOp = element.blendMode === 'knockout' ? 'destination-out' : 'destination-in';\n\n // Get affected elements and mark them as rendered\n const scope = elementConfig.knockoutParts?.scope || 'group';\n const compositingIndex = allElementConfigs.findIndex((el) => el.id === elementConfig.id);\n if (compositingIndex !== -1) {\n if (scope === 'artboard') {\n for (let i = 0; i < compositingIndex; i++) {\n const id = allElementConfigs[i].id;\n if (id) knockoutRenderedIds.add(id);\n }\n }\n }\n\n renderWithCompositing(\n ctx,\n elementConfig,\n allElementConfigs,\n renderElement,\n transparentBackground || !artboard.exportBackground ? undefined : backgroundColor,\n artboard,\n compositeOp\n );\n\n knockoutRenderedIds.add(element.id);\n }\n });\n\n // Second pass: render normal elements\n artboardElements.forEach((element) => {\n if (!knockoutRenderedIds.has(element.id)) {\n element.render(ctx, false);\n }\n });\n\n ctx.restore();\n\n // Convert to blob\n return new Promise<Blob>((resolve, reject) => {\n offscreenCanvas.toBlob(\n (blob) => {\n if (blob) {\n resolve(blob);\n } else {\n reject(new Error('Failed to create blob from canvas'));\n }\n },\n format === 'jpg' || format === 'jpeg' ? 'image/jpeg' : format === 'webp' ? 'image/webp' : 'image/png',\n quality\n );\n });\n }\n\n /**\n * Main thread export to data URL (fallback/legacy method).\n *\n * On iOS WebKit this is also the *primary* path (`isIOSWebKit()` skips the\n * worker), so font readiness matters here even when no fallback occurred.\n */\n private static async mainThreadExportToDataURL(\n artboard: ArtboardElement,\n elements: ExportElement[],\n _canvasElement: HTMLCanvasElement,\n options: ExportImageOptions = {}\n ): Promise<string> {\n const {\n format = 'png',\n quality = 0.95,\n scale = 1,\n transparentBackground = false,\n backgroundColor = artboard.backgroundColor,\n } = options;\n\n // CRITICAL: pre-load element fonts before rendering — see\n // `mainThreadExportToBlob` for the iOS Safari font-activation reasoning.\n await ensureFontsLoadedForExport(elements);\n\n // Create offscreen canvas at artboard dimensions\n const offscreenCanvas = document.createElement('canvas');\n const width = artboard.width * scale;\n const height = artboard.height * scale;\n offscreenCanvas.width = width;\n offscreenCanvas.height = height;\n\n const ctx = offscreenCanvas.getContext('2d')!;\n ctx.scale(scale, scale);\n\n // Draw background if not transparent AND exportBackground is enabled\n // Background is clipped to the artboard's clipShape\n if (!transparentBackground && artboard.exportBackground) {\n ctx.save();\n // Apply clip for background (coordinates are 0,0 relative since we haven't translated yet)\n this.applyExportBackgroundClipPath(ctx, artboard);\n\n // Check if artboard has a texture background\n if (artboard.backgroundType === 'texture' && artboard.backgroundTexture) {\n // Render preset color for this texture\n const presetColor = TextureManager.getTexturePresetColor(artboard.backgroundTexture);\n ctx.fillStyle = presetColor;\n ctx.fillRect(0, 0, artboard.width, artboard.height);\n\n // Render texture on top (if already loaded)\n const texture = TextureManager.getTexture(artboard.backgroundTexture);\n if (texture && texture.complete) {\n ctx.drawImage(texture, 0, 0, artboard.width, artboard.height);\n } else {\n // Texture not loaded - it should already be loaded by the time we export\n log.warn('Texture not loaded for export:', artboard.backgroundTexture);\n }\n } else {\n // Solid color background\n ctx.fillStyle = backgroundColor;\n ctx.fillRect(0, 0, artboard.width, artboard.height);\n }\n\n ctx.restore();\n }\n\n // Translate to artboard origin\n ctx.save();\n ctx.translate(-artboard.x, -artboard.y);\n\n // Clip to artboard bounds (respecting clipShape)\n this.applyExportClipPath(ctx, artboard);\n\n // Render elements within this artboard\n const artboardElementIds = new Set(artboard.getElementIds());\n const artboardElements = elements.filter((e) => artboardElementIds.has(e.id));\n\n // Create a map from element ID to actual element instance (preserves loaded images, etc.)\n const elementMap = new Map<string, ExportElement>();\n artboardElements.forEach((el) => elementMap.set(el.id, el));\n\n // Helper to render actual element instance\n const renderElement = (\n ctx: CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D,\n config: AnyElementConfig\n ) => {\n if (!config.id) return;\n const actualElement = elementMap.get(config.id);\n if (actualElement) {\n actualElement.render(ctx as CanvasRenderingContext2D, false);\n } else {\n log.warn('Element not found in map:', config.id);\n }\n };\n\n // Convert all elements to JSON for compositing processing\n const allElementConfigs = artboardElements.map((e) => e.toJSON()) as AnyElementConfig[];\n const knockoutRenderedIds = new Set<string>();\n\n // First pass: render compositing elements (knockout and clip)\n artboardElements.forEach((element, index) => {\n if (element.blendMode === 'knockout' || element.blendMode === 'clip') {\n const elementConfig = allElementConfigs[index];\n const compositeOp: CompositeOp = element.blendMode === 'knockout' ? 'destination-out' : 'destination-in';\n\n // Get affected elements and mark them as rendered\n const scope = elementConfig.knockoutParts?.scope || 'group';\n const compositingIndex = allElementConfigs.findIndex((el) => el.id === elementConfig.id);\n if (compositingIndex !== -1) {\n if (scope === 'artboard') {\n // Mark all elements below this one as rendered (they're part of compositing)\n for (let i = 0; i < compositingIndex; i++) {\n const id = allElementConfigs[i].id;\n if (id) knockoutRenderedIds.add(id);\n }\n }\n }\n\n renderWithCompositing(\n ctx,\n elementConfig,\n allElementConfigs,\n renderElement,\n transparentBackground || !artboard.exportBackground ? undefined : backgroundColor,\n artboard,\n compositeOp\n );\n\n knockoutRenderedIds.add(element.id);\n }\n });\n\n // Second pass: render normal elements (with per-element effects)\n artboardElements.forEach((element, index) => {\n if (!knockoutRenderedIds.has(element.id)) {\n const elementConfig = allElementConfigs[index];\n const hasDistress = elementConfig?.distressEffect?.enabled &&\n elementConfig.distressEffect.style === 'custom' &&\n elementConfig.distressEffect.textureUrl;\n const hasMasks = elementConfig?.masks && elementConfig.masks.length > 0;\n\n const baseRenderFn = (renderCtx: CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D) => {\n element.render(renderCtx as CanvasRenderingContext2D, false);\n };\n\n if (hasMasks && hasDistress) {\n renderWithMasks(ctx, elementConfig, (maskCtx) => {\n const bbox = element.getVisualBoundingBox();\n applyElementDistressTexture(maskCtx, elementConfig.distressEffect!, bbox, baseRenderFn);\n });\n } else if (hasMasks) {\n renderWithMasks(ctx, elementConfig, baseRenderFn);\n } else if (hasDistress) {\n const bbox = element.getVisualBoundingBox();\n applyElementDistressTexture(ctx, elementConfig.distressEffect!, bbox, baseRenderFn);\n } else {\n element.render(ctx, false);\n }\n }\n });\n\n // Apply artboard-level distress texture (after all elements, before restore)\n if (artboard.distressTexture?.enabled) {\n applyArtboardDistressTexture(ctx, artboard.distressTexture, {\n x: artboard.x,\n y: artboard.y,\n width: artboard.width,\n height: artboard.height,\n });\n }\n\n // Apply artboard-level image mask (after distress, before restore)\n if (artboard.imageMask?.enabled) {\n applyArtboardImageMask(ctx, artboard.imageMask, {\n x: artboard.x,\n y: artboard.y,\n width: artboard.width,\n height: artboard.height,\n });\n }\n\n ctx.restore();\n\n // Convert to data URL and return\n const mimeType = format === 'png' ? 'image/png' : format === 'webp' ? 'image/webp' : 'image/jpeg';\n return offscreenCanvas.toDataURL(mimeType, quality);\n }\n\n /**\n * Apply clip path for export background (uses 0,0 as origin since background is drawn before translate)\n */\n private static applyExportBackgroundClipPath(ctx: CanvasRenderingContext2D, artboard: ArtboardElement): void {\n const { width, height, clipShape } = artboard;\n const x = 0;\n const y = 0;\n\n ctx.beginPath();\n\n // No clip shape or 'rectangle' = standard rectangular clip\n if (!clipShape || clipShape === 'rectangle') {\n ctx.rect(x, y, width, height);\n } else if (clipShape === 'circle') {\n // Circle inscribed in artboard\n const centerX = x + width / 2;\n const centerY = y + height / 2;\n const radius = Math.min(width, height) / 2;\n ctx.arc(centerX, centerY, radius, 0, Math.PI * 2);\n } else if (typeof clipShape === 'object' && clipShape.type === 'rounded') {\n // Rounded rectangle\n const radius = Math.min(clipShape.radius, Math.min(width, height) / 2);\n if (typeof ctx.roundRect === 'function') {\n ctx.roundRect(x, y, width, height, radius);\n } else {\n ctx.moveTo(x + radius, y);\n ctx.lineTo(x + width - radius, y);\n ctx.arcTo(x + width, y, x + width, y + radius, radius);\n ctx.lineTo(x + width, y + height - radius);\n ctx.arcTo(x + width, y + height, x + width - radius, y + height, radius);\n ctx.lineTo(x + radius, y + height);\n ctx.arcTo(x, y + height, x, y + height - radius, radius);\n ctx.lineTo(x, y + radius);\n ctx.arcTo(x, y, x + radius, y, radius);\n }\n } else if (typeof clipShape === 'object' && clipShape.type === 'path') {\n try {\n const path = new Path2D(clipShape.d);\n ctx.clip(path);\n return;\n } catch (e) {\n log.warn('Invalid SVG path, falling back to rectangle:', e);\n ctx.rect(x, y, width, height);\n }\n }\n\n ctx.clip();\n }\n\n /**\n * Apply clip path for export based on artboard's clipShape\n * This creates the clip region for the given artboard during export\n */\n private static applyExportClipPath(ctx: CanvasRenderingContext2D, artboard: ArtboardElement): void {\n const { x, y, width, height, clipShape } = artboard;\n\n ctx.beginPath();\n\n // No clip shape or 'rectangle' = standard rectangular clip\n if (!clipShape || clipShape === 'rectangle') {\n ctx.rect(x, y, width, height);\n } else if (clipShape === 'circle') {\n // Circle inscribed in artboard\n const centerX = x + width / 2;\n const centerY = y + height / 2;\n const radius = Math.min(width, height) / 2;\n ctx.arc(centerX, centerY, radius, 0, Math.PI * 2);\n } else if (typeof clipShape === 'object' && clipShape.type === 'rounded') {\n // Rounded rectangle\n const radius = Math.min(clipShape.radius, Math.min(width, height) / 2);\n // Use built-in roundRect if available\n if (typeof ctx.roundRect === 'function') {\n ctx.roundRect(x, y, width, height, radius);\n } else {\n // Fallback for older browsers\n ctx.moveTo(x + radius, y);\n ctx.lineTo(x + width - radius, y);\n ctx.arcTo(x + width, y, x + width, y + radius, radius);\n ctx.lineTo(x + width, y + height - radius);\n ctx.arcTo(x + width, y + height, x + width - radius, y + height, radius);\n ctx.lineTo(x + radius, y + height);\n ctx.arcTo(x, y + height, x, y + height - radius, radius);\n ctx.lineTo(x, y + radius);\n ctx.arcTo(x, y, x + radius, y, radius);\n }\n } else if (typeof clipShape === 'object' && clipShape.type === 'path') {\n // Custom SVG path - use Path2D for parsing\n try {\n const path = new Path2D(clipShape.d);\n // Translate the path to artboard position\n ctx.translate(x, y);\n ctx.clip(path);\n ctx.translate(-x, -y);\n return; // Path2D handles the clip itself\n } catch (e) {\n log.warn('Invalid SVG path, falling back to rectangle:', e);\n ctx.rect(x, y, width, height);\n }\n }\n\n ctx.clip();\n }\n\n /**\n * Export all artboards as separate images (HIGH PERFORMANCE - parallel rendering)\n */\n static async exportAllArtboardsToImages(\n artboards: ArtboardElement[],\n elements: ExportElement[],\n canvasElement: HTMLCanvasElement,\n options: ExportImageOptions = {}\n ): Promise<void> {\n // PERFORMANCE OPTIMIZATION: Export all artboards in parallel instead of sequentially\n // This dramatically improves export speed for multiple artboards\n const exportPromises = artboards.map((artboard) =>\n this.exportArtboardToImage(artboard, elements, canvasElement, {\n ...options,\n filename: options.filename ? `${options.filename}-${artboard.name}.${options.format || 'png'}` : undefined,\n })\n );\n\n await Promise.all(exportPromises);\n }\n\n /**\n * Download a blob as a file\n */\n private static downloadBlob(blob: Blob, filename: string): void {\n const url = URL.createObjectURL(blob);\n const link = document.createElement('a');\n link.href = url;\n link.download = filename;\n document.body.appendChild(link);\n link.click();\n document.body.removeChild(link);\n URL.revokeObjectURL(url);\n }\n\n /**\n * Convert data URL to blob\n */\n private static async dataUrlToBlob(dataUrl: string): Promise<Blob> {\n const response = await fetch(dataUrl);\n return response.blob();\n }\n\n /**\n * Get export summary (for UI display)\n */\n static getExportSummary(\n artboards: ArtboardElement[],\n elements: ExportElement[]\n ): {\n artboardCount: number;\n totalElementCount: number;\n estimatedFileSize: string;\n } {\n const artboardCount = artboards.length;\n const totalElementCount = elements.length;\n\n // Rough estimate of JSON file size (in KB)\n const avgElementSize = 500; // bytes per element (rough estimate)\n const avgArtboardSize = 200; // bytes per artboard\n const estimatedBytes = artboardCount * avgArtboardSize + totalElementCount * avgElementSize;\n const estimatedKB = Math.ceil(estimatedBytes / 1024);\n\n return {\n artboardCount,\n totalElementCount,\n estimatedFileSize: estimatedKB < 1024 ? `${estimatedKB} KB` : `${(estimatedKB / 1024).toFixed(1)} MB`,\n };\n }\n\n /**\n * Performance benchmark: Compare worker vs main thread export\n * Returns timing data for both methods\n */\n static async benchmarkExport(\n artboard: ArtboardElement,\n elements: ExportElement[],\n canvasElement: HTMLCanvasElement,\n options: ExportImageOptions = {}\n ): Promise<{\n workerSupported: boolean;\n mainThread: {\n time: number;\n dataUrl: string;\n };\n worker?: {\n time: number;\n dataUrl: string;\n mainThreadBlockTime: number;\n };\n speedup?: number;\n recommendation: string;\n }> {\n\n // Benchmark main thread export\n const mainThreadStart = performance.now();\n const mainThreadDataUrl = await this.exportArtboardToDataURL(artboard, elements, canvasElement, {\n ...options,\n forceMainThread: true,\n });\n const mainThreadTime = performance.now() - mainThreadStart;\n\n const result = {\n workerSupported: this.supportsWorkerExport(),\n mainThread: {\n time: mainThreadTime,\n dataUrl: mainThreadDataUrl,\n },\n recommendation: '',\n };\n\n // Benchmark worker export if supported\n if (this.supportsWorkerExport()) {\n try {\n const workerStart = performance.now();\n\n // Get worker manager (will initialize if needed)\n const workerManager = await this.getWorkerManager();\n\n if (workerManager) {\n const artboardElementIds = new Set(artboard.getElementIds());\n const artboardElements = elements.filter((e) => artboardElementIds.has(e.id));\n\n const workerResult = await workerManager.exportArtboardToDataURL(artboard, artboardElements, {\n scale: options.scale || 1,\n format: (options.format === 'jpg' ? 'jpeg' : options.format) || 'png',\n quality: options.quality || 0.95,\n });\n\n const workerTime = performance.now() - workerStart;\n const speedup = mainThreadTime / workerTime;\n\n return {\n ...result,\n worker: {\n time: workerTime,\n dataUrl: workerResult.dataUrl,\n mainThreadBlockTime: workerResult.mainThreadBlockTime,\n },\n speedup,\n recommendation:\n speedup > 1.2\n ? `Worker export is ${speedup.toFixed(2)}x faster - recommended for continuous export`\n : speedup < 0.8\n ? `Main thread export is ${(1 / speedup).toFixed(2)}x faster - worker overhead not worth it for single exports`\n : 'Performance is similar, but worker keeps UI responsive during export',\n };\n }\n } catch (error) {\n log.error('Worker benchmark failed:', error);\n result.recommendation = 'Worker export not available - using main thread export';\n }\n } else {\n result.recommendation = 'Worker export not supported in this browser - using main thread export';\n }\n\n return result;\n }\n\n /**\n * Performance benchmark: Test continuous exports to measure UI impact\n * Returns statistics about export performance over time\n */\n static async benchmarkContinuousExport(\n artboard: ArtboardElement,\n elements: ExportElement[],\n canvasElement: HTMLCanvasElement,\n options: {\n duration?: number; // Duration in milliseconds\n interval?: number; // Interval between exports in milliseconds\n useWorker?: boolean;\n } = {}\n ): Promise<{\n totalExports: number;\n duration: number;\n averageTime: number;\n minTime: number;\n maxTime: number;\n totalMainThreadBlockTime: number;\n exportsPerSecond: number;\n recommendation: string;\n }> {\n const {\n duration = 5000, // 5 seconds\n interval = 500, // Every 500ms\n useWorker = this.supportsWorkerExport(),\n } = options;\n\n\n const exportTimes: number[] = [];\n let totalMainThreadBlockTime = 0;\n let running = true;\n\n // Stop after duration\n setTimeout(() => {\n running = false;\n }, duration);\n\n // Export continuously\n while (running) {\n const start = performance.now();\n\n await this.exportArtboardToDataURL(artboard, elements, canvasElement, {\n forceMainThread: !useWorker,\n });\n\n const time = performance.now() - start;\n exportTimes.push(time);\n\n if (!useWorker) {\n // Main thread export blocks the main thread for the entire duration\n totalMainThreadBlockTime += time;\n }\n\n // Wait for interval\n await new Promise((resolve) => setTimeout(resolve, Math.max(0, interval - time)));\n }\n\n const totalExports = exportTimes.length;\n const averageTime = exportTimes.reduce((sum, t) => sum + t, 0) / totalExports;\n const minTime = Math.min(...exportTimes);\n const maxTime = Math.max(...exportTimes);\n const exportsPerSecond = (totalExports / duration) * 1000;\n\n const blockPercent = (totalMainThreadBlockTime / duration) * 100;\n const recommendation =\n blockPercent > 20\n ? `Main thread blocked ${blockPercent.toFixed(1)}% of the time - STRONGLY recommend worker export`\n : blockPercent > 10\n ? `Main thread blocked ${blockPercent.toFixed(1)}% of the time - consider worker export`\n : `Main thread blocked ${blockPercent.toFixed(1)}% of the time - performance is acceptable`;\n\n return {\n totalExports,\n duration,\n averageTime,\n minTime,\n maxTime,\n totalMainThreadBlockTime,\n exportsPerSecond,\n recommendation,\n };\n }\n\n /**\n * Get performance statistics for the worker (if initialized)\n */\n static getWorkerStats(): {\n workerSupported: boolean;\n workerInitialized: boolean;\n workerStatus?: {\n isReady: boolean;\n pendingRequests: number;\n queuedRequests: number;\n crashCount: number;\n };\n } {\n return {\n workerSupported: this.supportsWorkerExport(),\n workerInitialized: this.workerManager !== null,\n workerStatus: this.workerManager?.getStatus(),\n };\n }\n\n /**\n * Get recommended export options for t-shirt designs\n * T-shirt designs should ALWAYS use transparent backgrounds with knockout effects\n */\n static getTShirtExportOptions(options: Partial<ExportImageOptions> = {}): ExportImageOptions {\n return {\n format: 'png', // PNG for transparency support\n scale: 2, // 2x for print quality\n quality: 1.0, // Maximum quality\n ...options,\n // Force transparent background - critical for knockout effects\n transparentBackground: true,\n };\n }\n\n /**\n * Get recommended export options for pillow/pattern designs\n * These may use group-scoped knockout with pattern backgrounds\n */\n static getPatternExportOptions(options: Partial<ExportImageOptions> = {}): ExportImageOptions {\n return {\n format: 'png',\n scale: 2,\n transparentBackground: false, // Patterns often include background\n quality: 1.0,\n ...options,\n };\n }\n\n /**\n * Validate export options for common issues\n * Returns warnings if options might cause problems\n */\n static validateExportOptions(options: ExportImageOptions, hasKnockout: boolean): string[] {\n const warnings: string[] = [];\n\n // Check for knockout with non-transparent background\n if (hasKnockout && !options.transparentBackground) {\n warnings.push(\n 'WARNING: Document has knockout effects but transparentBackground is false. ' +\n 'Knockout effects work best with transparent backgrounds for t-shirt designs.'\n );\n }\n\n // Check for JPEG with transparency\n if (options.transparentBackground && (options.format === 'jpg' || options.format === 'jpeg')) {\n warnings.push('WARNING: JPEG format does not support transparency. Use PNG format for transparent backgrounds.');\n }\n\n // Check for low quality with effects\n if (options.quality && options.quality < 0.9) {\n warnings.push('NOTE: Using quality < 0.9 may reduce the appearance of distress and other effects.');\n }\n\n // Check for low scale with print\n if (options.scale && options.scale < 2) {\n warnings.push('NOTE: For print-ready designs, recommend scale of 2x or higher.');\n }\n\n return warnings;\n }\n\n /**\n * Check if any elements in the list have knockout effects\n */\n static hasKnockoutEffects(elements: ExportElement[]): boolean {\n const checkElement = (el: ExportElement): boolean => {\n if ((el.blendMode === 'knockout' || el.blendMode === 'clip') && el.knockoutParts) {\n return true;\n }\n if ('children' in el && Array.isArray(el.children)) {\n return (el.children as ExportElement[]).some((child) => checkElement(child));\n }\n return false;\n };\n\n return elements.some((el) => checkElement(el));\n }\n\n /**\n * CRITICAL: Ensure artboard is export-safe\n * Strips preview background color to prevent accidental export\n * Returns a copy of the artboard safe for export\n */\n static makeArtboardExportSafe(artboard: ArtboardElement): ArtboardElement {\n // Clone the artboard\n const exportArtboard = Object.assign(Object.create(Object.getPrototypeOf(artboard)), artboard);\n\n // CRITICAL: Remove preview background - must NEVER be exported\n if ('previewBackgroundColor' in exportArtboard) {\n delete (exportArtboard as Record<string, unknown>).previewBackgroundColor;\n }\n\n return exportArtboard;\n }\n}\n\nexport default ExportManager;\n","/**\n * ElementFactory - Type-safe element creation and deserialization\n * Critical for database persistence and undo/redo functionality\n */\n\nimport type { AnyElementConfig, TransformType } from '../types';\nimport type { BaseElement } from './BaseElement';\nimport { TextElement } from './TextElement';\nimport { CustomTransform } from '../transforms/CustomTransform';\nimport { CircleTransform } from '../transforms/CircleTransform';\nimport { LeanTransform } from '../transforms/LeanTransform';\nimport { ArchTransform } from '../transforms/ArchTransform';\nimport { AscendTransform } from '../transforms/AscendTransform';\nimport { WaveTransform } from '../transforms/WaveTransform';\nimport { FlagTransform } from '../transforms/FlagTransform';\nimport { ImageElement } from './ImageElement';\nimport { GroupElement } from './GroupElement';\nimport { ShapeElement } from './ShapeElement';\nimport { PathElement } from './PathElement';\n\n/**\n * ElementFactory provides type-safe element creation from JSON configurations\n *\n * Benefits:\n * - Type-safe deserialization from database\n * - Exhaustive compile-time checking (TypeScript ensures all cases are covered)\n * - Single source of truth for element construction\n * - Safe undo/redo operations\n *\n * Usage:\n * ```typescript\n * // From database\n * const config = JSON.parse(dbRecord);\n * const element = ElementFactory.createFromJSON(config);\n *\n * // For undo/redo\n * const cloned = ElementFactory.createFromJSON(element.toJSON());\n * ```\n */\nexport class ElementFactory {\n /**\n * Create an element instance from a JSON configuration\n * TypeScript ensures all transform types are handled\n *\n * @param config - Element configuration object\n * @returns BaseElement instance (TextElement, ImageElement, GroupElement, ShapeElement, or PathElement)\n * @throws Error if transform type is unknown\n */\n static createFromJSON(config: AnyElementConfig): BaseElement {\n const { transformType } = config;\n\n switch (transformType) {\n case 'custom':\n return new CustomTransform(config);\n\n case 'distort':\n throw new Error('DistortTransform is not yet implemented');\n\n case 'circle':\n return new CircleTransform(config);\n\n case 'lean':\n return new LeanTransform(config);\n\n case 'arch':\n return new ArchTransform(config);\n\n case 'ascend':\n return new AscendTransform(config);\n\n case 'wave':\n return new WaveTransform(config);\n\n case 'flag':\n return new FlagTransform(config);\n\n case 'image':\n return new ImageElement(config);\n\n case 'group':\n // Recursively create children as actual instances\n // Cast is safe because createFromJSON returns concrete element types that are all valid children\n const children = (config.children || []).map((childConfig) =>\n ElementFactory.createFromJSON(childConfig) as Parameters<GroupElement['addChild']>[0]\n );\n // Create group and add children as instances\n const group = new GroupElement({\n id: config.id,\n x: config.x,\n y: config.y,\n rotation: config.rotation,\n });\n children.forEach((child) => group.addChild(child));\n return group;\n\n case 'shape':\n return new ShapeElement(config);\n\n case 'path':\n return new PathElement(config);\n\n default:\n // TypeScript ensures this is unreachable if all cases are covered\n // If you get an error here, you forgot to handle a transform type!\n const exhaustiveCheck: never = transformType;\n throw new Error(`Unknown transform type: ${exhaustiveCheck}`);\n }\n }\n\n /**\n * Create multiple elements from an array of JSON configurations\n * Useful for bulk deserialization (e.g., loading a document from DB)\n *\n * @param configs - Array of element configurations\n * @returns Array of BaseElement instances\n */\n static createManyFromJSON(configs: AnyElementConfig[]): BaseElement[] {\n return configs.map((config) => this.createFromJSON(config));\n }\n\n /**\n * Type guard to check if an object is a valid TextElement instance\n * Useful for runtime validation\n *\n * @param obj - Object to check\n * @returns true if obj is a TextElement\n */\n static isTextElement(obj: unknown): obj is TextElement {\n const o = obj as Record<string, unknown>;\n return (\n !!obj &&\n typeof obj === 'object' &&\n typeof o.id === 'string' &&\n typeof o.transformType === 'string' &&\n typeof o.getBoundingBox === 'function' &&\n typeof o.getVisualBoundingBox === 'function' &&\n typeof o.hitTest === 'function' &&\n typeof o.render === 'function' &&\n typeof o.toJSON === 'function' &&\n typeof o.clone === 'function'\n );\n }\n\n /**\n * Validate an element configuration object\n * Returns true if the config has all required properties\n *\n * @param config - Configuration to validate\n * @returns true if valid\n */\n static isValidConfig(config: unknown): config is AnyElementConfig {\n const c = config as Record<string, unknown>;\n return (\n !!config &&\n typeof config === 'object' &&\n typeof c.transformType === 'string' &&\n (c.id === undefined || typeof c.id === 'string')\n );\n }\n\n /**\n * Create a default element of a given type\n * Useful for UI \"Add Element\" buttons\n *\n * @param transformType - Type of transform to create\n * @returns Default element configuration\n */\n static createDefaultConfig(transformType: TransformType): AnyElementConfig {\n const baseConfig = {\n id: `${transformType}-${Date.now()}`,\n x: window.innerWidth / 2,\n y: window.innerHeight / 2,\n rotation: 0,\n };\n\n switch (transformType) {\n case 'custom':\n return {\n ...baseConfig,\n transformType: 'custom',\n text: 'Custom Text',\n transformData: {\n type: 'custom',\n controlPoints: [],\n },\n };\n\n case 'distort':\n return {\n ...baseConfig,\n transformType: 'distort',\n text: 'Distorted Text',\n transformData: {\n type: 'distort',\n },\n };\n\n case 'circle':\n return {\n ...baseConfig,\n transformType: 'circle',\n text: 'Circular Text',\n transformData: {\n type: 'circle',\n radius: 100,\n scale: 1,\n reverse: false,\n },\n };\n\n case 'lean':\n return {\n ...baseConfig,\n transformType: 'lean',\n text: 'Leaning Text',\n transformData: {\n type: 'lean',\n leanAmount: 0,\n },\n };\n\n case 'arch':\n return {\n ...baseConfig,\n transformType: 'arch',\n text: 'Arched Text',\n transformData: {\n type: 'arch',\n archHeight: 0.5,\n },\n };\n\n case 'ascend':\n return {\n ...baseConfig,\n transformType: 'ascend',\n text: 'Ascending Text',\n transformData: {\n type: 'ascend',\n ascendAngle: -15,\n },\n };\n\n case 'wave':\n return {\n ...baseConfig,\n transformType: 'wave',\n text: 'Wavy Text',\n transformData: {\n type: 'wave',\n amplitude: 0.5,\n frequency: 2,\n },\n };\n\n case 'flag':\n return {\n ...baseConfig,\n transformType: 'flag',\n text: 'Flag Text',\n transformData: {\n type: 'flag',\n amplitude: 0.5,\n frequency: 2,\n },\n };\n\n case 'image':\n return {\n ...baseConfig,\n transformType: 'image',\n imageUrl: '',\n transformData: {\n type: 'image',\n width: 200,\n height: 200,\n cropX: 0,\n cropY: 0,\n cropWidth: 1,\n cropHeight: 1,\n flipHorizontal: false,\n flipVertical: false,\n borderRadius: 0,\n },\n };\n\n case 'group':\n return {\n ...baseConfig,\n transformType: 'group',\n children: [],\n transformData: {\n type: 'group',\n },\n };\n\n case 'shape':\n return {\n ...baseConfig,\n transformType: 'shape',\n transformData: {\n type: 'shape',\n shapeType: 'rectangle',\n width: 200,\n height: 200,\n borderRadius: 0,\n fillColor: '#3b82f6',\n fillOpacity: 1,\n },\n };\n\n case 'path':\n return {\n ...baseConfig,\n transformType: 'path',\n transformData: {\n type: 'path',\n points: [],\n closed: false,\n width: 200,\n height: 200,\n fillEnabled: false,\n fillColor: '#3b82f6',\n fillOpacity: 1,\n strokeEnabled: true,\n strokeColor: '#000000',\n strokeWidth: 2,\n },\n };\n\n case 'artboard':\n throw new Error('Artboards cannot be created via ElementFactory');\n\n default:\n const exhaustiveCheck: never = transformType;\n throw new Error(`Unknown transform type: ${exhaustiveCheck}`);\n }\n }\n\n /**\n * Clone an element by serializing and deserializing\n * Ensures a deep copy with proper class instance\n *\n * @param element - Element to clone\n * @returns Cloned element instance\n */\n static clone(element: BaseElement): BaseElement {\n const json = element.toJSON();\n // Note: toJSON() returns 'type' but we need 'transformType' for createFromJSON\n // Cast through 'any' to handle this mismatch temporarily\n return this.createFromJSON(json as unknown as AnyElementConfig);\n }\n}\n","/**\n * ImportManager - Handles importing workspace from JSON and images\n */\n\nimport { ElementFactory } from '../core/ElementFactory.js';\nimport { ArtboardElement } from '../core/ArtboardElement.js';\nimport type { CanvasDocument } from './ExportManager.js';\nimport type { TextElement } from '../core/TextElement.js';\nimport type { ImageElement } from '../core/ImageElement.js';\nimport type { GroupElement } from '../core/GroupElement.js';\nimport { createLogger } from './logger.js';\n\nconst logger = createLogger('ImportManager');\n\n/** V1 document format (pre-artboard) */\ninterface V1CanvasDocument {\n metadata: { version: string };\n canvas?: { width?: number; height?: number; backgroundColor?: string };\n elements?: Record<string, unknown>[];\n}\n\nexport interface ImportResult {\n success: boolean;\n artboards?: ArtboardElement[];\n elements?: (TextElement | ImageElement | GroupElement)[];\n activeArtboardId?: string | null;\n error?: string;\n}\n\nexport interface ImageImportResult {\n success: boolean;\n dataUrl?: string;\n filename?: string;\n width?: number;\n height?: number;\n error?: string;\n}\n\nexport class ImportManager {\n private static readonly SUPPORTED_VERSIONS = ['1.0.0', '2.0.0'];\n\n /**\n * Import workspace from JSON file\n */\n static async importFromJSON(file: File): Promise<ImportResult> {\n try {\n // Read file as text\n const text = await this.readFileAsText(file);\n\n // Parse JSON\n const document: CanvasDocument = JSON.parse(text);\n\n // Validate structure\n this.validateDocument(document);\n\n // Check version compatibility\n if (!this.SUPPORTED_VERSIONS.includes(document.metadata.version)) {\n throw new Error(\n `Unsupported version: ${document.metadata.version}. ` +\n `Supported versions: ${this.SUPPORTED_VERSIONS.join(', ')}`\n );\n }\n\n // Handle version 1.0.0 (no artboards) - migrate to artboards\n if (document.metadata.version === '1.0.0') {\n return this.migrateV1Document(document as unknown as V1CanvasDocument);\n }\n\n // Deserialize artboards and elements\n const artboards: ArtboardElement[] = [];\n const allElements: (TextElement | ImageElement | GroupElement)[] = [];\n\n document.artboards.forEach((artboardData) => {\n // Create artboard\n const artboard = ArtboardElement.fromJSON({\n id: artboardData.id,\n name: artboardData.name,\n x: artboardData.x,\n y: artboardData.y,\n width: artboardData.width,\n height: artboardData.height,\n backgroundColor: artboardData.backgroundColor,\n elementIds: artboardData.elements.map((e) => e.id || ''),\n });\n\n // Deserialize elements for this artboard\n const elements = artboardData.elements\n .map((elementConfig) => {\n try {\n return ElementFactory.createFromJSON(elementConfig);\n } catch (error) {\n logger.error('Failed to create element:', elementConfig, error);\n return null;\n }\n })\n .filter((element) => element !== null) as (TextElement | ImageElement | GroupElement)[];\n\n artboards.push(artboard);\n allElements.push(...elements);\n });\n\n // PERFORMANCE: Wait for all images to load in parallel before returning\n await this.preloadAllImages(allElements);\n\n return {\n success: true,\n artboards,\n elements: allElements,\n activeArtboardId: document.activeArtboardId,\n };\n } catch (error) {\n return {\n success: false,\n error: error instanceof Error ? error.message : 'Unknown error',\n };\n }\n }\n\n /**\n * Migrate v1 document (no artboards) to v2 (with artboards)\n */\n private static async migrateV1Document(document: V1CanvasDocument): Promise<ImportResult> {\n try {\n // V1 format: { metadata, canvas, elements }\n const elements = document.elements || [];\n\n // Create a default artboard containing all elements\n const artboard = new ArtboardElement({\n id: 'artboard-migrated',\n name: 'Artboard 1',\n x: 0,\n y: 0,\n width: document.canvas?.width || 1920,\n height: document.canvas?.height || 1080,\n backgroundColor: document.canvas?.backgroundColor || '#ffffff',\n });\n\n // Deserialize elements\n const deserializedElements = elements\n .map((elementConfig: Record<string, unknown>) => {\n try {\n return ElementFactory.createFromJSON(elementConfig as unknown as import('../types/index.js').AnyElementConfig);\n } catch (error) {\n logger.error('Failed to create element:', elementConfig, error);\n return null;\n }\n })\n .filter((element): element is TextElement | ImageElement | GroupElement => element !== null);\n\n // Add all element IDs to artboard\n deserializedElements.forEach((element) => {\n artboard.addElementId(element.id);\n });\n\n // PERFORMANCE: Wait for all images to load in parallel before returning\n await this.preloadAllImages(deserializedElements);\n\n return {\n success: true,\n artboards: [artboard],\n elements: deserializedElements,\n activeArtboardId: artboard.id,\n };\n } catch (error) {\n return {\n success: false,\n error: error instanceof Error ? error.message : 'Migration failed',\n };\n }\n }\n\n /**\n * Import image file\n */\n static async importImage(file: File): Promise<ImageImportResult> {\n try {\n // Validate file type\n if (!file.type.startsWith('image/')) {\n throw new Error('File is not an image');\n }\n\n // Check file size (max 10MB)\n const maxSize = 10 * 1024 * 1024; // 10MB\n if (file.size > maxSize) {\n throw new Error('Image file is too large (max 10MB)');\n }\n\n // Read as data URL\n const dataUrl = await this.readFileAsDataURL(file);\n\n // Get image dimensions\n const { width, height } = await this.getImageDimensions(dataUrl);\n\n return {\n success: true,\n dataUrl,\n filename: file.name,\n width,\n height,\n };\n } catch (error) {\n return {\n success: false,\n error: error instanceof Error ? error.message : 'Unknown error',\n };\n }\n }\n\n /**\n * Validate document structure\n */\n private static validateDocument(document: unknown): asserts document is CanvasDocument {\n if (!document || typeof document !== 'object') {\n throw new Error('Invalid document');\n }\n const doc = document as Record<string, unknown>;\n if (!doc.metadata) {\n throw new Error('Missing metadata');\n }\n if (!(doc.metadata as Record<string, unknown>).version) {\n throw new Error('Missing version in metadata');\n }\n if (!doc.artboards && !doc.elements) {\n throw new Error('Missing artboards or elements array');\n }\n if (doc.artboards && !Array.isArray(doc.artboards)) {\n throw new Error('Invalid artboards array');\n }\n }\n\n /**\n * Read file as text\n */\n private static readFileAsText(file: File): Promise<string> {\n return new Promise((resolve, reject) => {\n const reader = new FileReader();\n reader.onload = (e) => resolve(e.target?.result as string);\n reader.onerror = () => reject(new Error('Failed to read file'));\n reader.readAsText(file);\n });\n }\n\n /**\n * Read file as data URL\n */\n private static readFileAsDataURL(file: File): Promise<string> {\n return new Promise((resolve, reject) => {\n const reader = new FileReader();\n reader.onload = (e) => resolve(e.target?.result as string);\n reader.onerror = () => reject(new Error('Failed to read file'));\n reader.readAsDataURL(file);\n });\n }\n\n /**\n * Get image dimensions from data URL\n */\n private static getImageDimensions(dataUrl: string): Promise<{ width: number; height: number }> {\n return new Promise((resolve, reject) => {\n const img = new Image();\n img.onload = () => {\n resolve({ width: img.width, height: img.height });\n };\n img.onerror = () => reject(new Error('Failed to load image'));\n img.src = dataUrl;\n });\n }\n\n /**\n * Validate imported data before applying to state\n */\n static validateImportedData(\n artboards: ArtboardElement[],\n elements: (TextElement | ImageElement | GroupElement)[]\n ): { valid: boolean; errors: string[] } {\n const errors: string[] = [];\n\n // Check for duplicate artboard IDs\n const artboardIds = new Set();\n artboards.forEach((artboard) => {\n if (artboardIds.has(artboard.id)) {\n errors.push(`Duplicate artboard ID: ${artboard.id}`);\n }\n artboardIds.add(artboard.id);\n });\n\n // Check for duplicate element IDs\n const elementIds = new Set();\n elements.forEach((element) => {\n if (elementIds.has(element.id)) {\n errors.push(`Duplicate element ID: ${element.id}`);\n }\n elementIds.add(element.id);\n });\n\n // Validate element-to-artboard references\n artboards.forEach((artboard) => {\n artboard.getElementIds().forEach((elementId: string) => {\n if (!elementIds.has(elementId)) {\n errors.push(`Artboard \"${artboard.name}\" references missing element: ${elementId}`);\n }\n });\n });\n\n return {\n valid: errors.length === 0,\n errors,\n };\n }\n\n /**\n * Get import summary (for UI display before confirming)\n */\n static getImportSummary(\n artboards: ArtboardElement[],\n elements: (TextElement | ImageElement | GroupElement)[]\n ): {\n artboardCount: number;\n elementCount: number;\n artboardNames: string[];\n warnings: string[];\n } {\n const validation = this.validateImportedData(artboards, elements);\n\n return {\n artboardCount: artboards.length,\n elementCount: elements.length,\n artboardNames: artboards.map((a) => a.name),\n warnings: validation.errors,\n };\n }\n\n /**\n * Preload all images in parallel for fast artboard switching\n * Recursively finds all ImageElements (including those in groups)\n */\n private static async preloadAllImages(elements: (TextElement | ImageElement | GroupElement)[]): Promise<void> {\n const imageElements: ImageElement[] = [];\n\n // Recursively find all image elements\n const findImages = (el: TextElement | ImageElement | GroupElement) => {\n if (el.transformType === 'image') {\n imageElements.push(el as ImageElement);\n } else if (el.transformType === 'group' && 'children' in el) {\n (el as GroupElement).children.forEach((child) => findImages(child as TextElement | ImageElement | GroupElement));\n }\n };\n\n elements.forEach(findImages);\n\n // Wait for all images to load in parallel\n const loadPromises = imageElements.map((img: ImageElement) => {\n return new Promise<void>((resolve) => {\n if (img.imageLoaded) {\n resolve();\n } else if (img.imageElement) {\n // Image is currently loading\n const imgEl = img.imageElement;\n const onLoad = () => {\n imgEl.removeEventListener('load', onLoad);\n imgEl.removeEventListener('error', onError);\n resolve();\n };\n const onError = () => {\n imgEl.removeEventListener('load', onLoad);\n imgEl.removeEventListener('error', onError);\n resolve(); // Resolve even on error to not block other images\n };\n imgEl.addEventListener('load', onLoad);\n imgEl.addEventListener('error', onError);\n } else {\n resolve();\n }\n });\n });\n\n await Promise.all(loadPromises);\n }\n}\n\nexport default ImportManager;\n"],"names":["theme","getThemeAccentColor","SELECTION_LINE_WIDTH","HANDLE_RADIUS","ROTATION_HANDLE_RADIUS","DASH_SIZE","DASH_GAP","ROTATION_ICON_SCALE","getLineWidth","zoom","getHandleRadius","getRotationHandleRadius","getDashPattern","renderRotationHandleIcon","ctx","x","y","scale","renderRotationHandle","accentColor","isHovering","rotationHandleRadius","HANDLE_SIZE","BASE_HANDLE_RADIUS","TransformHandles","element","bbox","rotationAnchor","enabledAnchors","padding","paddedBbox","allHandles","calculateResizeHandles","isRotated","handle","calculateRotationHandlePosition","showRotationHandle","rotationAngle","isRotating","isHoveringRotation","hoveredResizeHandle","isResizing","activeResizeHandle","renderRotationInCanvas","isHovered","isActive","handleX","handleY","isTopBottom","width","height","radius","visualRadius","angle","angleText","tooltipWidth","tooltipHeight","tooltipX","tooltipY","CORNER_HANDLE_HIT_RADIUS","hitTestCircle","rotation","handleType","getCursorForWorldPosition","ResizeHandler","dx","dy","startData","snapSystem","localDelta","Transform","localDx","localDy","startVisualWidth","startVisualHeight","startBboxWidth","startBboxHeight","newVisualWidth","newVisualHeight","newWidth","newHeight","widthChange","heightChange","scaleX","scaleY","unfrozenVisualWidth","unfrozenVisualHeight","freezeApplied","anchor","isCornerResizeHandle","isCropHandle","snapX","_a","snapY","_b","frozenState","state","imageElement","imageStartTransform","targetWidth","_c","aspectRatio","targetHeight","_d","widthScaleFromStart","heightScaleFromStart","updatedElement","resizeApplied","_e","startW","startH","strokeScale","scaledStrokeWidth","isFrozen","isCornerHandle","isCroppingImage","isGroup","positionOffset","startTransform","cosRot","sinRot","startBbox","newBbox","startRotationAnchor","newRotationAnchor","fixedLocal","localX","localY","bboxOffsetX","bboxOffsetY","cornerRelX","cornerRelY","rotatedX","rotatedY","fixedWorldX","fixedWorldY","newFixedLocal","newLocalX","newLocalY","newBboxOffsetX","newBboxOffsetY","newCornerRelX","newCornerRelY","newRotatedX","newRotatedY","currentFixedWorldX","currentFixedWorldY","coords","ResizePipeline","stage","fn","index","data","acc","result","params","beforeParams","position","beforeData","globalResizePipeline","InteractionStateMachine","resizePipeline","handler","pipeline","mouseX","mouseY","dragMode","baseStartData","imageTransformData","allElements","dragStartData","newX","newY","snapped","visualBbox","elementForResize","deltaX","deltaY","startAngle","currentRotation","centerX","centerY","rotStartData","rotationDelta","calculateAngle","newRotation","p1","p2","startCentroid","startDistance","pinchStartData","currentCentroid","currentDistance","currentAngle","safeStartDistance","rawScale","RotationAnchorResolver","anchors","angleRad","RotationUtils","key","point","center","epsilon","SpatialGrid","cellSize","item","cell","keys","id","excludeId","results","minCellX","maxCellX","minCellY","maxCellY","cx","cy","axis","value","commaIdx","cellX","cellY","items","getTransformDataWidth","td","getTransformDataHeight","setTransformDataWidth","setTransformDataHeight","AlignmentSnapSystem","options","enabled","threshold","rects","elements","anchorKey","compoundKey","gridItem","rect","x2","y2","elementId","tempElement","movingAnchors","otherElements","s","bestSnapX","bestSnapY","minDistX","minDistY","allXSnaps","allYSnaps","newGuides","movingKey","movingAnchor","xCandidates","candidate","meta","otherAnchor","otherKey","distX","xSnap","yCandidates","distY","ySnap","snappedX","snappedY","xSnapsByPosition","ySnapsByPosition","existing","snapDeltaX","_snapDeltaY","anchorStr","currentWidth","targetWidthAtSnap","_otherElements","snapKeys","targetSnapKeys","xSnaps","targetSnapKeysSet","candidates","ySnaps","snaps","b","aPriority","bPriority","snap","trackedAnchor","minY","maxY","otherElement","otherAnchors","minX","maxX","adjustedThreshold","snapDelta","_handle","currentHeight","finalWidth","finalHeight","isImageElement","anchorLower","activeSnap","bestSnap","currentValue","rawDistance","recalculatedFontSize","previousSnap","shouldPreserveFreeze","frozenFontSize","isPositionBased","frozenPos","frozenDimensions","existingSnap","beforeVisualBbox","tdWidth","rotationRad","cos","sin","leftEdgeShift","afterVisualBbox","rightEdgeShift","snapDeltaY","tdHeight","heightChanged","topEdgeShift","shouldCompensate","newVisualBbox","bottomEdgeShift","hasActiveSnap","frozenVisualWidth","frozenVisualHeight","xSnapResult","ySnapResult","isCornerResize","snappedElement","preservedFontSize","preservedWidth","preservedHeight","preservedPosition","isImageCropMode","xSnapAnchor","xSnapAnchorLower","ySnapAnchor","ySnapAnchorLower","isImageElement2","hasActiveSnap2","activeSnapState","imageAspectRatio","isHorizontalSideHandle","isVerticalSideHandle","xIsPositionBasedSnap","yIsPositionBasedSnap","_element","_allElements","commonAngles","snapAngle","isNear","SpacingSystem","movingElement","snapThreshold","SPACING_SNAP_THRESHOLD","movingBBox","visualOffsetX","visualOffsetY","didSnapX","didSnapY","horizontallyAligned","a","bboxA","bboxB","closestAbove","closestBelow","gaps","i","bbox1","gap","targetGap","aboveBBox","currentGap","belowBBox","verticallyAligned","closestLeft","closestRight","leftBBox","rightBBox","showAllMeasurements","leftElements","rightElements","topElements","bottomElements","otherBBox","distanceToLeft","distanceToRight","distanceToTop","distanceToBottom","verticalOverlap","horizontalOverlap","newIndicators","allMeasurements","indicators","hoveredElement","hoveredBBox","altHoverThreshold","horizontalCount","verticalCount","elementBBox","horizontalGap","showHorizontal","hx1","hx2","hy","horizontalOffset","verticalGap","showVertical","vx","vy1","vy2","verticalOffset","nearbyElements","direction","closest","closestDistance","closestBBox","wouldSnap","alignedElements","element1","element2","bbox2","y1","x1","avgGap","distance","isSnapTarget","logger","createLogger","_TextureManager","idOrUrl","url","loadingPromise","resolve","reject","img","idsOrUrls","t","texture","category","textureId","TextureManager","DEFAULT_OPTIONS","ArtboardRenderer","artboard","isSelected","presetColor","err","lightColor","darkColor","row","col","clipShape","borderColor","getThemeArtboardBorderColor","selectedBorderColor","path","e","fontSize","labelText","labelX","labelY","labelColor","getThemeArtboardLabelColor","artboards","selectedId","isDragging","handles","isTextElement","TextElement","ImageElement","isGroupElement","GroupElement","isShapeElement","ShapeElement","isPathElement","PathElement","renderElement","mode","renderImageElement","renderShapeElement","renderTextElement","textElement","text","renderTextStroke","renderTextFillOnly","transformData","createImagePath","flipH","flipV","renderImageStroke","isKnockoutRender","renderShapePath","renderShapeStroke","shapeType","renderRectanglePath","renderCirclePath","renderEllipsePath","renderStarPath","borderRadius","radiusX","radiusY","outerRadius","points","innerRadiusRatio","innerRadius","angleStep","renderingContext","renderWithCompositing","compositingElement","renderElementFn","artboardBackgroundColor","compositeOp","savedTransform","scope","affectedElements","getAffectedElements","renderNonCompositingParts","canvas","dpr","offscreen","createOffscreenCanvas","offCtx","renderElementStroke","renderElementFill","logicalWidth","logicalHeight","afterRestore","renderWithKnockout","knockoutElement","getAllElementsBelow","getGroupSiblings","knockoutIndex","el","parentGroup","findParentGroup","child","nestedParent","_renderFn","renderFn","knockoutParts","computeMaskCoverDimensions","parentW","parentH","maskNaturalW","maskNaturalH","oversize","maskAspect","parentAspect","fitW","fitH","THUMB_SIZE","MASK_SIZE","drawCircle","size","drawStar","outerR","innerR","r","drawHeart","drawDiamond","rx","ry","drawHexagon","drawShield","w","top","drawSplatter","seed","rand","dist","drawTornEdge","margin","steps","drawPaintStroke","y0","drawCloud","MASK_IMAGE_PRESETS","initialized","createDOMCanvas","ensureMaskPresetsReady","cache","ImageCache","preset","maskCanvas","maskCtx","dataUrl","thumbCanvas","thumbCtx","maskCache","workerMaskBitmaps","invalidateMaskCache","keysToDelete","_","clearMaskCache","renderWithMasks","transform","mask","applyMask","parentElement","applyClipMask","applyAlphaMask","applyLumaMask","applyDistressMask","renderMaskElement","applyFeathering","imageData","g","luma","maskElement","parentX","parentY","maskX","maskY","absoluteMaskElement","MASK_OVERSIZE","parentTd","parentAny","maskTd","loadedImage","loadedBitmap","imageConfig","resolvedTd","needsContainScaling","h","contain","featherRadius","applyArtboardImageMask","config","pixelX","pixelY","pixelWidth","pixelHeight","offWidth","offHeight","offCanvas","lumaCanvas","lumaCtx","SimplexNoise","random","j","hash","u","v","X","Y","generateWornEffect","intensity","createCanvas","noise","idx","edgeX","edgeY","edgeFactor","alpha","generateCrackedEffect","seededRandom","numCracks","startX","startY","drawCrackBranch","length","depth","endX","endY","branchAngle","generateGrungeEffect","density","generateRetroEffect","dotSize","spacing","BUILTIN_SEED","TEX_SIZE","toAlphaMask","layerAlpha","bData","DISTRESS_TEXTURE_PRESETS","worn","grunge","generateThumbnailDataUrl","fullCanvas","fullCtx","thumbData","pixels","gray","ensureBuiltinTexturesReady","registerAlphaMask","loadingUrls","pendingCallbacks","getContext","convertToAlphaMask","source","tempCanvas","tempCtx","getAlphaMask","cached","post","loadTexture","preloadTexture","callbacks","notifyPending","cb","entry","res","blob","bitmap","applyArtboardDistressTexture","artMaskCtx","artIntensity","mData","mW","mH","content","cData","my","mx","maskAlpha","ci","applyElementDistressTexture","distress","elementBounds","diagonal","extraW","extraH","strokePad","padX","padY","paddedBounds","SelectionRenderer","selectedElement","stateMachine","transformHandles","infoText","rotationHandle","getThemeTooltipShadowColor","getThemeTooltipBackground","getThemeTooltipForeground","hoverState","HoverRenderer","_isAltKeyPressed","FADE_DURATION","TARGET_OPACITY","opacity","elapsed","getThemeAccentHoverColor","strokeWidth","offset","halfWidth","halfHeight","triVerts","triNormals","next","len","offsetVerts","_v","n1","n2","bx","by","bLen","cosHalf","sides","_artboardBackgroundColor","transformType","fontFamily","bold","italic","textAlign","fontMetrics","getFontMetrics","lineSpacing","ringWidth","richText","explicitLines","splitRichTextIntoLines","wrappedLines","paragraphMetadata","lineSpans","availableWidth","HORIZONTAL_PADDING","wrapped","wrapRichTextSpans","wLine","wIndex","totalHeight","topLeftY","lineIndex","isParagraphStart","isParagraphEnd","lineWidth","fullLineText","leadingSpacesCount","trailingSpacesCount","charIdx","span","spanFontSize","spanFontFamily","spanBold","spanItalic","visibleText","spanStart","spanEnd","hiddenChars","trailingStart","leadingTrim","visibleChars","buildFontString","currentX","baselineY","textLines","lines","calculateVisualBoundsWithSpaceCollapsing","hasExplicitNewlines","applySpaceLayoutRules","line","yPos","color","textEl","weight","style","skewAngle","chars","charWidths","char","positions","applyCharTransform","pos","totalWidth","sum","charWidth","normalizedX","slope","WAVE_SKEW_FACTOR","distanceFromCenter","flagAmplitude","cosComponent","sinComponent","InteractionFeedbackRenderer","snapGuides","guide","spacingIndicators","indicator","spacingColor","getThemeSpacingColor","capLength","textWidth","textHeight","bgWidth","bgHeight","SPACING_LABEL_BORDER_RADIUS","SPACING_LABEL_TEXT_COLOR","EditModeRenderer","editModeData","cursorPosition","selectionStart","selectionEnd","editText","editRichText","cursorOpacity","isTouchDevice","selectionHandlePositionsRef","currentZoom","underline","strikethrough","lineBoxHeight","maxWidth","boxWidth","wrappedLine","currentY","cursorX","cursorY","cursorHeight","charPositions","charIndex","currentLineChars","charFontSize","charFontFamily","charBold","charItalic","charStyle","fontWeight","fontStyle","isFirstLine","isLastLine","c","lineX","charData","firstCharIndex","lastCharIndex","maxAllowedCursor","visibleTextWidth","k","isSpace","isVisible","isLeadingSpace","isTrailingSpace","leadingHidden","trailingHidden","hasSelection","startHandlePos","endHandlePos","minSel","maxSel","getThemeTextSelectionColor","selCharIndex","selCurrentY","lineChars","fontStyleStr","lineSelStart","lineSelEnd","xBeforeSelection","xBeforeSelectionEnd","selectionX","selectionWidth","customData","renderRichTextFillOnly","startPos","endPos","handleRadius","stemWidth","startHandleCenter","endHandleCenter","cursorPos","firstPos","lastPos","lastCharWidth","charPos","imgElement","cropBox","EDGE_HANDLE_THICKNESS","CROP_BOX_LINE_WIDTH","CORNER_HANDLE_RADIUS_SCALED","CORNER_HANDLE_VISUAL_RADIUS","EDGE_HANDLE_LENGTH_SCALED","EDGE_HANDLE_VISUAL_LENGTH","GRID_LINE_WIDTH","cropWidth","cropHeight","localOffsetX","localOffsetY","imageBounds","cropBottom","imageBottom","cropRight","imageRight","thirdWidth","thirdHeight","corner","edge","cornerHandles","cropCorners","minDistance","tooClose","cropCorner","renderLogger","_CanvasRenderer","error","isPreview","PREVIEW_ELEMENT_OPACITY","composite","piece","sub","rot","matrix","swap","visW","visH","inverseTransform","screenWidth","screenHeight","topLeft","bottomRight","worldMinX","worldMinY","worldMaxX","worldMaxY","compositeShape","compoundPath","showOverflowDimmed","suppressOverflowDim","activeChildContext","allElementConfigs","elementMap","knockoutRenderedIds","elementConfig","compositingIndex","hasCompositingParts","actualElement","isDraggingChildInThisGroup","shouldShowAsSelected","hasCustomDistress","renderContent","renderCtx","segments","currentContent","currentContentConfigs","segment","contentCanvas","contentCtx","maskIsSelected","maskIsHovered","innerMaskCtx","isEditing","paddingOffset","distressTexture","imageMask","effectiveDpr","offsetX","offsetY","zoomedSnapGuides","zoomedSpacingIndicators","hideHandles","isAltKeyPressed","hoverClipArtboard","cw","ch","CanvasRenderer","DEFAULT_MAX_BITMAP_DIMENSION","registeredBitmapKeys","getImageCacheKey","imageSrc","srcHash","hashString","str","clearRegisteredBitmapKeys","unregisterElementBitmaps","markBitmapRegistered","cacheKey","isBitmapRegistered","createCappedImageBitmap","maxDimension","naturalWidth","naturalHeight","workerCacheClearCallback","workerElementClearCallback","registerWorkerCacheCallbacks","clearAll","clearElement","unregisterWorkerCacheCallbacks","clearImageBitmapCache","removeFromImageBitmapCache","collectFonts","elementJson","fonts","json","spanObj","resolveMaskImageUrls","masks","imageUrl","serializeForWorkerExport","maxBitmapDimension","artboardElements","serializedElements","newBitmaps","hasMasks","visibleWidth","visibleHeight","bitmapWidth","bitmapHeight","serializedImage","serialized","fontsList","workerCode","log","WorkerExportManager","listener","event","bitmaps","message","workerUrl","urlError","timeout","readyHandler","now","backoffDelay","request","requestId","mainThreadStartTime","serializedData","exportRequest","resultPromise","response","mainThreadBlockTime","pending","failedRequests","_pending","restartError","sharedInstance","getSharedWorkerExportManager","terminateSharedWorkerExportManager","collectElementFontFamilies","out","m","ensureFontsLoadedForExport","families","loadPromises","family","_ExportManager","artboardManager","filename","document","elementIds","jsonString","timestamp","finalFilename","canvasElement","format","quality","transparentBackground","backgroundColor","forceMainThread","workerManager","artboardElementIds","_canvasElement","offscreenCanvas","hasDistress","baseRenderFn","mimeType","exportPromises","link","artboardCount","totalElementCount","estimatedBytes","estimatedKB","mainThreadStart","mainThreadDataUrl","mainThreadTime","workerStart","workerResult","workerTime","speedup","duration","interval","useWorker","exportTimes","totalMainThreadBlockTime","running","start","time","totalExports","averageTime","minTime","maxTime","exportsPerSecond","blockPercent","recommendation","hasKnockout","warnings","checkElement","exportArtboard","ExportManager","ElementFactory","CustomTransform","CircleTransform","LeanTransform","ArchTransform","AscendTransform","WaveTransform","FlagTransform","children","childConfig","group","exhaustiveCheck","configs","obj","o","baseConfig","_ImportManager","file","artboardData","ArtboardElement","deserializedElements","maxSize","doc","reader","errors","artboardIds","validation","imageElements","findImages","imgEl","onLoad","onError","ImportManager"],"mappings":"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AAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;A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"}