@qe-libs/qeviz 0.5.4 → 0.5.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -4
- package/dist/qeviz.es.js +695 -675
- package/dist/qeviz.es.js.map +1 -1
- package/dist/qeviz.umd.js +5 -5
- package/dist/qeviz.umd.js.map +1 -1
- package/package.json +1 -1
package/dist/qeviz.umd.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"qeviz.umd.js","sources":["../src/types/DataFrame.ts","../src/objects/Model.ts","../src/utils/debug.ts","../src/elements/QEVisual.ts","../src/objects/Color.ts","../src/objects/Transform.ts","../src/utils/Tools.ts","../src/types/EventBus.ts","../src/objects/Layers.ts","../src/objects/PlottedObject.ts","../src/objects/Extremes.ts","../src/objects/AxisPoint.ts","../src/objects/Graph.ts","../src/elements/DrawableElement.ts","../src/objects/polyfit.ts","../src/objects/Trajectory.ts","../src/objects/Edges.ts","../src/elements/Drawable.ts","../src/objects/Sizing.ts","../src/elements/QELine.ts","../src/elements/QEPoint.ts","../src/elements/QETrajectory.ts","../src/elements/QELayer.ts","../src/elements/QELabel.ts","../src/elements/QEChildElements.ts","../src/elements/QEGraph.ts","../src/index.ts"],"sourcesContent":["export interface DataFrameRowInterface {\n get names(): string[];\n get rowName(): string | undefined;\n get types(): DataFrameColumnType[];\n get parent(): DataFrame | undefined;\n}\n\nexport class DataFrameRow extends Array<any> implements DataFrameRowInterface {\n #rowNumber?: number;\n #rowName?: string;\n #names: string[];\n #parent?: DataFrame;\n #classes: string[] | undefined;\n\n constructor(names: string[], values: any[], rowName?: string, parent?: DataFrame, index?: number) {\n super(...values);\n this.#names = names;\n this.#rowName = rowName;\n this.#parent = parent;\n this.#classes = parent?.classes;\n this.#rowNumber = index;\n }\n\n get parent(): DataFrame | undefined {\n return this.#parent;\n }\n get names(): string[] {\n return this.#names;\n }\n get rowName(): string | undefined {\n return this.#rowName;\n }\n get types(): DataFrameColumnType[] {\n if (!this.#parent) throw new Error(\"No parent DataFrame attached to this row.\");\n return this.#parent.types;\n }\n get classes(): string[] | undefined {\n return this.#classes;\n }\n\n get rowNumber(): number | undefined {\n return this.#rowNumber;\n }\n\n col(wh: string | number): DataFrameColumn | undefined {\n if (!this.#parent) throw new Error(\"No parent DataFrame attached to this row.\");\n return this.#parent.col(wh);\n }\n cols(...wh: (string | number)[]): DataFrame {\n if (!this.#parent) throw new Error(\"No parent DataFrame attached to this row.\");\n return this.#parent.cols(...wh);\n }\n\n filter(predicate: (value: any, index: number, array: any[]) => boolean): any {\n console.error(\"DataFrameRow does not currently support filtering.\");\n // This method is intentionally left empty to prevent filtering on DataFrameRow.\n }\n}\n\nexport enum DataFrameColumnType {\n Character = 'character',\n Double = 'double',\n Logical = 'logical',\n Integer = 'integer'\n}\n\nexport interface DataFrameColumnInterface {\n get name(): string;\n get type(): DataFrameColumnType;\n get rowNames(): string[] | undefined;\n}\n\nexport class DataFrameColumn extends Array<any> implements DataFrameColumnInterface {\n #name: string;\n #type: DataFrameColumnType;\n #rowNames: string[] | undefined;\n #parent?: DataFrame;\n\n constructor(name: string, column: any, rowNames?: string[], parent?: DataFrame) {\n super(column.length);\n for (let i = 0; i < column.length; i++) {\n this[i] = column[i];\n }\n this.#name = name;\n\n if (column.type !== undefined) {\n this.#type = column.type;\n }\n // If undefined, infer type\n else {\n if (column.every((v: any) => typeof v === 'string' || v === null || v === undefined)) {\n this.#type = DataFrameColumnType.Character;\n }\n else if (column.every((v: any) => Number.isInteger(v) || v === null || v === undefined)) {\n // If only 1 and 0, consider as logical\n if (column.every((v: any) => v === 0 || v === 1 || v === null || v === undefined)) {\n this.#type = DataFrameColumnType.Logical;\n }\n else {\n this.#type = DataFrameColumnType.Integer;\n }\n }\n else if (column.every((v: any) => typeof v === 'number' || v === null || v === undefined)) {\n this.#type = DataFrameColumnType.Double;\n }\n else if (column.every((v: any) => typeof v === 'boolean' || v === null || v === undefined)) {\n this.#type = DataFrameColumnType.Logical;\n }\n\n // Default to character if mixed types\n else {\n this.#type = DataFrameColumnType.Character;\n }\n }\n this.#parent = parent;\n\n if (rowNames && rowNames.length !== this.length) {\n throw new Error(\"Row names length must match the number of rows in the DataFrameColumn.\");\n }\n if (rowNames && rowNames.length > 0) {\n this.#rowNames = rowNames;\n }\n else {\n this.#rowNames = undefined;\n }\n }\n\n get name(): string {\n return this.#name;\n }\n get type(): DataFrameColumnType {\n return this.#type;\n }\n get rowNames(): string[] | undefined {\n return this.#rowNames;\n }\n\n\n row(wh: string | number): DataFrameRow | undefined {\n if (!this.#parent) throw new Error(\"No parent DataFrame attached to this column.\");\n return this.#parent.row(wh);\n }\n rows(...wh: (string | number)[]): DataFrameRow[] {\n if (!this.#parent) throw new Error(\"No parent DataFrame attached to this column.\");\n return this.#parent.rows(...wh);\n }\n}\n\nexport interface DataFrameInterface {\n // Methods\n getColumnByName(name: string): DataFrameColumn | undefined;\n getRowByIndex(index: number): any[];\n getRowByName(name: string): any[] | undefined;\n row(wh: string | number): any[] | undefined;\n type(wh: string | number): DataFrameColumnType | undefined;\n\n get names(): string[];\n get rowNames(): string[] | undefined;\n get types(): string[];\n\n // Properties\n nrow: number;\n ncol: number;\n}\n\nexport class DataFrame extends Array<DataFrameColumn> implements DataFrameInterface {\n #names: string[];\n #rowNames: string[] | undefined;\n #classes: string[] | undefined;\n\n constructor(names?: string[], colValues?: any[], rowNames?: string[], classes?: string[]) {\n if (!names || !colValues) {\n colValues = [];\n names = [];\n }\n if (colValues.map( (c: any) => c.length ).every( (l: any) => l === names.length )) {\n // Transpose if needed\n const transposed: any[] = [];\n for (let i = 0; i < names.length; i++) {\n const col: any[] = [];\n for (let j = 0; j < colValues.length; j++) {\n col.push(colValues[j][i]);\n }\n transposed.push(col);\n }\n colValues = transposed;\n }\n\n super(colValues.length);\n\n colValues.forEach((col, index) => {\n if (col instanceof DataFrameColumn) {\n // If col is already a DataFrameColumn, just assign it\n this[index] = col as DataFrameColumn;\n } else {\n // Otherwise, create a new DataFrameColumn\n this[index] = new DataFrameColumn(names[index], col, rowNames, this) as DataFrameColumn;\n }\n });\n this.#names = names;\n if (rowNames && this[0] && rowNames.length !== this[0].length) {\n throw new Error(\"Row names length must match the number of rows in the DataFrame.\");\n }\n if (rowNames && rowNames.length > 0) {\n this.#rowNames = rowNames;\n }\n if (classes && classes.length !== this.length) {\n throw new Error(\"Classes length must match the number of columns in the DataFrame.\");\n }\n if (classes && classes.length > 0) {\n this.#classes = classes;\n }\n }\n\n get classes(): string[] | undefined {\n return this.#classes;\n }\n\n getColumnByName(name: string): DataFrameColumn | undefined {\n const idx = this.#names.indexOf(name);\n return idx >= 0 ? this[idx] : undefined;\n }\n getRowByIndex(index: number): DataFrameRow {\n if (this && this.length === 0) {\n console.warn(\"DataFrame is empty, cannot get row by index\", index);\n return new DataFrameRow(this.#names, [], undefined, this, index);\n }\n const result_vals: any[] = [];\n for (let col of this) {\n let v = col[index];\n result_vals.push(v);\n }\n return new DataFrameRow(this.#names, result_vals, this.#rowNames ? this.#rowNames[index] : undefined, this, index);\n }\n getRowByName(name: string): DataFrameRow | undefined {\n if (!this.#rowNames) return undefined;\n\n const index = this.#rowNames.indexOf(name);\n if (index === -1) return undefined;\n return this.getRowByIndex(index);\n }\n\n get types(): DataFrameColumnType[] {\n return this.map(col => col.type);\n }\n type(wh: string | number): DataFrameColumnType | undefined {\n if (typeof wh === 'number') {\n return this[wh]?.type;\n }\n else if (typeof wh === 'string') {\n const col = this.getColumnByName(wh);\n return col ? col.type : undefined;\n }\n return undefined;\n }\n\n // row(wh: string | number): DataFrameRow | undefined {\n\n row(wh: string | number): DataFrameRow | undefined {\n if (typeof wh === 'number') {\n return this.getRowByIndex(wh);\n }\n else if (typeof wh === 'string') {\n return this.getRowByName(wh);\n }\n return undefined;\n }\n // rows(...wh: (string | number)[]): DataFrame {\n rows(...wh: (string | number)[]): DataFrameRow[] {\n // Support: rows(\"Data\"), rows(\"Data\", \"Design\"), rows([\"Data\", \"Design\"]), rows()\n let\n selectors: (string | number)[],\n selectedRows: DataFrameRow[] = [],\n selectedRowNames: string[] | undefined = []\n ;\n\n // No arguments: return all rows\n if (wh.length === 0) {\n if (!this[0] || this.length === 0) {\n return [];\n }\n const numRows = this[0].length;\n selectedRows = Array.from({ length: numRows }, (_, i) => this.getRowByIndex(i));\n selectedRowNames = this.#rowNames;\n }\n\n else {\n // Single array argument\n if (wh.length === 1 && Array.isArray(wh[0])) {\n selectors = wh[0] as (string | number)[];\n }\n else {\n // Rest arguments\n selectors = wh;\n }\n\n selectedRows = selectors.map((item, i: number) => {\n let r = this.row(item);\n if (this.#rowNames && r) {\n selectedRowNames?.push(this.#rowNames[i]);\n }\n return r;\n }).filter((row): row is DataFrameRow => row !== undefined);\n }\n\n // Build columns from selected rows\n // const\n // colNames = this.#names,\n // columns = colNames.map((name, colIdx) => selectedRows.map(row => row[colIdx])),\n // colObjs = colNames.map((name, idx) => new DataFrameColumn(name, { values: columns[idx], type: this[idx].type }, selectedRowNames, this))\n // ;\n\n // return new DataFrame(\n // colNames,\n // colObjs,\n // selectedRowNames\n // );\n\n return selectedRows;\n }\n\n col(wh: string | number): DataFrameColumn | undefined {\n if (typeof wh === 'number') {\n return this[wh];\n } else if (typeof wh === 'string') {\n return this.getColumnByName(wh);\n }\n return undefined;\n }\n\n cols(...wh: (string | number)[]): DataFrame {\n // Support: cols(\"Data\"), cols(\"Data\", \"Design\"), cols([\"Data\", \"Design\"]), cols()\n let\n selectors: (string | number)[],\n selectedCols: DataFrameColumn[],\n selectedNames: string[] = []\n ;\n\n // No arguments: return all columns\n if (wh.length === 0) {\n selectedCols = this.slice();\n selectedNames = this.#names;\n }\n else {\n // Single array argument\n if (wh.length === 1 && Array.isArray(wh[0])) {\n selectors = wh[0] as (string | number)[];\n }\n // Rest arguments\n else {\n selectors = wh;\n }\n\n selectedCols = selectors.map((item) => this.col(item)).filter((col): col is DataFrameColumn => col !== undefined);\n selectedNames = selectedCols.map(col => col.name);\n }\n\n return new DataFrame(selectedNames, selectedCols, this.#rowNames);\n }\n\n subset(rows?: (string | number)[], cols?: (string | number)[]): DataFrame {\n const selectedCols: DataFrameColumn[] = (cols && cols.length > 0)\n ? this.cols(...cols)\n : this.slice();\n\n return new DataFrame(\n selectedCols.map(col => col.name),\n selectedCols.map(col => col.values),\n this.#rowNames\n );\n }\n\n get names(): string[] {\n return this.#names;\n }\n\n get rowNames(): string[] | undefined {\n return this.#rowNames;\n }\n\n get nrow(): number {\n return this[0] ? this[0].length : 0;\n }\n\n get ncol(): number {\n return this.length;\n }\n}\n","import { DataFrame, DataFrameRow } from \"../types/DataFrame\";\n\n/** Internal key union for Model.setByKey */\nexport type ModelKey =\n | \"updated\" | \"points\" | \"nodes\" | \"edges\"\n | \"dimensions\" | \"confidence\" | \"outlier\" | \"groups\" | \"trajectories\" | \"networks\" | \"pointsets\";\n\n/** Internal shape of the Model class — used by setByKey */\nexport interface ModelSpec {\n updated?: number;\n points: DataFrame;\n nodes: DataFrame;\n edges: DataFrame;\n dimensions: (string | number)[];\n confidence?: DataFrame;\n outlier?: DataFrame;\n groups?: DataFrame;\n trajectories?: DataFrame;\n networks?: DataFrame;\n pointsets?: DataFrame;\n}\n\nexport class Model implements ModelSpec {\n private _updated: number | undefined;\n private _points: DataFrame;\n private _nodes: DataFrame;\n private _edges: DataFrame;\n private _dimensions: (string | number)[];\n private _params: any;\n private _confidence: DataFrame | undefined;\n private _outlier: DataFrame | undefined;\n private _groups: DataFrame | undefined;\n private _trajectories: DataFrame | undefined;\n private _networks: DataFrame | undefined;\n private _pointsets: DataFrame | undefined;\n\n // Resolved column names — set by QEVisual.setModelData() via auto-detection\n // or caller-supplied overrides. Renderers read these instead of hardcoding.\n /** ID column in the points and edges frames */\n unit_id_col: string = 'id';\n /** ID column in the nodes frame */\n node_id_col: string = 'id';\n /** Group column in the points frame (null = no grouping) */\n group_col: string | null = null;\n /** Directed network mode — true renders arrowheads; false (default) undirected */\n directed: boolean = false;\n /** Group palette override (ModelData.palette); empty = qeviz default. */\n palette: string[] = [];\n\n constructor(o: Partial<ModelSpec> = {}) {\n this._points = o.points ?? new DataFrame();\n this._nodes = o.nodes ?? new DataFrame();\n this._edges = o.edges ?? new DataFrame();\n this._dimensions = o.dimensions ?? [];\n this._confidence = undefined;\n this._outlier = undefined;\n this._groups = undefined;\n }\n\n get updated(): number | undefined { return this._updated; }\n set updated(v: number | undefined) { this._updated = v; }\n\n get points(): DataFrame { return this._points; }\n set points(v: DataFrame) { this._points = v; }\n\n get nodes(): DataFrame { return this._nodes; }\n set nodes(v: DataFrame) { this._nodes = v; }\n\n get edges(): DataFrame { return this._edges; }\n set edges(v: DataFrame) { this._edges = v; }\n\n get confidence(): DataFrame | undefined { return this._confidence; }\n set confidence(v: DataFrame | undefined) { this._confidence = v; }\n\n get outlier(): DataFrame | undefined { return this._outlier; }\n set outlier(v: DataFrame | undefined) { this._outlier = v; }\n\n get groups(): DataFrame | undefined { return this._groups; }\n set groups(v: DataFrame | undefined) { this._groups = v; }\n\n get trajectories(): DataFrame | undefined { return this._trajectories; }\n set trajectories(v: DataFrame | undefined) { this._trajectories = v; }\n\n /** Explicit networks (one row per named layer, edge columns as in `edges`),\n * drawn by <qe-edges network=\"name\">. */\n get networks(): DataFrame | undefined { return this._networks; }\n set networks(v: DataFrame | undefined) { this._networks = v; }\n\n /** Explicit point sets (rows: set, id, x, y, group?, color?, shape?, label?),\n * drawn by <qe-points set=\"name\">. */\n get pointsets(): DataFrame | undefined { return this._pointsets; }\n set pointsets(v: DataFrame | undefined) { this._pointsets = v; }\n\n get dimensions(): (string | number)[] { return this._dimensions; }\n set dimensions(v: (string | number)[]) { this._dimensions = v; }\n\n get params(): any { return this._params; }\n set params(v: any) { this._params = v; }\n\n point(id: string): DataFrameRow | undefined {\n return this._points.row(id);\n }\n\n setByKey<K extends keyof ModelSpec>(key: K, value: ModelSpec[K]): void {\n (this as any)[key] = value;\n }\n}\n\nexport default Model;\n","export const DEBUG: boolean = (globalThis as any).__QEVIZ_DEBUG__ === true;\n\nexport function dbg(...args: any[]): void {\n if (DEBUG) console.log(...args);\n}\n","import { Label, Point } from \"../objects/PlottedObject\";\nimport { Edge } from \"../objects/Edges\";\nimport Model, { ModelKey } from \"../objects/Model\";\nimport { DataFrame } from \"../types/DataFrame.js\";\nimport { dbg } from \"../utils/debug.js\";\nimport { ModelData } from \"../types/ModelData.js\";\n\nexport const vizENA = {\n get: (n: number) => {\n const elements = [...(document as any).querySelectorAll(\"qe-graph\")];\n if (typeof n === \"number\" && n >= 0) {\n return elements[n];\n }\n return elements;\n },\n}\n\nexport class QEVisualElement extends HTMLElement {\n static tagName = 'qe-visual';\n\n static get observedAttributes() {\n return ['updated'];\n }\n\n static styles = `\n :host { display: block; width: 100%; }\n :host(.hidden) { display: none !important; }\n /* The output wrapper and the slotted graph fill the host so the plot\n stretches to its container instead of collapsing to intrinsic size. */\n div { display: block; width: 100%; height: 100%; }\n ::slotted(qe-graph) { display: block; width: 100%; height: 100%; }\n `;\n\n protected _outputElement!: HTMLElement;\n protected _isVisible: boolean = true;\n protected output: string = '';\n\n private _model: Model;\n /** Public accessor so ena-graph (and external code) can read the model. */\n get model(): Model {\n return this._model;\n }\n\n private _updated: string = '';\n get updated(): string {\n return this._updated;\n }\n set updated(val: string) {\n this._updated = val;\n this.setAttribute('updated', val);\n // Notify via CustomEvent instead of directly coupling to StateManager.\n // RQEVisualElement (and any other arbor consumer) listens for this and\n // forwards to globalStateManager.\n this.dispatchEvent(new CustomEvent('model-updated', {\n detail: this._model,\n bubbles: true,\n composed: true,\n }));\n }\n\n private _active_points: Point[] = [];\n private _points: Map<any, Point> = new Map();\n get points(): Map<any, Point> {\n return this._points;\n }\n set points(pts: Map<any, Point> | Point[]) {\n this._points.clear();\n if (pts instanceof Map) {\n this._points = pts;\n } else if (Array.isArray(pts)) {\n pts.forEach(p => this._points.set(p.ID, p));\n }\n }\n get active_points(): Point[] {\n return Array.from(this._active_points.values());\n }\n\n private _edges: Map<any, Edge> = new Map();\n get edges(): Map<any, Edge> {\n return this._edges;\n }\n set edges(edges: Map<any, Edge> | Edge[]) {\n this._edges.clear();\n if (edges instanceof Map) {\n this._edges = edges;\n } else if (Array.isArray(edges)) {\n this._edges = new Map();\n edges.forEach(e => this._edges.set(e.ID, e));\n }\n }\n\n private _labels: Map<any, Label> = new Map();\n get labels(): Map<any, Label> {\n return this._labels;\n }\n\n constructor() {\n super();\n\n this._model = new Model();\n\n const shadow = this.attachShadow({ mode: 'open' });\n\n const style = document.createElement('style');\n style.textContent = QEVisualElement.styles;\n shadow.appendChild(style);\n\n this._outputElement = document.createElement('div');\n shadow.appendChild(this._outputElement);\n }\n\n connectedCallback(): void {\n dbg(\"QEVisualElement connected\");\n this.render();\n }\n\n /**\n * Accept pre-fetched ENA model data and update the visualization.\n * Call this directly when data is available from any source —\n * rENA R package, Python package, or static JSON.\n */\n setModelData(data: ModelData): void {\n const frameKeys: ModelKey[] = ['nodes', 'edges', 'points', 'groups', 'confidence', 'outlier', 'trajectories', 'networks', 'pointsets'] as ModelKey[];\n\n // ── Step 1: ingest all frames into DataFrames ──────────────────────────\n frameKeys.forEach((name) => {\n const raw = (data as any)[name];\n if (!raw?.data?.length) return;\n\n const\n rows: any[] = raw.data,\n types: any = raw.types || {},\n colNames: string[] = Object.keys(rows[0]),\n colValues: any[][] = rows.map((v: any) => Object.values(v)),\n classes: string[] = colNames.map(col => (types[col] ?? 'character') as string);\n\n // Determine which column is the row-identifier (stored as DataFrame.rowName).\n // The caller can supply overrides; otherwise we auto-detect.\n let idCol: string | undefined;\n if (name === 'networks') {\n idCol = 'name'; // one row per explicit network layer\n } else if (name === 'pointsets') {\n idCol = 'id'; // point id within its set\n } else if (name === 'nodes') {\n idCol = data.node_id_col\n ?? colNames.find(c => (types[c] ?? 'character') === 'character');\n } else if (name === 'edges' || name === 'points' || name === 'trajectories') {\n idCol = data.id_col\n ?? colNames.find(c => (types[c] ?? 'character') === 'character');\n } else {\n // groups / confidence / outlier: first character column is the group id\n idCol = data.group_col\n ?? colNames.find(c => (types[c] ?? 'character') === 'character');\n }\n\n const removalCol = idCol ? colNames.indexOf(idCol) : 0;\n const rowNames = colValues.map((v: any) => String(v[removalCol]));\n this._model.setByKey(name, new DataFrame(colNames, colValues, rowNames, classes));\n });\n\n // ── Step 2: ingest scalar fields ─────────────────────────────────────\n if (data.updated !== undefined) this._model.setByKey('updated', data.updated);\n if (data.directed !== undefined) this._model.directed = data.directed;\n if (Array.isArray((data as any).palette)) this._model.palette = (data as any).palette.map(String);\n\n // ── Step 3: resolve and store column names on the model ───────────────\n // These are read by QEGraph at render time instead of hardcoded strings.\n\n // node id col — first character column in nodes, or override\n const nodesDF = this._model.nodes;\n this._model.node_id_col = data.node_id_col\n ?? nodesDF?.names?.find(n => nodesDF.col(n)?.type === 'character')\n ?? 'id';\n\n // unit id col — first character column in points, or override\n const pointsDF = this._model.points;\n this._model.unit_id_col = data.id_col\n ?? pointsDF?.names?.find(n => pointsDF.col(n)?.type === 'character')\n ?? 'id';\n\n // group col — caller override, or first non-unit-id character col in points\n const unitId = this._model.unit_id_col;\n this._model.group_col = data.group_col\n ?? pointsDF?.names?.find(n => n !== unitId && pointsDF.col(n)?.type === 'character')\n ?? null;\n\n // ── Step 4: auto-detect dimension (x/y) columns from nodes ───────────\n // Numeric columns that aren't the node id. Caller can override via\n // x_col / y_col but those are passed in ModelData for the renderer to use\n // directly; here we just set model.dimensions as the default.\n if (nodesDF?.names?.length) {\n const nodeId = this._model.node_id_col;\n const xColOvr = data.x_col;\n const yColOvr = data.y_col;\n if (xColOvr && yColOvr) {\n this._model.dimensions = [xColOvr, yColOvr];\n } else {\n const numCols = nodesDF.names.filter(n => {\n if (n === nodeId) return false;\n const col = nodesDF.col(n);\n return col && col.type !== 'character' && col.type !== 'logical';\n });\n if (numCols.length >= 2) {\n this._model.dimensions = [xColOvr ?? numCols[0], yColOvr ?? numCols[1]];\n }\n }\n }\n\n this.updated = this._model.updated !== undefined ? String(this._model.updated) : String(Date.now());\n dbg(\"Model updated via setModelData:\", this.updated);\n this.render();\n }\n\n /**\n * Base implementation is a no-op. Subclasses (e.g. RQEVisualElement) override\n * this to fetch data from a backend and call setModelData().\n */\n async calculate(): Promise<void> {}\n\n render(): void {\n if (!this._isVisible) {\n this.classList.add('hidden');\n } else {\n this.classList.remove('hidden');\n }\n\n if (this._model?.updated !== undefined && this._model.updated !== null) {\n this._outputElement.innerHTML = `${this.output}<slot></slot>`;\n } else {\n this._outputElement.innerHTML = \"Define the model on the left.\";\n }\n }\n}\ncustomElements.define(QEVisualElement.tagName, QEVisualElement);\n\nexport default QEVisualElement;\n","export class Color {\n base: string;\n\n constructor(base: Color | string) {\n this.base = typeof base === \"string\" ? base : base.base;\n\n // Return a Proxy to allow 0-based indexing for r, g, b\n return new Proxy(this, {\n get(target, prop) {\n if (typeof prop === \"string\" && /^[0-2]$/.test(prop)) {\n const { r, g, b } = Color.parseColor(target.base);\n return [r, g, b][Number(prop)];\n }\n return (target as any)[prop];\n }\n });\n }\n\n toString(): string {\n return this.base;\n }\n\n setBase(base: string): void {\n this.base = base;\n }\n\n static parseColor(color: string): { r: number; g: number; b: number } {\n // Parse hex color (e.g., \"#RRGGBB\")\n if (color.startsWith(\"#\")) {\n const bigint = parseInt(color.slice(1), 16);\n return {\n r: (bigint >> 16) & 255,\n g: (bigint >> 8) & 255,\n b: bigint & 255,\n };\n }\n throw new Error(\"Unsupported color format\");\n }\n\n static rgb(r: number, g: number, b: number): string {\n return `rgb(${r}, ${g}, ${b})`;\n }\n}\n\nexport class WeightedColor extends Color {\n weight: number;\n /** Optional alpha; defaults to `weight` (saturation and alpha together). */\n alpha: number | undefined;\n\n constructor(base: Color | string, weight: number, alpha?: number) {\n super(base);\n this.weight = weight;\n this.alpha = alpha;\n }\n\n // Parse hex → HSV (h in [0, 360), s/v in [0, 1]).\n static toHSV(hex: string): { h: number; s: number; v: number } {\n const { r, g, b } = Color.parseColor(hex);\n const rn = r / 255, gn = g / 255, bn = b / 255;\n const max = Math.max(rn, gn, bn), min = Math.min(rn, gn, bn);\n const d = max - min;\n const v = max;\n const s = max === 0 ? 0 : d / max;\n let h = 0;\n if (d > 0) {\n switch (max) {\n case rn: h = ((gn - bn) / d + (gn < bn ? 6 : 0)) / 6; break;\n case gn: h = ((bn - rn) / d + 2) / 6; break;\n default: h = ((rn - gn) / d + 4) / 6;\n }\n }\n return { h: h * 360, s, v };\n }\n\n // Convert HSV + alpha → rgba() CSS string.\n static hsvToRgba(h: number, s: number, v: number, a: number): string {\n const c = v * s;\n const x = c * (1 - Math.abs((h / 60) % 2 - 1));\n const m = v - c;\n let r = 0, g = 0, b = 0;\n if (h < 60) { r = c; g = x; b = 0; }\n else if (h < 120) { r = x; g = c; b = 0; }\n else if (h < 180) { r = 0; g = c; b = x; }\n else if (h < 240) { r = 0; g = x; b = c; }\n else if (h < 300) { r = x; g = 0; b = c; }\n else { r = c; g = 0; b = x; }\n return `rgba(${Math.round((r + m) * 255)},${Math.round((g + m) * 255)},${Math.round((b + m) * 255)},${a.toFixed(4)})`;\n }\n\n // Returns rgba(...) matching rENA's edge-color convention (ena.plot.network):\n // • hue and value (brightness) are preserved from the base color\n // • HSV saturation is set to |weight| directly (0 = grey, 1 = fully vivid)\n // • alpha is also set to |weight|\n //\n // rENA converts the input color to HSV, replaces the S component with the\n // normalized edge weight, and additionally sets plotly element opacity to the\n // same value. Working in HSV (not HSL) is essential: palette colors like\n // #EE6677 have HSL lightness ≈ 67%, so 100% HSL saturation still looks\n // washed-out, whereas HSV value ≈ 0.93 gives the expected vivid output.\n toString(): string {\n const { h, v } = WeightedColor.toHSV(this.base);\n const w = Math.min(1, Math.abs(this.weight));\n const a = this.alpha === undefined ? w : Math.min(1, Math.max(0, this.alpha));\n return WeightedColor.hsvToRgba(h, w, v, a);\n }\n}","export class Transform {\n private _values: number[] = [1, 0, 0, 1, 0, 0];\n private _keys: string[] = [\"a\", \"b\", \"c\", \"d\", \"e\", \"f\"];\n\n get values() {\n return this._values;\n }\n set values(vals: number[]) {\n if (vals && vals.length === 6) {\n this._values = vals;\n }\n }\n get keys() {\n return this._keys;\n }\n set keys(vals: string[]) {\n if (vals && vals.length === 6) {\n this._keys = vals;\n }\n }\n\n constructor(vals: number[] | null = null) {\n if (vals) {\n this.values = vals;\n }\n }\n\n toString() {\n let matrix_str = this.keys.map((k, i) => this.values[i]).join(\" \")\n ;\n\n return `matrix(${matrix_str})`;\n }\n\n toMatrix() {\n return Object.fromEntries(this._keys.map((k, i) => [k, this._values[i]]));\n }\n\n toArray() {\n return this._values;\n }\n\n set(wh: string, val: number) {\n if (val !== 0.0075 && val !== 0) {\n this._values[this._keys.findIndex(k => k === wh)] = val;\n }\n }\n get(wh: string) {\n return this._values[this._keys.findIndex(k => k === wh)];\n }\n\n scale(a: number, d: number = a) {\n this.a = a;\n this.d = d;\n }\n\n zoom(z: number) {\n this.a = z;\n this.d = z;\n }\n\n pan(x: number, y: number) {\n this.e = this.e + x;\n this.f = this.f + y;\n }\n\n set a(x: number) { this.set(\"a\", x); }\n set b(x: number) { this.set(\"b\", x); }\n set c(x: number) { this.set(\"c\", x); }\n set d(x: number) { this.set(\"d\", x); }\n set e(x: number) { this.set(\"e\", x); }\n set f(x: number) { this.set(\"f\", x); }\n\n get a() { return this.get(\"a\"); }\n get b() { return this.get(\"b\"); }\n get c() { return this.get(\"c\"); }\n get d() { return this.get(\"d\"); }\n get e() { return this.get(\"e\"); }\n get f() { return this.get(\"f\"); }\n}","// const __ = {\n// matrix_string: (matrix) => {\n// let matrix_str = ['a','b','c','d','e','f'].map( l => matrix[l] ).join(\" \")\n// return `matrix(${matrix_str})`\n// },\n// isArray: (obj) => {\n// return typeof Array.isArray === \"function\" ? Array.isArray(obj) :\n// (obj && typeof obj === \"object\" && obj.constructor.name === \"Array\");\n// },\n// recurse: (obj, opt, iterator) => {\n// function recurse(obj, i, parent = null) {\n// if (__.isArray(obj)) {\n// for (const [i, o] of obj.entries()) {\n// recurse(o, i, parent);\n// }\n// } else {\n// iterator(obj, i, parent);\n// if (obj && __.isArray(obj[opt.children])) {\n// for (const [i, o] of obj[opt.children].entries()) {\n// recurse(o, i, obj);\n// }\n// }\n// }\n// }\n\n// recurse(obj);\n// },\n// geom: {\n// point: {\n// // source https://github.com/HarryStevens/geometric/\n// translate: (point, angle, distance) => {\n// const r = __.geom.angle.torad(angle);\n// return [point[0] + distance * Math.cos(r), point[1] + distance * Math.sin(r)];\n// },\n\n// // source https://github.com/HarryStevens/geometric/\n// rotate: (point, angle, origin) => {\n\n// // See: https://en.wikipedia.org/wiki/Cartesian_coordinate_system#Rotation\n// function rotate(point, angle){\n// return [\n// (point[0] * Math.cos(angle)) - point[1] * Math.sin(angle),\n// (point[0] * Math.sin(angle)) + point[1] * Math.cos(angle)\n// ];\n// }\n\n// const r = __.geom.angle.torad(angle);\n\n// if (!origin || (origin[0] === 0 && origin[1] === 0)){\n// return rotate(point, r);\n// }\n// else {\n// // See: https://math.stackexchange.com/questions/1964905/rotation-around-non-zero-point\n// const p0 = point.map((c, i) => c - origin[i]);\n// const rotated = rotate(p0, r);\n// return rotated.map((c, i) => c + origin[i]);\n// }\n// }\n// },\n// line: {\n// slope: (p1, p2) => {\n// let\n// m = (p2[1] - p1[1])/(p2[0] - p1[0]),\n// n = p1[0] - m * p1[0]\n// ;\n// return m;\n// },\n// intercept: (p1, p2) => {\n// let\n// m = __.geom.line.slope(p1, p2),\n// n = p1[1] - m * p1[0]\n// ;\n// return n;\n// },\n// slope_intercept: (p1, p2) => {\n// return {\n// slope: __.geom.line.slope(p1, p2),\n// intercept: __.geom.line.intercept(p1, p2)\n// };\n// },\n// midpoint: (p1, p2, w = 0.5) => {\n// if(Array.isArray(p1[0])) {\n// p2 = (p1[1]);\n// p1 = (p1[0]);\n// }\n// return [0, 1].map( i => (parseFloat(p1[i]) + parseFloat(p2[i])) * w );\n// },\n// length: (p1, p2) => {\n// if(Array.isArray(p1[0])) {\n// p2 = p1[1];\n// p1 = p1[0];\n// }\n// return Math.sqrt([0, 1].map( i => Math.pow(p2[i] - p1[i], 2) ).reduce( (a,b) => a + b, 0))\n// },\n// interpolate: (line) => {\n// // source https://github.com/HarryStevens/geometric/\n// return t =>\n// t === 0 ?\n// line[0] :\n// t === 1 ?\n// line[1] :\n// __.geom.point.translate(line[0], __.geom.angle.line(line), __.geom.line.length(line) * t)\n// ;\n// },\n// point_along: (line, distance = 0) => {\n// let\n// len = __.geom.line.length(line),\n// ratio = distance / len,\n// Xt = ((1 - ratio) * line[0][0] + (ratio * line[1][0])),\n// Yt = ((1 - ratio) * line[0][1] + (ratio * line[1][1]))\n// ;\n// return [Xt, Yt];\n// },\n// rotate: (line, by = [0, 0]) => {\n// let\n// translated = [line[1][0] - by[0], line[1][1] - by[1]],\n// rotated = [-(translated[1]), translated[0]],\n// rotated_reflection = [-(rotated[0]), -(rotated[1])],\n// untranslated = [rotated[0] + by[0], rotated[1] + by[1]],\n// untranslated2 = [rotated_reflection[0] + by[0], rotated_reflection[1] + by[1]]\n// ;\n// return [untranslated, untranslated2];\n// },\n// rotate2: (line, fixed, angle = 90) => {\n// let\n// line_si = __.geom.line.slope_intercept(line[0], line[1]),\n// P = [0, line_si.intercept],\n// Q = [1, line_si.slope + line_si.intercept]\n// ;\n// line = [P, Q];\n\n// let\n// xx = [line[0][0], line[1][0]],\n// yy = [line[0][1], line[1][1]],\n// x_fixed = fixed[0],\n// y_fixed = fixed[1],\n// angle_rad = -2 * Math.PI * angle/360,\n// xx_new = xx.map( (x, i) => (x - x_fixed) * Math.cos(angle_rad) - (yy[i] - y_fixed) * Math.sin(angle_rad) + x_fixed ),\n// yy_new = yy.map( (y, i) => (xx[i] - x_fixed) * Math.sin(angle_rad) - (y - y_fixed) * Math.cos(angle_rad) + y_fixed ),\n// object_new = [\n// [xx_new[0], yy_new[0]],\n// [xx_new[1], yy_new[1]]\n// ]\n// ;\n\n// return(object_new);\n// },\n// intersection: (lineA, lineB) => {\n// const\n// [[x1, y1], [x2, y2]] = lineA,\n// [[x3, y3], [x4, y4]] = lineB,\n// D = ( (x1 - x2) * (y3 - y4) ) - ( (y1 - y2) * (x3 - x4) ),\n// num1 = ( ((x1 * y2) - (y1 * x2)) * (x3 - x4) ) -\n// ( (x1 - x2) * ((x3 * y4) - (y3 * x4)) ),\n// num2 = ( ((x1 * y2) - (y1 * x2)) * (y3 - y4) ) -\n// ( (y1 - y2) * ((x3 * y4) - (y3 * x4)) )\n// ;\n// return [num1 / D, num2 / D];\n// },\n// intersect_circle(line, circle_xy, circle_r) {\n// let { slope: m, intercept: n } = __.geom.line.slope_intercept(line[0], line[1]);\n// let\n// a = 1 + Math.pow(m,2),\n// b = 2 * m * n - 2 * circle_xy[1] * m - 2 * circle_xy[0],\n// c = Math.pow(circle_xy[0], 2) + Math.pow(n, 2) + Math.pow(circle_xy[1], 2) - 2 * circle_xy[1] * n - Math.pow(circle_r, 2),\n// int\n// ;\n// if (Math.sqrt( Math.pow(b, 2) - (4 * a * c)) >= 0) {\n// let\n// x1 = (-b + Math.sqrt( Math.pow(b, 2) - (4 * a * c)))/(2 * a),\n// x2 = (-b - Math.sqrt( Math.pow(b, 2) - (4 * a * c)))/(2 * a),\n// y1 = m * x1 + n,\n// y2 = m * x2 + n\n// ;\n// int = [[x1, y1], [x2, y2]];\n// }\n// else {\n// int = \"The line and the circumference do not intersect\"\n// }\n// return(int)\n// }\n// },\n// angle: {\n// torad: (a) => a / 180 * Math.PI,\n// todeg: (a) => a * 180 / Math.PI,\n// line: (line) => {\n// // source https://github.com/HarryStevens/geometric/\n// return __.geom.angle.todeg(\n// Math.atan2(line[1][1] - line[0][1], line[1][0] - line[0][0])\n// );\n// }\n// }\n// },\n// object: {\n// proxy(obj, handler, deep = false) {\n// if(deep === false) {\n// return new Proxy(obj, handler);\n// }\n// else {\n// if (typeof obj !== 'object' || obj === null) {\n// return obj;\n// }\n\n// for (const key in obj) {\n// if (obj.hasOwnProperty(key)) {\n// obj[key] = __.object.proxy(obj[key], handler, deep);\n// }\n// }\n\n// return new Proxy(obj, handler);\n// }\n// },\n// handler: {\n// set: function(target, property, value) {\n// target[property] = value;\n// window.dispatchEvent(__.event(\"settingUpdate\", this, { target, property, value }))\n\n// return true;\n// },\n// get: function(target, property) {\n// return target[property];\n// }\n// },\n// get: (obj, key) => {\n// const parts = key.split(\".\");\n// let current = obj;\n// for (const part of parts) {\n// if (current && typeof current === \"object\" && current.hasOwnProperty(part)) {\n// current = current[part];\n// }\n// else {\n// return undefined;\n// }\n// }\n// return current;\n// },\n// set: (obj, key, value) => {\n// const parts = key.split(\".\");\n// let current = obj,\n// i\n// ;\n\n// for (i = 0; i < parts.length - 1; i++) {\n// const part = parts[i];\n// if (current && typeof current === \"object\") {\n// if (!current.hasOwnProperty(part)) {\n// current[part] = {};\n// }\n// current = current[part];\n// }\n// else {\n// return false;\n// }\n// }\n\n// if (current && typeof current === \"object\") {\n// current[parts[i]] = value;\n// return true;\n// }\n// else {\n// return false;\n// }\n// }\n// },\n// array: {\n// unique: (x) => [...new Set(x)],\n// divide: (a, b) => {\n// let ret;\n\n// if(Array.isArray(a)) {\n// if(Array.isArray(b)) {\n// if(a.length === b.length) {\n// ret = a.map( (a_,i) => a_ / b[i] )\n// }\n// else {\n// console.error(\"If both are arrays, they must be equal length.\")\n// }\n// }\n// else {\n// ret = a.map( a_ => a_ / b );\n// }\n// }\n// else {\n// ret = a / b;\n// }\n\n// return(ret);\n// },\n// multiply: (a, b) => {\n// let ret;\n\n// if(Array.isArray(a)) {\n// if(Array.isArray(b)) {\n// if(a.length === b.length) {\n// ret = a.map( (a_,i) => a_ * b[i] )\n// }\n// else {\n// console.error(\"If both are arrays, they must be equal length.\")\n// }\n// }\n// else {\n// ret = a.map( a_ => a_ * b );\n// }\n// }\n// else {\n// ret = a * b;\n// }\n\n// return(ret);\n// },\n// subtract: (a, b) => {\n// let ret;\n\n// if(Array.isArray(a)) {\n// if(Array.isArray(b)) {\n// if(a.length === b.length) {\n// ret = a.map( (a_,i) => a_ - b[i] )\n// }\n// else {\n// console.error(\"If both are arrays, they must be equal length.\")\n// }\n// }\n// else {\n// ret = a.map( a_ => a_ - b );\n// }\n// }\n// else {\n// ret = a - b;\n// }\n\n// return(ret);\n// },\n// shift: () => {\n// return Array.from(a, (b, i) => a[i + 1]);\n// }\n// },\n// math: {\n// sum: (a) => a.reduce( (a,b) => a + b, 0),\n// mean: (a) => __.math.sum(a) / a.length,\n// round: (a, b) => {\n// const factor = Math.pow(10, b);\n// return Math.round(a * factor) / factor;\n// }\n// },\n// event: (nm, elm, data) => {\n// return new CustomEvent(nm, {\n// bubbles: true,\n// cancelable: true,\n// detail: {\n// element: elm,\n// data: data || (elm ? elm.__data__ : undefined)\n// }\n// })\n// },\n// hash: {\n// parts: () => location.hash.replace(/#/,'').split(/\\//).filter(a => a).map(a => a.split(/:/)),\n// exists: (x) => __.hash.parts().flat().findIndex(a => a === x) >= 0\n// },\n// url: {\n// parse: (l = window.location) => {\n// },\n// query: {\n// parse: (l = window.location.search) =>\n// Object.fromEntries(l.replace(/^\\?/,'').split(/&/).map( i => i.split(/=/) ))\n// ,\n// keys: (l = window.location.search) =>\n// l.replace(/^\\?/,'').split(/&/).map( i => i.split(/=/)[0] )\n// ,\n// has: (k, l = window.location.search) =>\n// __.url.query.keys(l).findIndex(i => i == k) >= 0\n// }\n// }\n// };\n\nexport namespace Tools {\n export namespace Matrix {\n export function matrixString(matrix: Record<string, number>): string {\n const matrixStr = ['a', 'b', 'c', 'd', 'e', 'f'].map(l => matrix[l]).join(' ');\n return `matrix(${matrixStr})`;\n }\n }\n\n export namespace Geometry {\n export namespace Point {\n export function translate(point: [number, number], angle: number, distance: number): [number, number] {\n const r = Angle.toRad(angle);\n return [point[0] + distance * Math.cos(r), point[1] + distance * Math.sin(r)];\n }\n\n export function rotate(point: [number, number], angle: number, origin?: [number, number]): [number, number] {\n const r = Angle.toRad(angle);\n\n function rotatePoint(p: [number, number], a: number): [number, number] {\n return [\n p[0] * Math.cos(a) - p[1] * Math.sin(a),\n p[0] * Math.sin(a) + p[1] * Math.cos(a),\n ];\n }\n\n if (!origin || (origin[0] === 0 && origin[1] === 0)) {\n return rotatePoint(point, r);\n } else {\n const p0 = point.map((c, i) => c - origin[i]) as [number, number];\n const rotated = rotatePoint(p0, r);\n return rotated.map((c, i) => c + origin[i]) as [number, number];\n }\n }\n }\n\n export namespace Line {\n export function slope(p1: [number, number], p2: [number, number]): number {\n return (p2[1] - p1[1]) / (p2[0] - p1[0]);\n }\n export function intercept(p1: [number, number], p2: [number, number]): number {\n const m = slope(p1, p2);\n return p1[1] - m * p1[0];\n }\n export function slopeIntercept(p1: [number, number], p2: [number, number]): { slope: number; intercept: number } {\n return {\n slope: slope(p1, p2),\n intercept: intercept(p1, p2),\n };\n }\n export function point_along(line: [[number, number], [number, number]], distance: number = 0): [number, number] {\n const ratio = distance;\n const Xt = ((1 - ratio) * line[0][0] + (ratio * line[1][0]));\n const Yt = ((1 - ratio) * line[0][1] + (ratio * line[1][1]));\n return [Xt, Yt];\n }\n export function midpoint(p1: [number, number], p2: [number, number], w = 0.5): [number, number] {\n if (Array.isArray(p1[0])) {\n p2 = (p1[1] as any);\n p1 = (p1[0] as any);\n }\n\n return [0, 1].map(i => (parseFloat(p1[i] as any) + parseFloat(p2[i] as any)) * w) as [number, number];\n }\n export function length(\n p1: [number, number] | [[number, number], [number, number]],\n p2?: [number, number]\n ): number {\n if (Array.isArray((p1 as any)[0])) {\n p2 = (p1 as [[number, number], [number, number]])[1];\n p1 = (p1 as [[number, number], [number, number]])[0];\n }\n return Math.sqrt(\n [0, 1].map(i => Math.pow((p2 as [number, number])[i] - (p1 as [number, number])[i], 2)).reduce((a, b) => a + b, 0)\n );\n }\n export function rotate(\n line: [[number, number], [number, number]],\n by: [number, number] = [0, 0]\n ): [[number, number], [number, number]] {\n const translated: [number, number] = [\n line[1][0] - by[0],\n line[1][1] - by[1]\n ];\n const rotated: [number, number] = [\n -translated[1],\n translated[0]\n ];\n const rotated_reflection: [number, number] = [\n -rotated[0],\n -rotated[1]\n ];\n const untranslated: [number, number] = [\n rotated[0] + by[0],\n rotated[1] + by[1]\n ];\n const untranslated2: [number, number] = [\n rotated_reflection[0] + by[0],\n rotated_reflection[1] + by[1]\n ];\n return [untranslated, untranslated2];\n }\n export function rotate2(\n line: [[number, number], [number, number]],\n fixed: [number, number],\n angle: number = 90\n ): [[number, number], [number, number]] {\n // Calculate slope and intercept\n const m = Tools.Geometry.Line.slope(line[0], line[1]);\n const n = Tools.Geometry.Line.intercept(line[0], line[1]);\n const P: [number, number] = [0, n];\n const Q: [number, number] = [1, m + n];\n line = [P, Q];\n\n const xx = [line[0][0], line[1][0]];\n const yy = [line[0][1], line[1][1]];\n const x_fixed = fixed[0];\n const y_fixed = fixed[1];\n const angle_rad = -2 * Math.PI * angle / 360;\n const xx_new = xx.map((x, i) =>\n (x - x_fixed) * Math.cos(angle_rad) - (yy[i] - y_fixed) * Math.sin(angle_rad) + x_fixed\n );\n const yy_new = yy.map((y, i) =>\n (xx[i] - x_fixed) * Math.sin(angle_rad) - (y - y_fixed) * Math.cos(angle_rad) + y_fixed\n );\n const object_new: [[number, number], [number, number]] = [\n [xx_new[0], yy_new[0]],\n [xx_new[1], yy_new[1]]\n ];\n\n return object_new;\n }\n export function intersection(\n lineA: [[number, number], [number, number]],\n lineB: [[number, number], [number, number]]\n ): [number, number] {\n const\n [[x1, y1], [x2, y2]] = lineA,\n [[x3, y3], [x4, y4]] = lineB,\n D = ((x1 - x2) * (y3 - y4)) - ((y1 - y2) * (x3 - x4)),\n num1 = (((x1 * y2) - (y1 * x2)) * (x3 - x4)) -\n ((x1 - x2) * ((x3 * y4) - (y3 * x4))),\n num2 = (((x1 * y2) - (y1 * x2)) * (y3 - y4)) -\n ((y1 - y2) * ((x3 * y4) - (y3 * x4)));\n return [num1 / D, num2 / D];\n }\n export function intersect_circle(line: [[number, number], [number, number]], circle_xy: [number, number], circle_r: number): [[number, number], [number, number]] {\n let { slope: m, intercept: n } = Tools.Geometry.Line.slopeIntercept(line[0], line[1]);\n let\n a = 1 + Math.pow(m, 2),\n b = 2 * m * n - 2 * circle_xy[1] * m - 2 * circle_xy[0],\n c = Math.pow(circle_xy[0], 2) + Math.pow(n, 2) + Math.pow(circle_xy[1], 2) - 2 * circle_xy[1] * n - Math.pow(circle_r, 2),\n int: [[number, number], [number, number]] = [[Infinity, Infinity], [Infinity, Infinity]]\n ;\n\n if (Math.sqrt(Math.pow(b, 2) - (4 * a * c)) >= 0) {\n let\n x1 = (-b + Math.sqrt(Math.pow(b, 2) - (4 * a * c))) / (2 * a),\n x2 = (-b - Math.sqrt(Math.pow(b, 2) - (4 * a * c))) / (2 * a),\n y1 = m * x1 + n,\n y2 = m * x2 + n\n ;\n int = [[x1, y1], [x2, y2]];\n }\n else {\n console.error(\"The line and the circumference do not intersect\");\n }\n\n return (int)\n }\n export function interpolate(line: [[number, number], [number, number]]): (t: number) => [number, number] {\n // source https://github.com/HarryStevens/geometric/\n return t =>\n t === 0 ?\n line[0] :\n t === 1 ?\n line[1] :\n Tools.Geometry.Point.translate(line[0], Tools.Geometry.Angle.line(line), Tools.Geometry.Line.length(line) * t)\n ;\n }\n }\n\n export namespace Angle {\n export function toRad(angle: number): number {\n return (angle / 180) * Math.PI;\n }\n\n export function toDeg(angle: number): number {\n return (angle * 180) / Math.PI;\n }\n // source https://github.com/HarryStevens/geometric/\n export function line(line: [[number, number], [number, number]]): number {\n if (line.length !== 2 || !Array.isArray(line[0]) || !Array.isArray(line[1]) || line[0].length !== 2 || line[1].length !== 2) {\n throw new Error('Invalid line format. Expected [[x1, y1], [x2, y2]].');\n }\n //console.log(\"line: \", line)\n return Tools.Geometry.Angle.toDeg(\n Math.atan2(line[1][1] - line[0][1], line[1][0] - line[0][0])\n );\n }\n }\n }\n\n export namespace ArrayTools {\n export function unique<T>(arr: T[]): T[] {\n return [...new Set(arr)];\n }\n\n export function divide(a: number | number[], b: number | number[]): number | number[] {\n if (Array.isArray(a)) {\n if (Array.isArray(b)) {\n if (a.length !== b.length) throw new Error('Arrays must be of equal length');\n return a.map((val, i) => val / b[i]);\n }\n return a.map(val => val / (b as number));\n }\n return (a as number) / (b as number);\n }\n\n export function isArray(obj: any): boolean {\n return typeof Array.isArray === \"function\" ? Array.isArray(obj) :\n (obj && typeof obj === \"object\" && obj.constructor.name === \"Array\");\n }\n }\n\n export namespace Mathematics {\n export function sum(arr: number[]): number {\n return arr.reduce((a, b) => a + b, 0);\n }\n\n export function mean(arr: number[]): number {\n return sum(arr) / arr.length;\n }\n\n export function round(value: number, decimals: number): number {\n const factor = Math.pow(10, decimals);\n return Math.round(value * factor) / factor;\n }\n }\n\n export namespace Events {\n export function createEvent(name: string, element?: HTMLElement, data?: any): CustomEvent {\n return new CustomEvent(name, {\n bubbles: true,\n cancelable: true,\n detail: {\n element,\n data: data || (element ? (element as any).__data__ : undefined),\n },\n });\n }\n }\n\n export namespace Hash {\n export function parts(): string[][] {\n return location.hash\n .replace(/#/, '')\n .split(/\\//)\n .filter(a => a)\n .map(a => a.split(/:/));\n }\n\n export function exists(key: string): boolean {\n return parts().flat().findIndex(a => a === key) >= 0;\n }\n }\n\n\n export namespace Objects {\n export function proxy<T extends object>(obj: T, handler: ProxyHandler<any>, deep = false): T {\n if (!deep) {\n return new Proxy(obj, handler);\n } else {\n if (typeof obj !== 'object' || obj === null) {\n return obj;\n }\n\n for (const key in obj) {\n if (Object.prototype.hasOwnProperty.call(obj, key)) {\n (obj as any)[key] = proxy((obj as any)[key], handler, deep);\n }\n }\n\n return new Proxy(obj, handler);\n }\n }\n\n export const handler: ProxyHandler<any> = {\n set(target, property, value) {\n target[property] = value;\n window.dispatchEvent(\n Tools.Events.createEvent(\"settingUpdate\", window as any, { target, property, value })\n );\n return true;\n },\n get(target, property) {\n return target[property];\n }\n };\n\n export function get(obj: any, key: string): any {\n const parts = key.split(\".\");\n let current = obj;\n for (const part of parts) {\n if (current && typeof current === \"object\" && Object.prototype.hasOwnProperty.call(current, part)) {\n current = current[part];\n } else {\n return undefined;\n }\n }\n return current;\n }\n\n export function set(obj: any, key: string, value: any): boolean {\n const parts = key.split(\".\");\n let current = obj;\n let i: number;\n\n for (i = 0; i < parts.length - 1; i++) {\n const part = parts[i];\n if (current && typeof current === \"object\") {\n if (!Object.prototype.hasOwnProperty.call(current, part)) {\n current[part] = {};\n }\n current = current[part];\n } else {\n return false;\n }\n }\n\n if (current && typeof current === \"object\") {\n current[parts[i]] = value;\n return true;\n } else {\n return false;\n }\n }\n }\n\n export namespace URL {\n export function parse(location: Location = window.location): Record<string, string> {\n return Object.fromEntries(new URLSearchParams(location.search));\n }\n\n export namespace Query {\n export function parse(location: string = window.location.search): Record<string, string> {\n return Object.fromEntries(\n location.replace(/^\\?/, '').split(/&/).map(i => i.split(/=/))\n );\n }\n\n export function keys(location: string = window.location.search): string[] {\n return location.replace(/^\\?/, '').split(/&/).map(i => i.split(/=/)[0]);\n }\n\n export function has(key: string, location: string = window.location.search): boolean {\n return keys(location).findIndex(i => i === key) >= 0;\n }\n }\n }\n}\n\n","export type EventBusListener = (details: { key: string, newValue: any, oldValue: any }) => any;\n\n/**\n * Minimal local pub/sub used by vizena Graph and Layer objects.\n * Has the same API surface as arbor's StateManager but carries no R/arbor deps.\n */\nexport class EventBus {\n private _state: Map<string, any> = new Map();\n private listeners: Map<string, Map<string, Set<EventBusListener>>> = new Map();\n\n get state(): Map<string, any> {\n return this._state;\n }\n\n hasVariable(key: string): boolean {\n return this._state.has(key);\n }\n\n getVariable(key: string): any {\n return this._state.get(key);\n }\n\n setVariable(key: string, value: any, options?: { lazy?: boolean }): void {\n const oldValue = this._state.get(key);\n this._state.set(key, value);\n if (!options?.lazy) {\n this.notifyListeners(key, value, oldValue);\n }\n }\n\n addListener(key: string, type: string, listener: EventBusListener): void {\n if (!this.listeners.has(key)) this.listeners.set(key, new Map());\n const typeMap = this.listeners.get(key)!;\n if (!typeMap.has(type)) typeMap.set(type, new Set());\n typeMap.get(type)!.add(listener);\n }\n\n removeListener(key: string, type: string, listener: EventBusListener): void {\n this.listeners.get(key)?.get(type)?.delete(listener);\n }\n\n getListeners(key: string, type: string): EventBusListener[] {\n return Array.from(this.listeners.get(key)?.get(type) ?? []);\n }\n\n notifyListeners(key: string, newValue: any, oldValue: any): void {\n const typeMap = this.listeners.get(key);\n if (!typeMap) return;\n for (const set of typeMap.values()) {\n set.forEach((listener) => {\n if (typeof listener === 'function') {\n listener({ key, newValue, oldValue });\n } else if (typeof (listener as any).calculate === 'function') {\n (listener as any).calculate.call(listener, { key, newValue, oldValue });\n }\n });\n }\n }\n}\n","import { Transform } from \"./Transform.js\";\nimport { Tools } from \"../utils/Tools.js\";\nconst { ArrayTools } = Tools;\nimport { Graph } from \"./Graph.js\";\nimport { PlottedObject } from \"./PlottedObject.js\";\nimport { EventBus as StateManager } from \"../types/EventBus.js\";\n\nexport type LayerLike = {\n name?: string;\n layers?: LayerArray;\n [key: string]: any;\n};\n\nexport class LayerArray extends Array<LayerLike> {\n constructor(...args: any[]) {\n super(...args);\n }\n\n search(key: string, name: string): LayerLike | undefined {\n let found: LayerLike | undefined;\n\n function fn(a: LayerLike): LayerLike | undefined {\n return a.name === name ? a : undefined;\n }\n\n function recurse(obj: any, i?: number, parent: any = null): LayerLike | undefined {\n if (ArrayTools.isArray(obj)) {\n for (const [i, o] of obj.entries()) {\n found = recurse(o, i, parent);\n if (found) {\n return found;\n }\n }\n } else {\n found = fn(obj);\n if (!found) {\n if (obj && ArrayTools.isArray(obj[key])) {\n for (const [i, o] of obj[key].entries()) {\n found = recurse(o, i, obj);\n if (found) {\n return found;\n }\n }\n }\n } else {\n return found;\n }\n }\n return found;\n }\n\n return recurse(this);\n }\n\n flatten(): LayerLike[] {\n return this.reduce<LayerLike[]>((a, l: LayerLike) => {\n a.push(l);\n if (l.layers && Array.isArray(l.layers)) {\n a.push(...l.layers);\n }\n return a;\n }, []);\n }\n \n recurse(\n key: string,\n callback: (layer: LayerLike, parent?: LayerLike | null, depth?: number) => any, \n parent: LayerLike | null = null, \n depth: number = 0\n ): any {\n let results: any[] = new LayerArray();\n for (const layer of this) {\n let result = callback(layer, parent, depth);\n \n if (layer[key] && Array.isArray(layer[key])) {\n let r = new LayerArray(...layer[key]).recurse(key, callback, layer, depth + 1);\n if (r !== undefined) {\n results.push(...r);\n }\n }\n\n results.push(result);\n }\n console.log(\"Recurse results: \", results);\n return results;\n }\n}\n\nexport class Layer {\n __state__: StateManager = new StateManager();\n\n name: string;\n ID: string;\n scale_x: number = 1;\n scale_y: number = 1;\n tabindex?: number;\n _transform: Transform;\n scale_objects: boolean = true;\n layers: LayerArray = new LayerArray();\n objects: Map<string, PlottedObject> = new Map();\n parent?: Layer | Graph;\n visible: boolean = true;\n\n constructor(ID: string, o: any, parent?: Graph | Layer) {\n this.ID = ID;\n this.name = o.name || `layer-${ID}`;\n this.tabindex = o.tabindex;\n this.parent = parent;\n this._transform = new Transform();\n\n parent?.__state__.addListener(\"graph_updated\", \"live\", ({ key, newValue, oldValue }) => {\n // console.log(`Graph updated, updating layer: ${this.name}`);\n });\n \n parent?.__state__.addListener(`graph_updated_${this.name}`, \"live\", ({ key, newValue, oldValue }) => {\n // console.log(`Graph updated, updating layer: ${this.name}, Key: ${key}`, \"New Value: \", newValue, \"Old Value: \", oldValue);\n this.objects = newValue;\n this.__state__.setVariable(`layer_updated`, this );\n });\n }\n\n get transform(): Transform {\n return this._transform;\n }\n set transform(t: Transform) {\n this._transform = t;\n }\n}","import { Transform } from './Transform';\nimport { Color } from './Color';\nimport { Edge } from './Edges';\nimport { DataFrameRow } from '../types/DataFrame';\n\nexport type DimensionType = DimensionVector | DataFrameRow | number[];\n\nexport interface DimensionVectorInterface extends Array<number> {\n\n [index: number]: number;\n flipped: boolean;\n flip(): DimensionVector;\n get names(): string[];\n get(wh: string | number): number | undefined;\n}\nexport class DimensionVector extends Array<number> implements DimensionVectorInterface {\n #flipped: boolean = false;\n #names: string[] | undefined;\n\n constructor(...args: number[]) {\n super(arguments.length);\n for (let i = 0; i < args.length; i++) {\n this[i] = args[i];\n }\n this.#flipped = false;\n }\n\n static fromArray(arr: DataFrameRow): DimensionVector {\n const vec = new DimensionVector();\n arr.forEach((v, i) => {\n vec.push(v);\n });\n vec.#names = arr.names;\n\n return vec;\n }\n\n flip(): DimensionVector {\n this.#flipped = !this.#flipped;\n for (let i = 0; i < this.length; i++) {\n this[i] = -this[i];\n }\n return this;\n }\n\n get(wh: string | number): number | undefined {\n if (typeof wh === 'number') {\n return this[wh];\n } else if (this.#names && this.#names.includes(wh)) {\n return this[this.#names.indexOf(wh)];\n } else {\n return undefined;\n }\n }\n\n get flipped(): boolean {\n return this.#flipped;\n }\n\n get names(): string[] {\n if (this.#names) {\n return this.#names;\n } else {\n return this.map((_, i) => `V${i + 1}`);\n }\n }\n}\n\nexport interface PlottedObjectOptions {\n ID: string;\n dimensions?: DimensionVector;\n x?: number | number[];\n y?: number | number[];\n size: number | 0;\n color: Color;\n highlight: Color | null;\n shape?: any;\n active: boolean;\n meta: any;\n\n [key: string]: any;\n}\n\nexport class PlottedObject implements PlottedObjectOptions {\n private readonly _original: PlottedObjectOptions;\n private readonly _dimensions: DimensionVector;\n\n ID: string;\n scale_x: number = 1;\n scale_y: number = 1;\n scale_size: number = 0.05;\n active: boolean = false;\n visible: boolean = false;\n highlighting: boolean = false;\n meta: any = {};\n \n _transform: Transform;\n _x: any = 0;\n _y: any = 0;\n _color: Color;\n _highlight: Color;\n _highlight_default: Color = new Color('#000000');\n _size: number = 0;\n\n shape?: any;\n\n // graph: Graph;\n parent: any;\n\n get dimensions(): DimensionVector {\n return this._dimensions;\n }\n\n get color(): Color {\n return (\n // This was expecting hightight to be an object with a color property\n // but now it is just a Color object, so we can simplify this.\n (this.highlighting && this._highlight) ? this._highlight : this._color\n );\n }\n set color(c: Color) {\n this._color = c;\n }\n get highlight(): Color {\n return this._highlight || this._highlight_default;\n }\n set highlight(h: Color) {\n this._highlight = h;\n }\n\n get size(): number {\n return this._size;\n }\n set size(s: number) {\n this._size = s;\n }\n\n get original(): PlottedObjectOptions {\n return this._original;\n }\n\n get x() {\n return this._x; // * this.graph.x_mirror();\n }\n get y() {\n return this._y; // * this.graph.y_mirror();\n }\n set x(x_: any) { this._x = x_; }\n set y(y_: any) { this._y = y_; }\n dimension(wh: string | number): number | undefined {\n return this._dimensions.get(wh);\n }\n\n get transform() { return this._transform; }\n set transform(t: any) { this._transform = t; }\n\n constructor(dimensions: DimensionType, o: PlottedObjectOptions) {\n this.ID = o.ID;\n // this.graph = graph;\n this._transform = new Transform();\n\n // If dimensions is already a DimensionVector, use it directly\n if (dimensions instanceof DimensionVector) {\n this._dimensions = dimensions;\n }\n else if (dimensions instanceof DataFrameRow) {\n // If dimensions is a DataFrameRow, convert it to a DimensionVector\n this._dimensions = DimensionVector.fromArray(dimensions);\n }\n\n // If dimensions is an array, convert it to a DimensionVector\n else if (Array.isArray(dimensions)) {\n this._dimensions = new DimensionVector(...dimensions);\n }\n\n // Else is a warning and fallback to a default DimensionVector\n else {\n console.warn(\"Invalid dimensions provided, using default DimensionVector(0, 0)\");\n this._dimensions = new DimensionVector(0, 0);\n }\n\n // make a copy of the object to avoid mutating the original\n let data: PlottedObjectOptions = { ...o };\n\n // keep the original data for reference\n this._original = { ...data };\n\n this.ID = data.ID;\n this.x = data.x || this._dimensions[0];\n this.y = data.y || this._dimensions[1];\n this._size = data.size || 1;\n this._color = data.color || new Color('#000000');\n this.active = data.active || false;\n this.shape = data.shape || null;\n this.meta = data.meta || {};\n\n this._highlight = this._highlight_default;\n if (data.highlight) {\n this._highlight = data.highlight;\n }\n // else if (graph && graph.options && graph.options[this.constructor.name.toUpperCase()]) {\n // this._highlight = graph.options[this.constructor.name.toUpperCase()].highlight;\n // }\n }\n}\n\nexport interface LineOptions extends PlottedObjectOptions {\n x1: number | string;\n y1: number | string;\n x2: number | string;\n y2: number | string;\n width?: number;\n color: Color;\n shape: string | null;\n [key: string]: any;\n}\n\nexport class Line extends PlottedObject {\n from: Point;\n to: Point;\n width?: number;\n _color!: Color;\n shape!: string;\n\n // constructor(x: LineOptions) {\n // super([], x);\n // // const data = Object.assign({}, x);\n // const { x1, y1, x2, y2, width, color, shape } = x;\n\n // // console.log(\"Line constructor data:\", data);\n // // console.warn(\" this was using `meta` but it is deprecated now - should be using `original` instead\");\n // // this.meta = Object.keys(data)\n // // .filter(k => ['ID', 'x1', 'y1', 'x2', 'y2', 'size', 'color'].indexOf(k) < 0)\n // // .reduce((n: any, k: string) => { n[k] = data[k]; return n; }, {});\n\n // this.x1 = parseFloat(x1 as string);\n // this.y1 = parseFloat(y1 as string);\n // this.x2 = parseFloat(x2 as string);\n // this.y2 = parseFloat(y2 as string);\n // this.width = width;\n // this._color = color || new Color('#000000');\n // this.shape = shape || 'line';\n // }\n\n constructor(data: DataFrameRow | any, from: Point, to: Point) {\n // let\n // // dimensions: DimensionType = data.classes.map( (c: string, i: number) => c === \"ena.co.occurrence\" ? data[i] : -1).filter(a => a !== -1),\n // // meta: any = data.classes.map( (c: string, i: number) => c === \"ena.metadata\" ? [data.names[i], data[i]] : null).filter(a => a !== null).reduce((n: any, c: any) => { n[c[0]] = c[1]; return n; }, {}),\n // // ID: string = data.rowName || `point-${Math.random().toString(36).substring(2, 9)}`\n // ;\n\n super([], {} as any);\n\n this.from = from;\n this.to = to;\n }\n\n get line(): [[number, number], [number, number]] {\n return [[this.from.x, this.from.y], [this.to.x, this.to.y]];\n }\n get midpoint(): [number, number] {\n return [\n (this.from.x + this.to.x) / 2,\n (this.from.y + this.to.y) / 2\n ];\n }\n get length(): number {\n return Math.sqrt(\n Math.pow(this.to.x - this.from.x, 2) +\n Math.pow(this.to.y - this.from.y, 2)\n );\n }\n get color(): Color { return this._color; }\n set color(c: Color) { this._color = c; }\n}\n\nexport interface PointOptions extends PlottedObjectOptions {\n shape?: string;\n label?: string;\n [key: string]: any;\n}\n\nexport class Point extends PlottedObject {\n static SHAPES = { CIRCLE: 'circle', SQUARE: 'rect' };\n\n private _label: Label | undefined;\n edges: Map<any, Edge> = new Map();\n shape: string = Point.SHAPES.CIRCLE;\n\n // constructor(dimensions: DimensionType, o: PointOptions) { //, graph?: any) {\n // super(dimensions, o);\n // this.active = o.active || false;\n // this.visible = o.visible || false;\n // this.size = o.size || 1;\n // this.color = o.color || new Color('#000000');\n // this.shape = o.shape ? o.shape : \"circle\";\n // this.scale_size = 2;\n // this._x = dimensions[0];\n // this._y = dimensions[1];\n // this.label = new Label(this.ID, this);\n // }\n constructor(data: DataFrameRow | any) {\n let\n dimensions: DimensionType | undefined, // = data.classes.map( (c, i) => (c === \"ena.co.occurrence\" || c === \"ena.dimension\") ? data[i] : -1).filter(a => a !== -1),\n meta: any, // = data.classes.map( (c, i) => c === \"ena.metadata\" ? [data.names[i], data[i]] : null).filter(a => a !== null).reduce((n: any, c: any) => { n[c[0]] = c[1]; return n; }, {}),\n ID: string // = data.rowName || `point-${Math.random().toString(36).substring(2, 9)}`\n ;\n\n if(data) {\n if(data instanceof DataFrameRow) {\n dimensions = data.classes?.map( (c, i) => (c === \"ena.co.occurrence\" || c === \"ena.dimension\") ? data[i] : -1).filter(a => a !== -1);\n meta = data.classes?.map( (c, i) => c === \"ena.metadata\" ? [data.names[i], data[i]] : null).filter(a => a !== null).reduce((n: any, c: any) => { n[c[0]] = c[1]; return n; }, {});\n ID = data.rowName || `point-${Math.random().toString(36).substring(2, 9)}`;\n }\n else if(typeof data === \"object\") {\n dimensions = data.dimensions || [];\n meta = data.meta || {};\n ID = data.ID || `point-${Math.random().toString(36).substring(2, 9)}`;\n }\n else {\n console.warn(\"Invalid data provided for Point, using default values\");\n dimensions = [];\n meta = {};\n ID = `point-${Math.random().toString(36).substring(2, 9)}`;\n }\n }\n else {\n dimensions = [];\n meta = {};\n ID = `point-${Math.random().toString(36).substring(2, 9)}`;\n }\n\n super(dimensions ?? [], { meta, ID } as any);\n }\n\n set label(l: Label | undefined) {\n this._label = l;\n }\n get label(): Label | undefined {\n return this._label;\n }\n get x(): number {\n // const dims = this.graph.options.GRAPH.dimensions;\n // const _ = this.meta[dims[0]];\n // const mult = 1;\n // return parseFloat(_) * mult;\n return this._x;\n }\n get y(): number {\n // const dims = this.graph.options.GRAPH.dimensions;\n // const _ = this.meta[dims[1]];\n // const mult = 1;\n // return parseFloat(_) * mult;\n return this._y;\n }\n set x(x_: number) { this._x = parseFloat(x_ as any); }\n set y(y_: number) { this._y = parseFloat(y_ as any); }\n}\n\nexport class ConfidenceInterval extends PlottedObject {\n width?: number;\n z: number = 1.959964;\n // meta: any;\n\n private _mean: any;\n\n constructor(mean: any) {\n super(mean.dimensions, mean);\n this.ID = \"mean_ci_\" + mean.ID;\n this._mean = mean;\n }\n\n get line(): [[number, number], [number, number]] {\n // x1, y1, x2, y2 should be defined on mean or this\n return [\n [this._mean.x1, this._mean.y1],\n [this._mean.x2, this._mean.y2]\n ];\n }\n get variance(): [number, number] {\n const points = [...this._mean.points.values()];\n return [\n points.length > 1 ? points.map(p => Math.pow(p.x - this._mean.x, 2)).reduce((a, b) => a + b, 0) / (points.length - 1) : 0,\n points.length > 1 ? points.map(p => Math.pow(p.y - this._mean.y, 2)).reduce((a, b) => a + b, 0) / (points.length - 1) : 0\n ];\n }\n get std(): [number, number] {\n return this.variance.map(Math.sqrt) as [number, number];\n }\n get value(): [number, number] {\n const pointsSize = this._mean.points.size;\n return this.std.map(s => this.z * (s / Math.sqrt(pointsSize))) as [number, number];\n }\n get length(): number {\n const [a, b] = this.line;\n return Math.sqrt(Math.pow(b[0] - a[0], 2) + Math.pow(b[1] - a[1], 2));\n }\n\n get path(): string {\n const x_ = this._mean.x;\n const y_ = this._mean.y;\n const v = this.value;\n const x = v[0];\n const y = v[1];\n const xl = x_ - x;\n const xr = x_ + x;\n const yt = y_ - y;\n const yb = y_ + y;\n return `M${xl},${yt} ${xr},${yt} ${xr},${yb} ${xl},${yb}z`;\n }\n}\n\nexport class Label extends PlottedObject {\n object: PlottedObject;\n _visible: boolean = false;\n text: string;\n offset: number = 0;\n dragging?: boolean;\n\n constructor(txt: string, object: PlottedObject) {\n // super(object.ID);\n super(object.dimensions, object);\n this.text = txt;\n this.ID = object.ID;\n this.object = object;\n this.x = this.dimensions[0]; //object.x;\n this.y = this.dimensions[1]; //object.y;\n this.offset = object.size || 0;\n this.size = this.offset / 4;\n this.visible = false;\n\n this._transform.set(\"e\", 1); // this.object.size * this.graph.SIZE_EFFECT * 2);\n this._transform.set(\"f\", 1); // this.object.size * this.graph.SIZE_EFFECT * 2);\n }\n\n get x(): number {\n return parseFloat(this._x);\n }\n get y(): number {\n return parseFloat(this._y);\n }\n set x(x_: number) { this._x = x_; }\n set y(y_: number) { this._y = y_; }\n\n get transform(): Transform {\n console.warn(\"transform is disabled - need updated reference for the graph options\")\n // if (\n // !this.dragging &&\n // this.graph.options[this.object.constructor.name.toUpperCase()].labelposition === Label.POSITION.OBJECT\n // ) {\n // const s = this.object.size;\n // const effect = 1; // this.graph.object.SIZE_EFFECT\n // this._transform.set(\"e\", s * effect / 2 / this._transform.a);\n // this._transform.set(\"f\", s * effect / 2 / this._transform.a);\n // } else if (\n // !this.dragging &&\n // this.graph.options[this.object.constructor.name.toUpperCase()].labelposition === Label.POSITION.STATIC\n // ) {\n // const eVal = this.graph.extremes[this.graph.options.LABEL.position[1] as keyof typeof this.graph.extremes];\n // const fVal = this.graph.extremes[this.graph.options.LABEL.position[0] as keyof typeof this.graph.extremes];\n // this._transform.set(\"e\", typeof eVal === \"number\" ? eVal : 0);\n // this._transform.set(\"f\", typeof fVal === \"number\" ? fVal : 0);\n // }\n return this._transform;\n }\n set transform(t: Transform) { this._transform = t; }\n\n static DISPLAY_TYPES = { OFF: 0, AUTO: 1, CLICK: 2, ON: 3 };\n static HIGHLIGHT = { OFF: 0, ON: 2 };\n static POSITION = { OBJECT: 1, STATIC: 2, CONTAINER: 3, CUSTOM: 4 };\n}\n","\nclass Extremes {\n x_max: number;\n y_max: number;\n // _point_max?: Point;\n // _node_max?: Point;\n\n /** Centre of the view; (0, 0) — the ENA origin — unless centred on the content */\n cx: number;\n cy: number;\n\n constructor(x: number, y: number, cx: number = 0, cy: number = 0) { //, n?: Point, p?: Point) {\n this.x_max = x;\n this.y_max = y;\n this.cx = cx;\n this.cy = cy;\n // this._point_max = p;\n // this._node_max = n;\n }\n as_viewBox(p: number = 1.2): string {\n let x = this.x_max * p;\n let y = this.y_max * p;\n return (`${this.cx - x} ${this.cy - y} ${x * 2} ${y * 2}`);\n }\n\n // get point_max(): Point {\n // return this._point_max || { x: 1, y: 1 };\n // }\n // get node_max(): Point {\n // return this._node_max || { x: 1, y: 1 };\n // }\n\n get height(): number {\n return this.y_max * 2;\n } \n get width(): number {\n return this.x_max * 2;\n }\n get top(): number {\n return this.y_max * -1;\n }\n get bottom(): number {\n return this.y_max;\n }\n get left(): number {\n return this.x_max * -1;\n }\n get right(): number {\n return this.x_max;\n }\n}\n\nexport { Extremes };","import { DimensionVector, PlottedObject } from \"./PlottedObject\";\n\nexport class AxisPoint extends PlottedObject {\n\n constructor(dimensions: DimensionVector, o: any) {\n super(dimensions, o);\n\n this.visible = true;\n\n this.size = o.size;\n }\n\n set size(s: number) {\n this._size = s;\n }\n get size(): number {\n return this._size;\n }\n\n get x(): number {\n return this._x;\n }\n get y(): number {\n return this._y;\n }\n set x(x_: number) { this._x = x_; }\n set y(y_: number) { this._y = y_; }\n\n get transform() {\n return this._transform;\n }\n}","import { Color } from \"./Color\";\nimport { Layer, LayerArray, LayerLike } from \"./Layers\";\nimport { DimensionVector, Label, Line, Point } from \"./PlottedObject\";\nimport { Transform } from \"./Transform\";\nimport { Extremes } from \"./Extremes\";\nimport { Node } from \"./Points\";\nimport { Edge } from \"./Edges\";\nimport { AxisPoint } from \"./AxisPoint\";\nimport { DataFrame, DataFrameRow } from \"../types/DataFrame\";\nimport { EventBus as StateManager } from \"../types/EventBus\";\n\nexport let DefaultGraphOptions = {\n GRAPH: {\n ratio: 1,\n x_max: 1,\n y_max: 1,\n selector: \"body\",\n width: 1,\n height: 1,\n axes: true,\n SIZE_EFFECT: 1,\n dimensions: [ 0, 1 ]\n },\n NODE: {\n size: 1,\n highlight: {\n color: 'yellow',\n labels: Label.DISPLAY_TYPES.ON,\n },\n labels: Label.DISPLAY_TYPES.ON,\n labelposition: Label.POSITION.OBJECT\n },\n POINT: {\n active: 2,\n size: 0.05,\n color: \"#000\",\n shape: Point.SHAPES.CIRCLE,\n labels: Label.DISPLAY_TYPES.AUTO,\n labelposition: Label.POSITION.OBJECT\n },\n MEAN: {\n shape: Point.SHAPES.SQUARE,\n labels: Label.DISPLAY_TYPES.AUTO,\n },\n LABEL: {\n highlight: Label.HIGHLIGHT.OFF,\n position: ['top', 'left'],\n container: \"#label-container\"\n },\n EDGE: {\n multiplier: 1\n }\n};\n\nexport class Graph {\n __state__: StateManager = new StateManager();\n\n name: string = \"unnamed-graph\";\n origin: AxisPoint | undefined = undefined;\n\n options: typeof DefaultGraphOptions;\n\n points: Map<string, Point | AxisPoint> = new Map();\n nodes: Map<string, Node> = new Map();\n edges: Map<string, Edge> = new Map();\n trajectories: Map<string, any> = new Map();\n labels: Map<string, Label> = new Map();\n transform: Transform = new Transform();\n\n scale_x: number = 1;\n scale_y: number = 1;\n\n _extremes!: Extremes;\n SIZE_EFFECT: number = 1;\n _mirror_y: boolean = true;\n _mirror_x: boolean = false;\n\n layers: LayerArray;\n _layers: LayerArray = new LayerArray(\n { name: \"graph\", tabindex: 0, layers: [\n { \n name: \"axes\",\n layers: [\n { \n name: \"axis_lines\", tabindex: 0, layers: [], \n objects: [\n\n ]\n },\n { \n name: \"axis_labels\", tabindex: 0, layers: [], objects: []\n },\n {\n name: \"axis_points\", \n tabindex: 0, \n layers: [], \n objects: [\n this.origin\n ]\n }\n ]\n },\n\n {\n name: \"network\",\n layers: [\n { name: \"edges\", layers: [], tabindex: 0 },\n { name: \"nodes\", layers: [], tabindex: 0 },\n { name: \"edgenodes\", layers: [], tabindex: 0 },\n ]\n },\n { name: \"trajectories\", layers: [], tabindex: 0 },\n { name: \"points\", layers: [], tabindex: 0 },\n\n { name: \"labels\", layers: [], tabindex: 0 },\n ] },\n );\n\n constructor(\n options: typeof DefaultGraphOptions = { ...DefaultGraphOptions }\n ) {\n this.options = options;\n \n this.origin = new AxisPoint(\n new DimensionVector(0, 0),\n {\n ID: \"origin\",\n x: 0, y: 0,\n size: 0,\n meta: {},\n graph: this,\n color: new Color(\"#FFFFFF\"),\n highlight: new Color(\"#FFFFFF\"),\n active: false\n }\n );\n\n let layer_id = 1;\n function buildLayerTree(layerData: any, parent: Layer | null, graph: Graph): Layer {\n const new_layer = new Layer(`${layer_id}`, layerData, graph);\n layer_id += 1;\n new_layer.parent = parent || undefined;\n if (layerData.layers && Array.isArray(layerData.layers)) {\n new_layer.layers = new LayerArray(...layerData.layers.map((child: any) => buildLayerTree(child, new_layer, graph)));\n }\n return new_layer;\n }\n\n this.layers = new LayerArray(...this._layers.map((l: any) => buildLayerTree(l, null, this)));\n\n let axisPointLayer: LayerLike | undefined = this.layers.search(\"layers\", \"axis_points\");\n if (axisPointLayer) {\n axisPointLayer.objects.set(this.origin.ID, this.origin);\n }\n \n let axisLineLayer: LayerLike | undefined = this.layers.search(\"layers\", \"axis_lines\");\n if (axisLineLayer) {\n let extremes = this.extremes || new Extremes(1, 1);\n let axis_x = new Line(\n {}, \n new Point({ ID: \"axis-x-start\", dimensions: [-extremes.x_max, 0], classes: [\"ena.dimension\", \"ena.dimension\"] }), \n new Point({ ID: \"axis-x-end\", dimensions: [extremes.x_max, 0], classes: [\"ena.dimension\", \"ena.dimension\"] })\n );\n axis_x.ID = \"axis-x\";\n axisLineLayer.objects.set(axis_x.ID, axis_x);\n let axis_y = new Line(\n {}, \n new Point({ ID: \"axis-y-start\", dimensions: [0, -extremes.y_max], classes: [\"ena.dimension\", \"ena.dimension\"] }),\n new Point({ ID: \"axis-y-end\", dimensions: [0, extremes.y_max], classes: [\"ena.dimension\", \"ena.dimension\"] })\n );\n axis_y.ID = \"axis-y\";\n axisLineLayer.objects.set(axis_y.ID, axis_y);\n console.log(\"Added axis lines to layer: \", axisLineLayer);\n }\n\n // Define extremes based on options\n this.extremes = new Extremes(options.GRAPH.x_max, options.GRAPH.y_max);\n }\n\n set extremes(e: Extremes) {\n this._extremes = e;\n }\n get extremes(): Extremes {\n return this._extremes;\n }\n get mirror_x(): boolean {\n return this._mirror_x;\n }\n set mirror_x(m: boolean) {\n this._mirror_x = m;\n }\n get mirror_y(): boolean {\n return this._mirror_y;\n }\n set mirror_y(m: boolean) {\n this._mirror_y = m;\n }\n\n x_mirror(): number {\n return (this.mirror_x ? -1 : 1);\n }\n y_mirror(): number {\n return (this.mirror_y ? -1 : 1);\n }\n\n add_point(p: DataFrameRow) {\n const point: Point = new Point(p);\n this.points.set(point.ID, point);\n\n // if (g_.options.POINT && g_.options.POINT.label) {\n // p.label = new Label(p.meta[g_.options.POINT.label], p, g_);\n // g_.labels.set(p.label.ID, p.label);\n // }\n // g_.points.set(p.ID, p);\n // const pointsLayer = g_.layers.search(\"layers\", \"points\");\n // if (pointsLayer) {\n // pointsLayer.objects.push(p);\n // }\n // g_.update_extremes();\n }\n add_points(ps: DataFrame) {\n let g_ = this;\n ps.rows().forEach((p: DataFrameRow) => {\n g_.add_point(p);\n });\n }\n\n add_nodes(ns: any[]) {\n let\n g_ = this\n ;\n\n ns.forEach((new_node) => {\n // if (g_.options.NODE && g_.options.NODE.label) {\n // new_node.label = new Label(new_node.meta[g_.options.NODE.label], new_node, g_);\n new_node.label = new Label(new_node.ID, new_node);\n g_.labels.set(new_node.label.ID, new_node.label);\n // }\n g_.nodes.set(new_node.ID, new_node);\n const nodesLayer = g_.layers.search(\"layers\", \"nodes\");\n if (nodesLayer) {\n nodesLayer.objects.push(new_node);\n }\n });\n g_.update_extremes();\n }\n add_edge(e: any, from?: any, to?: any) {\n let g_ = this;\n g_.edges.set(e.ID, e);\n\n this.add_nodes([from || e.from, to || e.to]);\n\n return (e);\n }\n add_edges(es: any[]) {\n let added = es.map(e => this.add_edge(e));\n const edgesLayer = this.layers.search(\"layers\", \"edges\");\n if (edgesLayer) {\n edgesLayer.objects.push(...added);\n }\n return (added);\n }\n\n /**\n * The visible extent: 1.3 × the farthest point or node. Centred on the\n * origin (the ENA convention: (0, 0) is the mean of the points), or with\n * `centerContent`, on the middle of the points' and nodes' bounding box, so\n * a network that sits off to one side of the origin fills the plot.\n */\n update_extremes(centerContent: boolean = false) {\n // let\n // dim1 = this.options.GRAPH.dimensions[0],\n // dim2 = this.options.GRAPH.dimensions[1],\n // // Get all points and nodes to calculate extremes\n // all_points = [...this.points.values(), ...this.nodes.values()].flat(),\n // x_max = Math.max(...all_points.map((p: PlottedObject) => Math.abs(p.dimension(dim1) || 0))),\n // y_max = Math.max(...all_points.map((p: PlottedObject) => Math.abs(p.dimension(dim2) || 0))),\n // max = Math.max(x_max, y_max)\n // ;\n // this.extremes = new Extremes(Math.ceil(max), Math.ceil(max), { x: 1, y: 1 }, { x: 1, y: 1 });\n\n const search_layers = [\n this.layers.search(\"layers\", \"points\"),\n this.layers.search(\"layers\", \"nodes\")\n ].filter((l): l is LayerLike => l !== undefined);\n if (search_layers.length === 0) {\n this.extremes = new Extremes(1, 1);\n }\n else {\n // Bound = largest |x|/|y| across points and nodes, plus a modest margin\n // for peripheral node labels. The previous Math.ceil() snapped this up to\n // the next integer, which — for ENA's small coordinate ranges (≈1–2) —\n // left the network floating in a lot of dead space. Keep the raw value so\n // the drawing fills the canvas.\n let minX = Infinity, maxX = -Infinity, minY = Infinity, maxY = -Infinity;\n search_layers.forEach(l => l.objects.forEach((o: any) => {\n if (Number.isFinite(o.x)) { minX = Math.min(minX, o.x); maxX = Math.max(maxX, o.x); }\n if (Number.isFinite(o.y)) { minY = Math.min(minY, o.y); maxY = Math.max(maxY, o.y); }\n }));\n const found = Number.isFinite(minX) && Number.isFinite(minY);\n const cx = centerContent && found ? (minX + maxX) / 2 : 0;\n const cy = centerContent && found ? (minY + maxY) / 2 : 0;\n const content_max = found\n ? Math.max(Math.abs(minX - cx), Math.abs(maxX - cx), Math.abs(minY - cy), Math.abs(maxY - cy))\n : 0;\n const found_max = (content_max > 0 ? content_max : 1) * 1.3;\n this.extremes = new Extremes(found_max, found_max, cx, cy);\n }\n }\n\n /** Farthest node from (cx, cy), on either axis */\n nodeExtentFrom(cx: number, cy: number): number {\n const nodes = this.layers.search(\"layers\", \"nodes\");\n let max = 0;\n nodes?.objects.forEach((o: any) => {\n if (Number.isFinite(o.x) && Number.isFinite(o.y)) max = Math.max(max, Math.abs(o.x - cx), Math.abs(o.y - cy));\n });\n return max;\n }\n\n base_point_size(scale = 8): number {\n let minDim = Math.min(this.extremes.x_max, this.extremes.y_max);\n let n = this.points.size + this.nodes.size;\n return Math.min(1, minDim / (Math.sqrt(n) * scale));\n }\n}\n","import { Graph } from \"../objects/Graph\";\nimport { Layer } from \"../objects/Layers\";\nimport { PlottedObject } from \"../objects/PlottedObject\";\n\nexport abstract class DrawableElement extends HTMLElement {\n \n static style: string = `\n :host {\n max-width: 100%;\n display: block;\n }\n .wrapper {\n height: 100%;\n display: flex;\n justify-content: center;\n }\n `;\n\n element: Element | null = null;\n object: PlottedObject | Graph | Layer | null = null;\n\n get wrapper() {\n const\n element = this,\n shadow = element.shadowRoot,\n wrapper = shadow?.querySelector(\".wrapper\")\n ;\n return wrapper;\n }\n\n constructor() {\n super();\n\n const\n element = this,\n shadow = element.attachShadow({ mode: 'open' }),\n style = document.createElement('style'),\n wrapper = document.createElement('div')\n ;\n\n style.textContent = (this.constructor as any).style;\n shadow.appendChild(style);\n\n wrapper.setAttribute('class', 'wrapper');\n shadow.appendChild(wrapper);\n }\n}","// Pure, DOM-free polynomial trajectory fitting.\n//\n// Ported from `ena.plot.trajectory()` in the ETM Explorer (RescuShell) R kit:\n// - near-origin filtering of the fit set (points at the cumulative origin are\n// drawn but excluded from the fit),\n// - `loocv_2d` degree selection (joint 2D leave-one-out CV via the hat-matrix\n// shortcut), with a `fixed` escape hatch,\n// - least-squares polynomial fit solved by QR for numerical parity with R's\n// `lm(y ~ poly(t, deg))`.\n//\n// Leverages and residuals depend only on the column space of the design, so a\n// raw monomial basis solved by QR reproduces R's selected degree and fitted\n// curve to floating-point tolerance despite R using orthogonal `poly()`.\n\n/** Near-origin tolerance; hardcoded to match the R kit's `zero_eps` default. */\nexport const TRAJECTORY_ZERO_EPS = 1e-8;\n\nexport interface XY {\n x: number;\n y: number;\n}\n\nexport type DegreeSelection = 'loocv_2d' | 'fixed';\n\nexport interface TrajectoryFit {\n degree: number;\n coeffsX: number[];\n coeffsY: number[];\n}\n\n/** Drop near-origin points (both coords within eps of 0) from the fit set. */\nexport function nearOriginFilter(pts: XY[], eps: number = TRAJECTORY_ZERO_EPS): XY[] {\n return pts.filter(p => Math.abs(p.x) > eps || Math.abs(p.y) > eps);\n}\n\n/** Evenly spaced parameter t in [0,1] by index — matches R's seq(0,1,length.out=n). */\nfunction normalizedT(n: number): number[] {\n if (n <= 0) return [];\n if (n === 1) return [0];\n const t = new Array(n);\n for (let i = 0; i < n; i++) t[i] = i / (n - 1);\n return t;\n}\n\n/** Vandermonde design [1, t, t^2, ..., t^deg], n×(deg+1). */\nfunction design(t: number[], degree: number): number[][] {\n return t.map(ti => {\n const row = new Array(degree + 1);\n let p = 1;\n for (let k = 0; k <= degree; k++) {\n row[k] = p;\n p *= ti;\n }\n return row;\n });\n}\n\n/**\n * Modified Gram-Schmidt QR. `A` is n×m (n >= m). Returns Q (n×m, orthonormal\n * columns) and R (m×m upper triangular). More stable than raw normal equations,\n * matching what R's `lm` does internally.\n */\nfunction qr(A: number[][]): { Q: number[][]; R: number[][] } {\n const n = A.length;\n const m = A[0].length;\n const Q = A.map(row => row.slice());\n const R = Array.from({ length: m }, () => new Array(m).fill(0));\n for (let j = 0; j < m; j++) {\n let norm = 0;\n for (let i = 0; i < n; i++) norm += Q[i][j] * Q[i][j];\n norm = Math.sqrt(norm);\n R[j][j] = norm;\n if (norm > 1e-300) {\n for (let i = 0; i < n; i++) Q[i][j] /= norm;\n }\n for (let k = j + 1; k < m; k++) {\n let dot = 0;\n for (let i = 0; i < n; i++) dot += Q[i][j] * Q[i][k];\n R[j][k] = dot;\n for (let i = 0; i < n; i++) Q[i][k] -= dot * Q[i][j];\n }\n }\n return { Q, R };\n}\n\n/** Qᵀy (length m). */\nfunction qtY(Q: number[][], y: number[]): number[] {\n const n = Q.length;\n const m = Q[0].length;\n const out = new Array(m).fill(0);\n for (let j = 0; j < m; j++) {\n let s = 0;\n for (let i = 0; i < n; i++) s += Q[i][j] * y[i];\n out[j] = s;\n }\n return out;\n}\n\n/** Back-substitution for R c = b, R upper triangular m×m. */\nfunction backSolve(R: number[][], b: number[]): number[] {\n const m = b.length;\n const c = new Array(m).fill(0);\n for (let i = m - 1; i >= 0; i--) {\n let s = b[i];\n for (let j = i + 1; j < m; j++) s -= R[i][j] * c[j];\n c[i] = Math.abs(R[i][i]) > 1e-12 ? s / R[i][i] : 0;\n }\n return c;\n}\n\n/** Leverages h_ii = sum_j Q[i][j]^2 (diagonal of the hat matrix). */\nfunction leverages(Q: number[][]): number[] {\n return Q.map(row => {\n let s = 0;\n for (let j = 0; j < row.length; j++) s += row[j] * row[j];\n return s;\n });\n}\n\n/** Least-squares monomial coefficients for y ~ poly(t, degree). */\nfunction fitCoeffs(t: number[], y: number[], degree: number): number[] {\n const X = design(t, degree);\n const { Q, R } = qr(X);\n return backSolve(R, qtY(Q, y));\n}\n\n/** Evaluate a monomial polynomial (ascending coeffs) at t. */\nexport function evalPoly(coeffs: number[], t: number): number {\n let v = 0;\n let p = 1;\n for (let k = 0; k < coeffs.length; k++) {\n v += coeffs[k] * p;\n p *= t;\n }\n return v;\n}\n\n/**\n * Joint 2D leave-one-out CV PRESS for a candidate degree. x(t) and y(t) share\n * one design (hence one hat matrix), so LOO residuals are e_i / (1 - h_ii).\n * Returns Infinity for a degenerate (saturated) fit so it is never selected.\n */\nfunction loocv2d(t: number[], x: number[], y: number[], degree: number): number {\n const X = design(t, degree);\n const { Q, R } = qr(X);\n const h = leverages(Q);\n const cx = backSolve(R, qtY(Q, x));\n const cy = backSolve(R, qtY(Q, y));\n let press = 0;\n for (let i = 0; i < t.length; i++) {\n const denom = 1 - h[i];\n if (denom <= 0) return Infinity;\n const ex = x[i] - evalPoly(cx, t[i]);\n const ey = y[i] - evalPoly(cy, t[i]);\n press += (ex / denom) ** 2 + (ey / denom) ** 2;\n }\n return press;\n}\n\n/**\n * Select a degree in 1..min(maxDegree, n-1). For `loocv_2d`, minimises the joint\n * 2D LOOCV PRESS; ties resolve to the smallest degree (matching R's which.min).\n * For `fixed`, or when there are too few points to run CV, returns the cap.\n */\nexport function selectDegree(fitPts: XY[], maxDegree: number, mode: DegreeSelection): number {\n const n = fitPts.length;\n const cap = Math.min(Math.max(1, Math.floor(maxDegree)), Math.max(1, n - 1));\n if (mode === 'fixed' || n < 3) return cap;\n const t = normalizedT(n);\n const x = fitPts.map(p => p.x);\n const y = fitPts.map(p => p.y);\n let best = 1;\n let bestVal = Infinity;\n for (let deg = 1; deg <= cap; deg++) {\n const v = loocv2d(t, x, y, deg);\n if (v < bestVal) {\n bestVal = v;\n best = deg;\n }\n }\n return best;\n}\n\n/**\n * Fit a trajectory polynomial. The near-origin filter is applied to both the\n * per-frame points and the (optional) full-trajectory `selectionSet`. The degree\n * is chosen on `selectionSet` when given — so it stays constant as a playhead\n * scrubs a growing prefix — then clamped to what the current frame can support,\n * and the coefficients are re-fit on the current frame's points.\n *\n * Returns null when fewer than three non-origin points are available (matching\n * the R kit's n_fit < 3 guard); callers should fall back to raw steps.\n */\nexport function fitTrajectory(\n activePts: XY[],\n opts: { maxDegree: number; degreeSelection: DegreeSelection; selectionSet?: XY[] | null }\n): TrajectoryFit | null {\n const fitPts = nearOriginFilter(activePts);\n if (fitPts.length < 3) return null;\n\n const selBasis = opts.selectionSet ? nearOriginFilter(opts.selectionSet) : fitPts;\n const basis = selBasis.length >= 3 ? selBasis : fitPts;\n let degree = selectDegree(basis, opts.maxDegree, opts.degreeSelection);\n\n // A growing playhead prefix may hold fewer points than the held degree needs.\n degree = Math.min(degree, Math.max(1, fitPts.length - 1));\n\n const t = normalizedT(fitPts.length);\n const coeffsX = fitCoeffs(t, fitPts.map(p => p.x), degree);\n const coeffsY = fitCoeffs(t, fitPts.map(p => p.y), degree);\n return { degree, coeffsX, coeffsY };\n}\n\n/** Sample the fitted curve at steps+1 evenly spaced points over t in [0,1]. */\nexport function sampleCurve(fit: TrajectoryFit, steps = 100): XY[] {\n const out: XY[] = [];\n for (let s = 0; s <= steps; s++) {\n const t = s / steps;\n out.push({ x: evalPoly(fit.coeffsX, t), y: evalPoly(fit.coeffsY, t) });\n }\n return out;\n}\n","import { PlottedObject, PlottedObjectOptions, Point } from './PlottedObject';\nimport { Color } from './Color';\nimport { DegreeSelection, fitTrajectory, sampleCurve } from './polyfit';\n\nexport interface TrajectoryOptions {\n ID?: string;\n unitId?: string;\n points?: Point[] | { x: number; y: number; time?: number; label?: string }[];\n color?: Color | string;\n smooth?: 'none' | 'poly' | 'spline';\n maxDegree?: number;\n degreeSelection?: DegreeSelection;\n polyCoeffsX?: number[];\n polyCoeffsY?: number[];\n currentTime?: number;\n showPoints?: boolean;\n showTips?: boolean;\n lineStyle?: 'uniform' | 'tapered';\n strokeWidth?: number;\n strokeWidthRange?: [number, number];\n opacityRange?: [number, number];\n size?: number;\n active?: boolean;\n meta?: any;\n [key: string]: any;\n}\n\nconst TRAJECTORY_CURVE_STEPS = 100;\n\nexport class Trajectory extends PlottedObject {\n readonly _typeName: string = 'Trajectory';\n trajPoints: Point[] = [];\n smooth: 'none' | 'poly' | 'spline' = 'none';\n maxDegree: number = 3;\n degreeSelection: DegreeSelection = 'loocv_2d';\n /** Degree chosen at the most recent fit; -1 until a poly curve is built. */\n selectedDegree: number = -1;\n polyCoeffsX: number[] = [];\n polyCoeffsY: number[] = [];\n currentTime: number = Infinity;\n showPoints: boolean = true;\n showTips: boolean = true;\n lineStyle: 'uniform' | 'tapered' = 'uniform';\n strokeWidth: number = 2;\n strokeWidthRange: [number, number] = [1, 6];\n opacityRange: [number, number] = [0.3, 1];\n\n constructor(options: TrajectoryOptions = {}) {\n const defaultColor = options.color instanceof Color ? options.color : new Color(typeof options.color === 'string' ? options.color : '#000000');\n super([], {\n ID: options.ID || `traj-${Math.random().toString(36).substring(2, 9)}`,\n size: options.size || 1,\n color: defaultColor,\n highlight: null,\n active: options.active || false,\n meta: options.meta || {},\n ...options\n } as PlottedObjectOptions);\n\n this.smooth = options.smooth || 'none';\n this.maxDegree = options.maxDegree !== undefined ? options.maxDegree : 3;\n this.degreeSelection = options.degreeSelection || 'loocv_2d';\n this.polyCoeffsX = options.polyCoeffsX || [];\n this.polyCoeffsY = options.polyCoeffsY || [];\n this.currentTime = options.currentTime !== undefined ? options.currentTime : Infinity;\n this.showPoints = options.showPoints !== undefined ? options.showPoints : true;\n this.showTips = options.showTips !== undefined ? options.showTips : true;\n this.lineStyle = options.lineStyle || 'uniform';\n this.strokeWidth = options.strokeWidth || 2;\n this.strokeWidthRange = options.strokeWidthRange || [1, 6];\n this.opacityRange = options.opacityRange || [0.3, 1];\n\n if (options.points && Array.isArray(options.points)) {\n this.trajPoints = options.points.map(p => {\n if (p instanceof Point) return p;\n const pt = new Point({ dimensions: [p.x, p.y], meta: { time: p.time, label: p.label } });\n pt.x = p.x;\n pt.y = p.y;\n return pt;\n });\n }\n }\n\n get activePoints(): Point[] {\n if (this.currentTime === Infinity) {\n return this.trajPoints;\n }\n return this.trajPoints.filter(p => {\n const t = (p.meta && typeof p.meta.time === 'number') ? p.meta.time : 0;\n return t <= this.currentTime;\n });\n }\n\n get path(): string {\n return this.pathPoints.reduce((acc, pt, idx) => {\n return idx === 0 ? `M${pt.x},${pt.y}` : `${acc} L${pt.x},${pt.y}`;\n }, '');\n }\n\n get pathPoints(): Array<{ x: number; y: number }> {\n const pts = this.activePoints;\n if (pts.length < 2) return [];\n\n if (this.smooth === 'poly') {\n // Precomputed coefficients override the fit (caller-supplied curve).\n if (this.polyCoeffsX.length > 0 && this.polyCoeffsY.length > 0) {\n return sampleCurve(\n { degree: this.polyCoeffsX.length - 1, coeffsX: this.polyCoeffsX, coeffsY: this.polyCoeffsY },\n TRAJECTORY_CURVE_STEPS\n );\n }\n\n // Select the degree on the full trajectory so it stays constant while a\n // playhead scrubs a growing prefix; fit coefficients on the visible frame.\n const fit = fitTrajectory(\n pts.map(p => ({ x: p.x, y: p.y })),\n {\n maxDegree: this.maxDegree,\n degreeSelection: this.degreeSelection,\n selectionSet: this.trajPoints.map(p => ({ x: p.x, y: p.y }))\n }\n );\n if (fit) {\n this.selectedDegree = fit.degree;\n return sampleCurve(fit, TRAJECTORY_CURVE_STEPS);\n }\n // Too few non-origin points to fit — fall back to raw steps below.\n }\n\n return pts.map(pt => ({ x: pt.x, y: pt.y }));\n }\n}\n","import { PlottedObject, Line, PlottedObjectOptions } from './PlottedObject.js';\nimport { Node } from './Points.js';\nimport { Color, WeightedColor } from './Color.js';\nimport { Tools } from '../utils/Tools.js';\nimport { DataFrameRow } from '../types/DataFrame.js';\n\n// Placeholder for zoom level, should be defined in the context of the application\nconst zoom_level = 1;\n\nexport class Edge extends Line {\n declare from: Node;\n declare to: Node;\n _totalweight: number = 0;\n _weight: number;\n declare _color: WeightedColor;\n\n constructor(data: DataFrameRow | any, from: Node, to: Node, weight: number = 0) {\n super(data, from, to);\n this._weight = weight;\n }\n\n get base_color(): Color { return this._color };\n get color(): WeightedColor {\n const base = this._color || new Color(\"#000000\");\n return new WeightedColor(base, Math.abs(this.weight));\n }\n set color(c: Color) { this._color = c as any; }\n\n base_weight() { return this._weight };\n get weight() {\n // let w = Array.isArray(this.#weight) ? this.#weight.reduce( (a, b) => a - b, 0) : this.#weight;\n let w = Array.isArray(this._weight) ? (this._weight[0] - this._weight[1]) : this._weight;\n return w; // * this.graph.options.EDGE.multiplier\n }\n set weight(w) {\n this._weight = w;\n }\n\n get totalweight(): number {\n return this.weight;\n }\n set totalweight(w: number) {\n this._totalweight = w;\n }\n}\n\nexport class SubtractedEdges extends Edge {\n edge_one: Edge;\n edge_two: Edge;\n\n #weight: number;\n #color: WeightedColor;\n\n constructor(e1: Edge, e2: Edge) {\n super(e1, e1.from, e1.to);\n\n this.edge_one = e1;\n this.edge_two = e2;\n\n this.#weight = this.edge_one.weight - this.edge_two.weight;\n\n let\n color_type_fn: new (color: Color | string, weight: number) => WeightedColor = this.edge_one.color.constructor as any,\n color: string = this.edge_one.color.base\n ;\n if (this.weight > 0) {\n color = this.edge_one.color.base;\n }\n else {\n color = this.edge_two.color.base;\n }\n\n this.#color = new color_type_fn(color, this.#weight);\n }\n\n get weight() {\n return this.#weight;\n }\n set weight(w) {\n this.#weight = w;\n }\n\n get color() {\n return this.#color;\n }\n set color(c) {\n this.#color = c;\n }\n}\n\nexport class MeanEdge extends Edge {\n edges: Set<Edge> = new Set<Edge>();\n\n constructor(o: any) {\n super(o, o.from, o.to);\n\n this.visible = true;\n // this.meta = o.meta || { ID: this.ID };\n }\n\n // get weight() { return __.math.mean([...this.edges.values()].map( e => e.weight )) * this.graph.options.EDGE.multiplier; }\n get weight() {\n let wt = Tools.Mathematics.mean([...this.edges.values()].map((e: Edge) => e.weight)) * 1;\n return wt;\n }\n set weight(w) { this._weight = w; }\n\n get path() {\n return `M${this.from.x} ${this.from.y} L${this.to.x} ${this.to.y}z`;\n }\n\n get totalweight() {\n return Array.from(this.edges).reduce((acc, edge) => acc + edge.totalweight, 0);\n }\n}\n\nexport class EdgeArrow extends PlottedObject {\n #edge;\n\n constructor(edge: PlottedObjectOptions) {\n super(edge.dimensions || [], edge);\n this.#edge = edge;\n }\n\n get edge() {\n return this.#edge;\n }\n\n get path(): string {\n /**\n *\n * mid_int0 nock_int0\n * --------------*-----*-------------- <- edge of arrow from midpoint to base_pt0\n * / /\n * / /\n * / /\n * / /\n * / /\n * / /\n * <-- edge node head--> * * * <-- nock ---> edge midpoint this way ---->\n * \\ ^-mid |\n * \\ | \\ |\n * \\ | \\ | <---- showing line from nock to edge used to find\n * \\ | \\ | intersection with edge\n * \\| \\|\n * --------------*-----*-------------- <- edge of arrow from midpoint to base_pt1\n * mid_int1---^ ^----nock_int1\n *\n */\n // Pure vector geometry on the tapered edge: T = target (wide end, base\n // points B0/B1), A = apex. The chevron sits 20% of the way from T toward\n // A, but its length follows the triangle's local width (≈ a constant\n // shape) rather than a fixed share of the edge length — on long, thin\n // edges the old fractional sizing stretched it into a sliver. (The old\n // slope-intercept intersections also misbehaved on near-vertical edges.)\n const _this = this.#edge;\n const T: [number, number] = [_this.to.x, _this.to.y];\n const A: [number, number] = _this.from_point;\n const [B0, B1] = _this.base_pts as [[number, number], [number, number]];\n const L = Math.hypot(A[0] - T[0], A[1] - T[1]);\n const W = Math.hypot(B0[0] - B1[0], B0[1] - B1[1]);\n if (!(L > 0) || !(W > 0)) return '';\n const u = [(A[0] - T[0]) / L, (A[1] - T[1]) / L]; // along the edge, T → A\n const b = Math.hypot(B0[0] - T[0], B0[1] - T[1]);\n const v = [(B0[0] - T[0]) / b, (B0[1] - T[1]) / b]; // across, toward B0\n const halfW = (d: number) => (W / 2) * Math.max(0, 1 - d / L);\n const at = (d: number, s: number) => `${T[0] + u[0] * d + v[0] * s} ${T[1] + u[1] * d + v[1] * s}`;\n\n const dh = 0.2 * L; // head\n const c = Math.min(0.15 * L, 0.8 * 2 * halfW(dh)); // length ≈ local width\n const dm = dh + c / 2, dn = dh + c; // notch, back\n const p = `M${at(dh, 0)} L${at(dm, halfW(dm))} L${at(dn, halfW(dn))} ` +\n `L${at(dm, 0)} L${at(dn, -halfW(dn))} L${at(dm, -halfW(dm))}z`;\n return p;\n }\n}\n\nexport enum EdgeDirection {\n FROM = 'from',\n TO = 'to'\n}\n\nexport class TaperedEdge extends Edge {\n // base_pts = [];\n _path: string = '';\n // Arrowheads are off by default — the tapered triangle shape already\n // communicates direction. Enabling #with_arrow currently throws because\n // EdgeArrow.constructor passes the edge as the lone super() arg.\n #with_arrow = false;\n #arrow;\n\n _directions: EdgeDirection[] = [EdgeDirection.FROM, EdgeDirection.TO];\n towards: EdgeDirection = EdgeDirection.TO;\n\n constructor(data: any, from: Node, to: Node) {\n super(data, from, to);\n\n if (this.#with_arrow === true) {\n this.#arrow = new EdgeArrow(this);\n }\n }\n\n get path(): string {\n return `M${this.from.x} ${this.from.y} L${this.base_pts[0].join(' ')} L${this.base_pts[1].join(' ')}z`;\n }\n static calculate_base_points(edg: TaperedEdge): [[number, number], [number, number]] {\n // Find the two endpoints of the tapered edge based on its `towards` direction.\n const top: EdgeDirection = edg.towards;\n const base: EdgeDirection = edg._directions.find(d => d !== edg.towards) as EdgeDirection;\n\n const bx = edg[base].x, by = edg[base].y;\n const tx = edg[top].x, ty = edg[top].y;\n const dx = tx - bx, dy = ty - by;\n const L = Math.hypot(dx, dy);\n\n // Degenerate: zero-length edge or unset weight — collapse to a point at `top`.\n const wt = (edg.weight ?? 0) * zoom_level;\n if (L === 0 || !isFinite(wt) || wt === 0) {\n return [[tx, ty], [tx, ty]];\n }\n\n // Unit perpendicular to the edge direction; offset both sides by wt/2.\n // Pure vector math here avoids the slope-intercept form used by\n // Tools.Geometry, which produces NaN for vertical edges and ill-conditioned\n // values for horizontal ones.\n const px = -dy / L, py = dx / L;\n const halfW = wt / 2;\n return [\n [tx + px * halfW, ty + py * halfW],\n [tx - px * halfW, ty - py * halfW],\n ];\n }\n get base_pts() {\n return TaperedEdge.calculate_base_points(this);\n }\n get arrow() {\n return this.#arrow;\n }\n get with_arrow() {\n return this.#with_arrow;\n }\n get from_point() {\n return [this.from.x, this.from.y];\n }\n}\n\nexport class TaperedMidpointEdge extends TaperedEdge {\n constructor(data: any, from: Node, to: Node) {\n super(data, from, to);\n }\n\n get path(): string {\n return `M${this.midpoint[0]} ${this.midpoint[1]} L${this.base_pts[0].join(' ')} L${this.base_pts[1].join(' ')}z`;\n }\n get from_point(): [number, number] {\n return this.midpoint;\n }\n}\n\nexport class TaperedWeightedMidpointEdge extends TaperedEdge {\n // Preserve the original data weight so that QELine.update()'s\n // `edge.weight = sw * 4` (which sets _weight for display sizing) doesn't\n // corrupt the midpoint calculation.\n private _dataWeight: number = 0;\n\n constructor(data: any, from: Node, to: Node) {\n super(data, from, to);\n this._totalweight = data.totalweight ?? 0;\n this._dataWeight = data.weight ?? this._weight;\n }\n\n get weighted_midpoint(): [number, number] {\n return Tools.Geometry.Line.interpolate(this.line)(1 - (this._dataWeight / this._totalweight));\n }\n\n get base_pts(): [[number, number], [number, number]] {\n return TaperedEdge.calculate_base_points(this);\n }\n\n static build_path(edg: TaperedWeightedMidpointEdge | MeanTaperedWeightedMidpointEdge): string {\n if (edg._totalweight > 0) {\n let p = `M${edg.weighted_midpoint[0]} ${edg.weighted_midpoint[1]} L${edg.base_pts[0].join(' ')} L${edg.base_pts[1].join(' ')}z`;\n\n return p\n }\n else {\n console.error(\"TaperedWeightedMidpointEdge: No totalweight, returning empty path\");\n return '';\n }\n }\n get path(): string {\n return TaperedWeightedMidpointEdge.build_path(this);\n }\n\n get from_point() {\n return this.weighted_midpoint;\n }\n}\n\nexport class MeanNodeEdge extends MeanEdge {\n constructor(o: any) {\n super(o);\n }\n get path() {\n return NodeEdge.build_path(this.weight, [...this.edges.values()][0].to)\n }\n get weight() {\n return Tools.Mathematics.mean([...this.edges.values()].map(e => e.weight)) * 1;\n }\n set weight(w) { this._weight = w; }\n}\n\nexport class MeanTaperedEdge extends MeanEdge {\n #with_arrow = true;\n #arrow;\n\n constructor(o: PlottedObjectOptions) {\n super(o);\n\n if (this.#with_arrow === true) {\n this.#arrow = new EdgeArrow(this);\n }\n }\n\n get with_arrow() {\n return this.#with_arrow;\n }\n get arrow() {\n return this.#arrow;\n }\n get from_point() {\n return [this.from.x, this.from.y];\n }\n}\n\nexport class MeanTaperedMidpointEdge extends MeanTaperedEdge {\n constructor(o: PlottedObjectOptions) {\n super(o);\n }\n\n get base_pts(): [[number, number], [number, number]] {\n const\n top = EdgeDirection.TO,\n base = EdgeDirection.FROM\n ;\n\n let\n edge_line: [[number, number], [number, number]] = [[this[base].x, this[base].y], [this[top].x, this[top].y]],\n perp_line = Tools.Geometry.Line.rotate2(edge_line, edge_line[1], 90),\n ints = Tools.Geometry.Line.intersect_circle(perp_line, edge_line[1], this.weight / 2)\n ;\n\n return ints;\n }\n get path(): string {\n return `M${this.midpoint[0]} ${this.midpoint[1]} L${this.base_pts[0].join(' ')} L${this.base_pts[1].join(' ')}z`;\n }\n get weight(): number {\n return Tools.Mathematics.mean([...this.edges.values()].map(e => e.weight)) * 1;\n }\n set weight(w) { this._weight = w; }\n}\n\nexport class MeanTaperedWeightedMidpointEdge extends MeanTaperedEdge {\n constructor(o: PlottedObjectOptions) {\n super(o);\n }\n\n get totalweight(): number {\n // debugger;\n // console.error(\"THIS NEEDS THE MEAN WEIGHT OF ITS COUNTERPART (FROM -> TO -- TO --> FROM)\")\n // or does the mean of the edges.totalweight equal to the same?\n return Tools.Mathematics.mean([...this.edges.values()].map(e => e.totalweight));\n }\n\n get weighted_midpoint() {\n // console.log(\"Weighted: \", this.weight, this.totalweight)\n return Tools.Geometry.Line.interpolate(this.line)(1 - (this.weight / this.totalweight))\n }\n\n get base_pts() {\n const\n top = EdgeDirection.TO, //this.#directions[this.#directions.findIndex( d => d === this.towards )],\n base = EdgeDirection.FROM //this.#directions[this.#directions.findIndex( d => d !== this.towards )]\n ;\n\n let\n edge_line: [[number, number], [number, number]] = [[this[base].x, this[base].y], [this[top].x, this[top].y]],\n perp_line = Tools.Geometry.Line.rotate2(edge_line, edge_line[1], 90),\n ints = Tools.Geometry.Line.intersect_circle(perp_line, edge_line[1], this.weight / 2)\n ;\n\n return ints;\n }\n\n get path() {\n let p = TaperedWeightedMidpointEdge.build_path(this)\n // console.log(\"Static p: \", p);\n return p;\n }\n get weight() {\n return Tools.Mathematics.mean([...this.edges.values()].map(e => e.weight)) * 1;\n }\n set weight(w) { this._weight = w; }\n}\n\nexport class NodeEdge extends Edge {\n\n constructor(data: any, from: Node, to: Node) {\n super(data, from, to);\n }\n\n static build_path(weight: number, to: Node) {\n let\n R = weight / 2,\n CX = to.x - R,\n R2 = R * 2,\n p = `M ${CX}, ${to.y} a ${R},${R} 0 1,0 ${R2},0 a ${R},${R} 0 1,0 -${R2},0`\n ;\n\n return p;\n }\n\n get path() {\n let wt = this.weight * zoom_level; //this.graph.get_graphs()[0].object.SIZE_EFFECT;\n return NodeEdge.build_path(wt, this.to);\n }\n}\n","import { PlottedObject } from \"../objects/PlottedObject\";\nimport { QEArray, } from \"./QELayer\";\nimport { QEGraphElement } from \"./QEGraph\";\n\nexport abstract class Drawable {\n abstract create(): SVGElement;\n \n svg_element: SVGElement;\n\n constructor(\n public __data__: PlottedObject, \n public parent: SVGElement, \n public graph: QEGraphElement,\n public __children__: QEArray = new QEArray()\n ) {\n this.svg_element = this.create();\n }\n\n get_size() {\n return this.__data__.size;\n }\n\n draw() {\n this.parent?.appendChild(this.svg_element);\n }\n\n update(elem: SVGElement, animate = true) {\n // this.update(elem);\n }\n\n animateSVGAttribute(elem: SVGElement, attr: string, to: number) {\n const from = parseFloat(elem.getAttribute(attr) || '0');\n if (from === to) return;\n\n const duration = 5000;\n const start = performance.now();\n function animate(now: number) {\n const t = Math.min(1, (now - start) / duration);\n const value = from + (to - from) * t;\n elem.setAttribute(attr, value.toString());\n if (t < 1) requestAnimationFrame(animate);\n else elem.setAttribute(attr, to.toString());\n }\n requestAnimationFrame(animate);\n }\n}\n","// Shared mark-size and colour rules, sizes in units of the coordinate extent.\n//\n// Width follows webENA: absolute, raw weight × a constant (`edge-width`, as a\n// fraction of the plot width), so equal weights draw equally wide in graphs of\n// the same size. That one width-per-weight drives undirected strokes, the\n// wide ends of directed edges, self-connection dots, and code nodes (whose\n// diameter is the sum of their edges' widths).\n//\n// Colour follows webENA's ramps (saturation 0.25–1, opacity 0.3–1), but the\n// rescaling range is taken across the whole model rather than per network.\n\n/** Default `<qe-graph edge-width>`: the width of an edge of weight 1 as a\n * fraction of the plot width. Width is absolute — raw weight × this — as in\n * webENA, so equal weights get equal widths in graphs of the same size. */\nexport const DEFAULT_EDGE_WIDTH = 0.04;\n\n/** webENA's colour ramps: non-zero weights are rescaled linearly from the\n * reference [min, max] onto these saturation and opacity ranges. */\nexport const SATURATION_RANGE: [number, number] = [0.25, 1];\nexport const OPACITY_RANGE: [number, number] = [0.3, 1];\n\n/** Linear map of |w| from [lo, hi] onto `range`; 0 stays 0 (not drawn). */\nexport function rampFor(w: number, lo: number, hi: number, range: [number, number]): number {\n const a = Math.abs(w);\n if (!(a > 0)) return 0;\n if (!(hi > lo)) return range[1];\n const t = Math.min(1, Math.max(0, (a - lo) / (hi - lo)));\n return range[0] + t * (range[1] - range[0]);\n}\n\n/** Edge stroke width for edges drawn outside the network rule (fallback). */\nexport const EDGE_WIDTH_PER_EXTENT = 0.011;\n\n/** On-screen width (CSS px) of the outline drawn around directed (tapered)\n * edges so long, thin triangles stay legible along their whole length. */\nexport const TAPERED_OUTLINE_PX = 0.75;\n\n/** Direction chevrons on directed edges: RGB multiplier applied to the\n * (opaque, white-flattened) edge colour, and the white halo's on-screen\n * width in CSS px. */\nexport const CHEVRON_DARKEN = 0.8;\nexport const CHEVRON_HALO_PX = 0.75;\n\n/** Point radius per unit of `size` (QEPoint). */\nexport const POINT_RADIUS_PER_EXTENT = 0.006;\n\n/** `size` for a code node with no drawn edges: a tiny dot that still marks\n * where the code sits (hide it with <qe-nodes unconnected=\"hide\">). */\nexport const UNCONNECTED_NODE_SIZE = 0.6;\n\n/** Width per unit of weight in extent units (plot width = 2 × extent). */\nexport function widthPerWeight(edgeWidth: number): number {\n return 2 * edgeWidth;\n}\n\n/** QEPoint `size` for a node whose diameter equals the summed widths of its\n * edges, `weightSum × widthFrac` (both in extent units). */\nexport function nodeSizeForEdges(weightSum: number, widthFrac: number): number {\n return (weightSum * widthFrac) / (2 * POINT_RADIUS_PER_EXTENT);\n}\n","import { Line } from \"../objects/PlottedObject\";\nimport { NodeEdge, TaperedEdge, EdgeArrow } from \"../objects/Edges\";\nimport { Color, WeightedColor } from \"../objects/Color\";\nimport { Drawable } from \"./Drawable\";\nimport { QEArray, QEElement } from \"./QELayer\";\nimport { QEGraphElement } from \"./QEGraph\";\nimport { CHEVRON_DARKEN, CHEVRON_HALO_PX, EDGE_WIDTH_PER_EXTENT, TAPERED_OUTLINE_PX } from \"../objects/Sizing\";\n\n/** Composite an rgba() colour over white, returning an opaque rgb(). */\nfunction flattenOnWhite(col: string): string {\n const m = /rgba?\\(([^)]+)\\)/.exec(col);\n if (!m) return col;\n const [r, g, b, a = 1] = m[1].split(',').map(Number);\n const f = (c: number) => Math.round(255 + (c - 255) * a);\n return `rgb(${f(r)},${f(g)},${f(b)})`;\n}\n\n/** Scale an rgba()/rgb() colour's RGB channels by `k` (alpha unchanged). */\nfunction darkenRgba(col: string, k: number): string {\n const m = /rgba?\\(([^)]+)\\)/.exec(col);\n if (!m) return col;\n const [r, g, b, a = 1] = m[1].split(',').map(Number);\n return `rgba(${Math.round(r * k)},${Math.round(g * k)},${Math.round(b * k)},${a})`;\n}\n\nexport class QELine extends Drawable implements QEElement {\n __name__: string = \"unnamed-line\";\n // Optional second element for the direction-indicator chevron on directed edges.\n private _arrow_el: SVGPathElement | null = null;\n // Invisible wide companion line giving thin undirected edges a clickable/\n // hoverable hit target for the qe-edge-* interaction events.\n private _hit_el: SVGLineElement | null = null;\n\n /** Stamp edge identity onto an element so <qe-graph> delegation can resolve\n * qe-edge-* events. No-op for non-edges (e.g. axis lines). */\n private _stampEdge(el: SVGElement): void {\n const meta = (this.__data__ as any).meta ?? {};\n if (!meta.isMeanEdge) return;\n el.setAttribute('data-edge-source', String(meta.source ?? ''));\n el.setAttribute('data-edge-target', String(meta.target ?? ''));\n el.setAttribute('data-edge-weight', String(meta.weight ?? 0));\n el.setAttribute('data-edge-directed', meta.isDirected ? 'true' : 'false');\n if (meta.isSelf) el.setAttribute('data-edge-self', 'true');\n if (meta.group != null) el.setAttribute('data-edge-group', String(meta.group));\n if (meta.unit != null) el.setAttribute('data-edge-unit', String(meta.unit));\n }\n\n constructor(\n public __data__: Line,\n public parent: SVGElement,\n public graph: QEGraphElement,\n public __children__: QEArray = new QEArray(),\n ) {\n super(__data__, parent, graph, __children__);\n\n this.svg_element = this.create();\n }\n\n create() {\n if (this.__data__ instanceof NodeEdge) {\n // Self-connection: filled circle inside the node, sized by weight.\n const path = document.createElementNS('http://www.w3.org/2000/svg', 'path');\n path.setAttribute('fill', this.__data__.color.toString());\n path.setAttribute('stroke', 'none');\n this.svg_element = path;\n return path;\n }\n\n if (this.__data__ instanceof TaperedEdge) {\n // Directed edges render as filled triangles via TaperedEdge.path.\n // A second SVG path is reserved for the direction-indicator chevron;\n // it is populated lazily in update() once meta.isDirected is known.\n const path = document.createElementNS('http://www.w3.org/2000/svg', 'path');\n path.setAttribute('fill', this.__data__.color.toString());\n path.setAttribute('stroke', 'none');\n this.svg_element = path;\n return path;\n }\n\n const line = document.createElementNS('http://www.w3.org/2000/svg', 'line');\n line.setAttribute('x1', this.__data__.from.x.toString());\n line.setAttribute('y1', this.__data__.from.y.toString());\n line.setAttribute('x2', this.__data__.to.x.toString());\n line.setAttribute('y2', this.__data__.to.y.toString());\n line.setAttribute('stroke-width', this.get_size().toString());\n line.setAttribute('stroke', this.__data__.color.toString());\n\n this.svg_element = line;\n return line;\n }\n\n update() {\n if (!this.svg_element) {\n this.create();\n }\n if (!this.svg_element.parentElement) {\n this.parent.appendChild(this.svg_element);\n }\n\n const extent = (this.graph.__data__ as any).extremes?.x_max ?? 1;\n const meta = (this.__data__ as any).meta ?? {};\n\n if (meta.isMeanEdge) {\n this._stampEdge(this.svg_element);\n const weight = typeof meta.weight === 'number' ? meta.weight : 0;\n const maxW = typeof meta.maxWeight === 'number' ? meta.maxWeight : 1;\n const opacity = typeof meta.opacity === 'number' ? meta.opacity : Math.min(1, weight / (maxW || 1));\n // Target ≈ multiplier×5 in plotly-px to match rENA (ena.plot.network\n // default: multiplier=5, width = raw_weight × 5). For a ±2.66-extent\n // coordinate space rendered at ~460px, 1 data-unit ≈ 86px, so\n // rENA's max stroke (0.47 × 5 ≈ 2.4px) ≈ 0.028 data units.\n // Factor 0.011 × extent(2.66) × 1.0 ≈ 0.029 → ~2.5px at 86px/unit.\n // Width = weight × the plot's shared width-per-weight (objects/Sizing.ts);\n // the fallback keeps edges visible if an edge arrives without one.\n const ext = extent > 0 ? extent : 1;\n const sw = typeof meta.widthFrac === 'number'\n ? ext * meta.widthFrac * weight\n : ext * EDGE_WIDTH_PER_EXTENT * (weight / (maxW || 1));\n\n // Build a WeightedColor from the stored base color + normalized weight so\n // that toString() produces hsla(h, s*w%, l%, w) — matching the Web ENA\n // convention of scaling both saturation and alpha together with weight.\n const baseColor = (this.__data__ as any)._color || new Color('#000000');\n // Saturation and opacity come from the graph's colour ramps\n // (<qe-edges color-scale>); older edges carry only opacity.\n const saturation = typeof meta.saturation === 'number' ? meta.saturation : opacity;\n const edgeColor = new WeightedColor(baseColor, saturation, opacity).toString();\n\n if (this.__data__ instanceof NodeEdge) {\n // Diameter = the self weight's width (same width-per-weight as edges\n // and nodes), matching ona. The node's diameter includes this self\n // weight, so the dot always fits inside it. Computed here because the\n // live extent is not known when the edge objects are built.\n (this.__data__ as NodeEdge).weight = sw;\n (this.svg_element as SVGPathElement).setAttribute('d', (this.__data__ as NodeEdge).path);\n this.svg_element.setAttribute('fill', edgeColor);\n this.svg_element.setAttribute('stroke', 'none');\n } else if (this.__data__ instanceof TaperedEdge) {\n // TaperedEdge.path uses .weight as the total base width (the wide end,\n // at the target node); node sizes sum these base widths.\n (this.__data__ as TaperedEdge).weight = sw;\n (this.svg_element as SVGPathElement).setAttribute('d', (this.__data__ as TaperedEdge).path);\n this.svg_element.setAttribute('fill', edgeColor);\n // Hairline outline (constant on-screen width, same weighted colour as\n // the fill). A long, thin triangle tapers below a pixel for most of its\n // length; the outline keeps the whole connection legible without\n // changing its width or colour encoding (ona draws a similar halo).\n this.svg_element.setAttribute('stroke', edgeColor);\n this.svg_element.setAttribute('stroke-width', String(TAPERED_OUTLINE_PX));\n this.svg_element.setAttribute('vector-effect', 'non-scaling-stroke');\n this.svg_element.setAttribute('stroke-linejoin', 'round');\n\n // ── Direction-indicator chevron ──────────────────────────────────────\n // For directed mean edges, overlay an EdgeArrow chevron filled with a\n // more-opaque/saturated version of the edge colour. Rendered over the\n // semi-transparent triangle body, the fully-opaque fill reads as a\n // visibly darker notch that indicates the direction without introducing\n // a foreign colour.\n if (meta.isDirected) {\n try {\n const arrow = new EdgeArrow(this.__data__ as any);\n const arrowPath = arrow.path;\n // Discard degenerate paths that contain NaN or Infinity (geometry\n // collapsed — zero-length edge, parallel lines, etc.).\n if (arrowPath && !arrowPath.includes('NaN') && !arrowPath.includes('Infinity')) {\n if (!this._arrow_el) {\n this._arrow_el = document.createElementNS('http://www.w3.org/2000/svg', 'path');\n this._arrow_el.setAttribute('stroke', 'none');\n }\n if (!this._arrow_el.parentElement) {\n this.parent.appendChild(this._arrow_el);\n }\n this._arrow_el.setAttribute('d', arrowPath);\n // As ona draws arrows: the edge's weighted colour flattened onto\n // white (\"fake alpha\", so it is opaque and weak edges still get\n // lighter chevrons), then darkened — plus ona's optional white\n // halo, at a constant on-screen width, so it stands out from the\n // triangle it sits on.\n this._arrow_el.setAttribute('fill', darkenRgba(flattenOnWhite(edgeColor), CHEVRON_DARKEN));\n this._arrow_el.setAttribute('stroke', '#ffffff');\n this._arrow_el.setAttribute('stroke-width', String(CHEVRON_HALO_PX));\n this._arrow_el.setAttribute('vector-effect', 'non-scaling-stroke');\n this._arrow_el.setAttribute('stroke-linejoin', 'round');\n }\n } catch (_) {\n // EdgeArrow geometry degenerates for very short or zero-weight edges —\n // silently skip rather than crashing the render loop.\n }\n }\n } else {\n // Regular undirected edge\n const x1 = this.__data__.from.x, y1 = this.__data__.from.y;\n const x2 = this.__data__.to.x, y2 = this.__data__.to.y;\n (this.svg_element as SVGLineElement).setAttribute('x1', x1.toString());\n (this.svg_element as SVGLineElement).setAttribute('y1', y1.toString());\n (this.svg_element as SVGLineElement).setAttribute('x2', x2.toString());\n (this.svg_element as SVGLineElement).setAttribute('y2', y2.toString());\n this.svg_element.setAttribute('stroke-width', sw.toString());\n this.svg_element.setAttribute('stroke', edgeColor);\n this.svg_element.setAttribute('pointer-events', 'stroke');\n this.svg_element.removeAttribute('marker-end');\n\n // Transparent wide hit target so thin edges are clickable/hoverable.\n // Sized to a comfortable minimum regardless of the visible stroke width.\n if (!this._hit_el) {\n this._hit_el = document.createElementNS('http://www.w3.org/2000/svg', 'line');\n this._hit_el.setAttribute('stroke', 'transparent');\n this._hit_el.setAttribute('stroke-linecap', 'round');\n this._hit_el.setAttribute('pointer-events', 'stroke');\n }\n if (!this._hit_el.parentElement) this.parent.appendChild(this._hit_el);\n this._hit_el.setAttribute('x1', x1.toString());\n this._hit_el.setAttribute('y1', y1.toString());\n this._hit_el.setAttribute('x2', x2.toString());\n this._hit_el.setAttribute('y2', y2.toString());\n this._hit_el.setAttribute('stroke-width', Math.max(sw, extent * 0.03).toString());\n this._stampEdge(this._hit_el);\n }\n } else {\n // Thin axis lines: ~0.4% of coordinate extent\n (this.svg_element as SVGLineElement).setAttribute('x1', this.__data__.from.x.toString());\n (this.svg_element as SVGLineElement).setAttribute('y1', this.__data__.from.y.toString());\n (this.svg_element as SVGLineElement).setAttribute('x2', this.__data__.to.x.toString());\n (this.svg_element as SVGLineElement).setAttribute('y2', this.__data__.to.y.toString());\n const sw = (extent > 0 ? extent : 1) * 0.004 * this.get_size();\n this.svg_element.setAttribute('stroke-width', sw.toString());\n this.svg_element.setAttribute('stroke-opacity', '1');\n this.svg_element.setAttribute('stroke', this.__data__.color.toString());\n }\n }\n\n draw() {\n if (this._hit_el) this.parent?.appendChild(this._hit_el);\n this.parent?.appendChild(this.svg_element);\n if (this._arrow_el) {\n this.parent?.appendChild(this._arrow_el);\n }\n }\n}\n","import { PlottedObject } from \"../objects/PlottedObject\";\nimport { Drawable } from \"./Drawable\";\nimport { QEArray, QEElement } from \"./QELayer\";\nimport { QEGraphElement } from \"./QEGraph\";\nimport { POINT_RADIUS_PER_EXTENT } from \"../objects/Sizing\";\n\nexport class QEPoint extends Drawable implements QEElement {\n __name__: string = \"unnamed-point\";\n\n constructor(\n public __data__: PlottedObject,\n public parent: SVGElement,\n public graph: QEGraphElement,\n public __children__: QEArray = new QEArray(),\n ) {\n super(__data__, parent, graph, __children__);\n\n this.svg_element = this.create();\n }\n\n get x() {\n return this.__data__.dimensions[this.graph.__data__.options.GRAPH.dimensions[0]];\n }\n get y() {\n return this.__data__.dimensions[this.graph.__data__.options.GRAPH.dimensions[1]];\n }\n\n get isSquare(): boolean {\n return (this.__data__ as any).shape === 'rect';\n }\n\n /** \"circle\" (default) | \"rect\" | \"triangle\" | \"diamond\". */\n get shapeKind(): 'circle' | 'rect' | 'triangle' | 'diamond' {\n const s = (this.__data__ as any).shape;\n return s === 'rect' || s === 'square' ? 'rect'\n : s === 'triangle' || s === 'diamond' ? s : 'circle';\n }\n\n /** SVG tag for the current shape. */\n private get tag(): string {\n const k = this.shapeKind;\n return k === 'circle' ? 'circle' : k === 'rect' ? 'rect' : 'path';\n }\n\n /** Position / size the element for its shape (r = half-size). */\n private setGeometry(el: SVGElement, r: number): void {\n const x = this.x, y = this.y;\n switch (this.shapeKind) {\n case 'rect':\n el.setAttribute('x', (x - r).toString()); el.setAttribute('y', (y - r).toString());\n el.setAttribute('width', (r * 2).toString()); el.setAttribute('height', (r * 2).toString());\n break;\n case 'triangle': {\n // Equilateral, pointing up (SVG y-down), centred on the point.\n const h = r * 1.15;\n el.setAttribute('d', `M${x} ${y - h} L${x + h * 0.866} ${y + h * 0.5} L${x - h * 0.866} ${y + h * 0.5}Z`);\n break;\n }\n case 'diamond':\n el.setAttribute('d', `M${x} ${y - r * 1.2} L${x + r} ${y} L${x} ${y + r * 1.2} L${x - r} ${y}Z`);\n break;\n default:\n el.setAttribute('cx', x.toString()); el.setAttribute('cy', y.toString());\n el.setAttribute('r', r.toString());\n }\n }\n\n /** Half-side length for squares / radius for circles, in SVG user units.\n * Factor 0.006 keeps code-node diameters in the same visual range as rENA\n * (≈ 1–2 % of the coordinate half-extent for a typical ENA network).\n */\n computeRadius(): number {\n const r = this.baseRadius();\n // Optional ceiling (user units): group means are capped to their CI box so\n // a tight interval is never hidden under the marker.\n const cap = (this.__data__ as any).meta?.maxRadius;\n return typeof cap === 'number' && cap > 0 ? Math.min(r, cap) : r;\n }\n\n private baseRadius(): number {\n const extent = (this.graph.__data__.extremes.x_max) || 1;\n const sizeScale = (this.__data__ as any).meta?.sizeScale ?? 1;\n // Fixed-on-screen mode (webENA size decoupling): keep a constant pixel size\n // regardless of data extent / container size / wheel-zoom, by converting a\n // target px into user units via the current px-per-unit and zoom. Otherwise\n // size scales with the coordinate space (default — nodes/edges do the same).\n if ((this.__data__ as any).meta?.fixedSize) {\n const rect = (this.graph.svg_element as SVGSVGElement)?.getBoundingClientRect?.();\n const zoom = (this.graph as any).zoom_level || 1;\n const pxPerUnit = rect && rect.width > 0 ? rect.width / (2 * extent) : 1;\n const targetPx = this.__data__.size * 2 * sizeScale; // size 2.5 → 5px radius\n return (targetPx / pxPerUnit) / zoom;\n }\n return extent * POINT_RADIUS_PER_EXTENT * this.__data__.size * sizeScale;\n }\n\n /** Optional halo stroke (e.g. white outline on unit points to separate\n * overlapping dots in dense clusters). Width scales with the dot so it holds\n * up at any zoom. No-op unless the object requests it via meta.stroke. */\n private applyStroke(el: SVGElement): void {\n const stroke = (this.__data__ as any).meta?.stroke;\n if (!stroke) return;\n el.setAttribute('stroke', stroke);\n el.setAttribute('stroke-width', (this.computeRadius() * 0.22).toString());\n }\n\n create() {\n const el = document.createElementNS('http://www.w3.org/2000/svg', this.tag) as SVGElement;\n\n el.setAttribute('data-point-id', this.__data__.ID);\n // Identity for <qe-graph> delegation → qe-node-* interaction events.\n const meta = (this.__data__ as any).meta ?? {};\n if (meta.kind) el.setAttribute('data-kind', meta.kind);\n if (meta.name != null) el.setAttribute('data-name', String(meta.name));\n if (meta.group != null) el.setAttribute('data-group', String(meta.group));\n if (meta.unit != null) el.setAttribute('data-unit', String(meta.unit));\n el.setAttribute('fill', this.__data__.color.toString());\n this.applyStroke(el);\n\n this.setGeometry(el, this.computeRadius());\n\n this.svg_element = el;\n\n el.addEventListener('click', () => {\n // Note: do NOT stopPropagation — the click must bubble to <qe-graph>'s\n // delegation so it can emit the public qe-node-click event.\n this.__data__.active = !this.__data__.active;\n this.update();\n\n const pointEvent = new CustomEvent('point-clicked', {\n detail: { pointData: this.__data__ },\n bubbles: true, composed: true\n });\n this.svg_element.dispatchEvent(pointEvent);\n });\n\n el.addEventListener('mouseover', () => {\n // Do not stopPropagation — the parent SVG uses mouseover delegation\n // to show AUTO-mode labels. The fill is already set; this handler is\n // retained as a hook for future hover-highlight logic.\n });\n\n return el;\n }\n\n update() {\n if (!this.svg_element) {\n (this.parent as any).__data__.__children__.push(this.create());\n }\n if (!this.svg_element.parentElement) {\n this.parent.appendChild(this.svg_element);\n }\n\n this.svg_element.setAttribute('fill', this.__data__.color.toString());\n this.applyStroke(this.svg_element);\n this.setGeometry(this.svg_element, this.computeRadius());\n }\n\n draw() {\n this.parent?.appendChild(this.svg_element);\n }\n}\n","import { Trajectory } from '../objects/Trajectory';\nimport { Drawable } from './Drawable';\nimport { QEArray, QEElement } from './QELayer';\nimport { QEGraphElement } from './QEGraph';\n\nexport class QETrajectory extends Drawable implements QEElement {\n __name__: string = 'trajectory';\n private _path_el: SVGPathElement | null = null;\n private _segments_group: SVGGElement | null = null;\n private _tip_el: SVGCircleElement | null = null;\n private _points_group: SVGGElement | null = null;\n\n constructor(\n public __data__: Trajectory,\n public parent: SVGElement,\n public graph: QEGraphElement,\n public __children__: QEArray = new QEArray()\n ) {\n super(__data__, parent, graph, __children__);\n this.svg_element = this.create();\n }\n\n // Trajectory styling is specified in display pixels, while SVG paths use\n // graph coordinates. Convert at render time so marks stay legible at any scale.\n private graphUnitsForPixels(pixels: number): number {\n const extent = this.graph.__data__.extremes.x_max || 1;\n const width = this.graph.svg_element?.getBoundingClientRect().width || 0;\n return width > 0 ? pixels * (2 * extent / width) : pixels * extent * 0.006;\n }\n\n create() {\n const group = document.createElementNS('http://www.w3.org/2000/svg', 'g');\n group.setAttribute('class', 'qe-trajectory-group');\n\n const path = document.createElementNS('http://www.w3.org/2000/svg', 'path');\n path.setAttribute('fill', 'none');\n path.setAttribute('stroke', this.__data__.color.toString());\n path.setAttribute('stroke-width', this.graphUnitsForPixels(this.__data__.strokeWidth).toString());\n group.appendChild(path);\n this._path_el = path;\n\n const segmentsGroup = document.createElementNS('http://www.w3.org/2000/svg', 'g');\n segmentsGroup.setAttribute('class', 'qe-trajectory-segments');\n group.appendChild(segmentsGroup);\n this._segments_group = segmentsGroup;\n\n const pointsGroup = document.createElementNS('http://www.w3.org/2000/svg', 'g');\n pointsGroup.setAttribute('class', 'qe-trajectory-points');\n group.appendChild(pointsGroup);\n this._points_group = pointsGroup;\n\n if (this.__data__.showTips) {\n const tip = document.createElementNS('http://www.w3.org/2000/svg', 'circle');\n tip.setAttribute('fill', this.__data__.color.toString());\n tip.setAttribute('r', this.graphUnitsForPixels(4).toString());\n tip.setAttribute('stroke', '#ffffff');\n tip.setAttribute('stroke-width', this.graphUnitsForPixels(1.5).toString());\n group.appendChild(tip);\n this._tip_el = tip;\n }\n\n this.svg_element = group;\n return group;\n }\n\n update() {\n if (!this.svg_element) {\n this.create();\n }\n if (!this.svg_element.parentElement) {\n this.parent.appendChild(this.svg_element);\n }\n\n const dStr = this.__data__.path;\n if (this._path_el) {\n this._path_el.setAttribute('d', dStr);\n this._path_el.setAttribute('stroke', this.__data__.color.toString());\n this._path_el.setAttribute('stroke-width', this.graphUnitsForPixels(this.__data__.strokeWidth).toString());\n this._path_el.style.display = this.__data__.lineStyle === 'tapered' ? 'none' : 'block';\n }\n\n if (this._segments_group) {\n this._segments_group.innerHTML = '';\n if (this.__data__.lineStyle === 'tapered') {\n const pathPts = this.__data__.pathPoints;\n const nSegments = pathPts.length - 1;\n const [minWidth, maxWidth] = this.__data__.strokeWidthRange;\n const [minOpacity, maxOpacity] = this.__data__.opacityRange;\n\n for (let i = 0; i < nSegments; i++) {\n const start = pathPts[i];\n const end = pathPts[i + 1];\n const progress = nSegments <= 1 ? 1 : i / (nSegments - 1);\n const width = minWidth + (maxWidth - minWidth) * progress;\n const opacity = minOpacity + (maxOpacity - minOpacity) * progress;\n const segment = document.createElementNS('http://www.w3.org/2000/svg', 'path');\n\n segment.setAttribute('d', `M${start.x},${start.y} L${end.x},${end.y}`);\n segment.setAttribute('fill', 'none');\n segment.setAttribute('stroke', this.__data__.color.toString());\n segment.setAttribute('stroke-linecap', 'round');\n segment.setAttribute('stroke-linejoin', 'round');\n segment.setAttribute('stroke-width', this.graphUnitsForPixels(width).toString());\n segment.setAttribute('opacity', opacity.toString());\n this._segments_group.appendChild(segment);\n }\n this._segments_group.style.display = 'block';\n } else {\n this._segments_group.style.display = 'none';\n }\n }\n\n const pts = this.__data__.activePoints;\n\n if (this._points_group) {\n if (this.__data__.showPoints && pts.length > 0) {\n this._points_group.innerHTML = '';\n pts.forEach(pt => {\n const dot = document.createElementNS('http://www.w3.org/2000/svg', 'circle');\n dot.setAttribute('cx', pt.x.toString());\n dot.setAttribute('cy', pt.y.toString());\n dot.setAttribute('r', this.graphUnitsForPixels(2.5).toString());\n dot.setAttribute('fill', this.__data__.color.toString());\n dot.setAttribute('opacity', '0.7');\n this._points_group?.appendChild(dot);\n });\n this._points_group.style.display = 'block';\n } else {\n this._points_group.style.display = 'none';\n }\n }\n\n if (this._tip_el && this.__data__.showTips) {\n if (pts.length > 0) {\n const lastPt = pts[pts.length - 1];\n this._tip_el.setAttribute('cx', lastPt.x.toString());\n this._tip_el.setAttribute('cy', lastPt.y.toString());\n this._tip_el.setAttribute('fill', this.__data__.color.toString());\n this._tip_el.setAttribute('r', this.graphUnitsForPixels(4).toString());\n this._tip_el.setAttribute('stroke-width', this.graphUnitsForPixels(1.5).toString());\n this._tip_el.style.display = 'block';\n } else {\n this._tip_el.style.display = 'none';\n }\n }\n }\n\n draw() {\n if (this.svg_element && !this.svg_element.parentElement) {\n this.parent.appendChild(this.svg_element);\n }\n this.update();\n }\n}\n","import { Tools } from \"../utils/Tools\";\nimport { Graph } from \"../objects/Graph\";\nimport { Layer, LayerLike } from \"../objects/Layers\";\nimport { PlottedObject, Point } from \"../objects/PlottedObject\";\nimport { Trajectory } from \"../objects/Trajectory\";\nimport { QELine } from \"./QELine\";\nimport { QEPoint } from \"./QEPoint\";\nimport { QETrajectory } from \"./QETrajectory\";\nimport { QEGraphElement } from \"./QEGraph\";\n\n\nconst { ArrayTools } = Tools;\nexport class QEArray extends Array<any> {\n constructor(...args: any[]) {\n super(...args);\n }\n\n search(key: string, name: string): LayerLike | undefined {\n let found: LayerLike | undefined;\n\n function fn(a: LayerLike): LayerLike | undefined {\n return a.name === name ? a : undefined;\n }\n\n function recurse(obj: any, i?: number, parent: any = null): LayerLike | undefined {\n if (ArrayTools.isArray(obj)) {\n for (const [i, o] of obj.entries()) {\n found = recurse(o, i, parent);\n if (found) {\n return found;\n }\n }\n } else {\n found = fn(obj);\n if (!found) {\n if (obj && ArrayTools.isArray(obj[key])) {\n for (const [i, o] of obj[key].entries()) {\n found = recurse(o, i, obj);\n if (found) {\n return found;\n }\n }\n }\n } else {\n return found;\n }\n }\n return found;\n }\n\n return recurse(this);\n }\n\n flatten(): LayerLike[] {\n return this.reduce<LayerLike[]>((a, l: LayerLike) => {\n a.push(l);\n if (l.layers && Array.isArray(l.layers)) {\n a.push(...l.layers);\n }\n return a;\n }, []);\n }\n}\n\nexport interface QEElement {\n svg_element: SVGElement;\n graph: QEGraphElement;\n parent: SVGElement | null;\n __name__: string;\n __data__: Graph | PlottedObject | LayerLike;\n __children__: QEArray;\n draw(): void;\n update(): void;\n}\n\nconst\n QEElementConstructors: Record<string, new (d: any, p: SVGElement, g: QEGraphElement) => QEElement> =\n {\n \"AxisPoint\": QEPoint,\n \"AxisLine\": QELine,\n \"Point\": QEPoint,\n \"Line\": QELine,\n \"Edge\": QELine,\n \"TaperedEdge\": QELine,\n \"TaperedWeightedMidpointEdge\": QELine,\n \"NodeEdge\": QELine,\n \"Trajectory\": QETrajectory,\n }\n;\n\nexport class QELayer implements QEElement {\n static tagName = 'g';\n\n svg_element: SVGElement; \n __name__: string;\n\n constructor(\n public __data__: Layer, \n public parent: SVGElement, \n public graph: QEGraphElement,\n public __children__: QEArray = new QEArray(),\n ) {\n this.__name__ = __data__.name || \"unnamed-layer\";\n\n __data__.__state__.addListener(`layer_updated`, \"live\", ({ key, newValue, oldValue } : any) => {\n const childId = (child: QEElement) => (child.__data__ as PlottedObject)?.ID;\n\n const removing = this.__children__.filter((child: QEElement) =>\n !newValue.objects.has(childId(child))\n );\n const updating = this.__children__.filter((child: QEElement) =>\n newValue.objects.has(childId(child))\n );\n const adding = [...newValue.objects.values()].filter((obj: PlottedObject) =>\n !this.__children__.some((child: QEElement) => childId(child) === obj.ID)\n );\n\n adding.forEach((obj: PlottedObject) => {\n const obj_name = (obj as any)._typeName || obj.constructor.name;\n let constructor = QEElementConstructors[obj_name];\n if (!constructor) {\n if (obj instanceof Trajectory) constructor = QETrajectory;\n else if (obj instanceof Point) constructor = QEPoint;\n else constructor = QELine;\n }\n const ena_element: QEElement = new constructor(obj, this.svg_element, this.graph);\n this.__children__.push(ena_element);\n });\n\n updating.forEach((child: QEElement) => {\n // Pull the *new* PlottedObject from the updated layer data so that any\n // changed properties (e.g. weight, color, meta flags) are picked up by\n // the child's update() call.\n const newData = newValue.objects.get(childId(child)) as PlottedObject;\n if (newData) (child as any).__data__ = newData;\n child.update();\n });\n\n removing.forEach((child: QEElement) => {\n if (child.svg_element.parentElement) {\n child.svg_element.parentElement.removeChild(child.svg_element);\n }\n const idx = this.__children__.indexOf(child);\n if (idx >= 0) this.__children__.splice(idx, 1);\n });\n\n this.update();\n });\n\n this.svg_element = this.create();\n }\n\n get name() {\n return this.__name__;\n }\n\n create(): SVGElement {\n if(!this.__data__) {\n throw new Error(\"Layer is null\");\n }\n let layer: Layer = this.__data__ as Layer;\n this.svg_element = document.createElementNS(\"http://www.w3.org/2000/svg\", QELayer.tagName);\n this.svg_element.setAttribute('data-layer-name', layer.name);\n this.svg_element.setAttribute('data-layer-id', layer.ID);\n\n (this.svg_element as any).__data__ = layer;\n\n this.svg_element.classList.add('ena-layer');\n\n if(this.__data__.layers && this.__data__.layers.length > 0) {\n this.__data__.layers.forEach((sublayer: LayerLike) => {\n const layer_g: QELayer = new QELayer(sublayer as any, this.svg_element, this.graph);\n this.__children__.push(layer_g);\n });\n }\n\n return this.svg_element;\n }\n\n update() {\n if(!this.__data__) {\n throw new Error(\"Layer is null\");\n }\n\n if(this.__data__.visible) {\n // Update layer properties here\n if(this.parent.nodeName.toLowerCase() === \"svg\") {\n // Compute the transform string based on the size of the parent SVG elemet. \n // -- a circle with radius 1 should be scaled to the size of the parent SVG element, \n // so that as the graph is zoomed in and out, the circle scales with it.\n // this.svg_element.style.transform = `scale(${this.parent.clientWidth / 100}, ${this.parent.clientHeight / 100})`;\n }\n\n // Update sublayers\n this.__children__.forEach((child: QEElement) => {\n child.update();\n });\n\n if(this.__data__.scale_objects === true) {\n if(this.__name__ === \"points\") {\n // this.svg_element.setAttribute('transform', `\n // scale(${this.graph.__data__.scale_x}, ${this.graph.__data__.scale_y})\n // `);\n }\n }\n else {\n // this.svg_element.setAttribute('transform', `scale(${this.graph.x_mirror()}, ${this.graph.y_mirror()})`); \n }\n }\n }\n\n draw(): void {\n this.parent?.appendChild(this.svg_element);\n\n this.__children__.forEach((child: QEElement) => {\n child.draw();\n });\n }\n\n add(child: QEElement) {\n this.__children__.push(child);\n }\n}","import { Label, Point } from \"../objects/PlottedObject\";\nimport { QEGraphElement } from \"./QEGraph\";\n\n/**\n * SVG <text> drawable for a single ENA label.\n *\n * ── Display modes (Label.DISPLAY_TYPES) ──────────────────────────────────────\n * OFF (0) — never shown\n * AUTO (1) — shown on mouseover of the associated point, hidden on mouseout\n * CLICK (2) — toggled by clicking the associated point\n * ON (3) — always shown\n *\n * ── Position modes (Label.POSITION) ─────────────────────────────────────────\n * OBJECT (1) — offset near the point (quadrant-aware, default)\n * STATIC (2) — centered directly on the point (no offset; label overlaps point)\n * CONTAINER (3) — projected to the viewBox boundary in the point's direction;\n * useful for code-node labels that appear at the outer ring\n * CUSTOM (4) — caller provides explicit (customX, customY) coordinates\n */\nexport class QELabel {\n svg_element: SVGTextElement;\n private _visible: boolean = false;\n // Drag offset (graph-space units) and pin state for host-repositionable labels.\n private _offsetX = 0;\n private _offsetY = 0;\n pinned = false;\n\n constructor(\n public readonly text: string,\n public readonly point: Point,\n public readonly parent: SVGElement,\n public readonly graph: QEGraphElement,\n public readonly displayMode: number = Label.DISPLAY_TYPES.ON,\n public readonly position: number = Label.POSITION.OBJECT,\n public customX?: number,\n public customY?: number,\n ) {\n this.svg_element = this._create();\n\n // Set initial visibility without calling update() yet.\n // The QEGraphElement calls update_labels() after update_extremes() so that\n // the first real positioning uses the correct graph extent, not the default 1.\n if (displayMode === Label.DISPLAY_TYPES.ON) {\n this._visible = true;\n this.svg_element.setAttribute('display', 'block');\n } else {\n this._visible = false;\n this.svg_element.setAttribute('display', 'none');\n }\n }\n\n private _create(): SVGTextElement {\n const el = document.createElementNS('http://www.w3.org/2000/svg', 'text') as SVGTextElement;\n el.textContent = this.text;\n el.setAttribute('data-label-for', this.point.ID);\n el.setAttribute('pointer-events', 'auto'); // draggable\n el.style.cursor = 'grab';\n this._attachDrag(el);\n this.parent.appendChild(el);\n return el;\n }\n\n /** Drag to reposition; pins the label open and emits qe-label-move on drop. */\n private _attachDrag(el: SVGTextElement): void {\n el.addEventListener('mousedown', (ev: MouseEvent) => {\n ev.preventDefault();\n ev.stopPropagation(); // don't start a graph pan\n const svg = el.ownerSVGElement;\n if (!svg) return;\n const toUser = (cx: number, cy: number) => {\n const p = svg.createSVGPoint(); p.x = cx; p.y = cy;\n const m = svg.getScreenCTM();\n return m ? p.matrixTransform(m.inverse()) : ({ x: 0, y: 0 } as DOMPoint);\n };\n const start = toUser(ev.clientX, ev.clientY);\n const baseX = this._offsetX, baseY = this._offsetY;\n el.style.cursor = 'grabbing';\n\n const onMove = (e: MouseEvent) => {\n const p = toUser(e.clientX, e.clientY);\n this._offsetX = baseX + (p.x - start.x);\n this._offsetY = baseY + (p.y - start.y);\n this.pinned = true; // keep it shown once moved\n this._visible = true;\n this.svg_element.setAttribute('display', 'block');\n this.update();\n };\n const onUp = () => {\n document.removeEventListener('mousemove', onMove);\n document.removeEventListener('mouseup', onUp);\n el.style.cursor = 'grab';\n // Public event so the host can persist / mirror across coordinated plots.\n this.graph.dispatchEvent(new CustomEvent('qe-label-move', {\n detail: { id: this.point.ID, transform: { x: this._offsetX, y: this._offsetY } },\n bubbles: true, composed: true,\n }));\n };\n document.addEventListener('mousemove', onMove);\n document.addEventListener('mouseup', onUp);\n });\n }\n\n /**\n * Recompute position and font-size from current graph extents.\n * No-ops when the label is hidden (AUTO/CLICK modes while not hovered/clicked).\n */\n update(): void {\n if (!this._visible) return;\n\n const extent = this.graph.__data__.extremes.x_max;\n if (extent <= 0) return; // graph not initialised yet\n\n // qe_labels(font_size =) is in CSS pixels (constant on screen); default\n // scales with the plot extent.\n const font = (this.graph as any)._labelFont ?? {};\n const fontSize = font.size ? font.size * (this.graph as any).unitsPerPixel() : extent * 0.06;\n const offset = fontSize * 1.2;\n\n let x: number, y: number, anchor: string;\n\n switch (this.position) {\n\n case Label.POSITION.STATIC: {\n // Centered on the point — label sits at exactly the point's coordinates.\n // Useful when the caller wants to control offset manually via customX/Y.\n x = this.point.x;\n y = this.point.y - offset * 0.3;\n anchor = 'middle';\n break;\n }\n\n case Label.POSITION.CONTAINER: {\n // Project from the view's centre (the origin, unless center=\"content\")\n // through the point onto the viewBox boundary. Labels ring the outer\n // edge of the plot, one per code/group direction.\n const { cx, cy } = this.graph.__data__.extremes;\n const px = this.point.x - cx;\n const py = this.point.y - cy;\n const dist = Math.sqrt(px * px + py * py) || 1;\n const scale = (extent * 0.93) / dist;\n x = cx + px * scale;\n y = cy + py * scale - offset * 0.3;\n anchor = px >= 0 ? 'start' : 'end';\n break;\n }\n\n case Label.POSITION.CUSTOM: {\n // Caller-provided coordinates; fall back to OBJECT behaviour if unset.\n if (this.customX != null && this.customY != null) {\n x = this.customX;\n y = this.customY;\n anchor = 'start';\n break;\n }\n // fall through to OBJECT\n }\n\n default:\n case Label.POSITION.OBJECT: {\n // Quadrant-aware offset: push label away from origin.\n const dx = this.point.x >= 0 ? offset : -offset;\n anchor = this.point.x >= 0 ? 'start' : 'end';\n x = this.point.x + dx;\n y = this.point.y - offset * 0.4;\n break;\n }\n }\n\n this.svg_element.setAttribute('x', x.toString());\n this.svg_element.setAttribute('y', y.toString());\n // Host drag offset (graph-space units) composes on top of the computed spot.\n if (this._offsetX || this._offsetY) {\n this.svg_element.setAttribute('transform', `translate(${this._offsetX}, ${this._offsetY})`);\n }\n this.svg_element.setAttribute('font-size', fontSize.toString());\n this.svg_element.setAttribute('font-family', font.family ?? 'system-ui, sans-serif');\n this.svg_element.setAttribute('font-weight', '500');\n this.svg_element.setAttribute('text-anchor', anchor);\n this.svg_element.setAttribute('fill', font.color ?? this.point.color?.toString() ?? '#333333');\n }\n\n /** Make the label visible and position it immediately. */\n show(): void {\n this._visible = true;\n this.svg_element.setAttribute('display', 'block');\n this.update();\n }\n\n hide(): void {\n if (this.pinned) return; // a dragged/pinned label stays visible\n this._visible = false;\n this.svg_element.setAttribute('display', 'none');\n }\n\n toggle(): void {\n this._visible ? this.hide() : this.show();\n }\n\n get visible(): boolean { return this._visible; }\n\n remove(): void {\n this.svg_element.remove();\n }\n}\n","/**\n * Declarative child layer elements for <qe-graph>.\n *\n * Each element is an inert configuration holder — no shadow DOM, no rendering\n * logic. <qe-graph> reads their presence and attributes via querySelector() to\n * configure each rendering layer.\n *\n * Presence = the layer is rendered.\n * Absence = the layer is hidden. (Code-node positions come from the\n * model and anchor the coordinate space whether or not\n * <qe-nodes> is present; the element only controls drawing.)\n *\n * HTML authoring example:\n *\n * <qe-graph width=\"100%\" height=\"440\">\n * <qe-nodes label=\"on\"></qe-nodes>\n * <qe-means groups=\"FirstGame,SecondGame\" confidence></qe-means>\n * <qe-points label=\"auto\"></qe-points>\n * <qe-edges group=\"FirstGame\" compare=\"SecondGame\"></qe-edges>\n * </qe-graph>\n */\n\n/**\n * <qe-nodes> — renders the code nodes.\n * Presence = draw nodes; absence = hide them (positions still set the extent).\n * A node's diameter equals the summed widths of its drawn edges: every edge\n * touching it (undirected), or the wide ends of the edges directed at it,\n * including its self-connection (directed / ONA).\n *\n * Attributes:\n * label \"on\" | \"off\" | \"click\" | \"auto\" (default \"on\")\n * unconnected \"dot\" (default) — nodes with no drawn edges show as a tiny\n * dot; \"hide\" — hide them (and their labels).\n */\nexport class QENodesElement extends HTMLElement {\n static tagName = 'qe-nodes' as const;\n}\n\n/**\n * <qe-means> — renders group mean markers and optional CI boxes.\n * Presence = show means; absence = hide means.\n *\n * Attributes:\n * groups Comma-separated group names to show. Omit for all groups.\n * confidence Boolean — show 95% CI rectangles.\n * label \"on\" | \"off\" | \"click\" | \"auto\" (default \"on\")\n * fixed-size Boolean — keep mean markers a constant on-screen pixel size\n * regardless of data extent, container size, or zoom (default:\n * markers scale with the coordinate space, like nodes and edges).\n */\nexport class QEMeansElement extends HTMLElement {\n static tagName = 'qe-means' as const;\n}\n\n/**\n * <qe-points> — renders individual unit scatter dots.\n * Presence = show unit points; absence = hide unit points.\n *\n * Attributes:\n * label \"on\" | \"off\" | \"click\" | \"auto\" (default \"auto\")\n * size Numeric dot size (default 2.5), relative to the code-node size.\n * fixed-size Boolean — keep unit dots a constant on-screen pixel size\n * regardless of data extent, container size, or zoom (default:\n * dots scale with the coordinate space, like nodes and edges).\n */\nexport class QEPointsElement extends HTMLElement {\n static tagName = 'qe-points' as const;\n}\n\n/**\n * <qe-edges> — renders an edge network.\n * Presence = draw edges; absence = no edge network.\n *\n * Attributes:\n * group Group name whose mean network to draw.\n * unit Individual unit ID whose personal network to draw\n * (e.g. \"FirstGame::steven z\"). Mutually exclusive with `group`.\n * compare Second group to subtract (group − compare).\n * also Second group to overlay alongside `group`.\n * scale Reference node weight for mark sizes — the node drawn at\n * <qe-graph mark-size> × the plot width (edge widths follow):\n * \"model\" (default) — the largest node among the model's\n * group-mean networks, so separate plots of\n * one model are comparable;\n * \"plot\" — this plot's own largest node;\n * <number> — a fixed node weight.\n * magnify Multiply this plot's edge widths and node sizes (not colour),\n * e.g. to read a faint subtraction. Whenever the attribute is\n * present — any value, including \"1\" — the plot is labelled\n * \"(scaled N.Nx)\", so exported plots state their scaling.\n * color-scale How |weight| maps onto webENA's colour ramps (saturation\n * 0.25–1, opacity 0.3–1):\n * \"model\" (default) — rescaled from the model's smallest to largest\n * non-zero weight (every unit), so plots of one\n * model share a colour scale;\n * \"plot\" — rescaled within this plot (webENA);\n * \"absolute\" — no ramps: saturation = opacity = |weight|.\n */\nexport class QEEdgesElement extends HTMLElement {\n static tagName = 'qe-edges' as const;\n}\n\n/**\n * <qe-trajectories> — renders epistemic cognitive trajectory curves and steps.\n * Presence = draw trajectories; absence = no trajectories.\n *\n * Attributes:\n * units Comma-separated unit IDs to show. Omit for all.\n * smooth \"none\" | \"poly\" (default \"none\")\n * max-degree Upper bound on polynomial degree if smooth=\"poly\" (default 3)\n * degree-selection \"loocv_2d\" | \"fixed\" (default \"loocv_2d\"). \"loocv_2d\"\n * picks the degree in 1..max-degree by joint 2D leave-one-out CV;\n * \"fixed\" always uses max-degree. Near-origin points are excluded\n * from the fit (still drawn).\n * points \"true\" | \"false\" — show discrete point markers along trajectory\n * tips \"true\" | \"false\" — show leading tip marker\n * playhead Number — current turn / time index for filtering/animation\n * line-style \"uniform\" | \"tapered\" (default \"uniform\")\n * stroke-width Number (default 2)\n * stroke-width-range \"min,max\" for tapered lines (default \"1,6\")\n * opacity-range \"min,max\" for tapered lines (default \"0.3,1\")\n */\nexport class QETrajectoriesElement extends HTMLElement {\n static tagName = 'qe-trajectories' as const;\n}\n\n/**\n * <qe-axes> — renders the x/y axis lines and, per axis, an optional title.\n * Presence = draw axes; absence = no axes.\n *\n * Attributes:\n * x Show the x-axis label. A value sets custom text; an empty/boolean\n * attribute defaults to the x dimension name (e.g. \"SVD1\").\n * y Show the y-axis label. Same rule with the y dimension name.\n *\n * Examples:\n * <qe-axes></qe-axes> lines only, no labels\n * <qe-axes x y></qe-axes> \"SVD1\" / \"SVD2\"\n * <qe-axes x=\"Task focus\" y> \"Task focus\" / \"SVD2\"\n */\nexport class QEAxesElement extends HTMLElement {\n static tagName = 'qe-axes' as const;\n}\n\ncustomElements.define(QENodesElement.tagName, QENodesElement);\ncustomElements.define(QEMeansElement.tagName, QEMeansElement);\ncustomElements.define(QEPointsElement.tagName, QEPointsElement);\ncustomElements.define(QEEdgesElement.tagName, QEEdgesElement);\ncustomElements.define(QETrajectoriesElement.tagName, QETrajectoriesElement);\ncustomElements.define(QEAxesElement.tagName, QEAxesElement);\n","import { DefaultGraphOptions, Graph } from \"../objects/Graph\";\nimport { DrawableElement } from \"./DrawableElement\";\nimport { QEArray, QEElement, QELayer } from \"./QELayer\";\nimport QEVisualElement from \"./QEVisual\";\nimport { DataFrameRow } from \"../types/DataFrame\";\nimport { NodeEdge, TaperedWeightedMidpointEdge } from \"../objects/Edges\";\nimport { Label, Line, Point } from \"../objects/PlottedObject\";\nimport { Trajectory } from \"../objects/Trajectory\";\nimport { LayerLike } from \"../objects/Layers\";\nimport { Color } from \"../objects/Color\";\nimport { Extremes } from \"../objects/Extremes\";\nimport { QELabel } from \"./QELabel\";\nimport { DEFAULT_EDGE_WIDTH, OPACITY_RANGE, SATURATION_RANGE, UNCONNECTED_NODE_SIZE, nodeSizeForEdges, rampFor, widthPerWeight } from \"../objects/Sizing\";\nimport \"./QEChildElements.js\";\n\n// Accessible color palette for group assignment (Paul Tol's bright scheme)\nconst GROUP_PALETTE = [\n '#4477AA', '#EE6677', '#228833', '#CCBB44',\n '#66CCEE', '#AA3377', '#BBBBBB', '#000000',\n];\n\n/**\n * Parse an edge column name into the two code IDs it connects.\n * Edge columns use \".\" as separator between the two codes, but codes can\n * themselves contain \".\" (e.g. \"Technical.Constraints\"). We resolve the\n * ambiguity by trying every prefix that matches a known code.\n *\n * Self-connections (\"A.A\") are detected first — they return [A, A].\n * In directed (ONA) mode the full unfolded matrix is expected, so A→B and\n * B→A are distinct columns; both resolve correctly as ordered pairs.\n */\nfunction parseEdgePair(colName: string, codes: string[]): [string, string] | null {\n // Self-connections first: exact match \"code.code\"\n for (const c of codes) {\n if (colName === `${c}.${c}`) return [c, c];\n }\n // Directed or undirected pairs: longest-prefix wins to handle dotted code names\n for (const c1 of codes) {\n if (colName.startsWith(c1 + '.')) {\n const c2 = colName.slice(c1.length + 1);\n if (codes.includes(c2)) return [c1, c2];\n }\n }\n return null;\n}\n\n/**\n * Compute half-width and half-height for a 95% CI rectangle on the group mean.\n *\n * Each axis is treated independently: half-extent = t(df,0.975) × SE,\n * where SE = sqrt(variance / n) and df = n − 1. This matches the standard\n * ENA rectangular CI displayed in the rENA / Web ENA tools.\n *\n * Inputs are the *raw* (un-scaled) variances; pointScale is applied here so\n * the returned values are in SVG coordinate space.\n */\nfunction computeCIRect(\n varX: number, varY: number, n: number, pointScale: number\n): { halfW: number; halfH: number } {\n // t(df, 0.975) — rough approximation good to ±0.02 for df ≥ 3\n const df = Math.max(1, n - 1);\n const t95 = df >= 120 ? 1.960\n : df >= 60 ? 2.000\n : df >= 30 ? 2.042\n : df >= 20 ? 2.086\n : df >= 10 ? 2.228\n : df >= 5 ? 2.571\n : 4.303; // df = 1\n const seX = Math.sqrt(Math.max(0, varX) / n) * pointScale;\n const seY = Math.sqrt(Math.max(0, varY) / n) * pointScale;\n return { halfW: t95 * seX, halfH: t95 * seY };\n}\n\n/** Mean markers never exceed this fraction of their interval box's shorter\n * half-side. Marker size is otherwise arbitrary (extent- or pixel-based), so\n * without a cap a tight CI disappears underneath the mean square. */\nconst MEAN_MAX_FRACTION_OF_INTERVAL = 0.5;\n\nfunction capMeanToInterval(meanPt: Point | undefined, halfW: number, halfH: number): void {\n if (!meanPt) return;\n const half = Math.min(Math.abs(halfW), Math.abs(halfH));\n if (!(half > 0)) return; // degenerate interval (n = 1, zero variance): keep default size\n (meanPt as any).meta = { ...((meanPt as any).meta ?? {}), maxRadius: half * MEAN_MAX_FRACTION_OF_INTERVAL };\n}\n\nfunction readIntervalBounds(\n row: DataFrameRow, dim0: string, dim1: string, prefix = ''\n): { x_low: number; x_high: number; y_low: number; y_high: number } | null {\n // prefix '' → CI ({dim}.low / .high); 'o' → outlier ({dim}.olow / .ohigh).\n const get = (col: string) => {\n const i = row.names.indexOf(col);\n const raw = i >= 0 ? row[i] : null;\n if (raw == null || raw === '') return undefined; // Number(null) would be 0\n const v = Number(raw);\n return Number.isFinite(v) ? v : undefined;\n };\n const xLow = get(`${dim0}.${prefix}low`) ?? get(`${dim0}_${prefix}low`);\n const xHigh = get(`${dim0}.${prefix}high`) ?? get(`${dim0}_${prefix}high`);\n const yLow = get(`${dim1}.${prefix}low`) ?? get(`${dim1}_${prefix}low`);\n const yHigh = get(`${dim1}.${prefix}high`) ?? get(`${dim1}_${prefix}high`);\n if (xLow == null || xHigh == null || yLow == null || yHigh == null) return null;\n return { x_low: xLow, x_high: xHigh, y_low: yLow, y_high: yHigh };\n}\n\n/**\n * <qe-edges color-scale>: the range that edge weights are rescaled from onto\n * webENA's saturation (0.25–1) and opacity (0.3–1) ramps.\n * \"model\" (default) — min / max non-zero |weight| across the whole model\n * (every unit), so separate plots of one model share\n * one colour scale.\n * \"plot\" — this plot's own min / max (webENA's per-network\n * behaviour).\n * \"absolute\" — no rescaling: saturation = opacity = |weight|.\n */\ntype ColorScale = 'model' | 'plot' | 'absolute';\n\n/** One <qe-edges> element: a named network or an explicit `network` row. */\ntype EdgeLayerSpec = {\n group: string | null; unit: string | null;\n compare: string | null; also: string | null;\n network: string | null;\n colors: [string, string | null] | null; // positive, negative (null → complement)\n threshold: [number, number] | null; // min, max (max = Infinity when omitted)\n name: string | null;\n};\n\nfunction parseEdgeLayer(el: Element): EdgeLayerSpec {\n const a = (k: string) => el.getAttribute(k);\n const cols = a('colors')?.split(',').map(c => c.trim()).filter(Boolean) ?? [];\n const thr = a('threshold')?.split(',').map(Number).filter(Number.isFinite) ?? [];\n return {\n group: a('group'), unit: a('unit'), compare: a('compare'), also: a('also'),\n network: a('network'),\n colors: cols.length ? [cols[0], cols[1] ?? null] : null,\n threshold: thr.length ? [thr[0], thr.length > 1 ? thr[1] : Infinity] : null,\n name: a('name'),\n };\n}\n\n/** Complementary hue (rENA: one colour → negatives use hue + 180°). */\nfunction complementColor(hex: string): string {\n const { r, g, b } = Color.parseColor(hex);\n const mx = Math.max(r, g, b), mn = Math.min(r, g, b);\n const f = (c: number) => (mx + mn - c).toString(16).padStart(2, '0');\n return `#${f(r)}${f(g)}${f(b)}`;\n}\n\nfunction parseColorScale(attr: string | null): ColorScale {\n const a = attr?.trim().toLowerCase();\n return a === 'plot' || a === 'absolute' ? a : 'model';\n}\n\n/**\n * Parse a label-mode attribute string into a Label.DISPLAY_TYPES integer.\n * \"on\" → 3 (ON)\n * \"off\" → 0 (OFF)\n * \"click\" → 2 (CLICK)\n * \"auto\" → 1 (AUTO)\n * Returns `defaultMode` for any unrecognized value or null.\n */\nfunction parseLabelMode(attr: string | null, defaultMode: number): number {\n switch (attr?.toLowerCase()) {\n case 'on': return 3;\n case 'off': return 0;\n case 'click': return 2;\n case 'auto': return 1;\n default: return defaultMode;\n }\n}\n\nexport class QEGraphElement extends DrawableElement implements QEElement {\n static tagName: string = \"qe-graph\";\n\n static get observedAttributes(): string[] {\n // Only layout / shorthand attributes live on <qe-graph> itself.\n // Layer-specific config (group, unit, compare, also, points, edges,\n // confidence, groups) lives on child elements and is observed via\n // MutationObserver in connectedCallback().\n return [\n 'width', 'height', 'for',\n 'scale-points', 'point-scale', 'center',\n 'labels', 'label-nodes', 'label-means', 'label-points',\n ];\n }\n\n static style: string = `\n ${DrawableElement.style}\n\n :host {\n display: block;\n }\n\n .wrapper {\n width: 100%;\n height: 100%;\n }\n\n svg {\n width: 100%;\n height: 100%;\n aspect-ratio: 1 / 1;\n background-color: #FFF;\n }\n `;\n\n svg_element: SVGElement;\n graph: QEGraphElement;\n parent: SVGElement | null;\n zoom_level: number = 1;\n\n __data__: Graph;\n __children__: QEArray = new QEArray();\n __name__: string;\n \n\n private _vizena!: QEVisualElement;\n get vizena() {\n return this._vizena;\n }\n\n private _hasModel = false;\n private _renderPending = false;\n private _childObserver: MutationObserver | null = null;\n\n // SVG <rect> elements for per-group CI boxes, keyed by group name.\n // Managed directly (not via QELayer) so they render behind unit points.\n private _ciRects: Map<string, SVGRectElement> = new Map();\n private _outlierRects: Map<string, SVGRectElement> = new Map();\n private _ciCross: Map<string, SVGPathElement> = new Map();\n\n // Cached reference to the labels <g> layer — set once in connectedCallback()\n // after draw() so it is guaranteed to be in the SVG DOM.\n private _labelsGroup: SVGGElement | null = null;\n\n // SVG <text> label elements for nodes, mean points, and unit points.\n private _nodeLabels: Map<string, QELabel> = new Map();\n private _meanLabels: Map<string, QELabel> = new Map();\n private _pointLabels: Map<string, QELabel> = new Map();\n\n // Axes (<qe-axes>): whether to show axis lines, and resolved label text\n // (null = no label for that axis). SVG <text> nodes are cached and positioned\n // in update_axis_labels() using the freshly-computed extremes.\n private _showAxes = false;\n private _axisXText: string | null = null;\n private _axisYText: string | null = null;\n private _axisLabelEls: Map<'x' | 'y', SVGTextElement> = new Map();\n // \"(scaled 1.5x)\" label, drawn whenever <qe-edges magnify> is present.\n private _magnifyText: string | null = null;\n private _magnifyEl: SVGTextElement | null = null;\n // <qe-graph range> / plot-title / label-font-* (qe_plot(range =, title =),\n // qe_labels(font_*)); resolved each render.\n private _rangeExtent: number | null = null;\n private _rangeMode: 'network' | 'points' | 'number' | null = null;\n /** center=\"content\": centre the view on the drawn content, not the origin */\n private _centerContent = false;\n private _plotTitle: string | null = null;\n private _titleEl: SVGTextElement | null = null;\n private _resizeObs: ResizeObserver | null = null;\n _labelFont: { size: number | null; family: string | null; color: string | null } =\n { size: null, family: null, color: null };\n\n /** SVG user units per CSS pixel at the current size / zoom. */\n unitsPerPixel(): number {\n const extent = this.__data__.extremes.x_max || 1;\n const rect = this.svg_element?.getBoundingClientRect?.();\n const zoom = (this as any).zoom_level || 1;\n return rect && rect.width > 0 ? (2 * extent / rect.width) / zoom : extent * 0.004;\n }\n\n constructor() {\n super();\n\n this.graph = this;\n this.parent = null;\n\n this.__data__ = new Graph(DefaultGraphOptions);\n this.__name__ = this.__data__.name || \"unnamed-graph\";\n this.svg_element = this.create();\n\n console.log(\"Created ena-graph svg element: \", this.svg_element);\n\n // Listen for the model-updated CustomEvent dispatched by VisualQEElement.\n // The Model object is carried in event.detail, so ena-graph works whether it\n // is a child, sibling, or anywhere else relative to ena-visual.\n document.addEventListener('model-updated', (e: Event) => {\n // When multiple qe-visual elements exist on the page, each qe-graph must\n // only react to events from its own associated visual. _vizena is resolved\n // in connectedCallback(); before that point we accept all events (initial\n // load), but once the association is known we filter strictly.\n // composedPath()[0]: inside a shadow root (e.g. a qe-visual in another\n // component), e.target is retargeted to the shadow host\n const origin = e.composedPath?.()[0] ?? e.target;\n if (this._vizena && origin !== this._vizena) return;\n\n const model = (e as CustomEvent).detail;\n if (!model) return;\n\n // Tweening (opt-in via `animate`): snapshot current mark/edge positions\n // BEFORE the rebuild so we can animate old→new after this.update().\n this._animateMs = this.hasAttribute('animate')\n ? (parseInt(this.getAttribute('animate') || '', 10) || 300)\n : 0;\n const tweenFrom = (this._animateMs > 0 && this._hasModel) ? this._captureTween() : null;\n\n this._hasModel = true;\n\n const dims = model.dimensions as string[];\n\n // Resolved column names from setModelData (auto-detected or caller-supplied)\n const unitIdCol = model.unit_id_col;\n const nodeIdCol = model.node_id_col;\n const groupColName = model.group_col;\n\n // ── Layer config (read once from child elements) ─────────────────────────\n const config = this._readLayerConfig();\n\n // ── Axes (<qe-axes>) ─────────────────────────────────────────────────────\n // Resolve label text now that dims are known: empty x/y attribute falls\n // back to the dimension name; a value is used verbatim; null = no label.\n this._showAxes = config.showAxes;\n this._axisXText = config.axisXLabel === null ? null : (config.axisXLabel || String(dims?.[0] ?? 'x'));\n // Present on any <qe-edges magnify>, including \"1\" — as webENA labels\n // its side plots \"(scaled 1.0x)\" so an exported set says which plot was\n // magnified.\n this._magnifyText = config.edgeMagnify == null ? null\n : `(scaled ${config.edgeMagnify.toFixed(1)}x)`;\n this._axisYText = config.axisYLabel === null ? null : (config.axisYLabel || String(dims?.[1] ?? 'y'));\n\n // ── Group color map ──────────────────────────────────────────────────────\n // Priority: (1) points groupCol, (2) groups frame row names, (3) empty.\n const groupColorMap: Record<string, string> = {};\n // Model palette (qe_plot(palette =)) or the default Tol \"bright\" scheme.\n const PALETTE: string[] = (model as any).palette?.length ? (model as any).palette : GROUP_PALETTE;\n if (groupColName && model.points?.names) {\n const groupCol = model.points.col(groupColName);\n if (groupCol) {\n const uniqueGroups: string[] = [...new Set([...groupCol].map(String))];\n uniqueGroups.forEach((g, i) => {\n groupColorMap[g] = PALETTE[i % PALETTE.length];\n });\n }\n }\n // Groups-frame rows: a `color` column overrides the palette, and rows that\n // are not groups of the points (e.g. the mean of an arbitrary subset,\n // qe_group(points =)) still get a colour so they count as known groups.\n if (model.groups?.rows && model.groups.rows().length > 0) {\n model.groups.rows().forEach((row: DataFrameRow) => {\n const g = row.rowName ?? String(row[0]);\n const ci = row.names.indexOf('color');\n const c = ci >= 0 ? row[ci] : null;\n if (c && String(c) !== 'NA') groupColorMap[g] = String(c);\n else if (!groupColorMap[g]) {\n groupColorMap[g] = PALETTE[Object.keys(groupColorMap).length % PALETTE.length];\n }\n });\n }\n\n // ── Active groups for MEANS display ─────────────────────────────────────\n // `groups` attribute: comma-separated list of group names whose means and\n // CI boxes should be rendered. Default (attribute absent or empty): show\n // means for ALL groups present in the model.\n //\n // Means display is intentionally independent of edge selection. The edge\n // section below reads `group` / `compare` / `also` to determine which\n // network(s) to draw; those attributes have no effect here.\n const _allGroupNames_ = Object.keys(groupColorMap);\n const activeMeanGroups: Set<string> = (config.activeMeanGroups && config.activeMeanGroups.trim())\n ? new Set(\n config.activeMeanGroups.split(',')\n .map(s => s.trim())\n .filter(g => groupColorMap[g]) // silently drop names not in model\n )\n : new Set(_allGroupNames_); // default: every group\n\n // ── Point-to-node coordinate scaling ────────────────────────────────────\n // Unit point coordinates are in a different (typically much smaller) range\n // Unit/mean point coordinates are rescaled by default so the outermost point\n // aligns with the outermost code node — matching the ENA Web Tool default.\n // Set scale-points=\"false\" on <qe-graph> to show raw SVD coordinates\n // (points cluster near origin relative to code nodes).\n const scalePointsEnabled = config.scalePoints;\n\n const getExtent = (rows: DataFrameRow[]): number => {\n let max = 0;\n rows.forEach(row => {\n const xIdx = row.names.indexOf(dims[0]);\n const yIdx = dims.length > 1 ? row.names.indexOf(dims[1]) : -1;\n if (xIdx >= 0) max = Math.max(max, Math.abs(Number(row[xIdx])));\n if (yIdx >= 0) max = Math.max(max, Math.abs(Number(row[yIdx])));\n });\n return max;\n };\n\n const maxNodeExtent = model.nodes?.rows ? getExtent(model.nodes.rows()) : 0;\n const maxPointExtent = model.points?.rows ? getExtent(model.points.rows()) : 0;\n const maxTrajExtent = model.trajectories?.rows ? getExtent(model.trajectories.rows()) : 0;\n const effectivePointExtent = maxPointExtent > 0 ? maxPointExtent : maxTrajExtent;\n // point-scale=\"N\" (optional, unset by default): an explicit factor, e.g.\n // 1 for raw coordinates or another tool's rescaling, instead of fitting\n // the outermost point to the outermost node\n const pointScale = config.pointScale !== null ? config.pointScale\n : (scalePointsEnabled && effectivePointExtent > 0 && maxNodeExtent > 0)\n ? maxNodeExtent / effectivePointExtent\n : 1;\n\n // <qe-graph range>: a symmetric axis range, as rENA's scale.to —\n // \"network\" = ±max |node| × 1.2, \"points\" = ±max |drawn point| × 1.2, or\n // a number. Absent → qeviz's default (1.3 × the largest drawn mark).\n this._rangeExtent =\n config.range === 'network' ? maxNodeExtent * 1.2\n : config.range === 'points' ? effectivePointExtent * pointScale * 1.2\n : typeof config.range === 'number' ? config.range\n : null;\n this._rangeMode = config.range === 'network' || config.range === 'points' ? config.range\n : typeof config.range === 'number' ? 'number' : null;\n this._centerContent = config.centerContent;\n this._plotTitle = config.plotTitle;\n this._labelFont = config.labelFont;\n\n // ── Label display modes — sourced from config (child elements or shorthand) ──\n const labelNodes = config.labelNodes;\n const labelMeans = config.labelMeans;\n const labelPoints = config.labelPoints;\n\n // Use the cached labels <g> reference (set once in connectedCallback).\n const labelSvg = this._labelsGroup;\n\n // ── Helper: build a Point from a DataFrame row ───────────────────────────\n // Looks up dimension values by column name so it works with any data format.\n // Y is negated because SVG y-axis points down while ENA convention is y-up.\n // `scale` multiplies x/y — use pointScale for unit/mean points, 1 for nodes.\n const rowToPoint = (row: DataFrameRow, idCol: string, colorStr?: string, scale = 1): Point => {\n const idIdx = row.names.indexOf(idCol);\n const xIdx = row.names.indexOf(dims[0]);\n const yIdx = dims.length > 1 ? row.names.indexOf(dims[1]) : -1;\n const pt = new Point({\n ID: idIdx >= 0 ? String(row[idIdx]) : (row.rowName || `pt-${Math.random().toString(36).slice(2)}`),\n dimensions: [\n xIdx >= 0 ? Number(row[xIdx]) * scale : 0,\n yIdx >= 0 ? -Number(row[yIdx]) * scale : 0, // negate Y: SVG y-down vs ENA y-up\n ],\n meta: {},\n });\n if (colorStr) pt.color = new Color(colorStr);\n return pt;\n };\n\n // ── Unit points + group means ────────────────────────────────────────────\n // groupSums is used later for mean edges and CI ellipses.\n // x2/y2/xy accumulate Σ(raw²) for variance computation.\n const groupSums: Record<string, {\n x: number; y: number; x2: number; y2: number; xy: number;\n n: number; color: string;\n }> = {};\n\n // <qe-points> presence controls unit-dot visibility.\n // <qe-means> presence controls mean markers and CI boxes.\n const showUnitPoints = config.showPoints;\n\n // ── Explicit point sets (qe_points(units =, points =)) ─────────────────\n // Each <qe-points set=\"…\"> draws that set's rows of model.pointsets, on\n // the same point scale as the unit points.\n const pointSetFrame = (model as any).pointsets;\n if (config.pointSets.length && pointSetFrame?.rows) {\n const psLayer = this.__children__.search('__children__', 'points') as QELayer;\n const col = (r: DataFrameRow, k: string) => { const i = r.names.indexOf(k); return i >= 0 ? r[i] : null; };\n config.pointSets.forEach((ps, si) => {\n pointSetFrame.rows().forEach((row: DataFrameRow) => {\n if (String(col(row, 'set')) !== ps.set) return;\n const id = String(col(row, 'id'));\n const group = col(row, 'group') != null && String(col(row, 'group')) !== 'NA' ? String(col(row, 'group')) : null;\n const color = col(row, 'color') && String(col(row, 'color')) !== 'NA' ? String(col(row, 'color'))\n : group && groupColorMap[group] ? groupColorMap[group]\n : PALETTE[si % PALETTE.length];\n const pt = rowToPoint(row, 'id', color, pointScale);\n pt.ID = `${ps.set}::${id}`;\n pt.size = ps.size ?? config.pointSize ?? 2.5;\n const shape = col(row, 'shape');\n if (shape && String(shape) !== 'NA') pt.shape = String(shape);\n const label = col(row, 'label');\n (pt as any).meta = {\n stroke: '#ffffff', kind: 'point',\n name: label != null && String(label) !== 'NA' ? String(label) : id,\n group: group ?? undefined, unit: id, set: ps.set,\n fixedSize: ps.fixedSize,\n };\n this.__data__.points.set(pt.ID, pt);\n psLayer?.__data__.objects.set(pt.ID, pt);\n });\n });\n }\n\n if (model.points?.rows) {\n const pointsLayer = this.__children__.search('__children__', 'points') as QELayer;\n if (pointsLayer) {\n model.points.rows().forEach((row: DataFrameRow) => {\n // Determine this point's group color\n const groupColIdx = groupColName ? row.names.indexOf(groupColName) : -1;\n const group = groupColIdx >= 0 ? String(row[groupColIdx]) : null;\n const colorStr = group ? (groupColorMap[group] ?? '#888888') : '#888888';\n\n // Only add unit dots to the layer when 'points' attribute is present.\n if (showUnitPoints) {\n const pt = rowToPoint(row, unitIdCol, colorStr, pointScale);\n // Unit-point size: <qe-points size=…> overrides the default 2.5.\n // (Point() defaults to 1, which renders smaller than code nodes.)\n pt.size = config.pointSize ?? 2.5;\n // White halo separates overlapping dots in dense clusters.\n // meta.kind/name/group feed the qe-node-* interaction events.\n (pt as any).meta = {\n ...((pt as any).meta ?? {}),\n stroke: '#ffffff', kind: 'point', name: pt.ID,\n group: group ?? undefined, unit: pt.ID,\n fixedSize: config.pointFixedSize,\n };\n this.__data__.points.set(pt.ID, pt);\n pointsLayer.__data__.objects.set(pt.ID, pt);\n }\n\n // Always accumulate for mean + variance (needed for Path B even without dots)\n if (group) {\n const xIdx = row.names.indexOf(dims[0]);\n const yIdx = dims.length > 1 ? row.names.indexOf(dims[1]) : -1;\n if (!groupSums[group]) groupSums[group] = { x: 0, y: 0, x2: 0, y2: 0, xy: 0, n: 0, color: colorStr };\n const rx = xIdx >= 0 ? Number(row[xIdx]) : 0;\n const ry = yIdx >= 0 ? Number(row[yIdx]) : 0;\n groupSums[group].x += rx;\n groupSums[group].y += ry;\n groupSums[group].x2 += rx * rx;\n groupSums[group].y2 += ry * ry;\n groupSums[group].xy += rx * ry;\n groupSums[group].n += 1;\n }\n });\n\n // ── Group means + bounds ──────────────────────────────────────────────\n // Two paths:\n // A) model.groups frame present → use pre-computed means + bounds.\n // This is the Phase 3+ preferred path. qeviz renders; adapters compute.\n // B) No groups frame → compute means from unit-point accumulations\n // (legacy fallback; also used when only points are provided).\n //\n // Deprecated frames (model.confidence, model.outlier) are still respected\n // in path B for backward compatibility with rENA adapters not yet updated.\n //\n // Means rendering is guarded by config.showMeans (<qe-means> presence).\n // When absent, activeGroupRows is kept empty so the labels section below\n // also skips mean labels cleanly.\n\n const hasGroupsFrame = !!(model.groups?.rows && model.groups.rows().length > 0);\n\n // Rows from the groups frame that are active in the current view.\n // Empty when <qe-means> is absent so downstream label logic is consistent.\n const activeGroupRows: DataFrameRow[] = (config.showMeans && hasGroupsFrame)\n ? model.groups.rows().filter((r: DataFrameRow) => {\n const g = r.rowName ?? String(r[0]);\n return activeMeanGroups.size === 0 || activeMeanGroups.has(g);\n })\n : [];\n\n if (config.showMeans) {\n const pointsLayerSvg = pointsLayer.svg_element as SVGGElement | null;\n const sw = (maxNodeExtent > 0 ? maxNodeExtent : 1) * 0.008;\n\n if (hasGroupsFrame) {\n // ── Path A: groups frame ─────────────────────────────────────────\n // Remove CI/outlier rects for groups no longer active.\n const activeNames = new Set(activeGroupRows.map((r: DataFrameRow) => r.rowName ?? String(r[0])));\n this._ciRects.forEach((el, g) => { if (!activeNames.has(g)) { el.remove(); this._ciRects.delete(g); } });\n this._outlierRects.forEach((el, g) => { if (!activeNames.has(g)) { el.remove(); this._outlierRects.delete(g); } });\n this._ciCross.forEach((el, k) => { if (!activeNames.has(k.slice(2))) { el.remove(); this._ciCross.delete(k); } });\n\n activeGroupRows.forEach((row: DataFrameRow) => {\n const group = row.rowName ?? String(row[0]);\n const color = groupColorMap[group] ?? '#888888';\n const xIdx = row.names.indexOf(dims[0]);\n const yIdx = dims.length > 1 ? row.names.indexOf(dims[1]) : -1;\n const mx = xIdx >= 0 ? Number(row[xIdx]) * pointScale : 0;\n const my = yIdx >= 0 ? -Number(row[yIdx]) * pointScale : 0;\n\n // Mean marker — square, larger than unit points\n const meanPt = new Point({\n ID: `mean-${group}`,\n dimensions: [mx, my],\n meta: { kind: 'mean', name: group, group, fixedSize: config.meanFixedSize },\n });\n meanPt.color = new Color(color);\n meanPt.size = 4; // radius = extent × 0.006 × 4 ≈ 0.024 for a unit extent\n const shapeIdx = row.names.indexOf('shape');\n const rowShape = shapeIdx >= 0 ? row[shapeIdx] : null;\n meanPt.shape = rowShape && String(rowShape) !== 'NA' ? String(rowShape) : 'rect';\n this.__data__.points.set(meanPt.ID, meanPt);\n pointsLayer.__data__.objects.set(meanPt.ID, meanPt);\n\n // Per-mean overrides (explicit means, as rENA's ena.plot.group\n // sets them per call): groups-frame `intervals` / `outlier`\n // columns win over the <qe-means> attributes when present.\n const cell = (name: string): any => {\n const i = row.names.indexOf(name);\n const v = i >= 0 ? row[i] : null;\n return v == null || String(v) === 'NA' || String(v) === '' ? null : v;\n };\n const rowIv = cell('intervals');\n const iv: 'box' | 'crosshairs' | 'none' =\n rowIv === 'box' || rowIv === 'crosshairs' || rowIv === 'none' ? rowIv : config.intervals;\n const rowOut = cell('outlier');\n const showOut = rowOut == null ? config.showOutlier : (rowOut === true || String(rowOut) === 'true');\n\n // Outlier interval (qe_group(outlier = TRUE)): {dim}.olow / .ohigh.\n const ob = showOut\n ? readIntervalBounds(row, dims[0] as string, dims[1] as string, 'o')\n : null;\n if (!ob) {\n this._outlierRects.get(group)?.remove(); this._outlierRects.delete(group);\n } else {\n let oel = this._outlierRects.get(group);\n if (!oel) {\n oel = document.createElementNS('http://www.w3.org/2000/svg', 'rect') as SVGRectElement;\n oel.setAttribute('data-outlier-group', group);\n this._outlierRects.set(group, oel);\n }\n oel.setAttribute('x', (ob.x_low * pointScale).toString());\n oel.setAttribute('y', (-ob.y_high * pointScale).toString());\n oel.setAttribute('width', ((ob.x_high - ob.x_low) * pointScale).toString());\n oel.setAttribute('height', ((ob.y_high - ob.y_low) * pointScale).toString());\n oel.setAttribute('fill', 'none');\n oel.setAttribute('stroke', color);\n oel.setAttribute('stroke-width', sw.toString());\n oel.setAttribute('stroke-opacity', '0.5');\n oel.setAttribute('stroke-dasharray', `${sw * 2} ${sw * 2}`);\n if (pointsLayerSvg && !oel.parentElement) pointsLayerSvg.insertBefore(oel, pointsLayerSvg.firstChild);\n }\n\n // CI (<qe-means intervals=\"box|crosshairs|none\">, or the legacy\n // `confidence` flag = box). Gated so qe_group(intervals = \"none\")\n // draws nothing.\n const bounds = iv !== 'none'\n ? readIntervalBounds(row, dims[0] as string, dims[1] as string)\n : null;\n const crossKey = `x:${group}`;\n if (!bounds || iv !== 'crosshairs') {\n this._ciCross.get(crossKey)?.remove(); this._ciCross.delete(crossKey);\n }\n if (bounds && iv === 'crosshairs') {\n this._ciRects.get(group)?.remove(); this._ciRects.delete(group);\n // Two arms through the mean: x_lo..x_hi at the mean's y, and\n // y_lo..y_hi at the mean's x.\n const x0 = bounds.x_low * pointScale, x1 = bounds.x_high * pointScale;\n const y0 = -bounds.y_high * pointScale, y1 = -bounds.y_low * pointScale;\n capMeanToInterval(meanPt, (x1 - x0) / 2, (y1 - y0) / 2);\n let cel = this._ciCross.get(crossKey);\n if (!cel) {\n cel = document.createElementNS('http://www.w3.org/2000/svg', 'path') as SVGPathElement;\n cel.setAttribute('data-ci-group', group);\n cel.setAttribute('data-ci-kind', 'crosshairs');\n this._ciCross.set(crossKey, cel);\n }\n cel.setAttribute('d', `M${x0} ${my} L${x1} ${my} M${mx} ${y0} L${mx} ${y1}`);\n cel.setAttribute('fill', 'none');\n cel.setAttribute('stroke', color);\n cel.setAttribute('stroke-width', (sw * 1.25).toString());\n cel.setAttribute('stroke-opacity', '0.8');\n if (pointsLayerSvg && !cel.parentElement) pointsLayerSvg.insertBefore(cel, pointsLayerSvg.firstChild);\n } else if (!bounds) {\n const stale = this._ciRects.get(group);\n if (stale) { stale.remove(); this._ciRects.delete(group); }\n } else {\n const rect_x = bounds.x_low * pointScale;\n const rect_y = -bounds.y_high * pointScale;\n const rect_width = (bounds.x_high - bounds.x_low) * pointScale;\n const rect_height = (bounds.y_high - bounds.y_low) * pointScale;\n capMeanToInterval(meanPt, rect_width / 2, rect_height / 2);\n\n let el = this._ciRects.get(group);\n if (!el) {\n el = document.createElementNS('http://www.w3.org/2000/svg', 'rect') as SVGRectElement;\n el.setAttribute('data-ci-group', group);\n this._ciRects.set(group, el);\n }\n el.setAttribute('x', rect_x.toString());\n el.setAttribute('y', rect_y.toString());\n el.setAttribute('width', rect_width.toString());\n el.setAttribute('height', rect_height.toString());\n el.setAttribute('fill', 'none');\n el.setAttribute('stroke', color);\n el.setAttribute('stroke-width', sw.toString());\n el.setAttribute('stroke-opacity', '0.8');\n el.setAttribute('stroke-dasharray', `${sw * 4} ${sw * 3}`);\n if (pointsLayerSvg && !el.parentElement) {\n pointsLayerSvg.insertBefore(el, pointsLayerSvg.firstChild);\n }\n }\n });\n\n } else {\n // ── Path B: legacy — compute means from groupSums ────────────────\n // Add one mean point per group — larger (size=1.5) and same group color\n Object.entries(groupSums).forEach(([group, { x, y, n, color }]) => {\n const meanPt = new Point({\n ID: `mean-${group}`,\n dimensions: [x / n * pointScale, -(y / n) * pointScale],\n meta: { kind: 'mean', name: group, group, fixedSize: config.meanFixedSize },\n });\n meanPt.color = new Color(color);\n meanPt.size = 4; // radius = extent × 0.006 × 4 ≈ 0.024 for a unit extent\n meanPt.shape = 'rect';\n this.__data__.points.set(meanPt.ID, meanPt);\n pointsLayer.__data__.objects.set(meanPt.ID, meanPt);\n });\n\n // ── CI boxes (deprecated confidence frame or JS fallback) ────────\n const showCI = config.showCI;\n if (showCI) {\n this._ciRects.forEach((el, g) => {\n if (!groupSums[g]) { el.remove(); this._ciRects.delete(g); }\n });\n\n if (model.confidence?.rows) {\n // Pre-computed path: deprecated model.confidence frame\n model.confidence.rows().forEach((row: DataFrameRow) => {\n const groupIdx = row.names.indexOf(groupColName ?? 'group');\n const group = groupIdx >= 0 ? String(row[groupIdx]) : (row.rowName ?? null);\n if (!group) return;\n const color = groupColorMap[group] ?? '#888888';\n const bounds = readIntervalBounds(row, dims[0] as string, dims[1] as string);\n if (!bounds) return;\n const rect_x = bounds.x_low * pointScale;\n const rect_y = -bounds.y_high * pointScale;\n const rect_width = (bounds.x_high - bounds.x_low) * pointScale;\n const rect_height = (bounds.y_high - bounds.y_low) * pointScale;\n capMeanToInterval(this.__data__.points.get(`mean-${group}`) as Point | undefined,\n rect_width / 2, rect_height / 2);\n let el = this._ciRects.get(group);\n if (!el) {\n el = document.createElementNS('http://www.w3.org/2000/svg', 'rect') as SVGRectElement;\n el.setAttribute('data-ci-group', group);\n this._ciRects.set(group, el);\n }\n el.setAttribute('x', rect_x.toString());\n el.setAttribute('y', rect_y.toString());\n el.setAttribute('width', rect_width.toString());\n el.setAttribute('height', rect_height.toString());\n el.setAttribute('fill', 'none');\n el.setAttribute('stroke', color);\n el.setAttribute('stroke-width', sw.toString());\n el.setAttribute('stroke-opacity', '0.8');\n el.setAttribute('stroke-dasharray', `${sw * 4} ${sw * 3}`);\n if (pointsLayerSvg && !el.parentElement) {\n pointsLayerSvg.insertBefore(el, pointsLayerSvg.firstChild);\n }\n });\n } else {\n // JS fallback: compute CI from accumulated variance\n Object.entries(groupSums).forEach(([group, { x, y, x2, y2, n, color }]) => {\n if (n < 2) return;\n const μx = x / n, μy = y / n;\n const rawVarX = x2 / n - μx * μx;\n const rawVarY = y2 / n - μy * μy;\n const { halfW, halfH } = computeCIRect(rawVarX, rawVarY, n, pointScale);\n const cx = μx * pointScale, cy = -(μy) * pointScale;\n capMeanToInterval(this.__data__.points.get(`mean-${group}`) as Point | undefined,\n halfW, halfH);\n let el = this._ciRects.get(group);\n if (!el) {\n el = document.createElementNS('http://www.w3.org/2000/svg', 'rect') as SVGRectElement;\n el.setAttribute('data-ci-group', group);\n this._ciRects.set(group, el);\n }\n el.setAttribute('x', (cx - halfW).toString());\n el.setAttribute('y', (cy - halfH).toString());\n el.setAttribute('width', (halfW * 2).toString());\n el.setAttribute('height', (halfH * 2).toString());\n el.setAttribute('fill', 'none');\n el.setAttribute('stroke', color);\n el.setAttribute('stroke-width', sw.toString());\n el.setAttribute('stroke-opacity', '0.8');\n el.setAttribute('stroke-dasharray', `${sw * 4} ${sw * 3}`);\n if (pointsLayerSvg && !el.parentElement) {\n pointsLayerSvg.insertBefore(el, pointsLayerSvg.firstChild);\n }\n });\n }\n }\n\n // ── Outlier boxes (deprecated model.outlier frame) ───────────────\n const showOutlier = true; // legacy frame; presence of model.outlier guards rendering\n if (showOutlier && model.outlier?.rows) {\n this._outlierRects.forEach((el, g) => {\n if (!groupColorMap[g]) { el.remove(); this._outlierRects.delete(g); }\n });\n model.outlier.rows().forEach((row: DataFrameRow) => {\n const groupIdx = row.names.indexOf(groupColName ?? 'group');\n const group = groupIdx >= 0 ? String(row[groupIdx]) : (row.rowName ?? null);\n if (!group) return;\n const color = groupColorMap[group] ?? '#888888';\n const bounds = readIntervalBounds(row, dims[0] as string, dims[1] as string);\n if (!bounds) return;\n const rect_x = bounds.x_low * pointScale;\n const rect_y = -bounds.y_high * pointScale;\n const rect_width = (bounds.x_high - bounds.x_low) * pointScale;\n const rect_height = (bounds.y_high - bounds.y_low) * pointScale;\n let el = this._outlierRects.get(group);\n if (!el) {\n el = document.createElementNS('http://www.w3.org/2000/svg', 'rect') as SVGRectElement;\n el.setAttribute('data-outlier-group', group);\n this._outlierRects.set(group, el);\n }\n el.setAttribute('x', rect_x.toString());\n el.setAttribute('y', rect_y.toString());\n el.setAttribute('width', rect_width.toString());\n el.setAttribute('height', rect_height.toString());\n el.setAttribute('fill', 'none');\n el.setAttribute('stroke', color);\n el.setAttribute('stroke-width', sw.toString());\n el.setAttribute('stroke-opacity', '0.5');\n el.setAttribute('stroke-dasharray', `${sw * 2} ${sw * 2}`);\n if (pointsLayerSvg && !el.parentElement) {\n pointsLayerSvg.insertBefore(el, pointsLayerSvg.firstChild);\n }\n });\n }\n } // end Path B\n } // end config.showMeans\n\n // ── Labels ──────────────────────────────────────────────────────────\n if (labelSvg) {\n // Remove labels for objects that no longer exist\n this._pointLabels.forEach((lbl, id) => {\n if (!pointsLayer.__data__.objects.get(id)) { lbl.remove(); this._pointLabels.delete(id); }\n });\n this._meanLabels.forEach((lbl, id) => {\n if (!pointsLayer.__data__.objects.get(`mean-${id}`)) { lbl.remove(); this._meanLabels.delete(id); }\n });\n\n // Unit point labels\n if (labelPoints !== 0) {\n model.points.rows().forEach((row: DataFrameRow) => {\n const qIdx = row.names.indexOf(unitIdCol);\n const unitId = qIdx >= 0 ? String(row[qIdx]) : null;\n if (!unitId) return;\n const pt = pointsLayer.__data__.objects.get(unitId) as Point | undefined;\n if (!pt) return;\n // Use the raw unit ID as the label text.\n // TODO: support a label-format attribute or callback so callers\n // can supply a custom display string (e.g. strip a prefix,\n // extract a sub-field from a compound ID, etc.)\n const displayText = unitId;\n let lbl = this._pointLabels.get(unitId);\n if (!lbl) {\n lbl = new QELabel(displayText, pt, labelSvg, this, labelPoints);\n this._pointLabels.set(unitId, lbl);\n } else {\n labelPoints === Label.DISPLAY_TYPES.ON ? lbl.show() : lbl.hide();\n }\n });\n }\n\n // Mean labels — use active groups frame rows if available, else groupSums keys\n if (labelMeans !== 0) {\n const meanGroupNames: string[] = hasGroupsFrame\n ? activeGroupRows.map((r: DataFrameRow) => r.rowName ?? String(r[0]))\n : Object.keys(groupSums);\n\n meanGroupNames.forEach((group: string) => {\n const meanId = `mean-${group}`;\n const pt = pointsLayer.__data__.objects.get(meanId) as Point | undefined;\n if (!pt) return;\n let lbl = this._meanLabels.get(group);\n if (!lbl) {\n lbl = new QELabel(group, pt, labelSvg, this, labelMeans);\n this._meanLabels.set(group, lbl);\n } else {\n labelMeans === Label.DISPLAY_TYPES.ON ? lbl.show() : lbl.hide();\n }\n });\n }\n }\n\n pointsLayer.__data__.__state__.setVariable('layer_updated', pointsLayer.__data__);\n }\n }\n\n // ── Cognitive Trajectories Layer ──────────────────────────────────────────\n const trajectoriesLayer = this.__children__.search('__children__', 'trajectories') as QELayer;\n const trajectoriesEnabled = config.showTrajectories;\n if (trajectoriesEnabled && trajectoriesLayer) {\n trajectoriesLayer.__data__.objects.clear();\n this.__data__.trajectories.clear();\n\n const trajSource = model.trajectories?.rows ? model.trajectories : model.points;\n if (trajSource?.rows) {\n const unitRows: Record<string, Array<{ x: number; y: number; time: number }>> = {};\n const selectedUnits = config.trajectoryUnits ? config.trajectoryUnits.split(',').map(s => s.trim()) : null;\n\n trajSource.rows().forEach((row: DataFrameRow) => {\n const uIdx = row.names.indexOf(unitIdCol) >= 0 ? row.names.indexOf(unitIdCol) : (row.names.indexOf('unit') >= 0 ? row.names.indexOf('unit') : (row.names.indexOf('ENA_UNIT') >= 0 ? row.names.indexOf('ENA_UNIT') : -1));\n const unit = uIdx >= 0 ? String(row[uIdx]) : (row.rowName || 'unit-1');\n\n if (selectedUnits && !selectedUnits.includes(unit)) return;\n\n const xIdx = row.names.indexOf(dims[0]);\n const yIdx = dims.length > 1 ? row.names.indexOf(dims[1]) : -1;\n const tIdx = row.names.indexOf('time') >= 0 ? row.names.indexOf('time') : (row.names.indexOf('ActivityNumber') >= 0 ? row.names.indexOf('ActivityNumber') : (row.names.indexOf('RowID') >= 0 ? row.names.indexOf('RowID') : -1));\n\n const time = tIdx >= 0 ? Number(row[tIdx]) : (unitRows[unit] ? unitRows[unit].length + 1 : 1);\n // Keep every row: the playhead is applied inside Trajectory via\n // currentTime so degree selection can run on the full trajectory\n // while only the visible prefix is fit and drawn.\n\n if (xIdx >= 0 && yIdx >= 0) {\n if (!unitRows[unit]) unitRows[unit] = [];\n unitRows[unit].push({\n x: Number(row[xIdx]) * pointScale,\n y: -Number(row[yIdx]) * pointScale,\n time\n });\n }\n });\n\n const unitKeys = Object.keys(unitRows);\n unitKeys.forEach((unitKey, uIdx) => {\n const rawPts = unitRows[unitKey];\n if (rawPts.length === 0) return;\n\n const colorStr = PALETTE[uIdx % PALETTE.length];\n\n const trajObj = new Trajectory({\n ID: `traj-${unitKey}`,\n unitId: unitKey,\n color: new Color(colorStr),\n lineStyle: config.trajectoryLineStyle,\n strokeWidth: config.trajectoryStrokeWidth,\n strokeWidthRange: config.trajectoryStrokeWidthRange,\n opacityRange: config.trajectoryOpacityRange,\n smooth: config.trajectorySmooth,\n maxDegree: config.trajectoryMaxDegree,\n degreeSelection: config.trajectoryDegreeSelection,\n currentTime: config.trajectoryPlayhead ?? Infinity,\n showPoints: config.trajectoryShowPoints,\n showTips: config.trajectoryShowTips,\n points: rawPts.map(p => ({ x: p.x, y: p.y, time: p.time }))\n });\n\n this.__data__.trajectories.set(unitKey, trajObj);\n trajectoriesLayer.__data__.objects.set(trajObj.ID, trajObj);\n });\n }\n trajectoriesLayer.__data__.__state__.setVariable('layer_updated', trajectoriesLayer.__data__);\n }\n\n // ── Mean network edges ───────────────────────────────────────────────────\n // For each group, compute the mean weight of every edge column across its\n // unit rows, then draw a Line for pairs whose mean weight is non-zero.\n const networkLayer = this.__children__.search('__children__', 'network') as QELayer;\n const edgeLayer = networkLayer?.__children__.search('__children__', 'edges') as QELayer;\n const nodeLayer = networkLayer?.__children__.search('__children__', 'nodes') as QELayer;\n // edgenodes sits above `nodes` in the layer tree — self-connections (NodeEdge)\n // must be drawn here so the dot is visible on top of the code node.\n const edgenodeLayer = networkLayer?.__children__.search('__children__', 'edgenodes') as QELayer;\n\n const edgesEnabled = config.showEdges;\n if (model.nodes?.rows && nodeLayer) {\n // ── Step 1: Populate node positions first ─────────────────────────────\n // Nodes are always placed so they anchor the coordinate space (extremes).\n // Sizes will be overwritten after edge weights are computed; when edges\n // are hidden the default size is used instead.\n model.nodes.rows().forEach((row: DataFrameRow) => {\n const pt = rowToPoint(row, nodeIdCol, '#444444');\n pt.size = 2; // default when no edge weights available\n // Display text: the nodes frame's optional `label` column\n // (qe_nodes(labels =)); the code id stays the node's identity.\n const li = row.names.indexOf('label');\n const lv = li >= 0 ? row[li] : null;\n (pt as any).meta = { ...((pt as any).meta ?? {}), kind: 'node',\n name: lv != null && String(lv) !== 'NA' && String(lv) !== '' ? String(lv) : pt.ID };\n nodeLayer.__data__.objects.set(pt.ID, pt);\n });\n\n if (edgesEnabled && edgeLayer && model.edges?.rows) {\n // ── Step 2: Build unit→group lookup from points data ─────────────────\n const unitGroupMap: Record<string, string> = {};\n if (groupColName && model.points?.rows) {\n model.points.rows().forEach((row: DataFrameRow) => {\n const qIdx = row.names.indexOf(unitIdCol);\n const gIdx = row.names.indexOf(groupColName!);\n if (qIdx >= 0 && gIdx >= 0) unitGroupMap[String(row[qIdx])] = String(row[gIdx]);\n });\n }\n\n // ── Step 3: Collect valid edge-column → code-pair mappings ───────────\n const codeNames: string[] = model.nodes.rows().map((r: DataFrameRow) => {\n const idx = r.names.indexOf(nodeIdCol);\n return idx >= 0 ? String(r[idx]) : '';\n }).filter(Boolean);\n\n const edgePairs: Array<{ col: string; pair: [string, string] }> = [];\n (model.edges.names ?? []).forEach((col: string) => {\n const pair = parseEdgePair(col, codeNames);\n if (pair) edgePairs.push({ col, pair });\n });\n\n // ── Step 4: Edge-weight helpers ───────────────────────────────────────\n type EdgeWeights = Record<string, number>;\n\n /** Raw weights for a single unit row. */\n const getUnitEdges = (unitId: string): EdgeWeights => {\n const result: EdgeWeights = {};\n model.edges.rows().forEach((row: DataFrameRow) => {\n const qIdx = row.names.indexOf(unitIdCol);\n if (qIdx < 0 || String(row[qIdx]) !== unitId) return;\n edgePairs.forEach(({ col }) => {\n const colIdx = row.names.indexOf(col);\n if (colIdx >= 0) result[col] = Number(row[colIdx]) || 0;\n });\n });\n return result;\n };\n\n /** Mean weights across all units in a group. */\n const getGroupEdges = (groupName: string): EdgeWeights => {\n const sums: EdgeWeights = {};\n let count = 0;\n model.edges.rows().forEach((row: DataFrameRow) => {\n const qIdx = row.names.indexOf(unitIdCol);\n const unitId = qIdx >= 0 ? String(row[qIdx]) : null;\n const gColIdx = groupColName ? row.names.indexOf(groupColName) : -1;\n const group = gColIdx >= 0 ? String(row[gColIdx]) : (unitId ? unitGroupMap[unitId] : null);\n if (group !== groupName) return;\n count++;\n edgePairs.forEach(({ col }) => {\n const colIdx = row.names.indexOf(col);\n if (colIdx >= 0) { const v = Number(row[colIdx]); if (!isNaN(v)) sums[col] = (sums[col] ?? 0) + v; }\n });\n });\n if (count === 0) return {};\n const result: EdgeWeights = {};\n edgePairs.forEach(({ col }) => { result[col] = (sums[col] ?? 0) / count; });\n return result;\n };\n\n /** Resolve an identifier to edge weights + color.\n * Checks group names first, then treats the value as a unit ID. */\n const resolve = (id: string): { weights: EdgeWeights; color: string; label: string } => {\n if (groupColorMap[id]) {\n return { weights: getGroupEdges(id), color: groupColorMap[id], label: id };\n }\n // Unit: color from its group, or neutral grey\n const groupOfUnit = unitGroupMap[id] ?? null;\n const color = groupOfUnit ? (groupColorMap[groupOfUnit] ?? '#888888') : '#888888';\n return { weights: getUnitEdges(id), color, label: id };\n };\n\n // ── Steps 5–6: Build the edges to draw, one <qe-edges> layer at a time ─\n //\n // Named layers (as before):\n // group=\"A\" — group mean\n // unit=\"u\" — one unit's network\n // group=\"A\" compare=\"B\" — subtraction A − B (sign → colour)\n // group=\"A\" also=\"B\" — two groups overlaid\n // Explicit layers (0.5):\n // network=\"n1\" — a row of model.networks (signed)\n // Per layer: colors=\"pos,neg\" overrides the palette; threshold=\"min,max\"\n // drops |w| < min and caps |w| > max (rENA semantics).\n // Each entry's weight is ≥ 0; the sign is carried by its colour.\n type DrawEdge = { col: string; pair: [string, string]; weight: number; color: string;\n layer: number; name?: string; group?: string; unit?: string };\n const drawEdges: DrawEdge[] = [];\n\n const networkRow = (name: string): EdgeWeights | null => {\n const frame = (model as any).networks;\n const row = frame?.rows?.().find((r: DataFrameRow) => r.rowName === name);\n if (!row) return null;\n const w: EdgeWeights = {};\n edgePairs.forEach(({ col }) => {\n const i = row.names.indexOf(col);\n if (i >= 0) { const v = Number(row[i]); if (Number.isFinite(v)) w[col] = v; }\n });\n return w;\n };\n const thresholded = (w: number, thr: [number, number] | null): number => {\n if (!thr) return w;\n const a = Math.abs(w);\n if (a < thr[0]) return 0;\n return a > thr[1] ? Math.sign(w) * thr[1] : w;\n };\n\n config.edgeLayers.forEach((L, li) => {\n const push = (col: string, pair: [string, string], w: number, color: string,\n meta: { name?: string; group?: string; unit?: string }) => {\n w = thresholded(w, L.threshold);\n if (Math.abs(w) < 1e-6) return;\n drawEdges.push({ col: `${li}:${col}`, pair, weight: Math.abs(w), color, layer: li, ...meta });\n };\n const signColors = (pos: string, neg: string): [string, string] => {\n if (!L.colors) return [pos, neg];\n return [L.colors[0], L.colors[1] ?? complementColor(L.colors[0])];\n };\n\n if (L.network) {\n // Explicit network: signed weights from model.networks.\n const w = networkRow(L.network);\n if (!w) return;\n const [pos, neg] = signColors(PALETTE[0], PALETTE[1]);\n const meta = { name: L.name ?? L.network };\n edgePairs.forEach(({ col, pair }) => {\n const v = w[col] ?? 0;\n push(col, pair, v, v >= 0 ? pos : neg, meta);\n });\n return;\n }\n\n // Named layer — unit overrides group; no default to the first group.\n const primaryId = L.unit ?? L.group ?? null;\n if (!primaryId) return;\n const primary = resolve(primaryId);\n const secondaryId = L.compare ?? L.also ?? null;\n const secondary = secondaryId ? resolve(secondaryId) : null;\n const meta = { name: L.name ?? primaryId, group: L.group ?? undefined, unit: L.unit ?? undefined };\n const [pos, neg] = signColors(primary.color, secondary?.color ?? primary.color);\n\n if (secondary && L.compare) {\n // A − B: positive → primary colour, negative → secondary colour\n edgePairs.forEach(({ col, pair }) => {\n const d = (primary.weights[col] ?? 0) - (secondary.weights[col] ?? 0);\n push(col, pair, d, d > 0 ? pos : neg, meta);\n });\n } else if (secondary && L.also) {\n // Overlay: both networks, each in its own colour\n edgePairs.forEach(({ col, pair }) => {\n const wA = primary.weights[col] ?? 0, wB = secondary.weights[col] ?? 0;\n if (wA > 0) push(col + '-a', pair, wA, pos, meta);\n if (wB > 0) push(col + '-b', pair, wB, neg, { ...meta, name: L.also ?? undefined, group: L.also ?? undefined });\n });\n } else {\n edgePairs.forEach(({ col, pair }) => {\n const w = primary.weights[col] ?? 0;\n if (w > 0) push(col, pair, w, pos, meta);\n });\n }\n });\n\n // Thin edges on top (rENA's thin.lines.in.front): later objects draw\n // over earlier ones, so add the heaviest first.\n drawEdges.sort((a, b) => b.weight - a.weight);\n\n // ── Step 7: Mark sizes and colour ────────────────────────────────────\n // Width is absolute (webENA): raw weight × one width-per-weight set by\n // <qe-graph edge-width>, shared by edges, directed wide ends,\n // self-connection dots and nodes (diameter = Σ edge widths).\n const isDirected = !!(model as any).directed;\n // <qe-edges magnify> scales this plot's widths and node sizes (not\n // colour) — e.g. to read a faint subtraction — and is always\n // labelled \"(scaled Nx)\" so it is never mistaken for the shared scale.\n const widthFrac = widthPerWeight(config.edgeWidth) * (config.edgeMagnify ?? 1);\n\n // Colour (webENA ramps): each class (lines vs self-loops) rescales\n // |weight| from [min, max] onto saturation 0.25–1 / opacity 0.3–1.\n // The range comes from the whole model — every non-zero weight in\n // the edges frame — so plots of one model share a colour scale;\n // webENA takes it from each plotted network (\"plot\").\n const rangeOf = (ws: number[]): [number, number] => {\n const nz = ws.map(Math.abs).filter(v => v > 0);\n return nz.length ? [Math.min(...nz), Math.max(...nz)] : [0, 0];\n };\n const modelRange = (self: boolean): [number, number] => {\n const vals: number[] = [];\n edgePairs.forEach(({ col, pair }) => {\n if ((pair[0] === pair[1]) !== self) return;\n const column = model.edges.col(col);\n if (column) for (const v of column) vals.push(Number(v));\n });\n return rangeOf(vals);\n };\n const plotRange = (self: boolean): [number, number] =>\n rangeOf(drawEdges.filter(e => (e.pair[0] === e.pair[1]) === self).map(e => e.weight));\n const cscale = config.edgeColorScale;\n const colourRange = (self: boolean): [number, number] =>\n cscale === 'plot' ? plotRange(self) : modelRange(self);\n const lineRange = colourRange(false), selfRange = colourRange(true);\n const colourOf = (w: number, self: boolean) => {\n if (cscale === 'absolute') { const a = Math.min(1, Math.abs(w)); return { saturation: a, opacity: a }; }\n const [lo, hi] = self ? selfRange : lineRange;\n return { saturation: rampFor(w, lo, hi, SATURATION_RANGE), opacity: rampFor(w, lo, hi, OPACITY_RANGE) };\n };\n\n // Weight accumulated at each node:\n // Undirected: every edge touching the node (both endpoints).\n // Directed: only edges directed *at* the node (pair[1] is the\n // target; its wide end is drawn there), including the\n // node's self-connection.\n const nodeWeightSum: Record<string, number> = {};\n drawEdges.forEach(({ pair, weight }) => {\n const isSelf = pair[0] === pair[1];\n if (isSelf && !isDirected) return; // skip illegal undirected diagonals\n const add = (id: string) => { nodeWeightSum[id] = (nodeWeightSum[id] ?? 0) + Math.abs(weight); };\n if (isDirected) { add(pair[1]); return; }\n add(pair[0]); add(pair[1]);\n });\n\n // Node sizes: diameter = Σ widths of the edges counted above. Nodes\n // with nothing counted get a tiny dot, or are hidden with\n // <qe-nodes unconnected=\"hide\">.\n model.nodes.rows().forEach((row: DataFrameRow) => {\n const codeIdx = row.names.indexOf(nodeIdCol);\n const id = codeIdx >= 0 ? String(row[codeIdx]) : '';\n if (!id) return;\n const pt = nodeLayer.__data__.objects.get(id) as Point | undefined;\n if (!pt) return;\n const w = nodeWeightSum[id] ?? 0;\n const unconnected = !(w > 0);\n pt.size = unconnected ? (config.hideUnconnectedNodes ? 0 : UNCONNECTED_NODE_SIZE)\n : nodeSizeForEdges(w, widthFrac);\n (pt as any).meta = { ...((pt as any).meta ?? {}),\n hidden: unconnected && config.hideUnconnectedNodes };\n });\n\n // ── Step 8: Create edge objects ───────────────────────────────────────\n // For directed models, TaperedWeightedMidpointEdge needs the combined\n // weight of both directions (A→B + B→A) so the apex can be positioned\n // proportionally along the edge. Build a lookup keyed by \"A.B\" per\n // drawn network: an `also` overlay draws two networks in one layer,\n // and pooling them left every triangle short of its counterpart.\n const totalWeightByPair: Record<string, number> = {};\n const pairKey = (layer: number, net: string | undefined, a: string, b: string) =>\n `${layer}:${net ?? ''}:${a}.${b}`;\n if (isDirected) {\n drawEdges.forEach(({ pair, weight, layer, name }) => {\n const key = pairKey(layer, name, pair[0], pair[1]);\n totalWeightByPair[key] = (totalWeightByPair[key] ?? 0) + weight;\n });\n }\n\n drawEdges.forEach(({ col, pair, weight, color, layer, name, group, unit }) => {\n const fromNode = nodeLayer.__data__.objects.get(pair[0]);\n const toNode = nodeLayer.__data__.objects.get(pair[1]);\n if (!fromNode || !toNode) return;\n\n const isSelf = pair[0] === pair[1];\n if (isSelf && !isDirected) return; // undirected ENA has zero diagonal\n\n // Colour ramps rescale within each visual class (lines vs\n // self-loops), since self-weights are typically smaller.\n const { saturation, opacity } = colourOf(weight, isSelf);\n const fromPt = new Point({ ID: `${pair[0]}-src`, dimensions: [fromNode.x, fromNode.y], meta: {} });\n const toPt = new Point({ ID: `${pair[1]}-dst`, dimensions: [toNode.x, toNode.y], meta: {} });\n // Pick the edge class by topology:\n // • self-connection (A→A) → NodeEdge (filled circle at the node)\n // • directed (A→B) → TaperedWeightedMidpointEdge (triangle\n // whose apex is placed proportionally\n // to weight(A→B) / (weight(A→B) + weight(B→A)))\n // • undirected → Line (straight stroke)\n let edgeLine: Line;\n if (isSelf) {\n edgeLine = new NodeEdge({}, fromPt as any, toPt as any);\n // Actual display size is deferred to QELine.update() so it uses\n // the live extremes.x_max (which is not yet computed here).\n // Set a placeholder weight; update() will overwrite it.\n (edgeLine as any).weight = 0;\n } else if (isDirected) {\n const fwd = totalWeightByPair[pairKey(layer, name, pair[0], pair[1])] ?? weight;\n const bwd = totalWeightByPair[pairKey(layer, name, pair[1], pair[0])] ?? 0;\n const totalweight = fwd + bwd;\n edgeLine = new TaperedWeightedMidpointEdge(\n { weight, totalweight },\n fromPt as any,\n toPt as any\n );\n } else {\n edgeLine = new Line({}, fromPt, toPt);\n }\n edgeLine.ID = `edge-${col}`;\n edgeLine.color = new Color(color);\n (edgeLine as any).meta = {\n isMeanEdge: true,\n weight,\n // Width per unit weight (extent units), shared by all marks.\n widthFrac,\n saturation,\n opacity,\n isDirected,\n isSelf,\n // Identity for the qe-edge-* interaction events.\n source: pair[0],\n target: pair[1],\n group,\n unit,\n layer: name,\n };\n // Self-connections go in the `edgenodes` layer (above `nodes` in\n // draw order) so the dot is visible on top of the code node.\n const targetLayer = isSelf ? (edgenodeLayer ?? edgeLayer) : edgeLayer;\n targetLayer.__data__.objects.set(edgeLine.ID, edgeLine);\n });\n\n edgeLayer.__data__.__state__.setVariable('layer_updated', edgeLayer.__data__);\n if (edgenodeLayer) edgenodeLayer.__data__.__state__.setVariable('layer_updated', edgenodeLayer.__data__);\n }\n\n // ── Node visibility ──────────────────────────────────────────────────\n // Node positions come from the model and stay in the layer either way,\n // so they keep anchoring the extent (the plot does not rescale when\n // nodes are toggled); <qe-nodes> presence only controls the drawing,\n // as <qe-axes> does for the axis sub-tree.\n const nodesVisible = config.showNodes;\n if (nodeLayer.svg_element) {\n (nodeLayer.svg_element as SVGElement).style.display = nodesVisible ? '' : 'none';\n }\n if (!nodesVisible) {\n this._nodeLabels.forEach(lbl => lbl.remove());\n this._nodeLabels.clear();\n }\n\n // ── Node labels ──────────────────────────────────────────────────────\n if (labelSvg && labelNodes !== 0 && nodesVisible) {\n // Clean up stale node labels\n this._nodeLabels.forEach((lbl, id) => {\n if (!nodeLayer.__data__.objects.get(id)) { lbl.remove(); this._nodeLabels.delete(id); }\n });\n model.nodes.rows().forEach((row: DataFrameRow) => {\n const codeIdx = row.names.indexOf(nodeIdCol);\n const id = codeIdx >= 0 ? String(row[codeIdx]) : '';\n if (!id) return;\n const pt = nodeLayer.__data__.objects.get(id) as Point | undefined;\n if (!pt) return;\n if ((pt as any).meta?.hidden) {\n this._nodeLabels.get(id)?.remove();\n this._nodeLabels.delete(id);\n return;\n }\n const text = String((pt as any).meta?.name ?? id);\n let lbl = this._nodeLabels.get(id);\n if (lbl && lbl.text !== text) { lbl.remove(); this._nodeLabels.delete(id); lbl = undefined; }\n if (!lbl) {\n lbl = new QELabel(text, pt, labelSvg, this, labelNodes);\n this._nodeLabels.set(id, lbl);\n } else {\n labelNodes === Label.DISPLAY_TYPES.ON ? lbl.show() : lbl.hide();\n }\n });\n }\n\n // Fire after both positions and sizes are set\n nodeLayer.__data__.__state__.setVariable('layer_updated', nodeLayer.__data__);\n }\n\n // ── Axis lines / points ──────────────────────────────────────────────────\n const axisPointsLayer = this.__children__.search('__children__', 'axis_points');\n const axisLinesLayer = this.__children__.search('__children__', 'axis_lines');\n if (axisPointsLayer) this.__data__.__state__.setVariable('graph_updated_axis_points', axisPointsLayer.__data__.objects);\n if (axisLinesLayer) this.__data__.__state__.setVariable('graph_updated_axis_lines', axisLinesLayer.__data__.objects);\n\n this.update();\n\n // Animate marks/edges from their pre-rebuild positions to the new ones.\n if (tweenFrom) this._runTween(tweenFrom);\n });\n }\n\n // ── Shared re-render scheduler ───────────────────────────────────────────────\n // Batches synchronous attribute / child-list changes into a single microtask\n // so that e.g. adding <qe-edges> and setting its attributes in the same tick\n // only triggers one render cycle.\n private _scheduleRerender(): void {\n if (!this._vizena || !this._hasModel) return;\n if (this._renderPending) return;\n this._renderPending = true;\n queueMicrotask(() => {\n this._renderPending = false;\n this._vizena?.dispatchEvent(new CustomEvent('model-updated', {\n detail: this._vizena.model,\n bubbles: true,\n composed: true,\n }));\n });\n }\n\n // ── Layer configuration reader ────────────────────────────────────────────────\n // Reads child element presence / attributes to determine what each layer\n // should render. Called once at the top of every model-updated handler so\n // all rendering decisions are derived from a single snapshot.\n private _readLayerConfig(): {\n // Nodes\n labelNodes: number;\n showNodes: boolean;\n edgeWidth: number;\n range: 'network' | 'points' | number | null;\n centerContent: boolean;\n plotTitle: string | null;\n labelFont: { size: number | null; family: string | null; color: string | null };\n hideUnconnectedNodes: boolean;\n scalePoints: boolean;\n pointScale: number | null;\n // Means\n showMeans: boolean;\n activeMeanGroups: string | null;\n showCI: boolean;\n intervals: 'box' | 'crosshairs' | 'none';\n showOutlier: boolean;\n labelMeans: number;\n meanFixedSize: boolean;\n // Points\n showPoints: boolean;\n pointSets: Array<{ set: string; size: number | null; fixedSize: boolean }>;\n labelPoints: number;\n pointSize: number | null;\n pointFixedSize: boolean;\n // Edges\n showEdges: boolean;\n edgeLayers: EdgeLayerSpec[];\n edgeColorScale: ColorScale;\n edgeMagnify: number | null;\n\n showTrajectories: boolean;\n trajectoryUnits: string | null;\n trajectorySmooth: 'none' | 'poly';\n trajectoryMaxDegree: number;\n trajectoryDegreeSelection: 'loocv_2d' | 'fixed';\n trajectoryShowPoints: boolean;\n trajectoryShowTips: boolean;\n trajectoryPlayhead: number | null;\n trajectoryLineStyle: 'uniform' | 'tapered';\n trajectoryStrokeWidth: number;\n trajectoryStrokeWidthRange: [number, number];\n trajectoryOpacityRange: [number, number];\n // Axes\n showAxes: boolean;\n axisXLabel: string | null;\n axisYLabel: string | null;\n } {\n const nodesEl = this.querySelector('qe-nodes');\n const meansEl = this.querySelector('qe-means');\n // <qe-points> without `set` = all unit points; with `set` = an explicit set.\n const allPointsEls = [...this.querySelectorAll('qe-points')];\n const pointsEl = allPointsEls.find(e => !e.hasAttribute('set')) ?? null;\n const setEls = allPointsEls.filter(e => e.hasAttribute('set'));\n // Every <qe-edges> child is one layer (0.5): a named network (group / unit\n // / compare / also) or an explicit one (network=\"name\" → model.networks).\n const edgeEls = [...this.querySelectorAll('qe-edges')];\n const firstAttr = (a: string) => edgeEls.find(e => e.hasAttribute(a))?.getAttribute(a) ?? null;\n const magnifyEl = edgeEls.find(e => e.hasAttribute('magnify'));\n const trajectoriesEl = this.querySelector('qe-trajectories');\n const axesEl = this.querySelector('qe-axes');\n const labelsShorthand = this.getAttribute('labels');\n\n return {\n // Nodes — always placed from the model (they anchor the coordinate\n // space); <qe-nodes> presence draws them, like every other layer.\n labelNodes: parseLabelMode(\n nodesEl?.getAttribute('label') ?? this.getAttribute('label-nodes') ?? labelsShorthand,\n Label.DISPLAY_TYPES.ON\n ),\n showNodes: !!nodesEl,\n range: (() => {\n const v = this.getAttribute('range');\n if (v === 'network' || v === 'points') return v;\n const n = Number(v);\n return v != null && Number.isFinite(n) && n > 0 ? n : null;\n })(),\n plotTitle: this.getAttribute('plot-title') || null,\n labelFont: {\n size: (() => { const n = Number(this.getAttribute('label-font-size'));\n return Number.isFinite(n) && n > 0 ? n : null; })(),\n family: this.getAttribute('label-font-family') || null,\n color: this.getAttribute('label-font-color') || null,\n },\n edgeWidth: (() => {\n const v = Number(this.getAttribute('edge-width'));\n return Number.isFinite(v) && v > 0 && v <= 1 ? v : DEFAULT_EDGE_WIDTH;\n })(),\n hideUnconnectedNodes: nodesEl?.getAttribute('unconnected')?.toLowerCase() === 'hide',\n scalePoints: this.getAttribute('scale-points') !== 'false',\n pointScale: (() => {\n const v = Number(this.getAttribute('point-scale'));\n return this.hasAttribute('point-scale') && Number.isFinite(v) && v > 0 ? v : null;\n })(),\n centerContent: this.getAttribute('center') === 'content',\n\n // Means — presence of <qe-means> = show; absence = hide.\n showMeans: !!meansEl,\n activeMeanGroups: meansEl?.getAttribute('groups') ?? null,\n showCI: !!meansEl && meansEl.hasAttribute('confidence'),\n // intervals=\"box|crosshairs|none\"; absent → the legacy `confidence` flag.\n intervals: (() => {\n const v = meansEl?.getAttribute('intervals');\n if (v === 'box' || v === 'crosshairs' || v === 'none') return v;\n return meansEl?.hasAttribute('confidence') ? 'box' : 'none';\n })() as 'box' | 'crosshairs' | 'none',\n showOutlier: !!meansEl && meansEl.hasAttribute('outlier'),\n labelMeans: parseLabelMode(\n meansEl?.getAttribute('label') ?? this.getAttribute('label-means') ?? labelsShorthand,\n Label.DISPLAY_TYPES.ON\n ),\n // fixed-size keeps mean markers a constant on-screen px size (webENA parity).\n meanFixedSize: !!meansEl && meansEl.hasAttribute('fixed-size'),\n\n // Points — presence of <qe-points> = show unit dots.\n showPoints: !!pointsEl,\n pointSets: setEls.map(e => ({\n set: e.getAttribute('set')!,\n size: e.getAttribute('size') ? parseFloat(e.getAttribute('size')!) : null,\n fixedSize: e.hasAttribute('fixed-size'),\n })),\n labelPoints: parseLabelMode(\n pointsEl?.getAttribute('label') ?? this.getAttribute('label-points') ?? labelsShorthand,\n Label.DISPLAY_TYPES.OFF\n ),\n pointSize: pointsEl?.getAttribute('size') ? parseFloat(pointsEl.getAttribute('size')!) : null,\n // fixed-size keeps unit dots a constant on-screen px size (webENA parity).\n pointFixedSize: !!pointsEl && pointsEl.hasAttribute('fixed-size'),\n\n // Edges — presence of <qe-edges> = draw a network.\n showEdges: edgeEls.length > 0,\n edgeLayers: edgeEls.map(parseEdgeLayer),\n // Plot-wide edge settings: the first <qe-edges> that sets them.\n edgeColorScale: parseColorScale(firstAttr('color-scale')),\n edgeMagnify: magnifyEl ? (() => {\n const v = Number(magnifyEl.getAttribute('magnify'));\n return Number.isFinite(v) && v > 0 ? v : 1;\n })() : null,\n\n // Trajectories — presence of <qe-trajectories> = draw cognitive trajectories\n showTrajectories: !!trajectoriesEl,\n trajectoryUnits: trajectoriesEl?.getAttribute('units') ?? null,\n trajectorySmooth: (trajectoriesEl?.getAttribute('smooth') as 'none' | 'poly') ?? 'none',\n trajectoryMaxDegree: trajectoriesEl?.getAttribute('max-degree') ? parseInt(trajectoriesEl.getAttribute('max-degree')!, 10) : 3,\n trajectoryDegreeSelection: (trajectoriesEl?.getAttribute('degree-selection') as 'loocv_2d' | 'fixed') ?? 'loocv_2d',\n trajectoryShowPoints: trajectoriesEl?.getAttribute('points') !== 'false',\n trajectoryShowTips: trajectoriesEl?.getAttribute('tips') !== 'false',\n trajectoryPlayhead: trajectoriesEl?.getAttribute('playhead') ? parseFloat(trajectoriesEl.getAttribute('playhead')!) : null,\n trajectoryLineStyle: (trajectoriesEl?.getAttribute('line-style') as 'uniform' | 'tapered') ?? 'uniform',\n trajectoryStrokeWidth: trajectoriesEl?.getAttribute('stroke-width') ? parseFloat(trajectoriesEl.getAttribute('stroke-width')!) : 2,\n trajectoryStrokeWidthRange: this._parseNumberPair(trajectoriesEl?.getAttribute('stroke-width-range'), [1, 6]),\n trajectoryOpacityRange: this._parseNumberPair(trajectoriesEl?.getAttribute('opacity-range'), [0.3, 1]),\n\n // Axes — presence of <qe-axes> = draw axis lines. The x / y attributes add\n // a per-axis label: a value is used verbatim, an empty attribute falls back\n // to the dimension name (resolved later, where dims are known). null = no\n // label for that axis.\n showAxes: !!axesEl,\n axisXLabel: axesEl?.hasAttribute('x') ? (axesEl.getAttribute('x') ?? '') : null,\n axisYLabel: axesEl?.hasAttribute('y') ? (axesEl.getAttribute('y') ?? '') : null,\n };\n }\n\n private _parseNumberPair(value: string | null | undefined, fallback: [number, number]): [number, number] {\n if (!value) return fallback;\n const parts = value.split(',').map(part => Number(part.trim()));\n if (parts.length < 2 || !parts.every(Number.isFinite)) return fallback;\n return [parts[0], parts[1]];\n }\n\n attributeChangedCallback(_name: string, oldValue: string | null, newValue: string | null): void {\n if (oldValue === newValue) return;\n this._scheduleRerender();\n }\n\n connectedCallback(): void {\n // Apply width/height HTML attributes as CSS dimensions on the host element\n // so the shadow-DOM wrapper's height:100% resolves to a real pixel value.\n const w = this.getAttribute('width');\n const h = this.getAttribute('height');\n this.style.display = 'block'; // custom elements are inline by default\n if (w) this.style.width = isNaN(Number(w)) ? w : `${w}px`;\n if (h) this.style.height = isNaN(Number(h)) ? h : `${h}px`;\n\n this.appendChild(this.svg_element);\n QEGraphElement._instances.add(this); // registry for getGraph()/instances()\n\n // Watch for child layer element additions/removals and attribute changes.\n // Any mutation schedules a re-render via the same microtask batch used by\n // attributeChangedCallback, so synchronous DOM mutations collapse to one pass.\n this._childObserver = new MutationObserver(() => this._scheduleRerender());\n this._childObserver.observe(this, {\n childList: true,\n attributes: true,\n subtree: true,\n attributeFilter: [\n 'group', 'unit', 'compare', 'also', 'color-scale', 'magnify',\n 'network', 'colors', 'threshold', 'name',\n 'groups', 'confidence', 'label', 'intervals', 'outlier', 'set', 'unconnected',\n 'scale-points', 'point-scale', 'edge-width', 'labels', 'range', 'center', 'plot-title',\n 'label-font-size', 'label-font-family', 'label-font-color', 'label-nodes', 'label-means', 'label-points',\n 'units', 'smooth', 'degree', 'points', 'tips', 'playhead',\n 'line-style', 'stroke-width', 'stroke-width-range', 'opacity-range',\n 'x', 'y', 'size', 'fixed-size',\n ],\n });\n // Find the associated ena-visual: check 'for' attribute first, then nearest\n // ancestor, then first one on the page. This lets ena-graph work as a child,\n // a sibling, or anywhere else in the document.\n const forId = this.getAttribute('for');\n this._vizena = (\n (forId ? document.getElementById(forId) : null) ??\n this.closest('qe-visual') ??\n this.parentElement?.closest('qe-visual') ??\n document.querySelector('qe-visual')\n ) as QEVisualElement;\n this.draw();\n\n // Cache the labels <g> after draw() has connected all layer elements to\n // the SVG DOM. We do this once here rather than searching on every\n // model-updated event to guarantee we always have a valid reference.\n const labelsLayer = this.__children__.search('__children__', 'labels') as QELayer;\n if (labelsLayer?.svg_element) {\n this._labelsGroup = labelsLayer.svg_element as SVGGElement;\n } else {\n // Fallback: create a new <g> directly inside the outermost graph layer.\n console.warn('[ena-graph] labels layer not found in layer tree; creating fallback <g>');\n const graphLayer = this.__children__[0] as QELayer;\n if (graphLayer?.svg_element) {\n this._labelsGroup = document.createElementNS('http://www.w3.org/2000/svg', 'g') as SVGGElement;\n this._labelsGroup.setAttribute('data-layer-name', 'labels-fallback');\n graphLayer.svg_element.appendChild(this._labelsGroup);\n }\n }\n }\n\n disconnectedCallback(): void {\n this._childObserver?.disconnect();\n this._childObserver = null;\n this._resizeObs?.disconnect();\n this._resizeObs = null;\n QEGraphElement._instances.delete(this);\n // Remove the body-level tooltip node so it doesn't outlive the graph.\n this._tooltipEl?.remove();\n this._tooltipEl = null;\n }\n\n // ── Instance registry + read APIs (webENA integration) ──────────────────────\n private static _instances: Set<QEGraphElement> = new Set();\n\n /** All connected <qe-graph> instances (newest membership order). */\n static instances(): QEGraphElement[] { return [...QEGraphElement._instances]; }\n\n /** Look up a graph by its `id` or `plot-group` attribute. */\n static getGraph(key: string): QEGraphElement | null {\n for (const g of QEGraphElement._instances) {\n if (g.id === key || g.getAttribute('plot-group') === key) return g;\n }\n return null;\n }\n\n /** Resolved code nodes with their current graph-space coordinates. */\n getNodes(): Array<{ id: string; name: string; x: number; y: number }> {\n const layer = this.__children__.search('__children__', 'nodes') as QELayer | undefined;\n if (!layer) return [];\n return [...layer.__data__.objects.values()].map((o: any) => ({\n id: o.ID, name: o.meta?.name ?? o.ID, x: o.x, y: o.y,\n }));\n }\n\n /** Resolved edges of the current network with weights and direction. */\n getEdges(): Array<{ source: string; target: string; weight: number; directed: boolean; self: boolean }> {\n const collect = (name: string) => {\n const l = this.__children__.search('__children__', name) as QELayer | undefined;\n return l ? [...l.__data__.objects.values()] : [];\n };\n return [...collect('edges'), ...collect('edgenodes')]\n .map((o: any) => {\n const m = o.meta ?? {};\n return { source: m.source, target: m.target, weight: m.weight ?? 0,\n directed: !!m.isDirected, self: !!m.isSelf };\n })\n .filter(e => e.source != null && e.target != null);\n }\n\n // ── Transition tweening (opt-in via the `animate` attribute; webENA P2.1) ───\n private _animateMs = 0;\n private _tweenRaf: number | null = null;\n\n /** Matches every numeric token in an SVG path `d` string (ints, decimals,\n * scientific notation, leading sign) while leaving command letters intact. */\n private static _PATH_NUM_RE = /-?\\d*\\.?\\d+(?:e[-+]?\\d+)?/gi;\n\n /** Marks (circles/rects), undirected edge lines, and directed / self-edge\n * triangle paths all participate in tweening. */\n private _tweenTargets(): SVGElement[] {\n return [...this.svg_element.querySelectorAll(\n 'circle[data-point-id], rect[data-point-id], line[data-edge-source], path[data-edge-source]'\n )] as SVGElement[];\n }\n\n private _readCoords(el: SVGElement): any {\n const tag = el.tagName.toLowerCase();\n const n = (a: string) => parseFloat(el.getAttribute(a) || '0');\n if (tag === 'circle') return { t: 'c', cx: n('cx'), cy: n('cy') };\n if (tag === 'rect') return { t: 'r', x: n('x'), y: n('y') };\n if (tag === 'line') return { t: 'l', x1: n('x1'), y1: n('y1'), x2: n('x2'), y2: n('y2') };\n if (tag === 'path') {\n const d = el.getAttribute('d') || '';\n return { t: 'p', d, nums: (d.match(QEGraphElement._PATH_NUM_RE) || []).map(Number) };\n }\n return null;\n }\n\n /** Snapshot current tween-target positions keyed by element. */\n private _captureTween(): Map<SVGElement, any> {\n const m = new Map<SVGElement, any>();\n this._tweenTargets().forEach(el => { const c = this._readCoords(el); if (c) m.set(el, c); });\n return m;\n }\n\n /** Animate each still-present element from its snapshot to its new position. */\n private _runTween(from: Map<SVGElement, any>): void {\n if (this._tweenRaf !== null) { cancelAnimationFrame(this._tweenRaf); this._tweenRaf = null; }\n const to = new Map<SVGElement, any>();\n this._tweenTargets().forEach(el => { if (from.has(el)) { const c = this._readCoords(el); if (c) to.set(el, c); } });\n if (!to.size) return;\n\n const dur = this._animateMs;\n const t0 = performance.now();\n const ease = (t: number) => (t < 0.5 ? 2 * t * t : 1 - Math.pow(-2 * t + 2, 2) / 2);\n const lerp = (a: number, b: number, k: number) => a + (b - a) * k;\n\n const step = (now: number) => {\n const t = Math.min(1, (now - t0) / dur);\n const k = ease(t);\n to.forEach((nc, el) => {\n const oc = from.get(el);\n if (!oc || oc.t !== nc.t) return;\n if (nc.t === 'c') {\n el.setAttribute('cx', String(lerp(oc.cx, nc.cx, k)));\n el.setAttribute('cy', String(lerp(oc.cy, nc.cy, k)));\n } else if (nc.t === 'r') {\n el.setAttribute('x', String(lerp(oc.x, nc.x, k)));\n el.setAttribute('y', String(lerp(oc.y, nc.y, k)));\n } else if (nc.t === 'l') {\n el.setAttribute('x1', String(lerp(oc.x1, nc.x1, k)));\n el.setAttribute('y1', String(lerp(oc.y1, nc.y1, k)));\n el.setAttribute('x2', String(lerp(oc.x2, nc.x2, k)));\n el.setAttribute('y2', String(lerp(oc.y2, nc.y2, k)));\n } else {\n // Directed / self-edge triangle path: interpolate the numeric tokens\n // in `d` when the command structure is stable (equal token count).\n // Otherwise leave the freshly-built `d` in place (graceful snap).\n if (!oc.nums || oc.nums.length !== nc.nums.length) return;\n let i = 0;\n const d = nc.d.replace(QEGraphElement._PATH_NUM_RE,\n () => String(lerp(oc.nums[i], nc.nums[i++], k)));\n el.setAttribute('d', d);\n }\n });\n this._tweenRaf = t < 1 ? requestAnimationFrame(step) : null;\n };\n this._tweenRaf = requestAnimationFrame(step);\n }\n\n /** Serialize the current plot as a standalone SVG string (webENA P2.3). */\n toSVG(): string {\n const svg = this.svg_element.cloneNode(true) as SVGSVGElement;\n svg.setAttribute('xmlns', 'http://www.w3.org/2000/svg');\n svg.setAttribute('xmlns:xlink', 'http://www.w3.org/1999/xlink');\n const rect = this.svg_element.getBoundingClientRect();\n if (rect.width) svg.setAttribute('width', String(Math.round(rect.width)));\n if (rect.height) svg.setAttribute('height', String(Math.round(rect.height)));\n return new XMLSerializer().serializeToString(svg);\n }\n\n /** Rasterize the current plot to a PNG data URL (webENA P2.3). `scale`\n * multiplies the pixel dimensions for a higher-resolution image. */\n toPNG(scale = 2): Promise<string> {\n const svgStr = this.toSVG();\n const rect = this.svg_element.getBoundingClientRect();\n const w = Math.max(1, Math.round(rect.width));\n const h = Math.max(1, Math.round(rect.height));\n return new Promise((resolve, reject) => {\n const blob = new Blob([svgStr], { type: 'image/svg+xml;charset=utf-8' });\n const url = URL.createObjectURL(blob);\n const img = new Image();\n img.onload = () => {\n try {\n const canvas = document.createElement('canvas');\n canvas.width = w * scale;\n canvas.height = h * scale;\n const ctx = canvas.getContext('2d');\n if (!ctx) { URL.revokeObjectURL(url); reject(new Error('no 2d context')); return; }\n ctx.scale(scale, scale);\n ctx.drawImage(img, 0, 0, w, h);\n URL.revokeObjectURL(url);\n resolve(canvas.toDataURL('image/png'));\n } catch (err) { URL.revokeObjectURL(url); reject(err); }\n };\n img.onerror = (e) => { URL.revokeObjectURL(url); reject(e); };\n img.src = url;\n });\n }\n\n /** Unit points with their current graph-space coordinates. */\n getPoints(): Array<{ id: string; group?: string; set?: string; x: number; y: number }> {\n const layer = this.__children__.search('__children__', 'points') as QELayer | undefined;\n if (!layer) return [];\n return [...layer.__data__.objects.values()]\n .filter((o: any) => o.meta?.kind === 'point')\n .map((o: any) => ({ id: o.meta?.unit ?? o.ID, group: o.meta?.group, set: o.meta?.set,\n x: o.x, y: o.y }));\n }\n\n /** Ids of unit points inside a graph-space rectangle (for drag/lasso select). */\n pointsInRect(rect: { x: number; y: number; w: number; h: number }): string[] {\n return this.getPoints()\n .filter(p => p.x >= rect.x && p.x <= rect.x + rect.w &&\n p.y >= rect.y && p.y <= rect.y + rect.h)\n .map(p => p.id);\n }\n\n // ── Host-driven highlight / selection (webENA P1.1) ─────────────────────────\n // Rendered as an overlay group so it never mutates the marks themselves, and\n // is re-applied after every render so selection survives model updates.\n private _highlight: { edges: Set<string>; nodes: Set<string> } = { edges: new Set(), nodes: new Set() };\n private _highlightGroup: SVGGElement | null = null;\n\n /** Order-independent key so an undirected pair matches either direction. */\n private _edgeKey(a: string, b: string): string {\n return a <= b ? `${a}\u0000${b}` : `${b}\u0000${a}`;\n }\n\n /** Mark edges/nodes as highlighted. Replaces the previous selection. */\n setHighlight(sel: { edges?: Array<{ source: string; target: string }>; nodes?: Array<string> }): void {\n this._highlight.edges = new Set((sel.edges ?? []).map(e => this._edgeKey(e.source, e.target)));\n this._highlight.nodes = new Set((sel.nodes ?? []).map(String));\n this._applyHighlights();\n }\n\n /** Clear all highlighting. */\n clearHighlight(): void {\n this._highlight.edges.clear();\n this._highlight.nodes.clear();\n this._applyHighlights();\n }\n\n private _applyHighlights(): void {\n if (!this.svg_element) return;\n if (!this._highlightGroup) {\n this._highlightGroup = document.createElementNS('http://www.w3.org/2000/svg', 'g') as SVGGElement;\n this._highlightGroup.setAttribute('data-layer-name', 'highlight');\n this._highlightGroup.setAttribute('pointer-events', 'none');\n }\n // Keep the overlay on top.\n this.svg_element.appendChild(this._highlightGroup);\n const g = this._highlightGroup;\n g.textContent = '';\n\n const extent = (this.__data__ as Graph).extremes.x_max || 1;\n const HL = '#f5a623';\n const mk = (tag: string, attrs: Record<string, string | number>) => {\n const el = document.createElementNS('http://www.w3.org/2000/svg', tag);\n for (const k in attrs) el.setAttribute(k, String(attrs[k]));\n return el;\n };\n\n // Edges — a translucent glow line between the two code-node centres.\n if (this._highlight.edges.size) {\n const xy: Record<string, { x: number; y: number }> = {};\n this.getNodes().forEach(n => { xy[n.id] = { x: n.x, y: n.y }; });\n this._highlight.edges.forEach(key => {\n const [a, b] = key.split('\u0000');\n const A = xy[a], B = xy[b];\n if (!A || !B) return;\n g.appendChild(mk('line', {\n x1: A.x, y1: A.y, x2: B.x, y2: B.y,\n stroke: HL, 'stroke-width': extent * 0.02, 'stroke-opacity': 0.6, 'stroke-linecap': 'round',\n }));\n });\n }\n\n // Nodes / means / points — a ring around the mark.\n this._highlight.nodes.forEach(id => {\n const el = this.svg_element.querySelector(`[data-point-id=\"${(window as any).CSS?.escape ? CSS.escape(id) : id}\"]`) as SVGElement | null;\n if (!el) return;\n const tag = el.tagName.toLowerCase();\n let cx: number, cy: number, r: number;\n if (tag === 'rect') {\n const w = parseFloat(el.getAttribute('width') || '0');\n cx = parseFloat(el.getAttribute('x') || '0') + w / 2;\n cy = parseFloat(el.getAttribute('y') || '0') + parseFloat(el.getAttribute('height') || '0') / 2;\n r = w / 2;\n } else {\n cx = parseFloat(el.getAttribute('cx') || '0');\n cy = parseFloat(el.getAttribute('cy') || '0');\n r = parseFloat(el.getAttribute('r') || '0');\n }\n g.appendChild(mk('circle', {\n cx, cy, r: r * 1.7 + extent * 0.004, fill: 'none', stroke: HL, 'stroke-width': extent * 0.006,\n }));\n });\n }\n\n create(): SVGElement {\n const\n svg = document.createElementNS(\"http://www.w3.org/2000/svg\", \"svg\")\n ;\n svg.classList.add(\"graph\");\n // Fill the host and keep the square ENA drawing centered (equal x/y scaling\n // preserves distances). Without this the SVG collapses to an intrinsic size\n // and pins to the left, leaving dead space in the container.\n svg.style.display = 'block';\n svg.style.width = '100%';\n svg.style.height = '100%';\n svg.setAttribute(\"preserveAspectRatio\", \"xMidYMid meet\");\n svg.setAttribute(\"viewBox\", (this.__data__ as Graph).extremes.as_viewBox());\n svg.setAttribute(\"transform\", (this.__data__ as Graph).transform.toString());\n svg.setAttribute(\"role\", \"figure\");\n svg.setAttribute(\"data-graph-size\", `${Math.min((this.__data__ as Graph).extremes.width, (this.__data__ as Graph).extremes.height)}`);\n this.svg_element = svg;\n\n // Pre-generate one arrowhead marker per palette color. Per-color markers are\n // the most reliable approach: `context-stroke` and `currentColor` inheritance\n // through SVG markers is inconsistent across browsers and shadow-DOM contexts.\n // Reference as url(#qe-arrow-RRGGBB) where RRGGBB is the hex without '#'.\n const defs = document.createElementNS('http://www.w3.org/2000/svg', 'defs');\n // Arrow dimensions in SVG user-space units (viewBox is ~4.8×4.8).\n // AW must be large enough so the body of the arrowhead is visible before it\n // disappears behind the target node circle. ~5% of the viewport (0.24 units)\n // works well. markerUnits=\"userSpaceOnUse\" keeps the size fixed regardless\n // of stroke-width, so even thin edges get a readable direction indicator.\n const AW = 0.22, AH = 0.15; // arrow length (along edge) and base width (perp)\n const makeArrow = (id: string, fill: string) => {\n const m = document.createElementNS('http://www.w3.org/2000/svg', 'marker');\n m.setAttribute('id', id);\n m.setAttribute('markerWidth', String(AW));\n m.setAttribute('markerHeight',String(AH));\n m.setAttribute('refX', String(AW)); // tip at reference point\n m.setAttribute('refY', String(AH / 2));\n m.setAttribute('orient', 'auto');\n m.setAttribute('markerUnits', 'userSpaceOnUse');\n const p = document.createElementNS('http://www.w3.org/2000/svg', 'path');\n p.setAttribute('d', `M0,0 L0,${AH} L${AW},${AH/2} z`);\n p.setAttribute('fill', fill);\n m.appendChild(p);\n defs.appendChild(m);\n };\n // One marker per GROUP_PALETTE entry (covers all possible edge colors)\n GROUP_PALETTE.forEach(color => makeArrow(`qe-arrow-${color.slice(1)}`, color));\n svg.appendChild(defs);\n\n this.__data__.layers.forEach((layer: LayerLike) => {\n const layer_g: QELayer = new QELayer(layer as any, this.svg_element, this);\n this.__children__.push(layer_g);\n });\n\n this.__data__.__state__.setVariable(\"graph_updated\", this.__data__ );\n\n this.attach_events();\n\n return svg;\n }\n\n attach_events() {\n // Attach event for zooming\n this.svg_element.addEventListener(\"wheel\", (ev: WheelEvent) => {\n console.log(\"Wheel event: \", ev);\n ev.preventDefault();\n const delta = Math.sign(ev.deltaY);\n if (delta < 0) {\n this.zoom_level *= 1.1;\n } else {\n this.zoom_level /= 1.1;\n }\n this.__data__.transform.zoom(this.zoom_level);\n this.update();\n });\n\n // Attach event for panning\n let isPanning = false;\n let startX: number, startY: number;\n\n this.svg_element.addEventListener(\"mousedown\", (ev: MouseEvent) => {\n isPanning = true;\n startX = ev.clientX;\n startY = ev.clientY;\n });\n let panAnimationFrame: number | null = null;\n let pendingPan: { dx: number, dy: number } | null = null;\n\n const panUpdate = () => {\n if (pendingPan) {\n this.__data__.transform.pan(pendingPan.dx, pendingPan.dy);\n this.__children__[0].svg_element.setAttribute(\"transform\", this.__data__.transform.toString());\n pendingPan = null;\n }\n panAnimationFrame = null;\n };\n\n this.svg_element.addEventListener(\"mousemove\", (ev: MouseEvent) => {\n if (!isPanning) return;\n const \n dx = ev.clientX - startX,\n dy = ev.clientY - startY\n ;\n pendingPan = { dx: dx / 100, dy: dy / 100 };\n startX = ev.clientX;\n startY = ev.clientY;\n \n if (panAnimationFrame === null) {\n panAnimationFrame = requestAnimationFrame(panUpdate);\n }\n });\n\n this.svg_element.addEventListener(\"mouseup\", (ev: MouseEvent) => {\n isPanning = false;\n });\n\n // ── Label interactions ───────────────────────────────────────────────────\n // CLICK mode: toggle label on point-clicked event\n this.svg_element.addEventListener('point-clicked', ((ev: CustomEvent) => {\n const id = ev.detail?.pointData?.ID;\n if (!id) return;\n const lbl = this._pointLabels.get(id)\n ?? this._meanLabels.get(id.replace('mean-', ''))\n ?? this._nodeLabels.get(id);\n if (lbl && lbl.displayMode === Label.DISPLAY_TYPES.CLICK) lbl.toggle();\n }) as EventListener);\n\n // AUTO mode: show/hide labels via event delegation on the SVG.\n // We look for the nearest ancestor (or the target itself) that has\n // data-point-id so the hit-area works even on complex shapes.\n const findPointId = (el: SVGElement | null): string | null => {\n while (el && el !== this.svg_element) {\n const id = el.getAttribute?.('data-point-id');\n if (id) return id;\n el = el.parentElement as SVGElement | null;\n }\n return null;\n };\n\n const getAutoLabel = (id: string): QELabel | undefined => {\n return this._pointLabels.get(id)\n ?? this._meanLabels.get(id.replace(/^mean-/, ''))\n ?? this._nodeLabels.get(id);\n };\n\n this.svg_element.addEventListener('mouseover', (ev: MouseEvent) => {\n const id = findPointId(ev.target as SVGElement);\n if (!id) return;\n const lbl = getAutoLabel(id);\n if (lbl?.displayMode === Label.DISPLAY_TYPES.AUTO) lbl.show();\n });\n\n this.svg_element.addEventListener('mouseout', (ev: MouseEvent) => {\n // Only hide when the mouse leaves the point element entirely,\n // not when it enters a child (e.g., a nested SVG element).\n const id = findPointId(ev.target as SVGElement);\n if (!id) return;\n // relatedTarget is where the mouse went — if it's still inside\n // the same point element, don't hide.\n const related = ev.relatedTarget as SVGElement | null;\n const relatedId = findPointId(related);\n if (relatedId === id) return; // still inside the same point\n const lbl = getAutoLabel(id);\n if (lbl?.displayMode === Label.DISPLAY_TYPES.AUTO) lbl.hide();\n });\n\n // ── Public interaction events (webENA integration surface) ────────────────\n // Dispatched on the public <qe-graph> element with bubbles+composed so a\n // host app can subscribe regardless of shadow DOM. See README \"Events\".\n this._attachInteractionEvents();\n }\n\n /** Emit a namespaced CustomEvent on the public element (bubbles + composed). */\n private _emit(name: string, detail: Record<string, any>): void {\n this.dispatchEvent(new CustomEvent(name, { detail, bubbles: true, composed: true }));\n }\n\n /** Walk up from a hit element to the nearest ancestor carrying `attr`. */\n private _closestWith(el: SVGElement | null, attr: string): SVGElement | null {\n while (el && el !== this.svg_element) {\n if (el.getAttribute?.(attr) != null && el.hasAttribute?.(attr)) return el;\n el = el.parentElement as SVGElement | null;\n }\n return null;\n }\n\n /** Resolve an edge hit element to a qe-edge-* detail, or null. */\n private _edgeDetail(el: SVGElement | null): Record<string, any> | null {\n const e = this._closestWith(el, 'data-edge-source');\n if (!e) return null;\n const d: Record<string, any> = {\n source: e.getAttribute('data-edge-source'),\n target: e.getAttribute('data-edge-target'),\n weight: parseFloat(e.getAttribute('data-edge-weight') || '0'),\n directed: e.getAttribute('data-edge-directed') === 'true',\n self: e.getAttribute('data-edge-self') === 'true',\n };\n if (e.hasAttribute('data-edge-group')) d.group = e.getAttribute('data-edge-group');\n if (e.hasAttribute('data-edge-unit')) d.unit = e.getAttribute('data-edge-unit');\n return d;\n }\n\n /** Resolve a node/mean/point hit element to a qe-node-* detail, or null. */\n private _nodeDetail(el: SVGElement | null): Record<string, any> | null {\n const n = this._closestWith(el, 'data-point-id');\n if (!n) return null;\n const tag = n.tagName.toLowerCase();\n let x: number, y: number;\n if (tag === 'rect') {\n x = parseFloat(n.getAttribute('x') || '0') + parseFloat(n.getAttribute('width') || '0') / 2;\n y = parseFloat(n.getAttribute('y') || '0') + parseFloat(n.getAttribute('height') || '0') / 2;\n } else {\n x = parseFloat(n.getAttribute('cx') || '0');\n y = parseFloat(n.getAttribute('cy') || '0');\n }\n const id = n.getAttribute('data-point-id')!;\n const d: Record<string, any> = {\n id,\n kind: n.getAttribute('data-kind') || 'point',\n name: n.getAttribute('data-name') || id,\n x, y,\n };\n if (n.hasAttribute('data-group')) d.group = n.getAttribute('data-group');\n if (n.hasAttribute('data-unit')) d.unit = n.getAttribute('data-unit');\n return d;\n }\n\n private _attachInteractionEvents(): void {\n const svg = this.svg_element;\n\n svg.addEventListener('click', (ev: MouseEvent) => {\n const target = ev.target as SVGElement;\n const edge = this._edgeDetail(target);\n if (edge) { this._emit('qe-edge-click', { ...edge, originalEvent: ev }); return; }\n const node = this._nodeDetail(target);\n if (node) this._emit('qe-node-click', { ...node, originalEvent: ev });\n });\n\n // Hover enter/leave, tracked so we emit one unhover→hover pair per change.\n let hovered: { type: 'edge' | 'node'; key: string } | null = null;\n const keyOf = (t: 'edge' | 'node', d: Record<string, any>) =>\n t === 'edge' ? `${d.source}\u0000${d.target}` : String(d.id);\n\n svg.addEventListener('mousemove', (ev: MouseEvent) => {\n const target = ev.target as SVGElement;\n const edge = this._edgeDetail(target);\n const node = edge ? null : this._nodeDetail(target);\n const next = edge ? { type: 'edge' as const, detail: edge }\n : node ? { type: 'node' as const, detail: node }\n : null;\n const nextKey = next ? keyOf(next.type, next.detail) : null;\n if (hovered && (!next || hovered.key !== nextKey)) {\n this._emit(hovered.type === 'edge' ? 'qe-edge-unhover' : 'qe-node-unhover', { key: hovered.key });\n hovered = null;\n }\n if (next && (!hovered || hovered.key !== nextKey)) {\n this._emit(next.type === 'edge' ? 'qe-edge-hover' : 'qe-node-hover', { ...next.detail, originalEvent: ev });\n hovered = { type: next.type, key: nextKey! };\n }\n // Opt-in built-in tooltip (P1.3 bonus): shown only when <qe-graph tooltip>.\n // The host is free to build its own from the hover events instead.\n if (this.hasAttribute('tooltip') && next) {\n this._showTooltip(this._tooltipText(next.type, next.detail), ev.clientX, ev.clientY);\n } else {\n this._hideTooltip();\n }\n });\n\n svg.addEventListener('mouseleave', () => {\n if (hovered) {\n this._emit(hovered.type === 'edge' ? 'qe-edge-unhover' : 'qe-node-unhover', { key: hovered.key });\n hovered = null;\n }\n this._hideTooltip();\n });\n }\n\n // ── Opt-in built-in tooltip ─────────────────────────────────────────────────\n private _tooltipEl: HTMLDivElement | null = null;\n\n /** \"source – target (weight)\" for edges; the mark name for nodes/means/points. */\n private _tooltipText(type: 'edge' | 'node', d: Record<string, any>): string {\n if (type === 'edge') {\n const w = Number(d.weight);\n const wStr = Number.isFinite(w) ? ` (${(+w.toFixed(3))})` : '';\n return `${d.source} – ${d.target}${wStr}`;\n }\n return String(d.name ?? d.id);\n }\n\n private _showTooltip(text: string, clientX: number, clientY: number): void {\n if (!this._tooltipEl) {\n const el = document.createElement('div');\n el.setAttribute('data-qe-tooltip', '');\n Object.assign(el.style, {\n position: 'fixed', zIndex: '2147483647', pointerEvents: 'none',\n background: 'rgba(20,20,20,0.92)', color: '#fff',\n font: '12px/1.4 system-ui, sans-serif', padding: '3px 7px',\n borderRadius: '4px', whiteSpace: 'nowrap',\n transform: 'translate(-50%, calc(-100% - 8px))',\n } as CSSStyleDeclaration);\n document.body.appendChild(el);\n this._tooltipEl = el;\n }\n this._tooltipEl.textContent = text;\n this._tooltipEl.style.left = `${clientX}px`;\n this._tooltipEl.style.top = `${clientY}px`;\n this._tooltipEl.style.display = 'block';\n }\n\n private _hideTooltip(): void {\n if (this._tooltipEl) this._tooltipEl.style.display = 'none';\n }\n\n draw() {\n if(!this.svg_element) {\n console.error(\"No element to draw to: \", this);\n return;\n }\n \n this.wrapper?.appendChild(this.svg_element);\n\n (this.__children__ as QELayer[]).forEach((enaLayer: QELayer) => {\n enaLayer.draw();\n });\n\n // Pixel-sized text (label-font-size, the plot title) is converted to model\n // units at the current width, so re-lay it out when the plot is resized.\n if (!this._resizeObs && typeof ResizeObserver !== 'undefined' && this.svg_element) {\n let lastW = 0;\n this._resizeObs = new ResizeObserver(entries => {\n const w = entries[0]?.contentRect.width ?? 0;\n if (w > 0 && Math.abs(w - lastW) > 0.5) {\n lastW = w;\n this.update_labels();\n this.update_axes();\n }\n });\n this._resizeObs.observe(this.svg_element);\n }\n }\n\n update() {\n // Two-pass update: first pass lays out elements and computes extremes;\n // second pass re-syncs the viewBox now that all element positions are final.\n this.update_extremes();\n this.update_layers();\n this.update_labels(); // positions labels using the freshly-computed extent\n this.update_extremes(); // re-apply viewBox after label/layer repositioning\n this.update_axes(); // axis line visibility + labels (uses final extent)\n this._applyHighlights(); // re-apply host highlight over the fresh render\n }\n\n /**\n * Axes (<qe-axes>): toggle the axis-line cross by presence, and draw/position\n * per-axis labels at the positive ends using the current extent. Labels are\n * cached SVG <text> nodes in the labels group; null text removes them.\n */\n update_axes(): void {\n // Show or hide the whole axis sub-tree (lines + origin) by <qe-axes> presence.\n const axesLayer = this.__children__.search('__children__', 'axes') as QELayer | undefined;\n if (axesLayer?.svg_element) {\n (axesLayer.svg_element as SVGElement).style.display = this._showAxes ? '' : 'none';\n }\n\n const parent = this._labelsGroup;\n const extent = this.__data__.extremes.x_max;\n const { cx, cy } = this.__data__.extremes;\n if (!parent || extent <= 0) return;\n\n const fontSize = extent * 0.06;\n const gap = fontSize * 0.6;\n\n const place = (axis: 'x' | 'y', text: string | null) => {\n let el = this._axisLabelEls.get(axis);\n if (!this._showAxes || text == null) { // remove when hidden / no label\n if (el) { el.remove(); this._axisLabelEls.delete(axis); }\n return;\n }\n if (!el) {\n el = document.createElementNS('http://www.w3.org/2000/svg', 'text') as SVGTextElement;\n el.setAttribute('data-axis-label', axis);\n el.setAttribute('pointer-events', 'none');\n parent.appendChild(el);\n this._axisLabelEls.set(axis, el);\n }\n el.textContent = text;\n el.setAttribute('font-size', fontSize.toString());\n el.setAttribute('font-family', 'system-ui, sans-serif');\n el.setAttribute('font-weight', '600');\n el.setAttribute('fill', '#556');\n if (axis === 'x') {\n // At the right (+x) tip, anchored end so any-length text grows inward\n // and never clips past the viewBox edge; nudged just above the axis.\n el.setAttribute('x', (cx + extent - gap).toString());\n el.setAttribute('y', (-gap).toString());\n el.setAttribute('text-anchor', 'end');\n } else {\n // Just below the top (−y) tip, centered on the y-axis, inside the box.\n el.setAttribute('x', (gap).toString());\n el.setAttribute('y', (cy - extent + fontSize + gap).toString());\n el.setAttribute('text-anchor', 'start');\n }\n };\n\n place('x', this._axisXText);\n place('y', this._axisYText);\n\n // Magnification label, top-left inside the plot; independent of axes.\n if (this._magnifyText == null) {\n this._magnifyEl?.remove();\n this._magnifyEl = null;\n } else {\n if (!this._magnifyEl) {\n this._magnifyEl = document.createElementNS('http://www.w3.org/2000/svg', 'text') as SVGTextElement;\n this._magnifyEl.setAttribute('data-magnify-label', '');\n this._magnifyEl.setAttribute('pointer-events', 'none');\n }\n if (!this._magnifyEl.parentElement) parent.appendChild(this._magnifyEl);\n const el = this._magnifyEl;\n el.textContent = this._magnifyText;\n el.setAttribute('font-size', (fontSize * 0.85).toString());\n el.setAttribute('font-family', 'system-ui, sans-serif');\n el.setAttribute('font-style', 'italic');\n el.setAttribute('fill', '#556');\n el.setAttribute('x', (cx - extent + gap).toString());\n el.setAttribute('y', (cy - extent + fontSize + gap).toString());\n el.setAttribute('text-anchor', 'start');\n }\n\n // Plot title (qe_plot(title =)), top centre, drawn into the SVG so it is\n // part of toSVG() / toPNG() exports.\n if (!this._plotTitle) {\n this._titleEl?.remove(); this._titleEl = null;\n } else {\n if (!this._titleEl) {\n this._titleEl = document.createElementNS('http://www.w3.org/2000/svg', 'text') as SVGTextElement;\n this._titleEl.setAttribute('data-plot-title', '');\n this._titleEl.setAttribute('pointer-events', 'none');\n }\n if (!this._titleEl.parentElement) parent.appendChild(this._titleEl);\n const px = (this._labelFont.size ?? 12) * 1.35;\n const ts = px * this.unitsPerPixel();\n const t = this._titleEl;\n t.textContent = this._plotTitle;\n t.setAttribute('font-size', ts.toString());\n t.setAttribute('font-family', this._labelFont.family ?? 'system-ui, sans-serif');\n t.setAttribute('font-weight', '600');\n t.setAttribute('fill', this._labelFont.color ?? '#223');\n t.setAttribute('x', cx.toString());\n t.setAttribute('y', (cy - extent + ts * 1.1).toString());\n t.setAttribute('text-anchor', 'middle');\n }\n }\n\n update_labels(): void {\n this._nodeLabels.forEach(lbl => lbl.update());\n this._meanLabels.forEach(lbl => lbl.update());\n this._pointLabels.forEach(lbl => lbl.update());\n }\n\n update_extremes() {\n const graph = this.__data__ as Graph;\n graph.update_extremes(this._centerContent);\n if (this._rangeExtent && this._rangeExtent > 0) {\n // A centred view measures range=\"network\" from its centre, not the origin\n const { cx, cy } = graph.extremes;\n const r = this._centerContent && this._rangeMode === 'network'\n ? graph.nodeExtentFrom(cx, cy) * 1.2\n : this._rangeExtent;\n graph.extremes = new Extremes(r, r, cx, cy);\n }\n\n const svgRect = this.svg_element?.getBoundingClientRect();\n if(this.svg_element && svgRect) {\n console.log(\"SVG rect: \", svgRect);\n let w, h;\n if(svgRect.width === 0 || svgRect.height === 0) {\n w = 1;\n h = 1;\n }\n else {\n w = svgRect.width;\n h = svgRect.height;\n }\n this.__data__.scale_x = 1 / (w / (4 * this.__data__.extremes.x_max));\n this.__data__.scale_y = 1 / (h / (4 * this.__data__.extremes.y_max));\n\n // this.svg_element.setAttribute(\"transform\", this.__data__.transform.toString());\n this.__children__[0].svg_element.setAttribute(\"transform\", this.__data__.transform.toString());\n\n this.svg_element.setAttribute(\"viewBox\", (this.__data__ as Graph).extremes.as_viewBox());\n\n let axisLineLayer: LayerLike | undefined = this.__data__.layers.search(\"layers\", \"axis_lines\");\n if (axisLineLayer) {\n let \n axis_x = axisLineLayer.objects.get(\"axis-x\") as Line,\n axis_y = axisLineLayer.objects.get(\"axis-y\") as Line\n ;\n if (axis_x && axis_y) {\n const ex = this.__data__.extremes;\n axis_x.from = new Point({ ID: \"axis-x-start\", dimensions: [ex.cx - ex.x_max, 0], classes: [\"ena.dimension\", \"ena.dimension\"] });\n axis_x.to = new Point({ ID: \"axis-x-end\", dimensions: [ex.cx + ex.x_max, 0], classes: [\"ena.dimension\", \"ena.dimension\"] });\n axis_y.from = new Point({ ID: \"axis-y-start\", dimensions: [0, ex.cy - ex.y_max], classes: [\"ena.dimension\", \"ena.dimension\"] });\n axis_y.to = new Point({ ID: \"axis-y-end\", dimensions: [0, ex.cy + ex.y_max], classes: [\"ena.dimension\", \"ena.dimension\"] });\n }\n }\n }\n }\n\n update_layers() {\n (this.__children__ as QELayer[]).forEach((enaLayer: QELayer) => {\n enaLayer.update();\n });\n }\n}\ncustomElements.define(QEGraphElement.tagName, QEGraphElement);\n","// QEViz standalone entry point — no arbor/webr dependency.\n// Import this bundle directly from rENA or any non-arbor context.\n\nexport { QEVisualElement, vizENA } from './elements/QEVisual.js';\nexport { QEGraphElement } from './elements/QEGraph.js';\nimport { QEGraphElement as _QEGraph } from './elements/QEGraph.js';\n/** Look up a connected <qe-graph> by its `id` or `plot-group` attribute. */\nexport const getGraph = (key: string) => _QEGraph.getGraph(key);\n/** All connected <qe-graph> instances. */\nexport const getGraphs = () => _QEGraph.instances();\nexport { QENodesElement, QEMeansElement, QEPointsElement, QEEdgesElement, QETrajectoriesElement, QEAxesElement } from './elements/QEChildElements.js';\nexport { QELayer } from './elements/QELayer.js';\nexport { QEPoint } from './elements/QEPoint.js';\nexport { QELine } from './elements/QELine.js';\nexport { QETrajectory } from './elements/QETrajectory.js';\n\nexport type { ModelData, QEFrame, ONAModelData, ENAModelData, ENADataFrame } from './types/ModelData.js';\n\nexport { Graph } from './objects/Graph.js';\nexport { Edge } from './objects/Edges.js';\nexport { Trajectory } from './objects/Trajectory.js';\nexport { fitTrajectory, selectDegree, sampleCurve, nearOriginFilter, TRAJECTORY_ZERO_EPS } from './objects/polyfit.js';\nexport type { XY, DegreeSelection, TrajectoryFit } from './objects/polyfit.js';\nexport { Color, WeightedColor } from './objects/Color.js';\n\nexport { DataFrame, DataFrameRow, DataFrameColumn, DataFrameColumnType } from './types/DataFrame.js'\n"],"names":["_DataFrameRow","names","values","rowName","parent","index","__privateAdd","_rowNumber","_rowName","_names","_parent","_classes","__privateSet","__privateGet","wh","predicate","__name","DataFrameRow","DataFrameColumnType","_DataFrameColumn","name","column","rowNames","_name","_type","_rowNames","i","v","DataFrameColumn","_DataFrame","colValues","classes","c","l","transposed","col","j","idx","result_vals","_a","selectors","selectedRows","selectedRowNames","numRows","_","item","r","row","selectedCols","selectedNames","rows","cols","DataFrame","_Model","o","id","key","value","Model","DEBUG","dbg","args","vizENA","n","elements","_QEVisualElement","shadow","style","val","pts","p","edges","data","raw","types","colNames","idCol","removalCol","nodesDF","pointsDF","_b","unitId","_c","_d","nodeId","xColOvr","yColOvr","numCols","QEVisualElement","_Color","base","target","prop","g","b","color","bigint","Color","_WeightedColor","weight","alpha","hex","rn","gn","bn","max","min","d","s","h","a","x","m","w","WeightedColor","_Transform","vals","k","z","y","Transform","Tools","Matrix","matrixString","matrix","Geometry","Point","translate","point","angle","distance","Angle","rotate","origin","rotatePoint","p0","Line","slope","p1","p2","intercept","slopeIntercept","point_along","line","ratio","Xt","Yt","midpoint","length","by","translated","rotated","rotated_reflection","untranslated","untranslated2","rotate2","fixed","P","Q","xx","yy","x_fixed","y_fixed","angle_rad","xx_new","yy_new","intersection","lineA","lineB","x1","y1","x2","y2","x3","y3","x4","y4","D","num1","num2","intersect_circle","circle_xy","circle_r","int","interpolate","t","toRad","toDeg","ArrayTools","unique","arr","divide","isArray","obj","Mathematics","sum","mean","round","decimals","factor","Events","createEvent","element","Hash","parts","exists","Objects","proxy","handler","deep","property","get","current","part","set","URL","parse","location","Query","keys","has","_EventBus","options","oldValue","type","listener","typeMap","newValue","EventBus","_LayerArray","found","fn","recurse","callback","depth","results","layer","result","LayerArray","_Layer","ID","StateManager","Layer","_DimensionVector","_flipped","vec","DimensionVector","_PlottedObject","dimensions","x_","y_","PlottedObject","_Line","from","to","_Point","meta","_Label","txt","object","Label","_Extremes","cx","cy","Extremes","_AxisPoint","AxisPoint","DefaultGraphOptions","_Graph","layer_id","buildLayerTree","layerData","graph","new_layer","child","axisPointLayer","axisLineLayer","extremes","axis_x","axis_y","e","ps","g_","ns","new_node","nodesLayer","es","added","edgesLayer","centerContent","search_layers","minX","maxX","minY","maxY","content_max","found_max","nodes","scale","minDim","Graph","_DrawableElement","wrapper","DrawableElement","TRAJECTORY_ZERO_EPS","nearOriginFilter","eps","normalizedT","design","degree","ti","qr","A","R","norm","dot","qtY","out","backSolve","leverages","fitCoeffs","X","evalPoly","coeffs","loocv2d","press","denom","ex","ey","selectDegree","fitPts","maxDegree","mode","cap","best","bestVal","deg","fitTrajectory","activePts","opts","selBasis","basis","coeffsX","coeffsY","sampleCurve","fit","steps","TRAJECTORY_CURVE_STEPS","_Trajectory","defaultColor","pt","acc","Trajectory","zoom_level","_Edge","Edge","_EdgeArrow","edge","_edge","_this","T","B0","B1","L","W","u","halfW","at","dh","dm","dn","EdgeArrow","_TaperedEdge","_with_arrow","_arrow","edg","top","bx","tx","ty","dx","dy","wt","px","py","TaperedEdge","_TaperedWeightedMidpointEdge","TaperedWeightedMidpointEdge","_NodeEdge","CX","R2","NodeEdge","_Drawable","__data__","__children__","QEArray","elem","animate","attr","duration","start","now","Drawable","DEFAULT_EDGE_WIDTH","SATURATION_RANGE","OPACITY_RANGE","rampFor","lo","hi","range","EDGE_WIDTH_PER_EXTENT","TAPERED_OUTLINE_PX","CHEVRON_DARKEN","CHEVRON_HALO_PX","POINT_RADIUS_PER_EXTENT","UNCONNECTED_NODE_SIZE","widthPerWeight","edgeWidth","nodeSizeForEdges","weightSum","widthFrac","flattenOnWhite","f","darkenRgba","_QELine","el","path","extent","maxW","opacity","ext","sw","baseColor","saturation","edgeColor","arrowPath","QELine","_QEPoint","sizeScale","rect","zoom","pxPerUnit","stroke","pointEvent","QEPoint","_QETrajectory","pixels","width","group","segmentsGroup","pointsGroup","tip","dStr","pathPts","nSegments","minWidth","maxWidth","minOpacity","maxOpacity","end","progress","segment","lastPt","QETrajectory","_QEArray","QEElementConstructors","_QELayer","childId","removing","updating","obj_name","constructor","ena_element","newData","sublayer","layer_g","QELayer","_QELabel","text","displayMode","position","customX","customY","ev","svg","toUser","baseX","baseY","onMove","onUp","font","fontSize","offset","anchor","dist","QELabel","_QENodesElement","QENodesElement","_QEMeansElement","QEMeansElement","_QEPointsElement","QEPointsElement","_QEEdgesElement","QEEdgesElement","_QETrajectoriesElement","QETrajectoriesElement","_QEAxesElement","QEAxesElement","GROUP_PALETTE","parseEdgePair","colName","codes","c1","c2","computeCIRect","varX","varY","pointScale","df","t95","seX","seY","MEAN_MAX_FRACTION_OF_INTERVAL","capMeanToInterval","meanPt","halfH","half","readIntervalBounds","dim0","dim1","prefix","xLow","xHigh","yLow","yHigh","parseEdgeLayer","thr","complementColor","mx","mn","parseColorScale","parseLabelMode","defaultMode","_QEGraphElement","model","tweenFrom","dims","unitIdCol","nodeIdCol","groupColName","config","groupColorMap","PALETTE","groupCol","ci","_allGroupNames_","activeMeanGroups","scalePointsEnabled","getExtent","xIdx","yIdx","maxNodeExtent","_e","maxPointExtent","_f","maxTrajExtent","_g","effectivePointExtent","labelNodes","labelMeans","labelPoints","labelSvg","rowToPoint","colorStr","idIdx","groupSums","showUnitPoints","pointSetFrame","psLayer","si","shape","label","_h","pointsLayer","groupColIdx","rx","ry","hasGroupsFrame","_i","activeGroupRows","pointsLayerSvg","activeNames","my","shapeIdx","rowShape","cell","rowIv","iv","rowOut","ob","oel","bounds","crossKey","x0","y0","cel","rect_x","rect_y","rect_width","rect_height","stale","_j","groupIdx","μx","μy","rawVarX","rawVarY","_k","lbl","qIdx","displayText","meanId","trajectoriesLayer","trajSource","_l","unitRows","selectedUnits","uIdx","unit","tIdx","time","unitKey","rawPts","trajObj","networkLayer","edgeLayer","nodeLayer","edgenodeLayer","edgesEnabled","_m","li","lv","_n","unitGroupMap","_o","gIdx","codeNames","edgePairs","pair","getUnitEdges","colIdx","getGroupEdges","groupName","sums","count","gColIdx","resolve","groupOfUnit","drawEdges","networkRow","frame","thresholded","push","signColors","pos","neg","primaryId","primary","secondaryId","secondary","wA","wB","isDirected","rangeOf","ws","nz","modelRange","self","plotRange","cscale","colourRange","lineRange","selfRange","colourOf","nodeWeightSum","add","codeIdx","unconnected","totalWeightByPair","pairKey","net","fromNode","toNode","isSelf","fromPt","toPt","edgeLine","fwd","bwd","totalweight","nodesVisible","axisPointsLayer","axisLinesLayer","nodesEl","meansEl","allPointsEls","pointsEl","setEls","edgeEls","firstAttr","magnifyEl","trajectoriesEl","axesEl","labelsShorthand","fallback","forId","labelsLayer","graphLayer","collect","tag","dur","t0","ease","lerp","step","nc","oc","svgStr","reject","blob","url","img","canvas","ctx","err","sel","HL","mk","attrs","xy","B","defs","AW","AH","makeArrow","fill","isPanning","startX","startY","panAnimationFrame","pendingPan","panUpdate","findPointId","getAutoLabel","related","detail","node","hovered","keyOf","next","nextKey","wStr","clientX","clientY","enaLayer","lastW","entries","axesLayer","gap","place","axis","ts","svgRect","QEGraphElement","getGraph","_QEGraph","getGraphs"],"mappings":"ssBAOO,MAAMA,GAAN,MAAMA,WAAqB,KAA4C,CAO5E,YAAYC,EAAiBC,EAAeC,EAAkBC,EAAoBC,EAAgB,CAChG,MAAM,GAAGH,CAAM,EAPjBI,GAAA,KAAAC,IACAD,GAAA,KAAAE,IACAF,GAAA,KAAAG,IACAH,GAAA,KAAAI,IACAJ,GAAA,KAAAK,IAIEC,EAAA,KAAKH,GAASR,GACdW,EAAA,KAAKJ,GAAWL,GAChBS,EAAA,KAAKF,GAAUN,GACfQ,EAAA,KAAKD,GAAWP,GAAA,YAAAA,EAAQ,SACxBQ,EAAA,KAAKL,GAAaF,EACpB,CAEA,IAAI,QAAgC,CAClC,OAAOQ,EAAA,KAAKH,GACd,CACA,IAAI,OAAkB,CACpB,OAAOG,EAAA,KAAKJ,GACd,CACA,IAAI,SAA8B,CAChC,OAAOI,EAAA,KAAKL,GACd,CACA,IAAI,OAA+B,CACjC,GAAI,CAACK,EAAA,KAAKH,IAAS,MAAM,IAAI,MAAM,2CAA2C,EAC9E,OAAOG,EAAA,KAAKH,IAAQ,KACtB,CACA,IAAI,SAAgC,CAClC,OAAOG,EAAA,KAAKF,GACd,CAEA,IAAI,WAAgC,CAClC,OAAOE,EAAA,KAAKN,GACd,CAEA,IAAIO,EAAkD,CACpD,GAAI,CAACD,EAAA,KAAKH,IAAS,MAAM,IAAI,MAAM,2CAA2C,EAC9E,OAAOG,EAAA,KAAKH,IAAQ,IAAII,CAAE,CAC5B,CACA,QAAQA,EAAoC,CAC1C,GAAI,CAACD,EAAA,KAAKH,IAAS,MAAM,IAAI,MAAM,2CAA2C,EAC9E,OAAOG,EAAA,KAAKH,IAAQ,KAAK,GAAGI,CAAE,CAChC,CAEA,OAAOC,EAAsE,CAC3E,QAAQ,MAAM,oDAAoD,CAEpE,CACF,EAjDER,GAAA,YACAC,GAAA,YACAC,GAAA,YACAC,GAAA,YACAC,GAAA,YAL4EK,EAAAhB,GAAA,gBAAvE,IAAMiB,EAANjB,GAoDA,IAAKkB,IAAAA,IACVA,EAAA,UAAY,YACZA,EAAA,OAAS,SACTA,EAAA,QAAU,UACVA,EAAA,QAAU,UAJAA,IAAAA,IAAA,CAAA,CAAA,EAaL,MAAMC,GAAN,MAAMA,WAAwB,KAA+C,CAMlF,YAAYC,EAAcC,EAAaC,EAAqBlB,EAAoB,CAC9E,MAAMiB,EAAO,MAAM,EANrBf,GAAA,KAAAiB,IACAjB,GAAA,KAAAkB,IACAlB,GAAA,KAAAmB,IACAnB,GAAA,KAAAI,IAIE,QAASgB,EAAI,EAAGA,EAAIL,EAAO,OAAQK,IACjC,KAAKA,CAAC,EAAIL,EAAOK,CAAC,EAmCpB,GAjCAd,EAAA,KAAKW,GAAQH,GAETC,EAAO,OAAS,OAClBT,EAAA,KAAKY,GAAQH,EAAO,MAIhBA,EAAO,MAAOM,GAAW,OAAOA,GAAM,UAAYA,IAAM,MAAQA,IAAM,MAAS,EACjFf,EAAA,KAAKY,GAAQ,aAENH,EAAO,MAAOM,GAAW,OAAO,UAAUA,CAAC,GAAKA,IAAM,MAAQA,IAAM,MAAS,EAEhFN,EAAO,MAAOM,GAAWA,IAAM,GAAKA,IAAM,GAAKA,IAAM,MAAQA,IAAM,MAAS,EAC9Ef,EAAA,KAAKY,GAAQ,WAGbZ,EAAA,KAAKY,GAAQ,WAGRH,EAAO,MAAOM,GAAW,OAAOA,GAAM,UAAYA,IAAM,MAAQA,IAAM,MAAS,EACtFf,EAAA,KAAKY,GAAQ,UAENH,EAAO,MAAOM,GAAW,OAAOA,GAAM,WAAaA,IAAM,MAAQA,IAAM,MAAS,EACvFf,EAAA,KAAKY,GAAQ,WAKbZ,EAAA,KAAKY,GAAQ,aAGjBZ,EAAA,KAAKF,GAAUN,GAEXkB,GAAYA,EAAS,SAAW,KAAK,OACvC,MAAM,IAAI,MAAM,wEAAwE,EAEtFA,GAAYA,EAAS,OAAS,EAChCV,EAAA,KAAKa,GAAYH,GAGjBV,EAAA,KAAKa,GAAY,OAErB,CAEA,IAAI,MAAe,CACjB,OAAOZ,EAAA,KAAKU,GACd,CACA,IAAI,MAA4B,CAC9B,OAAOV,EAAA,KAAKW,GACd,CACA,IAAI,UAAiC,CACnC,OAAOX,EAAA,KAAKY,GACd,CAGA,IAAIX,EAA+C,CACjD,GAAI,CAACD,EAAA,KAAKH,IAAS,MAAM,IAAI,MAAM,8CAA8C,EACjF,OAAOG,EAAA,KAAKH,IAAQ,IAAII,CAAE,CAC5B,CACA,QAAQA,EAAyC,CAC/C,GAAI,CAACD,EAAA,KAAKH,IAAS,MAAM,IAAI,MAAM,8CAA8C,EACjF,OAAOG,EAAA,KAAKH,IAAQ,KAAK,GAAGI,CAAE,CAChC,CACF,EAzEES,GAAA,YACAC,GAAA,YACAC,GAAA,YACAf,GAAA,YAJkFM,EAAAG,GAAA,mBAA7E,IAAMS,GAANT,GA6FA,MAAMU,GAAN,MAAMA,WAAkB,KAAqD,CAKlF,YAAY5B,EAAkB6B,EAAmBR,EAAqBS,EAAoB,CAKxF,IAJI,CAAC9B,GAAS,CAAC6B,KACbA,EAAY,CAAA,EACZ7B,EAAQ,CAAA,GAEN6B,EAAU,IAAME,GAAWA,EAAE,MAAO,EAAE,MAAQC,GAAWA,IAAMhC,EAAM,MAAO,EAAG,CAEjF,MAAMiC,EAAoB,CAAA,EAC1B,QAASR,EAAI,EAAGA,EAAIzB,EAAM,OAAQyB,IAAK,CACrC,MAAMS,EAAa,CAAA,EACnB,QAASC,EAAI,EAAGA,EAAIN,EAAU,OAAQM,IACpCD,EAAI,KAAKL,EAAUM,CAAC,EAAEV,CAAC,CAAC,EAE1BQ,EAAW,KAAKC,CAAG,CACrB,CACAL,EAAYI,CACd,CAEA,MAAMJ,EAAU,MAAM,EAtBxBxB,GAAA,KAAAG,IACAH,GAAA,KAAAmB,IACAnB,GAAA,KAAAK,IAsBE,GAAAmB,EAAU,QAAQ,CAACK,EAAK9B,IAAU,CAC5B8B,aAAeP,GAEjB,KAAKvB,CAAK,EAAI8B,EAGd,KAAK9B,CAAK,EAAI,IAAIuB,GAAgB3B,EAAMI,CAAK,EAAG8B,EAAKb,EAAU,IAAI,CAEvE,CAAC,EACDV,EAAA,KAAKH,GAASR,GACVqB,GAAY,KAAK,CAAC,GAAKA,EAAS,SAAW,KAAK,CAAC,EAAE,OACrD,MAAM,IAAI,MAAM,kEAAkE,EAKpF,GAHIA,GAAYA,EAAS,OAAS,GAChCV,EAAA,KAAKa,GAAYH,GAEfS,GAAWA,EAAQ,SAAW,KAAK,OACrC,MAAM,IAAI,MAAM,mEAAmE,EAEjFA,GAAWA,EAAQ,OAAS,GAC9BnB,EAAA,KAAKD,GAAWoB,EAEpB,CAEA,IAAI,SAAgC,CAClC,OAAOlB,EAAA,KAAKF,GACd,CAEA,gBAAgBS,EAA2C,CACzD,MAAMiB,EAAMxB,EAAA,KAAKJ,IAAO,QAAQW,CAAI,EACpC,OAAOiB,GAAO,EAAI,KAAKA,CAAG,EAAI,MAChC,CACA,cAAchC,EAA6B,CACzC,GAAI,MAAQ,KAAK,SAAW,EAC1B,eAAQ,KAAK,8CAA+CA,CAAK,EAC1D,IAAIY,EAAaJ,EAAA,KAAKJ,IAAQ,CAAA,EAAI,OAAW,KAAMJ,CAAK,EAEjE,MAAMiC,EAAqB,CAAA,EAC3B,QAASH,KAAO,KAAM,CACpB,IAAIR,EAAIQ,EAAI9B,CAAK,EACjBiC,EAAY,KAAKX,CAAC,CACpB,CACA,OAAO,IAAIV,EAAaJ,EAAA,KAAKJ,IAAQ6B,EAAazB,EAAA,KAAKY,IAAYZ,EAAA,KAAKY,IAAUpB,CAAK,EAAI,OAAW,KAAMA,CAAK,CACnH,CACA,aAAae,EAAwC,CACnD,GAAI,CAACP,EAAA,KAAKY,IAAW,OAErB,MAAMpB,EAAQQ,EAAA,KAAKY,IAAU,QAAQL,CAAI,EACzC,GAAIf,IAAU,GACd,OAAO,KAAK,cAAcA,CAAK,CACjC,CAEA,IAAI,OAA+B,CACjC,OAAO,KAAK,IAAI8B,GAAOA,EAAI,IAAI,CACjC,CACA,KAAKrB,EAAsD,OACzD,GAAI,OAAOA,GAAO,SAChB,OAAOyB,EAAA,KAAKzB,CAAE,IAAP,YAAAyB,EAAU,KACnB,GACS,OAAOzB,GAAO,SAAU,CAC/B,MAAMqB,EAAM,KAAK,gBAAgBrB,CAAE,EACnC,OAAOqB,EAAMA,EAAI,KAAO,MAC1B,CAEF,CAIA,IAAIrB,EAA+C,CACjD,GAAI,OAAOA,GAAO,SAChB,OAAO,KAAK,cAAcA,CAAE,EAC9B,GACS,OAAOA,GAAO,SACrB,OAAO,KAAK,aAAaA,CAAE,CAG/B,CAEA,QAAQA,EAAyC,CAE/C,IACE0B,EACAC,EAA+B,CAAA,EAC/BC,EAAyC,CAAA,EAI3C,GAAI5B,EAAG,SAAW,EAAG,CACnB,GAAI,CAAC,KAAK,CAAC,GAAK,KAAK,SAAW,EAC9B,MAAO,CAAA,EAET,MAAM6B,EAAU,KAAK,CAAC,EAAE,OACxBF,EAAe,MAAM,KAAK,CAAE,OAAQE,CAAA,EAAW,CAACC,EAAGlB,IAAM,KAAK,cAAcA,CAAC,CAAC,EAC9EgB,EAAmB7B,EAAA,KAAKY,GAC1B,MAIMX,EAAG,SAAW,GAAK,MAAM,QAAQA,EAAG,CAAC,CAAC,EACxC0B,EAAY1B,EAAG,CAAC,EAIhB0B,EAAY1B,EAGd2B,EAAeD,EAAU,IAAI,CAACK,EAAMnB,IAAc,CAChD,IAAIoB,EAAI,KAAK,IAAID,CAAI,EACrB,OAAIhC,EAAA,KAAKY,KAAaqB,IACpBJ,GAAA,MAAAA,EAAkB,KAAK7B,EAAA,KAAKY,IAAUC,CAAC,IAElCoB,CACT,CAAC,EAAE,OAAQC,GAA6BA,IAAQ,MAAS,EAgB3D,OAAON,CACT,CAEA,IAAI3B,EAAkD,CACpD,GAAI,OAAOA,GAAO,SAChB,OAAO,KAAKA,CAAE,EAChB,GAAW,OAAOA,GAAO,SACvB,OAAO,KAAK,gBAAgBA,CAAE,CAGlC,CAEA,QAAQA,EAAoC,CAE1C,IACE0B,EACAQ,EACAC,EAA0B,CAAA,EAI5B,OAAInC,EAAG,SAAW,GAChBkC,EAAe,KAAK,MAAA,EACpBC,EAAgBpC,EAAA,KAAKJ,MAIjBK,EAAG,SAAW,GAAK,MAAM,QAAQA,EAAG,CAAC,CAAC,EACxC0B,EAAY1B,EAAG,CAAC,EAIhB0B,EAAY1B,EAGdkC,EAAeR,EAAU,IAAKK,GAAS,KAAK,IAAIA,CAAI,CAAC,EAAE,OAAQV,GAAgCA,IAAQ,MAAS,EAChHc,EAAgBD,EAAa,IAAIb,GAAOA,EAAI,IAAI,GAG3C,IAAIN,GAAUoB,EAAeD,EAAcnC,EAAA,KAAKY,GAAS,CAClE,CAEA,OAAOyB,EAA4BC,EAAuC,CACxE,MAAMH,EAAmCG,GAAQA,EAAK,OAAS,EAC3D,KAAK,KAAK,GAAGA,CAAI,EACjB,KAAK,MAAA,EAET,OAAO,IAAItB,GACTmB,EAAa,IAAIb,GAAOA,EAAI,IAAI,EAChCa,EAAa,IAAIb,GAAOA,EAAI,MAAM,EAClCtB,EAAA,KAAKY,GAAA,CAET,CAEA,IAAI,OAAkB,CACpB,OAAOZ,EAAA,KAAKJ,GACd,CAEA,IAAI,UAAiC,CACnC,OAAOI,EAAA,KAAKY,GACd,CAEA,IAAI,MAAe,CACjB,OAAO,KAAK,CAAC,EAAI,KAAK,CAAC,EAAE,OAAS,CACpC,CAEA,IAAI,MAAe,CACjB,OAAO,KAAK,MACd,CACF,EA7NEhB,GAAA,YACAgB,GAAA,YACAd,GAAA,YAHkFK,EAAAa,GAAA,aAA7E,IAAMuB,GAANvB,GC/IA,MAAMwB,GAAN,MAAMA,EAA2B,CA2BtC,YAAYC,EAAwB,GAAI,CAVxC,KAAA,YAAsB,KAEtB,KAAA,YAAsB,KAEtB,KAAA,UAA6B,KAE7B,KAAA,SAAuB,GAEvB,KAAA,QAAwB,CAAA,EAGtB,KAAK,QAAcA,EAAE,QAAc,IAAIF,GACvC,KAAK,OAAcE,EAAE,OAAc,IAAIF,GACvC,KAAK,OAAcE,EAAE,OAAc,IAAIF,GACvC,KAAK,YAAcE,EAAE,YAAc,CAAA,EACnC,KAAK,YAAc,OACnB,KAAK,SAAc,OACnB,KAAK,QAAc,MACrB,CAEA,IAAI,SAA8B,CAAE,OAAO,KAAK,QAAU,CAC1D,IAAI,QAAQ3B,EAAuB,CAAE,KAAK,SAAWA,CAAG,CAExD,IAAI,QAAoB,CAAE,OAAO,KAAK,OAAS,CAC/C,IAAI,OAAOA,EAAc,CAAE,KAAK,QAAUA,CAAG,CAE7C,IAAI,OAAmB,CAAE,OAAO,KAAK,MAAQ,CAC7C,IAAI,MAAMA,EAAc,CAAE,KAAK,OAASA,CAAG,CAE3C,IAAI,OAAmB,CAAE,OAAO,KAAK,MAAQ,CAC7C,IAAI,MAAMA,EAAc,CAAE,KAAK,OAASA,CAAG,CAE3C,IAAI,YAAoC,CAAE,OAAO,KAAK,WAAa,CACnE,IAAI,WAAWA,EAA0B,CAAE,KAAK,YAAcA,CAAG,CAEjE,IAAI,SAAiC,CAAE,OAAO,KAAK,QAAU,CAC7D,IAAI,QAAQA,EAA0B,CAAE,KAAK,SAAWA,CAAG,CAE3D,IAAI,QAAgC,CAAE,OAAO,KAAK,OAAS,CAC3D,IAAI,OAAOA,EAA0B,CAAE,KAAK,QAAUA,CAAG,CAEzD,IAAI,cAAsC,CAAE,OAAO,KAAK,aAAe,CACvE,IAAI,aAAaA,EAA0B,CAAE,KAAK,cAAgBA,CAAG,CAIrE,IAAI,UAAkC,CAAE,OAAO,KAAK,SAAW,CAC/D,IAAI,SAASA,EAA0B,CAAE,KAAK,UAAYA,CAAG,CAI7D,IAAI,WAAmC,CAAE,OAAO,KAAK,UAAY,CACjE,IAAI,UAAUA,EAA0B,CAAE,KAAK,WAAaA,CAAG,CAE/D,IAAI,YAAkC,CAAE,OAAO,KAAK,WAAa,CACjE,IAAI,WAAWA,EAAwB,CAAE,KAAK,YAAcA,CAAG,CAE/D,IAAI,QAAc,CAAE,OAAO,KAAK,OAAS,CACzC,IAAI,OAAOA,EAAQ,CAAE,KAAK,QAAUA,CAAG,CAEvC,MAAM4B,EAAsC,CAC1C,OAAO,KAAK,QAAQ,IAAIA,CAAE,CAC5B,CAEA,SAAoCC,EAAQC,EAA2B,CACpE,KAAaD,CAAG,EAAIC,CACvB,CACF,EApFwCzC,EAAAqC,GAAA,SAAjC,IAAMK,GAANL,GCtBA,MAAMM,GAAkB,WAAmB,kBAAoB,GAE/D,SAASC,MAAOC,EAAmB,CACpCF,IAAO,QAAQ,IAAI,GAAGE,CAAI,CAChC,CAFgB7C,EAAA4C,GAAA,OCKT,MAAME,GAAS,CACpB,IAAK9C,EAAC+C,GAAc,CAClB,MAAMC,EAAW,CAAC,GAAI,SAAiB,iBAAiB,UAAU,CAAC,EACnE,OAAI,OAAOD,GAAM,UAAYA,GAAK,EACzBC,EAASD,CAAC,EAEZC,CACT,EANK,MAOP,EAEaC,GAAN,MAAMA,WAAwB,WAAY,CA+E/C,aAAc,CACZ,MAAA,EA/DF,KAAU,WAAsB,GAChC,KAAU,OAAiB,GAQ3B,KAAQ,SAAmB,GAiB3B,KAAQ,eAA0B,CAAA,EAClC,KAAQ,YAA+B,IAgBvC,KAAQ,WAA6B,IAcrC,KAAQ,YAA+B,IAQrC,KAAK,OAAS,IAAIP,GAElB,MAAMQ,EAAS,KAAK,aAAa,CAAE,KAAM,OAAQ,EAE3CC,EAAQ,SAAS,cAAc,OAAO,EAC5CA,EAAM,YAAcF,GAAgB,OACpCC,EAAO,YAAYC,CAAK,EAExB,KAAK,eAAiB,SAAS,cAAc,KAAK,EAClDD,EAAO,YAAY,KAAK,cAAc,CACxC,CAzFA,WAAW,oBAAqB,CAC9B,MAAO,CAAC,SAAS,CACnB,CAiBA,IAAI,OAAe,CACjB,OAAO,KAAK,MACd,CAGA,IAAI,SAAkB,CACpB,OAAO,KAAK,QACd,CACA,IAAI,QAAQE,EAAa,CACvB,KAAK,SAAWA,EAChB,KAAK,aAAa,UAAWA,CAAG,EAIhC,KAAK,cAAc,IAAI,YAAY,gBAAiB,CAClD,OAAQ,KAAK,OACb,QAAS,GACT,SAAU,EAAA,CACX,CAAC,CACJ,CAIA,IAAI,QAA0B,CAC5B,OAAO,KAAK,OACd,CACA,IAAI,OAAOC,EAAgC,CACzC,KAAK,QAAQ,MAAA,EACTA,aAAe,IACjB,KAAK,QAAUA,EACN,MAAM,QAAQA,CAAG,GAC1BA,EAAI,WAAa,KAAK,QAAQ,IAAIC,EAAE,GAAIA,CAAC,CAAC,CAE9C,CACA,IAAI,eAAyB,CAC3B,OAAO,MAAM,KAAK,KAAK,eAAe,QAAQ,CAChD,CAGA,IAAI,OAAwB,CAC1B,OAAO,KAAK,MACd,CACA,IAAI,MAAMC,EAAgC,CACxC,KAAK,OAAO,MAAA,EACRA,aAAiB,IACnB,KAAK,OAASA,EACL,MAAM,QAAQA,CAAK,IAC5B,KAAK,WAAa,IAClBA,EAAM,WAAa,KAAK,OAAO,IAAI,EAAE,GAAI,CAAC,CAAC,EAE/C,CAGA,IAAI,QAA0B,CAC5B,OAAO,KAAK,OACd,CAiBA,mBAA0B,CACxBX,GAAI,2BAA2B,EAC/B,KAAK,OAAA,CACP,CAOA,aAAaY,EAAuB,aACJ,CAAC,QAAS,QAAS,SAAU,SAAU,aAAc,UAAW,eAAgB,WAAY,WAAW,EAG3H,QAASpD,GAAS,OAC1B,MAAMqD,EAAOD,EAAapD,CAAI,EAC9B,GAAI,GAACmB,EAAAkC,GAAA,YAAAA,EAAK,OAAL,MAAAlC,EAAW,QAAQ,OAExB,MACEW,EAAqBuB,EAAI,KACzBC,EAAqBD,EAAI,OAAS,CAAA,EAClCE,EAAsB,OAAO,KAAKzB,EAAK,CAAC,CAAC,EACzCpB,EAAsBoB,EAAK,IAAKvB,GAAW,OAAO,OAAOA,CAAC,CAAC,EAC3DI,EAAsB4C,EAAS,IAAIxC,GAAQuC,EAAMvC,CAAG,GAAK,WAAsB,EAIjF,IAAIyC,EACAxD,IAAS,WACXwD,EAAQ,OACCxD,IAAS,YAClBwD,EAAQ,KACCxD,IAAS,QAClBwD,EAAQJ,EAAK,aACRG,EAAS,SAAWD,EAAM1C,CAAC,GAAK,eAAiB,WAAW,EACxDZ,IAAS,SAAWA,IAAS,UAAYA,IAAS,eAC3DwD,EAAQJ,EAAK,QACRG,EAAS,SAAWD,EAAM1C,CAAC,GAAK,eAAiB,WAAW,EAGjE4C,EAAQJ,EAAK,WACRG,EAAS,SAAWD,EAAM1C,CAAC,GAAK,eAAiB,WAAW,EAGnE,MAAM6C,EAAaD,EAAQD,EAAS,QAAQC,CAAK,EAAI,EAC/CtD,EAAaQ,EAAU,IAAKH,GAAW,OAAOA,EAAEkD,CAAU,CAAC,CAAC,EAClE,KAAK,OAAO,SAASzD,EAAM,IAAIgC,GAAUuB,EAAU7C,EAAWR,EAAUS,CAAO,CAAC,CAClF,CAAC,EAGGyC,EAAK,UAAa,QAAW,KAAK,OAAO,SAAS,UAAWA,EAAK,OAAO,EACzEA,EAAK,WAAa,SAAW,KAAK,OAAO,SAAWA,EAAK,UACzD,MAAM,QAASA,EAAa,OAAO,IAAG,KAAK,OAAO,QAAWA,EAAa,QAAQ,IAAI,MAAM,GAMhG,MAAMM,EAAU,KAAK,OAAO,MAC5B,KAAK,OAAO,YAAcN,EAAK,eAC1BjC,EAAAuC,GAAA,YAAAA,EAAS,QAAT,YAAAvC,EAAgB,KAAKwB,GAAA,OAAK,QAAAxB,EAAAuC,EAAQ,IAAIf,CAAC,IAAb,YAAAxB,EAAgB,QAAS,gBACnD,KAGL,MAAMwC,EAAW,KAAK,OAAO,OAC7B,KAAK,OAAO,YAAcP,EAAK,UAC1BQ,EAAAD,GAAA,YAAAA,EAAU,QAAV,YAAAC,EAAiB,KAAKjB,GAAA,OAAK,QAAAxB,EAAAwC,EAAS,IAAIhB,CAAC,IAAd,YAAAxB,EAAiB,QAAS,gBACrD,KAGL,MAAM0C,EAAS,KAAK,OAAO,YAS3B,GARA,KAAK,OAAO,UAAYT,EAAK,aACxBU,EAAAH,GAAA,YAAAA,EAAU,QAAV,YAAAG,EAAiB,KAAKnB,GAAA,OAAK,OAAAA,IAAMkB,KAAU1C,EAAAwC,EAAS,IAAIhB,CAAC,IAAd,YAAAxB,EAAiB,QAAS,gBACrE,MAMD4C,EAAAL,GAAA,YAAAA,EAAS,QAAT,MAAAK,EAAgB,OAAQ,CAC1B,MAAMC,EAAU,KAAK,OAAO,YACtBC,EAAUb,EAAK,MACfc,EAAUd,EAAK,MACrB,GAAIa,GAAWC,EACb,KAAK,OAAO,WAAa,CAACD,EAASC,CAAO,MACrC,CACL,MAAMC,EAAUT,EAAQ,MAAM,OAAOf,GAAK,CACxC,GAAIA,IAAMqB,EAAQ,MAAO,GACzB,MAAMjD,EAAM2C,EAAQ,IAAIf,CAAC,EACzB,OAAO5B,GAAOA,EAAI,OAAS,aAAeA,EAAI,OAAS,SACzD,CAAC,EACGoD,EAAQ,QAAU,IACpB,KAAK,OAAO,WAAa,CAACF,GAAWE,EAAQ,CAAC,EAAGD,GAAWC,EAAQ,CAAC,CAAC,EAE1E,CACF,CAEA,KAAK,QAAU,KAAK,OAAO,UAAY,OAAY,OAAO,KAAK,OAAO,OAAO,EAAI,OAAO,KAAK,KAAK,EAClG3B,GAAI,kCAAmC,KAAK,OAAO,EACnD,KAAK,OAAA,CACP,CAMA,MAAM,WAA2B,CAAC,CAElC,QAAe,OACR,KAAK,WAGR,KAAK,UAAU,OAAO,QAAQ,EAF9B,KAAK,UAAU,IAAI,QAAQ,IAKzBrB,EAAA,KAAK,SAAL,YAAAA,EAAa,WAAY,QAAa,KAAK,OAAO,UAAY,KAChE,KAAK,eAAe,UAAY,GAAG,KAAK,MAAM,gBAE9C,KAAK,eAAe,UAAY,+BAEpC,CACF,EAvNiDvB,EAAAiD,GAAA,mBAC/CA,GAAO,QAAU,YAMjBA,GAAO,OAAS;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAPX,IAAMuB,GAANvB,GAwNP,eAAe,OAAOuB,GAAgB,QAASA,EAAe,ECzOvD,MAAMC,GAAN,MAAMA,EAAM,CAGjB,YAAYC,EAAsB,CAChC,YAAK,KAAO,OAAOA,GAAS,SAAWA,EAAOA,EAAK,KAG5C,IAAI,MAAM,KAAM,CACrB,IAAIC,EAAQC,EAAM,CAChB,GAAI,OAAOA,GAAS,UAAY,UAAU,KAAKA,CAAI,EAAG,CACpD,KAAM,CAAE,EAAA9C,EAAG,EAAA+C,EAAG,EAAAC,CAAA,EAAML,GAAM,WAAWE,EAAO,IAAI,EAChD,MAAO,CAAC7C,EAAG+C,EAAGC,CAAC,EAAE,OAAOF,CAAI,CAAC,CAC/B,CACA,OAAQD,EAAeC,CAAI,CAC7B,CAAA,CACD,CACH,CAEA,UAAmB,CACjB,OAAO,KAAK,IACd,CAEA,QAAQF,EAAoB,CAC1B,KAAK,KAAOA,CACd,CAEA,OAAO,WAAWK,EAAoD,CAEpE,GAAIA,EAAM,WAAW,GAAG,EAAG,CACzB,MAAMC,EAAS,SAASD,EAAM,MAAM,CAAC,EAAG,EAAE,EAC1C,MAAO,CACL,EAAIC,GAAU,GAAM,IACpB,EAAIA,GAAU,EAAK,IACnB,EAAGA,EAAS,GAAA,CAEhB,CACA,MAAM,IAAI,MAAM,0BAA0B,CAC5C,CAEA,OAAO,IAAIlD,EAAW+C,EAAWC,EAAmB,CAClD,MAAO,OAAOhD,CAAC,KAAK+C,CAAC,KAAKC,CAAC,GAC7B,CACF,EA1CmB9E,EAAAyE,GAAA,SAAZ,IAAMQ,GAANR,GA4CA,MAAMS,GAAN,MAAMA,WAAsBD,EAAM,CAKvC,YAAYP,EAAsBS,EAAgBC,EAAgB,CAChE,MAAMV,CAAI,EACV,KAAK,OAASS,EACd,KAAK,MAAQC,CACf,CAGA,OAAO,MAAMC,EAAkD,CAC7D,KAAM,CAAE,EAAAvD,EAAG,EAAA+C,EAAG,EAAAC,GAAMG,GAAM,WAAWI,CAAG,EAClCC,EAAKxD,EAAI,IAAKyD,EAAKV,EAAI,IAAKW,EAAKV,EAAI,IACrCW,EAAM,KAAK,IAAIH,EAAIC,EAAIC,CAAE,EAAGE,EAAM,KAAK,IAAIJ,EAAIC,EAAIC,CAAE,EACrDG,EAAIF,EAAMC,EACV/E,EAAI8E,EACJG,EAAIH,IAAQ,EAAI,EAAIE,EAAIF,EAC9B,IAAII,EAAI,EACR,GAAIF,EAAI,EACN,OAAQF,EAAA,CACN,KAAKH,EAAIO,IAAMN,EAAKC,GAAMG,GAAKJ,EAAKC,EAAK,EAAI,IAAM,EAAG,MACtD,KAAKD,EAAIM,IAAML,EAAKF,GAAMK,EAAI,GAAK,EAAG,MACtC,QAAUE,IAAMP,EAAKC,GAAMI,EAAI,GAAK,CAAA,CAGxC,MAAO,CAAE,EAAGE,EAAI,IAAK,EAAAD,EAAG,EAAAjF,CAAA,CAC1B,CAGA,OAAO,UAAUkF,EAAWD,EAAWjF,EAAWmF,EAAmB,CACnE,MAAM9E,EAAIL,EAAIiF,EACRG,EAAI/E,GAAK,EAAI,KAAK,IAAK6E,EAAI,GAAM,EAAI,CAAC,GACtCG,EAAIrF,EAAIK,EACd,IAAIc,EAAI,EAAG+C,EAAI,EAAGC,EAAI,EACtB,OAASe,EAAI,IAAO/D,EAAId,EAAG6D,EAAIkB,EAAGjB,EAAI,GAC7Be,EAAI,KAAO/D,EAAIiE,EAAGlB,EAAI7D,EAAG8D,EAAI,GAC7Be,EAAI,KAAO/D,EAAI,EAAG+C,EAAI7D,EAAG8D,EAAIiB,GAC7BF,EAAI,KAAO/D,EAAI,EAAG+C,EAAIkB,EAAGjB,EAAI9D,GAC7B6E,EAAI,KAAO/D,EAAIiE,EAAGlB,EAAI,EAAGC,EAAI9D,IAClBc,EAAId,EAAG6D,EAAI,EAAGC,EAAIiB,GAC/B,QAAQ,KAAK,OAAOjE,EAAIkE,GAAK,GAAG,CAAC,IAAI,KAAK,OAAOnB,EAAImB,GAAK,GAAG,CAAC,IAAI,KAAK,OAAOlB,EAAIkB,GAAK,GAAG,CAAC,IAAIF,EAAE,QAAQ,CAAC,CAAC,GACpH,CAYA,UAAmB,CACjB,KAAM,CAAE,EAAAD,EAAG,EAAAlF,CAAA,EAAMuE,GAAc,MAAM,KAAK,IAAI,EACxCe,EAAI,KAAK,IAAI,EAAG,KAAK,IAAI,KAAK,MAAM,CAAC,EACrCH,EAAI,KAAK,QAAU,OAAYG,EAAI,KAAK,IAAI,EAAG,KAAK,IAAI,EAAG,KAAK,KAAK,CAAC,EAC5E,OAAOf,GAAc,UAAUW,EAAGI,EAAGtF,EAAGmF,CAAC,CAC3C,CACF,EA7DyC9F,EAAAkF,GAAA,iBAAlC,IAAMgB,GAANhB,GC5CA,MAAMiB,GAAN,MAAMA,EAAU,CAqBrB,YAAYC,EAAwB,KAAM,CApB1C,KAAQ,QAAoB,CAAC,EAAG,EAAG,EAAG,EAAG,EAAG,CAAC,EAC7C,KAAQ,MAAkB,CAAC,IAAK,IAAK,IAAK,IAAK,IAAK,GAAG,EAoBjDA,IACF,KAAK,OAASA,EAElB,CArBA,IAAI,QAAS,CACX,OAAO,KAAK,OACd,CACA,IAAI,OAAOA,EAAgB,CACrBA,GAAQA,EAAK,SAAW,IAC1B,KAAK,QAAUA,EAEnB,CACA,IAAI,MAAO,CACT,OAAO,KAAK,KACd,CACA,IAAI,KAAKA,EAAgB,CACnBA,GAAQA,EAAK,SAAW,IAC1B,KAAK,MAAQA,EAEjB,CAQA,UAAW,CAIT,MAAO,UAHU,KAAK,KAAK,IAAI,CAACC,EAAG3F,IAAM,KAAK,OAAOA,CAAC,CAAC,EAAE,KAAK,GAAG,CAGtC,GAC7B,CAEA,UAAW,CACT,OAAO,OAAO,YAAY,KAAK,MAAM,IAAI,CAAC2F,EAAG3F,IAAM,CAAC2F,EAAG,KAAK,QAAQ3F,CAAC,CAAC,CAAC,CAAC,CAC1E,CAEA,SAAU,CACR,OAAO,KAAK,OACd,CAEA,IAAIZ,EAAYsD,EAAa,CACvBA,IAAQ,OAAUA,IAAQ,IAC5B,KAAK,QAAQ,KAAK,MAAM,aAAeiD,IAAMvG,CAAE,CAAC,EAAIsD,EAExD,CACA,IAAItD,EAAY,CACd,OAAO,KAAK,QAAQ,KAAK,MAAM,UAAUuG,GAAKA,IAAMvG,CAAE,CAAC,CACzD,CAEA,MAAMgG,EAAWH,EAAYG,EAAG,CAC9B,KAAK,EAAIA,EACT,KAAK,EAAIH,CACX,CAEA,KAAKW,EAAW,CACd,KAAK,EAAIA,EACT,KAAK,EAAIA,CACX,CAEA,IAAIP,EAAWQ,EAAW,CACxB,KAAK,EAAI,KAAK,EAAIR,EAClB,KAAK,EAAI,KAAK,EAAIQ,CACpB,CAEA,IAAI,EAAER,EAAW,CAAE,KAAK,IAAI,IAAKA,CAAC,CAAG,CACrC,IAAI,EAAEA,EAAW,CAAE,KAAK,IAAI,IAAKA,CAAC,CAAG,CACrC,IAAI,EAAEA,EAAW,CAAE,KAAK,IAAI,IAAKA,CAAC,CAAG,CACrC,IAAI,EAAEA,EAAW,CAAE,KAAK,IAAI,IAAKA,CAAC,CAAG,CACrC,IAAI,EAAEA,EAAW,CAAE,KAAK,IAAI,IAAKA,CAAC,CAAG,CACrC,IAAI,EAAEA,EAAW,CAAE,KAAK,IAAI,IAAKA,CAAC,CAAG,CAErC,IAAI,GAAI,CAAE,OAAO,KAAK,IAAI,GAAG,CAAG,CAChC,IAAI,GAAI,CAAE,OAAO,KAAK,IAAI,GAAG,CAAG,CAChC,IAAI,GAAI,CAAE,OAAO,KAAK,IAAI,GAAG,CAAG,CAChC,IAAI,GAAI,CAAE,OAAO,KAAK,IAAI,GAAG,CAAG,CAChC,IAAI,GAAI,CAAE,OAAO,KAAK,IAAI,GAAG,CAAG,CAChC,IAAI,GAAI,CAAE,OAAO,KAAK,IAAI,GAAG,CAAG,CAClC,EA/EuB/F,EAAAmG,GAAA,aAAhB,IAAMK,GAANL,GCsXA,IAAUM,IAAAA,GAAV,EACYC,GAAV,CACE,SAASC,EAAaC,EAAwC,CAEnE,MAAO,UADW,CAAC,IAAK,IAAK,IAAK,IAAK,IAAK,GAAG,EAAE,OAASA,EAAO3F,CAAC,CAAC,EAAE,KAAK,GAAG,CACnD,GAC5B,CAHgBjB,EAAA2G,EAAA,gBAATD,EAAS,aAAAC,CAAA,GADDF,EAAA,SAAAA,EAAA,OAAA,CAAA,EAAA,GAOAI,GAAV,EACYC,GAAV,CACE,SAASC,EAAUC,EAAyBC,EAAeC,EAAoC,CACpG,MAAMpF,EAAIqF,EAAM,MAAMF,CAAK,EAC3B,MAAO,CAACD,EAAM,CAAC,EAAIE,EAAW,KAAK,IAAIpF,CAAC,EAAGkF,EAAM,CAAC,EAAIE,EAAW,KAAK,IAAIpF,CAAC,CAAC,CAC9E,CAHgB9B,EAAA+G,EAAA,aAATD,EAAS,UAAAC,EAKT,SAASK,EAAOJ,EAAyBC,EAAeI,EAA6C,CAC1G,MAAMvF,EAAIqF,EAAM,MAAMF,CAAK,EAE3B,SAASK,EAAYhE,EAAqBwC,EAA6B,CACrE,MAAO,CACLxC,EAAE,CAAC,EAAI,KAAK,IAAIwC,CAAC,EAAIxC,EAAE,CAAC,EAAI,KAAK,IAAIwC,CAAC,EACtCxC,EAAE,CAAC,EAAI,KAAK,IAAIwC,CAAC,EAAIxC,EAAE,CAAC,EAAI,KAAK,IAAIwC,CAAC,CAAA,CAE1C,CAEA,GAPS9F,EAAAsH,EAAA,eAOL,CAACD,GAAWA,EAAO,CAAC,IAAM,GAAKA,EAAO,CAAC,IAAM,EAC/C,OAAOC,EAAYN,EAAOlF,CAAC,EACtB,CACL,MAAMyF,EAAKP,EAAM,IAAI,CAAC,EAAGtG,IAAM,EAAI2G,EAAO3G,CAAC,CAAC,EAE5C,OADgB4G,EAAYC,EAAIzF,CAAC,EAClB,IAAI,CAAC,EAAGpB,IAAM,EAAI2G,EAAO3G,CAAC,CAAC,CAC5C,CACF,CAjBgBV,EAAAoH,EAAA,UAATN,EAAS,OAAAM,CAAA,GANDP,EAAA,QAAAA,EAAA,MAAA,CAAA,EAAA,GA0BAW,GAAV,CACE,SAASC,EAAMC,EAAsBC,EAA8B,CACxE,OAAQA,EAAG,CAAC,EAAID,EAAG,CAAC,IAAMC,EAAG,CAAC,EAAID,EAAG,CAAC,EACxC,CAFgB1H,EAAAyH,EAAA,SAATD,EAAS,MAAAC,EAGT,SAASG,EAAUF,EAAsBC,EAA8B,CAC5E,MAAM3B,EAAIyB,EAAMC,EAAIC,CAAE,EACtB,OAAOD,EAAG,CAAC,EAAI1B,EAAI0B,EAAG,CAAC,CACzB,CAHgB1H,EAAA4H,EAAA,aAATJ,EAAS,UAAAI,EAIT,SAASC,EAAeH,EAAsBC,EAA4D,CAC/G,MAAO,CACL,MAAOF,EAAMC,EAAIC,CAAE,EACnB,UAAWC,EAAUF,EAAIC,CAAE,CAAA,CAE/B,CALgB3H,EAAA6H,EAAA,kBAATL,EAAS,eAAAK,EAMT,SAASC,EAAYC,EAA4Cb,EAAmB,EAAqB,CAC9G,MAAMc,EAAQd,EACRe,GAAO,EAAID,GAASD,EAAK,CAAC,EAAE,CAAC,EAAKC,EAAQD,EAAK,CAAC,EAAE,CAAC,EACnDG,GAAO,EAAIF,GAASD,EAAK,CAAC,EAAE,CAAC,EAAKC,EAAQD,EAAK,CAAC,EAAE,CAAC,EACzD,MAAO,CAACE,EAAIC,CAAE,CAChB,CALgBlI,EAAA8H,EAAA,eAATN,EAAS,YAAAM,EAMT,SAASK,EAAST,EAAsBC,EAAsB1B,EAAI,GAAuB,CAC9F,OAAI,MAAM,QAAQyB,EAAG,CAAC,CAAC,IACrBC,EAAMD,EAAG,CAAC,EACVA,EAAMA,EAAG,CAAC,GAGL,CAAC,EAAG,CAAC,EAAE,QAAU,WAAWA,EAAGhH,CAAC,CAAQ,EAAI,WAAWiH,EAAGjH,CAAC,CAAQ,GAAKuF,CAAC,CAClF,CAPgBjG,EAAAmI,EAAA,YAATX,EAAS,SAAAW,EAQT,SAASC,EACdV,EACAC,EACQ,CACR,OAAI,MAAM,QAASD,EAAW,CAAC,CAAC,IAC9BC,EAAMD,EAA4C,CAAC,EACnDA,EAAMA,EAA4C,CAAC,GAE9C,KAAK,KACV,CAAC,EAAG,CAAC,EAAE,IAAIhH,GAAK,KAAK,IAAKiH,EAAwBjH,CAAC,EAAKgH,EAAwBhH,CAAC,EAAG,CAAC,CAAC,EAAE,OAAO,CAACoF,EAAGhB,IAAMgB,EAAIhB,EAAG,CAAC,CAAA,CAErH,CAXgB9E,EAAAoI,EAAA,UAATZ,EAAS,OAAAY,EAYT,SAAShB,EACdW,EACAM,EAAuB,CAAC,EAAG,CAAC,EACU,CACtC,MAAMC,EAA+B,CACnCP,EAAK,CAAC,EAAE,CAAC,EAAIM,EAAG,CAAC,EACjBN,EAAK,CAAC,EAAE,CAAC,EAAIM,EAAG,CAAC,CAAA,EAEbE,EAA4B,CAChC,CAACD,EAAW,CAAC,EACbA,EAAW,CAAC,CAAA,EAERE,EAAuC,CAC3C,CAACD,EAAQ,CAAC,EACV,CAACA,EAAQ,CAAC,CAAA,EAENE,EAAiC,CACrCF,EAAQ,CAAC,EAAIF,EAAG,CAAC,EACjBE,EAAQ,CAAC,EAAIF,EAAG,CAAC,CAAA,EAEbK,EAAkC,CACtCF,EAAmB,CAAC,EAAIH,EAAG,CAAC,EAC5BG,EAAmB,CAAC,EAAIH,EAAG,CAAC,CAAA,EAE9B,MAAO,CAACI,EAAcC,CAAa,CACrC,CAzBgB1I,EAAAoH,EAAA,UAATI,EAAS,OAAAJ,EA0BT,SAASuB,EACdZ,EACAa,EACA3B,EAAgB,GACsB,CAEtC,MAAMjB,EAAIS,EAAM,SAAS,KAAK,MAAMsB,EAAK,CAAC,EAAGA,EAAK,CAAC,CAAC,EAC9ChF,EAAI0D,EAAM,SAAS,KAAK,UAAUsB,EAAK,CAAC,EAAGA,EAAK,CAAC,CAAC,EAClDc,EAAsB,CAAC,EAAG9F,CAAC,EAC3B+F,EAAsB,CAAC,EAAG9C,EAAIjD,CAAC,EACrCgF,EAAO,CAACc,EAAGC,CAAC,EAEZ,MAAMC,GAAK,CAAChB,EAAK,CAAC,EAAE,CAAC,EAAGA,EAAK,CAAC,EAAE,CAAC,CAAC,EAC5BiB,GAAK,CAACjB,EAAK,CAAC,EAAE,CAAC,EAAGA,EAAK,CAAC,EAAE,CAAC,CAAC,EAC5BkB,GAAUL,EAAM,CAAC,EACjBM,GAAUN,EAAM,CAAC,EACjBO,EAAY,GAAK,KAAK,GAAKlC,EAAQ,IACnCmC,GAASL,GAAG,IAAI,CAAChD,GAAGrF,MACvBqF,GAAIkD,IAAW,KAAK,IAAIE,CAAS,GAAKH,GAAGtI,EAAC,EAAIwI,IAAW,KAAK,IAAIC,CAAS,EAAIF,EAAA,EAE5EI,GAASL,GAAG,IAAI,CAACzC,GAAG7F,MACvBqI,GAAGrI,EAAC,EAAIuI,IAAW,KAAK,IAAIE,CAAS,GAAK5C,GAAI2C,IAAW,KAAK,IAAIC,CAAS,EAAID,EAAA,EAOlF,MALyD,CACvD,CAACE,GAAO,CAAC,EAAGC,GAAO,CAAC,CAAC,EACrB,CAACD,GAAO,CAAC,EAAGC,GAAO,CAAC,CAAC,CAAA,CAIzB,CA7BgBrJ,EAAA2I,EAAA,WAATnB,EAAS,QAAAmB,EA8BT,SAASW,EACdC,EACAC,EACkB,CAClB,KACE,CAAC,CAACC,EAAIC,CAAE,EAAG,CAACC,EAAIC,CAAE,CAAC,EAAIL,EACvB,CAAC,CAACM,EAAIC,EAAE,EAAG,CAACC,GAAIC,EAAE,CAAC,EAAIR,EACvBS,IAAMR,EAAKE,IAAOG,GAAKE,KAASN,EAAKE,IAAOC,EAAKE,IACjDG,GAAUT,EAAKG,EAAOF,EAAKC,IAAQE,EAAKE,KACpCN,EAAKE,IAAQE,EAAKG,GAAOF,GAAKC,IAClCI,IAAUV,EAAKG,EAAOF,EAAKC,IAAQG,GAAKE,KACpCN,EAAKE,IAAQC,EAAKG,GAAOF,GAAKC,IACpC,MAAO,CAACG,EAAOD,GAAGE,GAAOF,EAAC,CAC5B,CAbgBjK,EAAAsJ,EAAA,gBAAT9B,EAAS,aAAA8B,EAcT,SAASc,EAAiBrC,EAA4CsC,EAA6BC,EAAwD,CAChK,GAAI,CAAE,MAAOtE,EAAG,UAAWjD,GAAM0D,EAAM,SAAS,KAAK,eAAesB,EAAK,CAAC,EAAGA,EAAK,CAAC,CAAC,EAElFjC,EAAI,EAAI,KAAK,IAAIE,EAAG,CAAC,EACrBlB,EAAI,EAAIkB,EAAIjD,EAAI,EAAIsH,EAAU,CAAC,EAAIrE,EAAI,EAAIqE,EAAU,CAAC,EACtDrJ,GAAI,KAAK,IAAIqJ,EAAU,CAAC,EAAG,CAAC,EAAI,KAAK,IAAItH,EAAG,CAAC,EAAI,KAAK,IAAIsH,EAAU,CAAC,EAAG,CAAC,EAAI,EAAIA,EAAU,CAAC,EAAItH,EAAI,KAAK,IAAIuH,EAAU,CAAC,EACxHC,GAA4C,CAAC,CAAC,IAAU,GAAQ,EAAG,CAAC,IAAU,GAAQ,CAAC,EAGzF,GAAI,KAAK,KAAK,KAAK,IAAIzF,EAAG,CAAC,EAAK,EAAIgB,EAAI9E,EAAE,GAAK,EAAG,CAChD,IACEyI,IAAM,CAAC3E,EAAI,KAAK,KAAK,KAAK,IAAIA,EAAG,CAAC,EAAK,EAAIgB,EAAI9E,EAAE,IAAM,EAAI8E,GAC3D6D,IAAM,CAAC7E,EAAI,KAAK,KAAK,KAAK,IAAIA,EAAG,CAAC,EAAK,EAAIgB,EAAI9E,EAAE,IAAM,EAAI8E,GAC3D4D,EAAK1D,EAAIyD,GAAK1G,EACd6G,GAAK5D,EAAI2D,GAAK5G,EAEhBwH,GAAM,CAAC,CAACd,GAAIC,CAAE,EAAG,CAACC,GAAIC,EAAE,CAAC,CAC3B,MAEE,QAAQ,MAAM,iDAAiD,EAGjE,OAAQW,EACV,CAvBgBvK,EAAAoK,EAAA,oBAAT5C,EAAS,iBAAA4C,EAwBT,SAASI,EAAYzC,EAA6E,CAEvG,OAAO0C,GACLA,IAAM,EACJ1C,EAAK,CAAC,EACN0C,IAAM,EACJ1C,EAAK,CAAC,EACNtB,EAAM,SAAS,MAAM,UAAUsB,EAAK,CAAC,EAAGtB,EAAM,SAAS,MAAM,KAAKsB,CAAI,EAAGtB,EAAM,SAAS,KAAK,OAAOsB,CAAI,EAAI0C,CAAC,CAErH,CATgBzK,EAAAwK,EAAA,eAAThD,EAAS,YAAAgD,CAAA,GAtID3D,EAAA,OAAAA,EAAA,KAAA,CAAA,EAAA,EAkJV,IAAUM,GAAAA,GAAV,CACE,SAASuD,EAAMzD,EAAuB,CAC3C,OAAQA,EAAQ,IAAO,KAAK,EAC9B,CAFgBjH,EAAA0K,EAAA,SAATvD,EAAS,MAAAuD,EAIT,SAASC,EAAM1D,EAAuB,CAC3C,OAAQA,EAAQ,IAAO,KAAK,EAC9B,CAFgBjH,EAAA2K,EAAA,SAATxD,EAAS,MAAAwD,EAIT,SAAS5C,EAAKA,EAAoD,CACvE,GAAIA,EAAK,SAAW,GAAK,CAAC,MAAM,QAAQA,EAAK,CAAC,CAAC,GAAK,CAAC,MAAM,QAAQA,EAAK,CAAC,CAAC,GAAKA,EAAK,CAAC,EAAE,SAAW,GAAKA,EAAK,CAAC,EAAE,SAAW,EACxH,MAAM,IAAI,MAAM,qDAAqD,EAGvE,OAAOtB,EAAM,SAAS,MAAM,MAC1B,KAAK,MAAMsB,EAAK,CAAC,EAAE,CAAC,EAAIA,EAAK,CAAC,EAAE,CAAC,EAAGA,EAAK,CAAC,EAAE,CAAC,EAAIA,EAAK,CAAC,EAAE,CAAC,CAAC,CAAA,CAE/D,CARgB/H,EAAA+H,EAAA,QAATZ,EAAS,KAAAY,CAAA,GATDZ,EAAAN,EAAA,QAAAA,EAAA,MAAA,CAAA,EAAA,CAAA,GA7KFJ,EAAA,WAAAA,EAAA,SAAA,CAAA,EAAA,GAkMAmE,GAAV,CACE,SAASC,EAAUC,EAAe,CACvC,MAAO,CAAC,GAAG,IAAI,IAAIA,CAAG,CAAC,CACzB,CAFgB9K,EAAA6K,EAAA,UAATD,EAAS,OAAAC,EAIT,SAASE,EAAOjF,EAAsBhB,EAAyC,CACpF,GAAI,MAAM,QAAQgB,CAAC,EAAG,CACpB,GAAI,MAAM,QAAQhB,CAAC,EAAG,CACpB,GAAIgB,EAAE,SAAWhB,EAAE,OAAQ,MAAM,IAAI,MAAM,gCAAgC,EAC3E,OAAOgB,EAAE,IAAI,CAAC1C,EAAK1C,IAAM0C,EAAM0B,EAAEpE,CAAC,CAAC,CACrC,CACA,OAAOoF,EAAE,IAAI1C,GAAOA,EAAO0B,CAAY,CACzC,CACA,OAAQgB,EAAgBhB,CAC1B,CATgB9E,EAAA+K,EAAA,UAATH,EAAS,OAAAG,EAWT,SAASC,EAAQC,EAAmB,CACzC,OAAO,OAAO,MAAM,SAAY,WAAa,MAAM,QAAQA,CAAG,EAC3DA,GAAO,OAAOA,GAAQ,UAAYA,EAAI,YAAY,OAAS,OAChE,CAHgBjL,EAAAgL,EAAA,WAATJ,EAAS,QAAAI,CAAA,GAhBDvE,EAAA,aAAAA,EAAA,WAAA,CAAA,EAAA,GAsBAyE,GAAV,CACE,SAASC,EAAIL,EAAuB,CACzC,OAAOA,EAAI,OAAO,CAAChF,EAAGhB,IAAMgB,EAAIhB,EAAG,CAAC,CACtC,CAFgB9E,EAAAmL,EAAA,OAATD,EAAS,IAAAC,EAIT,SAASC,EAAKN,EAAuB,CAC1C,OAAOK,EAAIL,CAAG,EAAIA,EAAI,MACxB,CAFgB9K,EAAAoL,EAAA,QAATF,EAAS,KAAAE,EAIT,SAASC,EAAM5I,EAAe6I,EAA0B,CAC7D,MAAMC,EAAS,KAAK,IAAI,GAAID,CAAQ,EACpC,OAAO,KAAK,MAAM7I,EAAQ8I,CAAM,EAAIA,CACtC,CAHgBvL,EAAAqL,EAAA,SAATH,EAAS,MAAAG,CAAA,GATD5E,EAAA,cAAAA,EAAA,YAAA,CAAA,EAAA,GAeA+E,GAAV,CACE,SAASC,EAAYrL,EAAcsL,EAAuBlI,EAAyB,CACxF,OAAO,IAAI,YAAYpD,EAAM,CAC3B,QAAS,GACT,WAAY,GACZ,OAAQ,CACN,QAAAsL,EACA,KAAMlI,IAASkI,EAAWA,EAAgB,SAAW,OAAA,CACvD,CACD,CACH,CATgB1L,EAAAyL,EAAA,eAATD,EAAS,YAAAC,CAAA,GADDhF,EAAA,SAAAA,EAAA,OAAA,CAAA,EAAA,GAaAkF,GAAV,CACE,SAASC,GAAoB,CAClC,OAAO,SAAS,KACb,QAAQ,IAAK,EAAE,EACf,MAAM,IAAI,EACV,OAAO9F,GAAKA,CAAC,EACb,OAASA,EAAE,MAAM,GAAG,CAAC,CAC1B,CANgB9F,EAAA4L,EAAA,SAATD,EAAS,MAAAC,EAQT,SAASC,EAAOrJ,EAAsB,CAC3C,OAAOoJ,EAAA,EAAQ,OAAO,UAAU9F,GAAKA,IAAMtD,CAAG,GAAK,CACrD,CAFgBxC,EAAA6L,EAAA,UAATF,EAAS,OAAAE,CAAA,GATDpF,EAAA,OAAAA,EAAA,KAAA,CAAA,EAAA,GAeAqF,GAAV,CACE,SAASC,EAAwBd,EAAQe,EAA4BC,EAAO,GAAU,CAC3F,GAAKA,EAEE,CACL,GAAI,OAAOhB,GAAQ,UAAYA,IAAQ,KACrC,OAAOA,EAGT,UAAWzI,KAAOyI,EACZ,OAAO,UAAU,eAAe,KAAKA,EAAKzI,CAAG,IAC9CyI,EAAYzI,CAAG,EAAIuJ,EAAOd,EAAYzI,CAAG,EAAGwJ,EAASC,CAAI,GAI9D,OAAO,IAAI,MAAMhB,EAAKe,CAAO,CAC/B,KAbE,QAAO,IAAI,MAAMf,EAAKe,CAAO,CAcjC,CAhBgBhM,EAAA+L,EAAA,SAATD,EAAS,MAAAC,EAkBHD,EAAA,QAA6B,CACxC,IAAInH,EAAQuH,EAAUzJ,EAAO,CAC3B,OAAAkC,EAAOuH,CAAQ,EAAIzJ,EACnB,OAAO,cACLgE,EAAM,OAAO,YAAY,gBAAiB,OAAe,CAAE,OAAA9B,EAAQ,SAAAuH,EAAU,MAAAzJ,CAAA,CAAO,CAAA,EAE/E,EACT,EACA,IAAIkC,EAAQuH,EAAU,CACpB,OAAOvH,EAAOuH,CAAQ,CACxB,CAAA,EAGK,SAASC,EAAIlB,EAAUzI,EAAkB,CAC9C,MAAMoJ,EAAQpJ,EAAI,MAAM,GAAG,EAC3B,IAAI4J,EAAUnB,EACd,UAAWoB,KAAQT,EACjB,GAAIQ,GAAW,OAAOA,GAAY,UAAY,OAAO,UAAU,eAAe,KAAKA,EAASC,CAAI,EAC9FD,EAAUA,EAAQC,CAAI,MAEtB,QAGJ,OAAOD,CACT,CAXgBpM,EAAAmM,EAAA,OAATL,EAAS,IAAAK,EAaT,SAASG,EAAIrB,EAAUzI,EAAaC,EAAqB,CAC9D,MAAMmJ,EAAQpJ,EAAI,MAAM,GAAG,EAC3B,IAAI4J,EAAUnB,EACVvK,EAEJ,IAAKA,EAAI,EAAGA,EAAIkL,EAAM,OAAS,EAAGlL,IAAK,CACrC,MAAM2L,EAAOT,EAAMlL,CAAC,EACpB,GAAI0L,GAAW,OAAOA,GAAY,SAC3B,OAAO,UAAU,eAAe,KAAKA,EAASC,CAAI,IACrDD,EAAQC,CAAI,EAAI,CAAA,GAElBD,EAAUA,EAAQC,CAAI,MAEtB,OAAO,EAEX,CAEA,OAAID,GAAW,OAAOA,GAAY,UAChCA,EAAQR,EAAMlL,CAAC,CAAC,EAAI+B,EACb,IAEA,EAEX,CAvBgBzC,EAAAsM,EAAA,OAATR,EAAS,IAAAQ,CAAA,GA7CD7F,EAAA,UAAAA,EAAA,QAAA,CAAA,EAAA,GAuEA8F,GAAV,CACE,SAASC,EAAMC,EAAqB,OAAO,SAAkC,CAClF,OAAO,OAAO,YAAY,IAAI,gBAAgBA,EAAS,MAAM,CAAC,CAChE,CAFgBzM,EAAAwM,EAAA,SAATD,EAAS,MAAAC,GAICE,GAAV,CACE,SAASF,EAAMC,EAAmB,OAAO,SAAS,OAAgC,CACvF,OAAO,OAAO,YACZA,EAAS,QAAQ,MAAO,EAAE,EAAE,MAAM,GAAG,EAAE,IAAI/L,GAAKA,EAAE,MAAM,GAAG,CAAC,CAAA,CAEhE,CAJgB8L,EAAAA,EAAAA,UAATE,EAAS,MAAAF,EAMT,SAASG,EAAKF,EAAmB,OAAO,SAAS,OAAkB,CACxE,OAAOA,EAAS,QAAQ,MAAO,EAAE,EAAE,MAAM,GAAG,EAAE,OAAS/L,EAAE,MAAM,GAAG,EAAE,CAAC,CAAC,CACxE,CAFgBV,EAAA2M,EAAA,QAATD,EAAS,KAAAC,EAIT,SAASC,EAAIpK,EAAaiK,EAAmB,OAAO,SAAS,OAAiB,CACnF,OAAOE,EAAKF,CAAQ,EAAE,UAAU/L,GAAKA,IAAM8B,CAAG,GAAK,CACrD,CAFgBxC,EAAA4M,EAAA,OAATF,EAAS,IAAAE,CAAA,GAXDL,EAAA,QAAAA,EAAA,MAAA,CAAA,EAAA,CAAA,GALF9F,EAAA,MAAAA,EAAA,IAAA,CAAA,EAAA,CAAA,GAlVFA,KAAAA,GAAA,CAAA,EAAA,EChXV,MAAMoG,GAAN,MAAMA,EAAS,CAAf,aAAA,CACL,KAAQ,WAA+B,IACvC,KAAQ,cAAiE,GAAI,CAE7E,IAAI,OAA0B,CAC5B,OAAO,KAAK,MACd,CAEA,YAAYrK,EAAsB,CAChC,OAAO,KAAK,OAAO,IAAIA,CAAG,CAC5B,CAEA,YAAYA,EAAkB,CAC5B,OAAO,KAAK,OAAO,IAAIA,CAAG,CAC5B,CAEA,YAAYA,EAAaC,EAAYqK,EAAoC,CACvE,MAAMC,EAAW,KAAK,OAAO,IAAIvK,CAAG,EACpC,KAAK,OAAO,IAAIA,EAAKC,CAAK,EACrBqK,GAAA,MAAAA,EAAS,MACZ,KAAK,gBAAgBtK,EAAKC,EAAOsK,CAAQ,CAE7C,CAEA,YAAYvK,EAAawK,EAAcC,EAAkC,CAClE,KAAK,UAAU,IAAIzK,CAAG,GAAG,KAAK,UAAU,IAAIA,EAAK,IAAI,GAAK,EAC/D,MAAM0K,EAAU,KAAK,UAAU,IAAI1K,CAAG,EACjC0K,EAAQ,IAAIF,CAAI,KAAW,IAAIA,EAAM,IAAI,GAAK,EACnDE,EAAQ,IAAIF,CAAI,EAAG,IAAIC,CAAQ,CACjC,CAEA,eAAezK,EAAawK,EAAcC,EAAkC,UAC1EjJ,GAAAzC,EAAA,KAAK,UAAU,IAAIiB,CAAG,IAAtB,YAAAjB,EAAyB,IAAIyL,KAA7B,MAAAhJ,EAAoC,OAAOiJ,EAC7C,CAEA,aAAazK,EAAawK,EAAkC,OAC1D,OAAO,MAAM,OAAKzL,EAAA,KAAK,UAAU,IAAIiB,CAAG,IAAtB,YAAAjB,EAAyB,IAAIyL,KAAS,EAAE,CAC5D,CAEA,gBAAgBxK,EAAa2K,EAAeJ,EAAqB,CAC/D,MAAMG,EAAU,KAAK,UAAU,IAAI1K,CAAG,EACtC,GAAK0K,EACL,UAAWZ,KAAOY,EAAQ,SACxBZ,EAAI,QAASW,GAAa,CACpB,OAAOA,GAAa,WACtBA,EAAS,CAAE,IAAAzK,EAAK,SAAA2K,EAAU,SAAAJ,CAAA,CAAU,EAC3B,OAAQE,EAAiB,WAAc,YAC/CA,EAAiB,UAAU,KAAKA,EAAU,CAAE,IAAAzK,EAAK,SAAA2K,EAAU,SAAAJ,EAAU,CAE1E,CAAC,CAEL,CACF,EApDsB/M,EAAA6M,GAAA,YAAf,IAAMO,GAANP,GCJP,KAAM,CAAA,WAAEjC,IAAenE,GAWV4G,GAAN,MAAMA,WAAmB,KAAiB,CAC/C,eAAexK,EAAa,CAC1B,MAAM,GAAGA,CAAI,CACf,CAEA,OAAOL,EAAapC,EAAqC,CACvD,IAAIkN,EAEJ,SAASC,EAAGzH,EAAqC,CAC/C,OAAOA,EAAE,OAAS1F,EAAO0F,EAAI,MAC/B,CAFS9F,EAAAuN,EAAA,MAIT,SAASC,EAAQvC,EAAUvK,EAAYtB,EAAc,KAA6B,CAChF,GAAIwL,GAAW,QAAQK,CAAG,GACxB,SAAW,CAACvK,EAAG4B,CAAC,IAAK2I,EAAI,UAEvB,GADAqC,EAAQE,EAAQlL,EAAG5B,EAAGtB,CAAM,EACxBkO,EACF,OAAOA,MAGN,CAEL,GADAA,EAAQC,EAAGtC,CAAG,EACTqC,EAUH,OAAOA,EATP,GAAIrC,GAAOL,GAAW,QAAQK,EAAIzI,CAAG,CAAC,GACpC,SAAW,CAAC9B,EAAG4B,CAAC,IAAK2I,EAAIzI,CAAG,EAAE,UAE5B,GADA8K,EAAQE,EAAQlL,EAAG5B,EAAGuK,CAAG,EACrBqC,EACF,OAAOA,EAOjB,CACA,OAAOA,CACT,CAxBS,OAAAtN,EAAAwN,EAAA,WA0BFA,EAAQ,IAAI,CACrB,CAEA,SAAuB,CACrB,OAAO,KAAK,OAAoB,CAAC1H,EAAG7E,KAClC6E,EAAE,KAAK7E,CAAC,EACJA,EAAE,QAAU,MAAM,QAAQA,EAAE,MAAM,GACpC6E,EAAE,KAAK,GAAG7E,EAAE,MAAM,EAEb6E,GACN,CAAA,CAAE,CACP,CAEA,QACEtD,EACAiL,EACArO,EAA2B,KAC3BsO,EAAgB,EACX,CACL,IAAIC,EAAiB,IAAIN,GACzB,UAAWO,KAAS,KAAM,CACxB,IAAIC,EAASJ,EAASG,EAAOxO,EAAQsO,CAAK,EAE1C,GAAIE,EAAMpL,CAAG,GAAK,MAAM,QAAQoL,EAAMpL,CAAG,CAAC,EAAG,CAC3C,IAAIV,EAAI,IAAIuL,GAAW,GAAGO,EAAMpL,CAAG,CAAC,EAAE,QAAQA,EAAKiL,EAAUG,EAAOF,EAAQ,CAAC,EACzE5L,IAAM,QACR6L,EAAQ,KAAK,GAAG7L,CAAC,CAErB,CAEA6L,EAAQ,KAAKE,CAAM,CACrB,CACA,eAAQ,IAAI,oBAAqBF,CAAO,EACjCA,CACT,CACF,EAzEiD3N,EAAAqN,GAAA,cAA1C,IAAMS,GAANT,GA2EA,MAAMU,GAAN,MAAMA,EAAM,CAejB,YAAYC,EAAY1L,EAAQlD,EAAwB,CAdxD,KAAA,UAA0B,IAAI6O,GAI9B,KAAA,QAAkB,EAClB,KAAA,QAAkB,EAGlB,KAAA,cAAyB,GACzB,KAAA,OAAqB,IAAIH,GACzB,KAAA,YAA0C,IAE1C,KAAA,QAAmB,GAGjB,KAAK,GAAKE,EACV,KAAK,KAAO1L,EAAE,MAAQ,SAAS0L,CAAE,GACjC,KAAK,SAAW1L,EAAE,SAClB,KAAK,OAASlD,EACd,KAAK,WAAa,IAAIoH,GAEtBpH,GAAA,MAAAA,EAAQ,UAAU,YAAY,gBAAiB,OAAQ,CAAC,CAAE,IAAAoD,EAAK,SAAA2K,EAAU,SAAAJ,KAAe,CAExF,GAEA3N,GAAA,MAAAA,EAAQ,UAAU,YAAY,iBAAiB,KAAK,IAAI,GAAI,OAAQ,CAAC,CAAE,IAAAoD,EAAK,SAAA2K,EAAU,SAAAJ,CAAA,IAAe,CAEnG,KAAK,QAAUI,EACf,KAAK,UAAU,YAAY,gBAAiB,IAAK,CACnD,EACF,CAEA,IAAI,WAAuB,CACzB,OAAO,KAAK,UACd,CACA,IAAI,UAAU,EAAc,CAC1B,KAAK,WAAa,CACpB,CACF,EAvCmBnN,EAAA+N,GAAA,SAAZ,IAAMG,GAANH,GCzEA,MAAMI,GAAN,MAAMA,WAAwB,KAAkD,CAIrF,eAAetL,EAAgB,CAC7B,MAAM,UAAU,MAAM,EAJxBvD,GAAA,KAAA8O,GAAoB,IACpB9O,GAAA,KAAAG,IAIE,QAASiB,EAAI,EAAGA,EAAImC,EAAK,OAAQnC,IAC/B,KAAKA,CAAC,EAAImC,EAAKnC,CAAC,EAElBd,EAAA,KAAKwO,GAAW,GAClB,CAEA,OAAO,UAAUtD,EAAoC,CACnD,MAAMuD,EAAM,IAAIF,GAChB,OAAArD,EAAI,QAAQ,CAACnK,EAAGD,IAAM,CACpB2N,EAAI,KAAK1N,CAAC,CACZ,CAAC,EACDf,EAAAyO,EAAI5O,GAASqL,EAAI,OAEVuD,CACT,CAEA,MAAwB,CACtBzO,EAAA,KAAKwO,GAAW,CAACvO,EAAA,KAAKuO,KACtB,QAAS1N,EAAI,EAAGA,EAAI,KAAK,OAAQA,IAC/B,KAAKA,CAAC,EAAI,CAAC,KAAKA,CAAC,EAEnB,OAAO,IACT,CAEA,IAAIZ,EAAyC,CAC3C,OAAI,OAAOA,GAAO,SACT,KAAKA,CAAE,EACLD,EAAA,KAAKJ,KAAUI,EAAA,KAAKJ,IAAO,SAASK,CAAE,EACxC,KAAKD,EAAA,KAAKJ,IAAO,QAAQK,CAAE,CAAC,EAEnC,MAEJ,CAEA,IAAI,SAAmB,CACrB,OAAOD,EAAA,KAAKuO,GACd,CAEA,IAAI,OAAkB,CACpB,OAAIvO,EAAA,KAAKJ,IACAI,EAAA,KAAKJ,IAEL,KAAK,IAAI,CAACmC,EAAGlB,IAAM,IAAIA,EAAI,CAAC,EAAE,CAEzC,CACF,EAlDE0N,GAAA,YACA3O,GAAA,YAFqFO,EAAAmO,GAAA,mBAAhF,IAAMG,GAANH,GAoEA,MAAMI,GAAN,MAAMA,EAA8C,CAyEzD,YAAYC,EAA2BlM,EAAyB,CApEhE,KAAA,QAAkB,EAClB,KAAA,QAAkB,EAClB,KAAA,WAAqB,IACrB,KAAA,OAAkB,GAClB,KAAA,QAAmB,GACnB,KAAA,aAAwB,GACxB,KAAA,KAAY,CAAA,EAGZ,KAAA,GAAU,EACV,KAAA,GAAU,EAGV,KAAA,mBAA4B,IAAI2C,GAAM,SAAS,EAC/C,KAAA,MAAgB,EAuDd,KAAK,GAAK3C,EAAE,GAEZ,KAAK,WAAa,IAAIkE,GAGlBgI,aAAsBF,GACxB,KAAK,YAAcE,EAEZA,aAAsBvO,EAE7B,KAAK,YAAcqO,GAAgB,UAAUE,CAAU,EAIhD,MAAM,QAAQA,CAAU,EAC/B,KAAK,YAAc,IAAIF,GAAgB,GAAGE,CAAU,GAKpD,QAAQ,KAAK,kEAAkE,EAC/E,KAAK,YAAc,IAAIF,GAAgB,EAAG,CAAC,GAI7C,IAAI9K,EAA6B,CAAE,GAAGlB,CAAA,EAGtC,KAAK,UAAY,CAAE,GAAGkB,CAAA,EAEtB,KAAK,GAAKA,EAAK,GACf,KAAK,EAAIA,EAAK,GAAK,KAAK,YAAY,CAAC,EACrC,KAAK,EAAIA,EAAK,GAAK,KAAK,YAAY,CAAC,EACrC,KAAK,MAAQA,EAAK,MAAQ,EAC1B,KAAK,OAASA,EAAK,OAAS,IAAIyB,GAAM,SAAS,EAC/C,KAAK,OAASzB,EAAK,QAAU,GAC7B,KAAK,MAAQA,EAAK,OAAS,KAC3B,KAAK,KAAOA,EAAK,MAAQ,CAAA,EAEzB,KAAK,WAAa,KAAK,mBACnBA,EAAK,YACP,KAAK,WAAaA,EAAK,UAK3B,CA9FA,IAAI,YAA8B,CAChC,OAAO,KAAK,WACd,CAEA,IAAI,OAAe,CACjB,OAGG,KAAK,cAAgB,KAAK,WAAc,KAAK,WAAa,KAAK,MAEpE,CACA,IAAI,MAAMxC,EAAU,CAClB,KAAK,OAASA,CAChB,CACA,IAAI,WAAmB,CACrB,OAAO,KAAK,YAAc,KAAK,kBACjC,CACA,IAAI,UAAU6E,EAAU,CACtB,KAAK,WAAaA,CACpB,CAEA,IAAI,MAAe,CACjB,OAAO,KAAK,KACd,CACA,IAAI,KAAKD,EAAW,CAClB,KAAK,MAAQA,CACf,CAEA,IAAI,UAAiC,CACnC,OAAO,KAAK,SACd,CAEA,IAAI,GAAI,CACN,OAAO,KAAK,EACd,CACA,IAAI,GAAI,CACN,OAAO,KAAK,EACd,CACA,IAAI,EAAE6I,EAAS,CAAE,KAAK,GAAKA,CAAI,CAC/B,IAAI,EAAEC,EAAS,CAAE,KAAK,GAAKA,CAAI,CAC/B,UAAU5O,EAAyC,CACjD,OAAO,KAAK,YAAY,IAAIA,CAAE,CAChC,CAEA,IAAI,WAAY,CAAE,OAAO,KAAK,UAAY,CAC1C,IAAI,UAAU,EAAQ,CAAE,KAAK,WAAa,CAAG,CAkD/C,EAzH2DE,EAAAuO,GAAA,iBAApD,IAAMI,GAANJ,GAsIA,MAAMK,GAAN,MAAMA,WAAaD,EAAc,CA2BtC,YAAYnL,EAA0BqL,EAAaC,EAAW,CAO5D,MAAM,CAAA,EAAI,EAAS,EAEnB,KAAK,KAAOD,EACZ,KAAK,GAAKC,CACZ,CAEA,IAAI,MAA6C,CAC/C,MAAO,CAAC,CAAC,KAAK,KAAK,EAAG,KAAK,KAAK,CAAC,EAAG,CAAC,KAAK,GAAG,EAAG,KAAK,GAAG,CAAC,CAAC,CAC5D,CACA,IAAI,UAA6B,CAC/B,MAAO,EACJ,KAAK,KAAK,EAAI,KAAK,GAAG,GAAK,GAC3B,KAAK,KAAK,EAAI,KAAK,GAAG,GAAK,CAAA,CAEhC,CACA,IAAI,QAAiB,CACnB,OAAO,KAAK,KACV,KAAK,IAAI,KAAK,GAAG,EAAI,KAAK,KAAK,EAAG,CAAC,EACnC,KAAK,IAAI,KAAK,GAAG,EAAI,KAAK,KAAK,EAAG,CAAC,CAAA,CAEvC,CACA,IAAI,OAAe,CAAE,OAAO,KAAK,MAAQ,CACzC,IAAI,MAAM9N,EAAU,CAAE,KAAK,OAASA,CAAG,CACzC,EAzDwChB,EAAA4O,GAAA,QAAjC,IAAMpH,GAANoH,GAiEA,MAAMG,GAAN,MAAMA,WAAcJ,EAAc,CAmBvC,YAAYnL,EAA0B,SACpC,IACEgL,EACAQ,EACAhB,EAGCxK,EACEA,aAAgBvD,GACjBuO,GAAajN,EAAAiC,EAAK,UAAL,YAAAjC,EAAc,IAAK,CAACP,EAAGN,IAAOM,IAAM,qBAAuBA,IAAM,gBAAmBwC,EAAK9C,CAAC,EAAI,IAAI,OAAO,GAAK,IAAM,IACjIsO,GAAOhL,EAAAR,EAAK,UAAL,YAAAQ,EAAc,IAAK,CAAChD,EAAGN,IAAMM,IAAM,eAAiB,CAACwC,EAAK,MAAM9C,CAAC,EAAG8C,EAAK9C,CAAC,CAAC,EAAI,MAAM,OAAO,GAAK,IAAM,MAAM,OAAO,CAACqC,EAAQ/B,KAAa+B,EAAE/B,EAAE,CAAC,CAAC,EAAIA,EAAE,CAAC,EAAU+B,GAAM,CAAA,GAC9KiL,EAAKxK,EAAK,SAAW,SAAS,KAAK,OAAA,EAAS,SAAS,EAAE,EAAE,UAAU,EAAG,CAAC,CAAC,IAElE,OAAOA,GAAS,UACtBgL,EAAahL,EAAK,YAAc,CAAA,EAChCwL,EAAOxL,EAAK,MAAQ,CAAA,EACpBwK,EAAKxK,EAAK,IAAM,SAAS,KAAK,OAAA,EAAS,SAAS,EAAE,EAAE,UAAU,EAAG,CAAC,CAAC,KAGnE,QAAQ,KAAK,uDAAuD,EACpEgL,EAAa,CAAA,EACbQ,EAAO,CAAA,EACPhB,EAAK,SAAS,KAAK,OAAA,EAAS,SAAS,EAAE,EAAE,UAAU,EAAG,CAAC,CAAC,KAI1DQ,EAAa,CAAA,EACbQ,EAAO,CAAA,EACPhB,EAAK,SAAS,KAAK,OAAA,EAAS,SAAS,EAAE,EAAE,UAAU,EAAG,CAAC,CAAC,IAG1D,MAAMQ,GAAc,CAAA,EAAI,CAAE,KAAAQ,EAAM,GAAAhB,EAAW,EA9C7C,KAAA,UAA4B,IAC5B,KAAA,MAAgBe,GAAM,OAAO,MA8C7B,CAEA,IAAI,MAAM9N,EAAsB,CAC9B,KAAK,OAASA,CAChB,CACA,IAAI,OAA2B,CAC7B,OAAO,KAAK,MACd,CACA,IAAI,GAAY,CAKd,OAAO,KAAK,EACd,CACA,IAAI,GAAY,CAKd,OAAO,KAAK,EACd,CACA,IAAI,EAAEwN,EAAY,CAAE,KAAK,GAAK,WAAWA,CAAS,CAAG,CACrD,IAAI,EAAEC,EAAY,CAAE,KAAK,GAAK,WAAWA,CAAS,CAAG,CACvD,EA3EyC1O,EAAA+O,GAAA,SACvCA,GAAO,OAAS,CAAE,OAAQ,SAAU,OAAQ,MAAA,EADvC,IAAMjI,EAANiI,GAkIA,MAAME,GAAN,MAAMA,WAAcN,EAAc,CAOvC,YAAYO,EAAaC,EAAuB,CAE9C,MAAMA,EAAO,WAAYA,CAAM,EAPjC,KAAA,SAAoB,GAEpB,KAAA,OAAiB,EAMf,KAAK,KAAOD,EACZ,KAAK,GAAKC,EAAO,GACjB,KAAK,OAASA,EACd,KAAK,EAAI,KAAK,WAAW,CAAC,EAC1B,KAAK,EAAI,KAAK,WAAW,CAAC,EAC1B,KAAK,OAASA,EAAO,MAAQ,EAC7B,KAAK,KAAO,KAAK,OAAS,EAC1B,KAAK,QAAU,GAEf,KAAK,WAAW,IAAI,IAAK,CAAC,EAC1B,KAAK,WAAW,IAAI,IAAK,CAAC,CAC5B,CAEA,IAAI,GAAY,CACd,OAAO,WAAW,KAAK,EAAE,CAC3B,CACA,IAAI,GAAY,CACd,OAAO,WAAW,KAAK,EAAE,CAC3B,CACA,IAAI,EAAEV,EAAY,CAAE,KAAK,GAAKA,CAAI,CAClC,IAAI,EAAEC,EAAY,CAAE,KAAK,GAAKA,CAAI,CAElC,IAAI,WAAuB,CACzB,eAAQ,KAAK,sEAAsE,EAkB5E,KAAK,UACd,CACA,IAAI,UAAU,EAAc,CAAE,KAAK,WAAa,CAAG,CAKrD,EA1DyC1O,EAAAiP,GAAA,SAuDvCA,GAAO,cAAgB,CAAE,IAAK,EAAG,KAAM,EAAG,MAAO,EAAG,GAAI,CAAA,EACxDA,GAAO,UAAY,CAAE,IAAK,EAAG,GAAI,CAAA,EACjCA,GAAO,SAAW,CAAE,OAAQ,EAAG,OAAQ,EAAG,UAAW,EAAG,OAAQ,CAAA,EAzD3D,IAAMG,EAANH,GC3ZP,MAAMI,GAAN,MAAMA,EAAS,CAUb,YAAYtJ,EAAWQ,EAAW+I,EAAa,EAAGC,EAAa,EAAG,CAChE,KAAK,MAAQxJ,EACb,KAAK,MAAQQ,EACb,KAAK,GAAK+I,EACV,KAAK,GAAKC,CAGZ,CACA,WAAWjM,EAAY,IAAa,CAClC,IAAIyC,EAAI,KAAK,MAAQzC,EACjBiD,EAAI,KAAK,MAAQjD,EACrB,MAAQ,GAAG,KAAK,GAAKyC,CAAC,IAAI,KAAK,GAAKQ,CAAC,IAAIR,EAAI,CAAC,IAAIQ,EAAI,CAAC,EACzD,CASA,IAAI,QAAiB,CACnB,OAAO,KAAK,MAAQ,CACtB,CACA,IAAI,OAAgB,CAClB,OAAO,KAAK,MAAQ,CACtB,CACA,IAAI,KAAc,CAChB,OAAO,KAAK,MAAQ,EACtB,CACA,IAAI,QAAiB,CACnB,OAAO,KAAK,KACd,CACA,IAAI,MAAe,CACjB,OAAO,KAAK,MAAQ,EACtB,CACA,IAAI,OAAgB,CAClB,OAAO,KAAK,KACd,CACF,EAjDevG,EAAAqP,GAAA,YAAf,IAAMG,GAANH,GCCO,MAAMI,GAAN,MAAMA,WAAkBd,EAAc,CAE3C,YAAYH,EAA6BlM,EAAQ,CAC/C,MAAMkM,EAAYlM,CAAC,EAEnB,KAAK,QAAU,GAEf,KAAK,KAAOA,EAAE,IAChB,CAEA,IAAI,KAAKsD,EAAW,CAClB,KAAK,MAAQA,CACf,CACA,IAAI,MAAe,CACjB,OAAO,KAAK,KACd,CAEA,IAAI,GAAY,CACd,OAAO,KAAK,EACd,CACA,IAAI,GAAY,CACd,OAAO,KAAK,EACd,CACA,IAAI,EAAE6I,EAAY,CAAE,KAAK,GAAKA,CAAI,CAClC,IAAI,EAAEC,EAAY,CAAE,KAAK,GAAKA,CAAI,CAElC,IAAI,WAAY,CACd,OAAO,KAAK,UACd,CACF,EA7B6C1O,EAAAyP,GAAA,aAAtC,IAAMC,GAAND,GCSIE,GAAsB,CAC/B,MAAO,CACL,MAAO,EACP,MAAO,EACP,MAAO,EACP,SAAU,OACV,MAAO,EACP,OAAQ,EACR,KAAM,GACN,YAAa,EACb,WAAY,CAAE,EAAG,CAAE,CAAA,EAErB,KAAM,CACJ,KAAM,EACN,UAAW,CACT,MAAO,SACP,OAAQP,EAAM,cAAc,EAAA,EAE9B,OAAQA,EAAM,cAAc,GAC5B,cAAeA,EAAM,SAAS,MAAA,EAEhC,MAAO,CACL,OAAQ,EACR,KAAM,IACN,MAAO,OACP,MAAOtI,EAAM,OAAO,OACpB,OAAQsI,EAAM,cAAc,KAC5B,cAAeA,EAAM,SAAS,MAAA,EAEhC,KAAM,CACJ,MAAOtI,EAAM,OAAO,OACpB,OAAQsI,EAAM,cAAc,IAAA,EAE9B,MAAO,CACL,UAAWA,EAAM,UAAU,IAC3B,SAAU,CAAC,MAAO,MAAM,EACxB,UAAW,kBAAA,EAEb,KAAM,CACJ,WAAY,CAAA,CAEhB,EAEO,MAAMQ,GAAN,MAAMA,EAAM,CAgEjB,YACE9C,EAAsC,CAAE,GAAG6C,IAC3C,CAjEF,KAAA,UAA0B,IAAI1B,GAE9B,KAAA,KAAe,gBACf,KAAA,OAAgC,OAIhC,KAAA,WAA6C,IAC7C,KAAA,UAA+B,IAC/B,KAAA,UAA+B,IAC/B,KAAA,iBAAqC,IACrC,KAAA,WAAiC,IACjC,KAAA,UAAuB,IAAIzH,GAE3B,KAAA,QAAkB,EAClB,KAAA,QAAkB,EAGlB,KAAA,YAAsB,EACtB,KAAA,UAAqB,GACrB,KAAA,UAAqB,GAGrB,KAAA,QAAsB,IAAIsH,GACxB,CAAE,KAAM,QAAS,SAAU,EAAG,OAAQ,CACpC,CACE,KAAM,OACN,OAAQ,CACN,CACE,KAAM,aAAc,SAAU,EAAG,OAAQ,CAAA,EACzC,QAAS,CAAA,CAET,EAEF,CACE,KAAM,cAAe,SAAU,EAAG,OAAQ,CAAA,EAAI,QAAS,CAAA,CAAC,EAE1D,CACE,KAAM,cACN,SAAU,EACV,OAAQ,CAAA,EACR,QAAS,CACP,KAAK,MAAA,CACP,CACF,CACF,EAGF,CACE,KAAM,UACN,OAAQ,CACN,CAAE,KAAM,QAAS,OAAQ,CAAA,EAAI,SAAU,CAAA,EACvC,CAAE,KAAM,QAAS,OAAQ,CAAA,EAAI,SAAU,CAAA,EACvC,CAAE,KAAM,YAAa,OAAQ,CAAA,EAAI,SAAU,CAAA,CAAE,CAC/C,EAEF,CAAE,KAAM,eAAgB,OAAQ,CAAA,EAAI,SAAU,CAAA,EAC9C,CAAE,KAAM,SAAU,OAAQ,CAAA,EAAI,SAAU,CAAA,EAExC,CAAE,KAAM,SAAU,OAAQ,CAAA,EAAI,SAAU,CAAA,CAAE,CAC5C,CAAE,EAMF,KAAK,QAAUhB,EAEf,KAAK,OAAS,IAAI4C,GAChB,IAAIpB,GAAgB,EAAG,CAAC,EACxB,CACE,GAAI,SACJ,EAAG,EAAG,EAAG,EACT,KAAM,EACN,KAAM,CAAA,EACN,MAAO,KACP,MAAO,IAAIrJ,GAAM,SAAS,EAC1B,UAAW,IAAIA,GAAM,SAAS,EAC9B,OAAQ,EAAA,CACV,EAGF,IAAI4K,EAAW,EACf,SAASC,EAAeC,EAAgB3Q,EAAsB4Q,EAAqB,CACjF,MAAMC,EAAY,IAAI/B,GAAM,GAAG2B,CAAQ,GAAIE,EAAWC,CAAK,EAC3D,OAAAH,GAAY,EACZI,EAAU,OAAS7Q,GAAU,OACzB2Q,EAAU,QAAU,MAAM,QAAQA,EAAU,MAAM,IACpDE,EAAU,OAAS,IAAInC,GAAW,GAAGiC,EAAU,OAAO,IAAKG,GAAeJ,EAAeI,EAAOD,EAAWD,CAAK,CAAC,CAAC,GAE7GC,CACT,CARSjQ,EAAA8P,EAAA,kBAUT,KAAK,OAAS,IAAIhC,GAAW,GAAG,KAAK,QAAQ,IAAK7M,GAAW6O,EAAe7O,EAAG,KAAM,IAAI,CAAC,CAAC,EAE3F,IAAIkP,EAAwC,KAAK,OAAO,OAAO,SAAU,aAAa,EAClFA,GACFA,EAAe,QAAQ,IAAI,KAAK,OAAO,GAAI,KAAK,MAAM,EAGxD,IAAIC,EAAuC,KAAK,OAAO,OAAO,SAAU,YAAY,EACpF,GAAIA,EAAe,CACjB,IAAIC,EAAW,KAAK,UAAY,IAAIb,GAAS,EAAG,CAAC,EAC7Cc,EAAS,IAAI9I,GACf,CAAA,EACA,IAAIV,EAAM,CAAE,GAAI,eAAgB,WAAY,CAAC,CAACuJ,EAAS,MAAO,CAAC,EAAG,QAAS,CAAC,gBAAiB,eAAe,EAAG,EAC/G,IAAIvJ,EAAM,CAAE,GAAI,aAAc,WAAY,CAACuJ,EAAS,MAAO,CAAC,EAAG,QAAS,CAAC,gBAAiB,eAAe,EAAG,CAAA,EAE9GC,EAAO,GAAK,SACZF,EAAc,QAAQ,IAAIE,EAAO,GAAIA,CAAM,EAC3C,IAAIC,EAAS,IAAI/I,GACf,CAAA,EACA,IAAIV,EAAM,CAAE,GAAI,eAAgB,WAAY,CAAC,EAAG,CAACuJ,EAAS,KAAK,EAAG,QAAS,CAAC,gBAAiB,eAAe,EAAG,EAC/G,IAAIvJ,EAAM,CAAE,GAAI,aAAc,WAAY,CAAC,EAAGuJ,EAAS,KAAK,EAAG,QAAS,CAAC,gBAAiB,eAAe,EAAG,CAAA,EAE9GE,EAAO,GAAK,SACZH,EAAc,QAAQ,IAAIG,EAAO,GAAIA,CAAM,EAC3C,QAAQ,IAAI,8BAA+BH,CAAa,CAC1D,CAGA,KAAK,SAAW,IAAIZ,GAAS1C,EAAQ,MAAM,MAAOA,EAAQ,MAAM,KAAK,CACvE,CAEA,IAAI,SAAS0D,EAAa,CACxB,KAAK,UAAYA,CACnB,CACA,IAAI,UAAqB,CACvB,OAAO,KAAK,SACd,CACA,IAAI,UAAoB,CACtB,OAAO,KAAK,SACd,CACA,IAAI,SAASxK,EAAY,CACvB,KAAK,UAAYA,CACnB,CACA,IAAI,UAAoB,CACtB,OAAO,KAAK,SACd,CACA,IAAI,SAASA,EAAY,CACvB,KAAK,UAAYA,CACnB,CAEA,UAAmB,CACjB,OAAQ,KAAK,SAAW,GAAK,CAC/B,CACA,UAAmB,CACjB,OAAQ,KAAK,SAAW,GAAK,CAC/B,CAEA,UAAU1C,EAAiB,CACzB,MAAM0D,EAAe,IAAIF,EAAMxD,CAAC,EAChC,KAAK,OAAO,IAAI0D,EAAM,GAAIA,CAAK,CAYjC,CACA,WAAWyJ,EAAe,CACxB,IAAIC,EAAK,KACTD,EAAG,KAAA,EAAO,QAASnN,GAAoB,CACrCoN,EAAG,UAAUpN,CAAC,CAChB,CAAC,CACH,CAEA,UAAUqN,EAAW,CACnB,IACED,EAAK,KAGPC,EAAG,QAASC,GAAa,CAGvBA,EAAS,MAAQ,IAAIxB,EAAMwB,EAAS,GAAIA,CAAQ,EAChDF,EAAG,OAAO,IAAIE,EAAS,MAAM,GAAIA,EAAS,KAAK,EAE/CF,EAAG,MAAM,IAAIE,EAAS,GAAIA,CAAQ,EAClC,MAAMC,EAAaH,EAAG,OAAO,OAAO,SAAU,OAAO,EACjDG,GACFA,EAAW,QAAQ,KAAKD,CAAQ,CAEpC,CAAC,EACDF,EAAG,gBAAA,CACL,CACA,SAASF,EAAQ3B,EAAYC,EAAU,CAErC,OADS,KACN,MAAM,IAAI0B,EAAE,GAAIA,CAAC,EAEpB,KAAK,UAAU,CAAC3B,GAAQ2B,EAAE,KAAM1B,GAAM0B,EAAE,EAAE,CAAC,EAEnCA,CACV,CACA,UAAUM,EAAW,CACnB,IAAIC,EAAQD,EAAG,OAAS,KAAK,SAASN,CAAC,CAAC,EACxC,MAAMQ,EAAa,KAAK,OAAO,OAAO,SAAU,OAAO,EACvD,OAAIA,GACFA,EAAW,QAAQ,KAAK,GAAGD,CAAK,EAE1BA,CACV,CAQA,gBAAgBE,EAAyB,GAAO,CAY9C,MAAMC,EAAgB,CACpB,KAAK,OAAO,OAAO,SAAU,QAAQ,EACrC,KAAK,OAAO,OAAO,SAAU,OAAO,CAAA,EACpC,OAAQjQ,GAAsBA,IAAM,MAAS,EAC/C,GAAIiQ,EAAc,SAAW,EAC3B,KAAK,SAAW,IAAI1B,GAAS,EAAG,CAAC,MAE9B,CAMH,IAAI2B,EAAO,IAAUC,EAAO,KAAWC,EAAO,IAAUC,EAAO,KAC/DJ,EAAc,QAAQjQ,GAAKA,EAAE,QAAQ,QAASqB,GAAW,CACnD,OAAO,SAASA,EAAE,CAAC,IAAK6O,EAAO,KAAK,IAAIA,EAAM7O,EAAE,CAAC,EAAG8O,EAAO,KAAK,IAAIA,EAAM9O,EAAE,CAAC,GAC7E,OAAO,SAASA,EAAE,CAAC,IAAK+O,EAAO,KAAK,IAAIA,EAAM/O,EAAE,CAAC,EAAGgP,EAAO,KAAK,IAAIA,EAAMhP,EAAE,CAAC,EACnF,CAAC,CAAC,EACF,MAAMgL,EAAQ,OAAO,SAAS6D,CAAI,GAAK,OAAO,SAASE,CAAI,EACrD/B,EAAK2B,GAAiB3D,GAAS6D,EAAOC,GAAQ,EAAI,EAClD7B,EAAK0B,GAAiB3D,GAAS+D,EAAOC,GAAQ,EAAI,EAClDC,EAAcjE,EAChB,KAAK,IAAI,KAAK,IAAI6D,EAAO7B,CAAE,EAAG,KAAK,IAAI8B,EAAO9B,CAAE,EAAG,KAAK,IAAI+B,EAAO9B,CAAE,EAAG,KAAK,IAAI+B,EAAO/B,CAAE,CAAC,EAC3F,EACEiC,GAAaD,EAAc,EAAIA,EAAc,GAAK,IACxD,KAAK,SAAW,IAAI/B,GAASgC,EAAWA,EAAWlC,EAAIC,CAAE,CAC3D,CACF,CAGA,eAAeD,EAAYC,EAAoB,CAC7C,MAAMkC,EAAQ,KAAK,OAAO,OAAO,SAAU,OAAO,EAClD,IAAIhM,EAAM,EACV,OAAAgM,GAAA,MAAAA,EAAO,QAAQ,QAASnP,GAAW,CAC7B,OAAO,SAASA,EAAE,CAAC,GAAK,OAAO,SAASA,EAAE,CAAC,IAAGmD,EAAM,KAAK,IAAIA,EAAK,KAAK,IAAInD,EAAE,EAAIgN,CAAE,EAAG,KAAK,IAAIhN,EAAE,EAAIiN,CAAE,CAAC,EAC9G,GACO9J,CACT,CAEA,gBAAgBiM,EAAQ,EAAW,CACjC,IAAIC,EAAS,KAAK,IAAI,KAAK,SAAS,MAAO,KAAK,SAAS,KAAK,EAC1D5O,EAAI,KAAK,OAAO,KAAO,KAAK,MAAM,KACtC,OAAO,KAAK,IAAI,EAAG4O,GAAU,KAAK,KAAK5O,CAAC,EAAI2O,EAAM,CACpD,CACF,EA/QmB1R,EAAA4P,GAAA,SAAZ,IAAMgC,GAANhC,GClDA,MAAeiC,GAAf,MAAeA,WAAwB,WAAY,CA0BxD,aAAc,CACZ,MAAA,EAbF,KAAA,QAA0B,KAC1B,KAAA,OAA+C,KAc7C,MACEnG,EAAU,KACVxI,EAASwI,EAAQ,aAAa,CAAE,KAAM,MAAA,CAAQ,EAC9CvI,EAAQ,SAAS,cAAc,OAAO,EACtC2O,EAAU,SAAS,cAAc,KAAK,EAGxC3O,EAAM,YAAe,KAAK,YAAoB,MAC9CD,EAAO,YAAYC,CAAK,EAExB2O,EAAQ,aAAa,QAAS,SAAS,EACvC5O,EAAO,YAAY4O,CAAO,CAC5B,CAxBA,IAAI,SAAU,CACZ,MACEpG,EAAU,KACVxI,EAASwI,EAAQ,WAGnB,OAFYxI,GAAA,YAAAA,EAAQ,cAAc,WAGpC,CAkBF,EA1C0DlD,EAAA6R,GAAA,mBAExDA,GAAO,MAAgB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAFlB,IAAeE,GAAfF,GCWA,MAAMG,GAAsB,KAgB5B,SAASC,GAAiB5O,EAAW6O,EAAcF,GAA2B,CACnF,OAAO3O,EAAI,OAAOC,GAAK,KAAK,IAAIA,EAAE,CAAC,EAAI4O,GAAO,KAAK,IAAI5O,EAAE,CAAC,EAAI4O,CAAG,CACnE,CAFgBlS,EAAAiS,GAAA,oBAKhB,SAASE,GAAYpP,EAAqB,CACxC,GAAIA,GAAK,EAAG,MAAO,CAAA,EACnB,GAAIA,IAAM,EAAG,MAAO,CAAC,CAAC,EACtB,MAAM,EAAI,IAAI,MAAMA,CAAC,EACrB,QAASrC,EAAI,EAAGA,EAAIqC,EAAGrC,IAAK,EAAEA,CAAC,EAAIA,GAAKqC,EAAI,GAC5C,OAAO,CACT,CANS/C,EAAAmS,GAAA,eAST,SAASC,GAAO3H,EAAa4H,EAA4B,CACvD,OAAO5H,EAAE,IAAI6H,GAAM,CACjB,MAAMvQ,EAAM,IAAI,MAAMsQ,EAAS,CAAC,EAChC,IAAI/O,EAAI,EACR,QAAS+C,EAAI,EAAGA,GAAKgM,EAAQhM,IAC3BtE,EAAIsE,CAAC,EAAI/C,EACTA,GAAKgP,EAEP,OAAOvQ,CACT,CAAC,CACH,CAVS/B,EAAAoS,GAAA,UAiBT,SAASG,GAAGC,EAAiD,CAC3D,MAAMzP,EAAIyP,EAAE,OACNxM,EAAIwM,EAAE,CAAC,EAAE,OACT1J,EAAI0J,EAAE,IAAIzQ,GAAOA,EAAI,OAAO,EAC5B0Q,EAAI,MAAM,KAAK,CAAE,OAAQzM,CAAA,EAAK,IAAM,IAAI,MAAMA,CAAC,EAAE,KAAK,CAAC,CAAC,EAC9D,QAAS5E,EAAI,EAAGA,EAAI4E,EAAG5E,IAAK,CAC1B,IAAIsR,EAAO,EACX,QAAShS,EAAI,EAAGA,EAAIqC,EAAGrC,IAAKgS,GAAQ5J,EAAEpI,CAAC,EAAEU,CAAC,EAAI0H,EAAEpI,CAAC,EAAEU,CAAC,EAGpD,GAFAsR,EAAO,KAAK,KAAKA,CAAI,EACrBD,EAAErR,CAAC,EAAEA,CAAC,EAAIsR,EACNA,EAAO,OACT,QAAShS,EAAI,EAAGA,EAAIqC,EAAGrC,IAAKoI,EAAEpI,CAAC,EAAEU,CAAC,GAAKsR,EAEzC,QAASrM,EAAIjF,EAAI,EAAGiF,EAAIL,EAAGK,IAAK,CAC9B,IAAIsM,EAAM,EACV,QAASjS,EAAI,EAAGA,EAAIqC,EAAGrC,IAAKiS,GAAO7J,EAAEpI,CAAC,EAAEU,CAAC,EAAI0H,EAAEpI,CAAC,EAAE2F,CAAC,EACnDoM,EAAErR,CAAC,EAAEiF,CAAC,EAAIsM,EACV,QAASjS,EAAI,EAAGA,EAAIqC,EAAGrC,IAAKoI,EAAEpI,CAAC,EAAE2F,CAAC,GAAKsM,EAAM7J,EAAEpI,CAAC,EAAEU,CAAC,CACrD,CACF,CACA,MAAO,CAAE,EAAA0H,EAAG,EAAA2J,CAAA,CACd,CArBSzS,EAAAuS,GAAA,MAwBT,SAASK,GAAI9J,EAAevC,EAAuB,CACjD,MAAMxD,EAAI+F,EAAE,OACN9C,EAAI8C,EAAE,CAAC,EAAE,OACT+J,EAAM,IAAI,MAAM7M,CAAC,EAAE,KAAK,CAAC,EAC/B,QAAS5E,EAAI,EAAGA,EAAI4E,EAAG5E,IAAK,CAC1B,IAAIwE,EAAI,EACR,QAASlF,EAAI,EAAGA,EAAIqC,EAAGrC,IAAKkF,GAAKkD,EAAEpI,CAAC,EAAEU,CAAC,EAAImF,EAAE7F,CAAC,EAC9CmS,EAAIzR,CAAC,EAAIwE,CACX,CACA,OAAOiN,CACT,CAVS7S,EAAA4S,GAAA,OAaT,SAASE,GAAUL,EAAe3N,EAAuB,CACvD,MAAMkB,EAAIlB,EAAE,OACN9D,EAAI,IAAI,MAAMgF,CAAC,EAAE,KAAK,CAAC,EAC7B,QAAS,EAAIA,EAAI,EAAG,GAAK,EAAG,IAAK,CAC/B,IAAIJ,EAAId,EAAE,CAAC,EACX,QAAS1D,EAAI,EAAI,EAAGA,EAAI4E,EAAG5E,IAAKwE,GAAK6M,EAAE,CAAC,EAAErR,CAAC,EAAIJ,EAAEI,CAAC,EAClDJ,EAAE,CAAC,EAAI,KAAK,IAAIyR,EAAE,CAAC,EAAE,CAAC,CAAC,EAAI,MAAQ7M,EAAI6M,EAAE,CAAC,EAAE,CAAC,EAAI,CACnD,CACA,OAAOzR,CACT,CATShB,EAAA8S,GAAA,aAYT,SAASC,GAAUjK,EAAyB,CAC1C,OAAOA,EAAE,IAAI/G,GAAO,CAClB,IAAI6D,EAAI,EACR,QAASxE,EAAI,EAAGA,EAAIW,EAAI,OAAQX,IAAKwE,GAAK7D,EAAIX,CAAC,EAAIW,EAAIX,CAAC,EACxD,OAAOwE,CACT,CAAC,CACH,CANS5F,EAAA+S,GAAA,aAST,SAASC,GAAUvI,EAAalE,EAAa8L,EAA0B,CACrE,MAAMY,EAAIb,GAAO3H,EAAG4H,CAAM,EACpB,CAAE,EAAAvJ,EAAG,EAAA2J,GAAMF,GAAGU,CAAC,EACrB,OAAOH,GAAUL,EAAGG,GAAI9J,EAAGvC,CAAC,CAAC,CAC/B,CAJSvG,EAAAgT,GAAA,aAOF,SAASE,GAASC,EAAkB,EAAmB,CAC5D,IAAIxS,EAAI,EACJ2C,EAAI,EACR,QAAS+C,EAAI,EAAGA,EAAI8M,EAAO,OAAQ9M,IACjC1F,GAAKwS,EAAO9M,CAAC,EAAI/C,EACjBA,GAAK,EAEP,OAAO3C,CACT,CARgBX,EAAAkT,GAAA,YAehB,SAASE,GAAQ3I,EAAa1E,EAAaQ,EAAa8L,EAAwB,CAC9E,MAAMY,EAAIb,GAAO3H,EAAG4H,CAAM,EACpB,CAAE,EAAAvJ,EAAG,EAAA2J,GAAMF,GAAGU,CAAC,EACfpN,EAAIkN,GAAUjK,CAAC,EACfwG,EAAKwD,GAAUL,EAAGG,GAAI9J,EAAG/C,CAAC,CAAC,EAC3BwJ,EAAKuD,GAAUL,EAAGG,GAAI9J,EAAGvC,CAAC,CAAC,EACjC,IAAI8M,EAAQ,EACZ,QAAS3S,EAAI,EAAGA,EAAI+J,EAAE,OAAQ/J,IAAK,CACjC,MAAM4S,EAAQ,EAAIzN,EAAEnF,CAAC,EACrB,GAAI4S,GAAS,EAAG,MAAO,KACvB,MAAMC,EAAKxN,EAAErF,CAAC,EAAIwS,GAAS5D,EAAI7E,EAAE/J,CAAC,CAAC,EAC7B8S,EAAKjN,EAAE7F,CAAC,EAAIwS,GAAS3D,EAAI9E,EAAE/J,CAAC,CAAC,EACnC2S,IAAUE,EAAKD,IAAU,GAAKE,EAAKF,IAAU,CAC/C,CACA,OAAOD,CACT,CAfSrT,EAAAoT,GAAA,WAsBF,SAASK,GAAaC,EAAcC,EAAmBC,EAA+B,CAC3F,MAAM7Q,EAAI2Q,EAAO,OACXG,EAAM,KAAK,IAAI,KAAK,IAAI,EAAG,KAAK,MAAMF,CAAS,CAAC,EAAG,KAAK,IAAI,EAAG5Q,EAAI,CAAC,CAAC,EAC3E,GAAI6Q,IAAS,SAAW7Q,EAAI,EAAG,OAAO8Q,EACtC,MAAMpJ,EAAI0H,GAAYpP,CAAC,EACjBgD,EAAI2N,EAAO,IAAIpQ,GAAKA,EAAE,CAAC,EACvBiD,EAAImN,EAAO,IAAIpQ,GAAKA,EAAE,CAAC,EAC7B,IAAIwQ,EAAO,EACPC,EAAU,IACd,QAASC,EAAM,EAAGA,GAAOH,EAAKG,IAAO,CACnC,MAAMrT,EAAIyS,GAAQ3I,EAAG1E,EAAGQ,EAAGyN,CAAG,EAC1BrT,EAAIoT,IACNA,EAAUpT,EACVmT,EAAOE,EAEX,CACA,OAAOF,CACT,CAjBgB9T,EAAAyT,GAAA,gBA6BT,SAASQ,GACdC,EACAC,EACsB,CACtB,MAAMT,EAASzB,GAAiBiC,CAAS,EACzC,GAAIR,EAAO,OAAS,EAAG,OAAO,KAE9B,MAAMU,EAAWD,EAAK,aAAelC,GAAiBkC,EAAK,YAAY,EAAIT,EACrEW,EAAQD,EAAS,QAAU,EAAIA,EAAWV,EAChD,IAAIrB,EAASoB,GAAaY,EAAOF,EAAK,UAAWA,EAAK,eAAe,EAGrE9B,EAAS,KAAK,IAAIA,EAAQ,KAAK,IAAI,EAAGqB,EAAO,OAAS,CAAC,CAAC,EAExD,MAAMjJ,EAAI0H,GAAYuB,EAAO,MAAM,EAC7BY,EAAUtB,GAAUvI,EAAGiJ,EAAO,IAAIpQ,GAAKA,EAAE,CAAC,EAAG+O,CAAM,EACnDkC,EAAUvB,GAAUvI,EAAGiJ,EAAO,IAAIpQ,GAAKA,EAAE,CAAC,EAAG+O,CAAM,EACzD,MAAO,CAAE,OAAAA,EAAQ,QAAAiC,EAAS,QAAAC,CAAA,CAC5B,CAlBgBvU,EAAAiU,GAAA,iBAqBT,SAASO,GAAYC,EAAoBC,EAAQ,IAAW,CACjE,MAAM7B,EAAY,CAAA,EAClB,QAAS,EAAI,EAAG,GAAK6B,EAAO,IAAK,CAC/B,MAAMjK,EAAI,EAAIiK,EACd7B,EAAI,KAAK,CAAE,EAAGK,GAASuB,EAAI,QAAShK,CAAC,EAAG,EAAGyI,GAASuB,EAAI,QAAShK,CAAC,EAAG,CACvE,CACA,OAAOoI,CACT,CAPgB7S,EAAAwU,GAAA,eC3LhB,MAAMG,GAAyB,IAElBC,GAAN,MAAMA,WAAmBjG,EAAc,CAkB5C,YAAY7B,EAA6B,GAAI,CAC3C,MAAM+H,EAAe/H,EAAQ,iBAAiB7H,GAAQ6H,EAAQ,MAAQ,IAAI7H,GAAM,OAAO6H,EAAQ,OAAU,SAAWA,EAAQ,MAAQ,SAAS,EAC7I,MAAM,CAAA,EAAI,CACR,GAAIA,EAAQ,IAAM,QAAQ,KAAK,OAAA,EAAS,SAAS,EAAE,EAAE,UAAU,EAAG,CAAC,CAAC,GACpE,KAAMA,EAAQ,MAAQ,EACtB,MAAO+H,EACP,UAAW,KACX,OAAQ/H,EAAQ,QAAU,GAC1B,KAAMA,EAAQ,MAAQ,CAAA,EACtB,GAAGA,CAAA,CACoB,EA3B3B,KAAS,UAAoB,aAC7B,KAAA,WAAsB,CAAA,EACtB,KAAA,OAAqC,OACrC,KAAA,UAAoB,EACpB,KAAA,gBAAmC,WAEnC,KAAA,eAAyB,GACzB,KAAA,YAAwB,CAAA,EACxB,KAAA,YAAwB,CAAA,EACxB,KAAA,YAAsB,IACtB,KAAA,WAAsB,GACtB,KAAA,SAAoB,GACpB,KAAA,UAAmC,UACnC,KAAA,YAAsB,EACtB,KAAA,iBAAqC,CAAC,EAAG,CAAC,EAC1C,KAAA,aAAiC,CAAC,GAAK,CAAC,EActC,KAAK,OAASA,EAAQ,QAAU,OAChC,KAAK,UAAYA,EAAQ,YAAc,OAAYA,EAAQ,UAAY,EACvE,KAAK,gBAAkBA,EAAQ,iBAAmB,WAClD,KAAK,YAAcA,EAAQ,aAAe,CAAA,EAC1C,KAAK,YAAcA,EAAQ,aAAe,CAAA,EAC1C,KAAK,YAAcA,EAAQ,cAAgB,OAAYA,EAAQ,YAAc,IAC7E,KAAK,WAAaA,EAAQ,aAAe,OAAYA,EAAQ,WAAa,GAC1E,KAAK,SAAWA,EAAQ,WAAa,OAAYA,EAAQ,SAAW,GACpE,KAAK,UAAYA,EAAQ,WAAa,UACtC,KAAK,YAAcA,EAAQ,aAAe,EAC1C,KAAK,iBAAmBA,EAAQ,kBAAoB,CAAC,EAAG,CAAC,EACzD,KAAK,aAAeA,EAAQ,cAAgB,CAAC,GAAK,CAAC,EAE/CA,EAAQ,QAAU,MAAM,QAAQA,EAAQ,MAAM,IAChD,KAAK,WAAaA,EAAQ,OAAO,IAAIxJ,GAAK,CACxC,GAAIA,aAAawD,EAAO,OAAOxD,EAC/B,MAAMwR,EAAK,IAAIhO,EAAM,CAAE,WAAY,CAACxD,EAAE,EAAGA,EAAE,CAAC,EAAG,KAAM,CAAE,KAAMA,EAAE,KAAM,MAAOA,EAAE,KAAA,EAAS,EACvF,OAAAwR,EAAG,EAAIxR,EAAE,EACTwR,EAAG,EAAIxR,EAAE,EACFwR,CACT,CAAC,EAEL,CAEA,IAAI,cAAwB,CAC1B,OAAI,KAAK,cAAgB,IAChB,KAAK,WAEP,KAAK,WAAW,OAAOxR,IACjBA,EAAE,MAAQ,OAAOA,EAAE,KAAK,MAAS,SAAYA,EAAE,KAAK,KAAO,IAC1D,KAAK,WAClB,CACH,CAEA,IAAI,MAAe,CACjB,OAAO,KAAK,WAAW,OAAO,CAACyR,EAAKD,EAAIzT,IAC/BA,IAAQ,EAAI,IAAIyT,EAAG,CAAC,IAAIA,EAAG,CAAC,GAAK,GAAGC,CAAG,KAAKD,EAAG,CAAC,IAAIA,EAAG,CAAC,GAC9D,EAAE,CACP,CAEA,IAAI,YAA8C,CAChD,MAAMzR,EAAM,KAAK,aACjB,GAAIA,EAAI,OAAS,EAAG,MAAO,CAAA,EAE3B,GAAI,KAAK,SAAW,OAAQ,CAE1B,GAAI,KAAK,YAAY,OAAS,GAAK,KAAK,YAAY,OAAS,EAC3D,OAAOmR,GACL,CAAE,OAAQ,KAAK,YAAY,OAAS,EAAG,QAAS,KAAK,YAAa,QAAS,KAAK,WAAA,EAChFG,EAAA,EAMJ,MAAMF,EAAMR,GACV5Q,EAAI,IAAIC,IAAM,CAAE,EAAGA,EAAE,EAAG,EAAGA,EAAE,CAAA,EAAI,EACjC,CACE,UAAW,KAAK,UAChB,gBAAiB,KAAK,gBACtB,aAAc,KAAK,WAAW,IAAIA,IAAM,CAAE,EAAGA,EAAE,EAAG,EAAGA,EAAE,CAAA,EAAI,CAAA,CAC7D,EAEF,GAAImR,EACF,YAAK,eAAiBA,EAAI,OACnBD,GAAYC,EAAKE,EAAsB,CAGlD,CAEA,OAAOtR,EAAI,IAAIyR,IAAO,CAAE,EAAGA,EAAG,EAAG,EAAGA,EAAG,CAAA,EAAI,CAC7C,CACF,EAtG8C9U,EAAA4U,GAAA,cAAvC,IAAMI,GAANJ,GCtBP,MAAMK,GAAa,EAENC,GAAN,MAAMA,WAAa1N,EAAK,CAO7B,YAAYhE,EAA0BqL,EAAYC,EAAU3J,EAAiB,EAAG,CAC9E,MAAM3B,EAAMqL,EAAMC,CAAE,EALtB,KAAA,aAAuB,EAMrB,KAAK,QAAU3J,CACjB,CAEA,IAAI,YAAoB,CAAE,OAAO,KAAK,MAAO,CAC7C,IAAI,OAAuB,CACzB,MAAMT,EAAO,KAAK,QAAU,IAAIO,GAAM,SAAS,EAC/C,OAAO,IAAIiB,GAAcxB,EAAM,KAAK,IAAI,KAAK,MAAM,CAAC,CACtD,CACA,IAAI,MAAM1D,EAAU,CAAE,KAAK,OAASA,CAAU,CAE9C,aAAc,CAAE,OAAO,KAAK,OAAQ,CACpC,IAAI,QAAS,CAGX,OADQ,MAAM,QAAQ,KAAK,OAAO,EAAK,KAAK,QAAQ,CAAC,EAAI,KAAK,QAAQ,CAAC,EAAK,KAAK,OAEnF,CACA,IAAI,OAAOiF,EAAG,CACZ,KAAK,QAAUA,CACjB,CAEA,IAAI,aAAsB,CACxB,OAAO,KAAK,MACd,CACA,IAAI,YAAYA,EAAW,CACzB,KAAK,aAAeA,CACtB,CACF,EAnC+BjG,EAAAkV,GAAA,QAAxB,IAAMC,GAAND,GA2GA,MAAME,GAAN,MAAMA,WAAkBzG,EAAc,CAG3C,YAAY0G,EAA4B,CACtC,MAAMA,EAAK,YAAc,CAAA,EAAIA,CAAI,EAHnC/V,GAAA,KAAAgW,IAIE1V,EAAA,KAAK0V,GAAQD,EACf,CAEA,IAAI,MAAO,CACT,OAAOxV,EAAA,KAAKyV,GACd,CAEA,IAAI,MAAe,CA2BjB,MAAMC,EAAQ1V,EAAA,KAAKyV,IACbE,EAAsB,CAACD,EAAM,GAAG,EAAGA,EAAM,GAAG,CAAC,EAC7C/C,EAAsB+C,EAAM,WAC5B,CAACE,EAAIC,CAAE,EAAIH,EAAM,SACjBI,EAAI,KAAK,MAAMnD,EAAE,CAAC,EAAIgD,EAAE,CAAC,EAAGhD,EAAE,CAAC,EAAIgD,EAAE,CAAC,CAAC,EACvCI,EAAI,KAAK,MAAMH,EAAG,CAAC,EAAIC,EAAG,CAAC,EAAGD,EAAG,CAAC,EAAIC,EAAG,CAAC,CAAC,EACjD,GAAI,EAAEC,EAAI,IAAM,EAAEC,EAAI,GAAI,MAAO,GACjC,MAAMC,EAAI,EAAErD,EAAE,CAAC,EAAIgD,EAAE,CAAC,GAAKG,GAAInD,EAAE,CAAC,EAAIgD,EAAE,CAAC,GAAKG,CAAC,EACzC7Q,EAAI,KAAK,MAAM2Q,EAAG,CAAC,EAAID,EAAE,CAAC,EAAGC,EAAG,CAAC,EAAID,EAAE,CAAC,CAAC,EACzC7U,EAAI,EAAE8U,EAAG,CAAC,EAAID,EAAE,CAAC,GAAK1Q,GAAI2Q,EAAG,CAAC,EAAID,EAAE,CAAC,GAAK1Q,CAAC,EAC3CgR,EAAQ9V,EAAC2F,GAAeiQ,EAAI,EAAK,KAAK,IAAI,EAAG,EAAIjQ,EAAIgQ,CAAC,EAA9C,SACRI,EAAK/V,EAAA,CAAC2F,EAAWC,IAAc,GAAG4P,EAAE,CAAC,EAAIK,EAAE,CAAC,EAAIlQ,EAAIhF,EAAE,CAAC,EAAIiF,CAAC,IAAI4P,EAAE,CAAC,EAAIK,EAAE,CAAC,EAAIlQ,EAAIhF,EAAE,CAAC,EAAIiF,CAAC,GAArF,MAELoQ,EAAK,GAAML,EACX3U,EAAK,KAAK,IAAI,IAAO2U,EAAG,GAAM,EAAIG,EAAME,CAAE,CAAC,EAC3CC,EAAKD,EAAKhV,EAAI,EAAGkV,EAAKF,EAAKhV,EAGjC,MAFU,IAAI+U,EAAGC,EAAI,CAAC,CAAC,KAAKD,EAAGE,EAAIH,EAAMG,CAAE,CAAC,CAAC,KAAKF,EAAGG,EAAIJ,EAAMI,CAAE,CAAC,CAAC,KACrDH,EAAGE,EAAI,CAAC,CAAC,KAAKF,EAAGG,EAAI,CAACJ,EAAMI,CAAE,CAAC,CAAC,KAAKH,EAAGE,EAAI,CAACH,EAAMG,CAAE,CAAC,CAAC,GAEvE,CACF,EA1DEX,GAAA,YAD2CtV,EAAAoV,GAAA,aAAtC,IAAMe,GAANf,GAkEA,MAAMgB,GAAN,MAAMA,WAAoBjB,EAAK,CAYpC,YAAY3R,EAAWqL,EAAYC,EAAU,CAC3C,MAAMtL,EAAMqL,EAAMC,CAAE,EAPtBxP,GAAA,KAAA+W,IACA/W,GAAA,KAAAgX,IALA,KAAA,MAAgB,GAIhB1W,EAAA,KAAAyW,GAAc,IAGd,KAAA,YAA+B,CAAC,OAAoB,IAAA,EACpD,KAAA,QAAyB,KAKnBxW,EAAA,KAAKwW,MAAgB,IACvBzW,EAAA,KAAK0W,GAAS,IAAIH,GAAU,IAAI,EAEpC,CAEA,IAAI,MAAe,CACjB,MAAO,IAAI,KAAK,KAAK,CAAC,IAAI,KAAK,KAAK,CAAC,KAAK,KAAK,SAAS,CAAC,EAAE,KAAK,GAAG,CAAC,KAAK,KAAK,SAAS,CAAC,EAAE,KAAK,GAAG,CAAC,GACrG,CACA,OAAO,sBAAsBI,EAAwD,CAEnF,MAAMC,EAAqBD,EAAI,QACzB7R,EAAsB6R,EAAI,YAAY,KAAK5Q,GAAKA,IAAM4Q,EAAI,OAAO,EAEjEE,EAAKF,EAAI7R,CAAI,EAAE,EAAG2D,EAAKkO,EAAI7R,CAAI,EAAE,EACjCgS,EAAKH,EAAIC,CAAG,EAAE,EAAIG,EAAKJ,EAAIC,CAAG,EAAE,EAChCI,EAAKF,EAAKD,EAAII,EAAKF,EAAKtO,EACxBsN,EAAK,KAAK,MAAMiB,EAAIC,CAAE,EAGtBC,GAAMP,EAAI,QAAU,GAAKtB,GAC/B,GAAIU,IAAM,GAAK,CAAC,SAASmB,CAAE,GAAKA,IAAO,EACrC,MAAO,CAAC,CAACJ,EAAIC,CAAE,EAAG,CAACD,EAAIC,CAAE,CAAC,EAO5B,MAAMI,EAAK,CAACF,EAAKlB,EAAGqB,EAAKJ,EAAKjB,EACxBG,EAAQgB,EAAK,EACnB,MAAO,CACL,CAACJ,EAAKK,EAAKjB,EAAOa,EAAKK,EAAKlB,CAAK,EACjC,CAACY,EAAKK,EAAKjB,EAAOa,EAAKK,EAAKlB,CAAK,CAAA,CAErC,CACA,IAAI,UAAW,CACb,OAAOM,GAAY,sBAAsB,IAAI,CAC/C,CACA,IAAI,OAAQ,CACV,OAAOvW,EAAA,KAAKyW,GACd,CACA,IAAI,YAAa,CACf,OAAOzW,EAAA,KAAKwW,GACd,CACA,IAAI,YAAa,CACf,MAAO,CAAC,KAAK,KAAK,EAAG,KAAK,KAAK,CAAC,CAClC,CACF,EAxDEA,GAAA,YACAC,GAAA,YAPoCtW,EAAAoW,GAAA,eAA/B,IAAMa,GAANb,GA6EA,MAAMc,GAAN,MAAMA,WAAoCD,EAAY,CAM3D,YAAYzT,EAAWqL,EAAYC,EAAU,CAC3C,MAAMtL,EAAMqL,EAAMC,CAAE,EAHtB,KAAQ,YAAsB,EAI5B,KAAK,aAAetL,EAAK,aAAe,EACxC,KAAK,YAAeA,EAAK,QAAU,KAAK,OAC1C,CAEA,IAAI,mBAAsC,CACxC,OAAOiD,GAAM,SAAS,KAAK,YAAY,KAAK,IAAI,EAAE,EAAK,KAAK,YAAc,KAAK,YAAa,CAC9F,CAEA,IAAI,UAAiD,CACnD,OAAOwQ,GAAY,sBAAsB,IAAI,CAC/C,CAEA,OAAO,WAAWV,EAA4E,CAC5F,OAAIA,EAAI,aAAe,EACb,IAAIA,EAAI,kBAAkB,CAAC,CAAC,IAAIA,EAAI,kBAAkB,CAAC,CAAC,KAAKA,EAAI,SAAS,CAAC,EAAE,KAAK,GAAG,CAAC,KAAKA,EAAI,SAAS,CAAC,EAAE,KAAK,GAAG,CAAC,KAK5H,QAAQ,MAAM,mEAAmE,EAC1E,GAEX,CACA,IAAI,MAAe,CACjB,OAAOW,GAA4B,WAAW,IAAI,CACpD,CAEA,IAAI,YAAa,CACf,OAAO,KAAK,iBACd,CACF,EAtC6DlX,EAAAkX,GAAA,+BAAtD,IAAMC,GAAND,GAmJA,MAAME,GAAN,MAAMA,WAAiBjC,EAAK,CAEjC,YAAY3R,EAAWqL,EAAYC,EAAU,CAC3C,MAAMtL,EAAMqL,EAAMC,CAAE,CACtB,CAEA,OAAO,WAAW3J,EAAgB2J,EAAU,CAC1C,IACE2D,EAAItN,EAAS,EACbkS,EAAKvI,EAAG,EAAI2D,EACZ6E,EAAK7E,EAAI,EAIX,MAHM,KAAK4E,CAAE,KAAKvI,EAAG,CAAC,MAAM2D,CAAC,IAAIA,CAAC,UAAU6E,CAAE,QAAQ7E,CAAC,IAAIA,CAAC,WAAW6E,CAAE,IAI3E,CAEA,IAAI,MAAO,CACT,IAAIR,EAAK,KAAK,OAAS7B,GACvB,OAAOmC,GAAS,WAAWN,EAAI,KAAK,EAAE,CACxC,CACF,EArBmC9W,EAAAoX,GAAA,YAA5B,IAAMG,GAANH,GClZA,MAAeI,GAAf,MAAeA,EAAS,CAK7B,YACWC,EACArY,EACA4Q,EACA0H,EAAwB,IAAIC,GACnC,CAJO,KAAA,SAAAF,EACA,KAAA,OAAArY,EACA,KAAA,MAAA4Q,EACA,KAAA,aAAA0H,EAEP,KAAK,YAAc,KAAK,OAAA,CAC1B,CAEF,UAAW,CACT,OAAO,KAAK,SAAS,IACvB,CAEA,MAAO,QACLnW,EAAA,KAAK,SAAL,MAAAA,EAAa,YAAY,KAAK,YAChC,CAEA,OAAOqW,EAAkBC,EAAU,GAAM,CAEzC,CAEA,oBAAoBD,EAAkBE,EAAchJ,EAAY,CAC9D,MAAMD,EAAO,WAAW+I,EAAK,aAAaE,CAAI,GAAK,GAAG,EACtD,GAAIjJ,IAASC,EAAI,OAEjB,MAAMiJ,EAAW,IACXC,EAAQ,YAAY,IAAA,EAC1B,SAASH,EAAQI,EAAa,CAC5B,MAAMxN,EAAI,KAAK,IAAI,GAAIwN,EAAMD,GAASD,CAAQ,EACxCtV,EAAQoM,GAAQC,EAAKD,GAAQpE,EACnCmN,EAAK,aAAaE,EAAMrV,EAAM,SAAA,CAAU,EACpCgI,EAAI,EAAG,sBAAsBoN,CAAO,EACnCD,EAAK,aAAaE,EAAMhJ,EAAG,UAAU,CAC5C,CANS9O,EAAA6X,EAAA,WAOT,sBAAsBA,CAAO,CAC/B,CACF,EAzC+B7X,EAAAwX,GAAA,YAAxB,IAAeU,GAAfV,GCUA,MAAMW,GAAqB,IAIrBC,GAAqC,CAAC,IAAM,CAAC,EAC7CC,GAAkC,CAAC,GAAK,CAAC,EAG/C,SAASC,GAAQrS,EAAWsS,EAAYC,EAAYC,EAAiC,CAC1F,MAAM3S,EAAI,KAAK,IAAIG,CAAC,EACpB,GAAI,EAAEH,EAAI,GAAI,MAAO,GACrB,GAAI,EAAE0S,EAAKD,GAAK,OAAOE,EAAM,CAAC,EAC9B,MAAMhO,EAAI,KAAK,IAAI,EAAG,KAAK,IAAI,GAAI3E,EAAIyS,IAAOC,EAAKD,EAAG,CAAC,EACvD,OAAOE,EAAM,CAAC,EAAIhO,GAAKgO,EAAM,CAAC,EAAIA,EAAM,CAAC,EAC3C,CANgBzY,EAAAsY,GAAA,WAST,MAAMI,GAAwB,KAIxBC,GAAqB,IAKrBC,GAAiB,GACjBC,GAAkB,IAGlBC,GAA0B,KAI1BC,GAAwB,GAG9B,SAASC,GAAeC,EAA2B,CACxD,MAAO,GAAIA,CACb,CAFgBjZ,EAAAgZ,GAAA,kBAMT,SAASE,GAAiBC,EAAmBC,EAA2B,CAC7E,OAAQD,EAAYC,GAAc,EAAIN,GACxC,CAFgB9Y,EAAAkZ,GAAA,oBChDhB,SAASG,GAAelY,EAAqB,CAC3C,MAAM6E,EAAI,mBAAmB,KAAK7E,CAAG,EACrC,GAAI,CAAC6E,EAAG,OAAO7E,EACf,KAAM,CAACW,EAAG+C,EAAGC,EAAGgB,EAAI,CAAC,EAAIE,EAAE,CAAC,EAAE,MAAM,GAAG,EAAE,IAAI,MAAM,EAC7CsT,EAAItZ,EAACgB,GAAc,KAAK,MAAM,KAAOA,EAAI,KAAO8E,CAAC,EAA7C,KACV,MAAO,OAAOwT,EAAExX,CAAC,CAAC,IAAIwX,EAAEzU,CAAC,CAAC,IAAIyU,EAAExU,CAAC,CAAC,GACpC,CANS9E,EAAAqZ,GAAA,kBAST,SAASE,GAAWpY,EAAakF,EAAmB,CAClD,MAAML,EAAI,mBAAmB,KAAK7E,CAAG,EACrC,GAAI,CAAC6E,EAAG,OAAO7E,EACf,KAAM,CAACW,EAAG+C,EAAGC,EAAGgB,EAAI,CAAC,EAAIE,EAAE,CAAC,EAAE,MAAM,GAAG,EAAE,IAAI,MAAM,EACnD,MAAO,QAAQ,KAAK,MAAMlE,EAAIuE,CAAC,CAAC,IAAI,KAAK,MAAMxB,EAAIwB,CAAC,CAAC,IAAI,KAAK,MAAMvB,EAAIuB,CAAC,CAAC,IAAIP,CAAC,GACjF,CALS9F,EAAAuZ,GAAA,cAOF,MAAMC,GAAN,MAAMA,WAAetB,EAA8B,CAsBxD,YACST,EACArY,EACA4Q,EACA0H,EAAwB,IAAIC,GACnC,CACA,MAAMF,EAAUrY,EAAQ4Q,EAAO0H,CAAY,EALpC,KAAA,SAAAD,EACA,KAAA,OAAArY,EACA,KAAA,MAAA4Q,EACA,KAAA,aAAA0H,EAzBT,KAAA,SAAmB,eAEnB,KAAQ,UAAmC,KAG3C,KAAQ,QAAiC,KAwBvC,KAAK,YAAc,KAAK,OAAA,CAC1B,CArBQ,WAAW+B,EAAsB,CACvC,MAAMzK,EAAQ,KAAK,SAAiB,MAAQ,CAAA,EACvCA,EAAK,aACVyK,EAAG,aAAa,mBAAoB,OAAOzK,EAAK,QAAU,EAAE,CAAC,EAC7DyK,EAAG,aAAa,mBAAoB,OAAOzK,EAAK,QAAU,EAAE,CAAC,EAC7DyK,EAAG,aAAa,mBAAoB,OAAOzK,EAAK,QAAU,CAAC,CAAC,EAC5DyK,EAAG,aAAa,qBAAsBzK,EAAK,WAAa,OAAS,OAAO,EACpEA,EAAK,QAAQyK,EAAG,aAAa,iBAAkB,MAAM,EACrDzK,EAAK,OAAS,MAAMyK,EAAG,aAAa,kBAAmB,OAAOzK,EAAK,KAAK,CAAC,EACzEA,EAAK,MAAS,MAAMyK,EAAG,aAAa,iBAAmB,OAAOzK,EAAK,IAAI,CAAC,EAC9E,CAaA,QAAS,CACP,GAAI,KAAK,oBAAoBuI,GAAU,CAErC,MAAMmC,EAAO,SAAS,gBAAgB,6BAA8B,MAAM,EAC1E,OAAAA,EAAK,aAAa,OAAU,KAAK,SAAS,MAAM,UAAU,EAC1DA,EAAK,aAAa,SAAU,MAAM,EAClC,KAAK,YAAcA,EACZA,CACT,CAEA,GAAI,KAAK,oBAAoBzC,GAAa,CAIxC,MAAMyC,EAAO,SAAS,gBAAgB,6BAA8B,MAAM,EAC1E,OAAAA,EAAK,aAAa,OAAU,KAAK,SAAS,MAAM,UAAU,EAC1DA,EAAK,aAAa,SAAU,MAAM,EAClC,KAAK,YAAcA,EACZA,CACT,CAEA,MAAM3R,EAAO,SAAS,gBAAgB,6BAA8B,MAAM,EAC1E,OAAAA,EAAK,aAAa,KAAQ,KAAK,SAAS,KAAK,EAAE,UAAU,EACzDA,EAAK,aAAa,KAAQ,KAAK,SAAS,KAAK,EAAE,UAAU,EACzDA,EAAK,aAAa,KAAQ,KAAK,SAAS,GAAG,EAAE,UAAU,EACvDA,EAAK,aAAa,KAAQ,KAAK,SAAS,GAAG,EAAE,UAAU,EACvDA,EAAK,aAAa,eAAgB,KAAK,SAAA,EAAW,UAAU,EAC5DA,EAAK,aAAa,SAAU,KAAK,SAAS,MAAM,UAAU,EAE1D,KAAK,YAAcA,EACZA,CACT,CAEA,QAAS,OACF,KAAK,aACR,KAAK,OAAA,EAEF,KAAK,YAAY,eACpB,KAAK,OAAO,YAAY,KAAK,WAAW,EAG1C,MAAM4R,IAAUpY,EAAA,KAAK,MAAM,SAAiB,WAA5B,YAAAA,EAAsC,QAAS,EACzDyN,EAAU,KAAK,SAAiB,MAAQ,CAAA,EAE9C,GAAIA,EAAK,WAAY,CACnB,KAAK,WAAW,KAAK,WAAW,EAChC,MAAM7J,EAAU,OAAO6J,EAAK,QAAc,SAAWA,EAAK,OAAY,EAChE4K,EAAU,OAAO5K,EAAK,WAAc,SAAWA,EAAK,UAAY,EAChE6K,EAAU,OAAO7K,EAAK,SAAc,SAAWA,EAAK,QAAY,KAAK,IAAI,EAAG7J,GAAUyU,GAAQ,EAAE,EAQhGE,EAAUH,EAAS,EAAIA,EAAS,EAChCI,EAAU,OAAO/K,EAAK,WAAc,SACtC8K,EAAM9K,EAAK,UAAY7J,EACvB2U,EAAMpB,IAAyBvT,GAAUyU,GAAQ,IAK/CI,EAAa,KAAK,SAAiB,QAAU,IAAI/U,GAAM,SAAS,EAGhEgV,EAAa,OAAOjL,EAAK,YAAe,SAAWA,EAAK,WAAa6K,EACrEK,EAAY,IAAIhU,GAAc8T,EAAWC,EAAYJ,CAAO,EAAE,SAAA,EAEpE,GAAI,KAAK,oBAAoBtC,GAK1B,KAAK,SAAsB,OAASwC,EACpC,KAAK,YAA+B,aAAa,IAAM,KAAK,SAAsB,IAAI,EACvF,KAAK,YAAY,aAAa,OAAUG,CAAS,EACjD,KAAK,YAAY,aAAa,SAAU,MAAM,UACrC,KAAK,oBAAoBjD,IAqBlC,GAlBC,KAAK,SAAyB,OAAS8C,EACvC,KAAK,YAA+B,aAAa,IAAM,KAAK,SAAyB,IAAI,EAC1F,KAAK,YAAY,aAAa,OAAUG,CAAS,EAKjD,KAAK,YAAY,aAAa,SAAUA,CAAS,EACjD,KAAK,YAAY,aAAa,eAAgB,OAAOvB,EAAkB,CAAC,EACxE,KAAK,YAAY,aAAa,gBAAiB,oBAAoB,EACnE,KAAK,YAAY,aAAa,kBAAmB,OAAO,EAQpD3J,EAAK,WACP,GAAI,CAEF,MAAMmL,EADQ,IAAIhE,GAAU,KAAK,QAAe,EACxB,KAGpBgE,GAAa,CAACA,EAAU,SAAS,KAAK,GAAK,CAACA,EAAU,SAAS,UAAU,IACtE,KAAK,YACR,KAAK,UAAY,SAAS,gBAAgB,6BAA8B,MAAM,EAC9E,KAAK,UAAU,aAAa,SAAU,MAAM,GAEzC,KAAK,UAAU,eAClB,KAAK,OAAO,YAAY,KAAK,SAAS,EAExC,KAAK,UAAU,aAAa,IAAKA,CAAS,EAM1C,KAAK,UAAU,aAAa,OAAQZ,GAAWF,GAAea,CAAS,EAAGtB,EAAc,CAAC,EACzF,KAAK,UAAU,aAAa,SAAU,SAAS,EAC/C,KAAK,UAAU,aAAa,eAAgB,OAAOC,EAAe,CAAC,EACnE,KAAK,UAAU,aAAa,gBAAiB,oBAAoB,EACjE,KAAK,UAAU,aAAa,kBAAmB,OAAO,EAE1D,MAAY,CAGZ,MAEG,CAEL,MAAMpP,EAAK,KAAK,SAAS,KAAK,EAAGC,EAAK,KAAK,SAAS,KAAK,EACnDC,EAAK,KAAK,SAAS,GAAG,EAAKC,EAAK,KAAK,SAAS,GAAG,EACtD,KAAK,YAA+B,aAAa,KAAMH,EAAG,UAAU,EACpE,KAAK,YAA+B,aAAa,KAAMC,EAAG,UAAU,EACpE,KAAK,YAA+B,aAAa,KAAMC,EAAG,UAAU,EACpE,KAAK,YAA+B,aAAa,KAAMC,EAAG,UAAU,EACrE,KAAK,YAAY,aAAa,eAAgBmQ,EAAG,UAAU,EAC3D,KAAK,YAAY,aAAa,SAAgBG,CAAS,EACvD,KAAK,YAAY,aAAa,iBAAkB,QAAQ,EACxD,KAAK,YAAY,gBAAgB,YAAY,EAIxC,KAAK,UACR,KAAK,QAAU,SAAS,gBAAgB,6BAA8B,MAAM,EAC5E,KAAK,QAAQ,aAAa,SAAU,aAAa,EACjD,KAAK,QAAQ,aAAa,iBAAkB,OAAO,EACnD,KAAK,QAAQ,aAAa,iBAAkB,QAAQ,GAEjD,KAAK,QAAQ,oBAAoB,OAAO,YAAY,KAAK,OAAO,EACrE,KAAK,QAAQ,aAAa,KAAMzQ,EAAG,UAAU,EAC7C,KAAK,QAAQ,aAAa,KAAMC,EAAG,UAAU,EAC7C,KAAK,QAAQ,aAAa,KAAMC,EAAG,UAAU,EAC7C,KAAK,QAAQ,aAAa,KAAMC,EAAG,UAAU,EAC7C,KAAK,QAAQ,aAAa,eAAgB,KAAK,IAAImQ,EAAIJ,EAAS,GAAI,EAAE,SAAA,CAAU,EAChF,KAAK,WAAW,KAAK,OAAO,CAC9B,CACF,KAAO,CAEJ,KAAK,YAA+B,aAAa,KAAM,KAAK,SAAS,KAAK,EAAE,UAAU,EACtF,KAAK,YAA+B,aAAa,KAAM,KAAK,SAAS,KAAK,EAAE,UAAU,EACtF,KAAK,YAA+B,aAAa,KAAM,KAAK,SAAS,GAAG,EAAE,UAAU,EACpF,KAAK,YAA+B,aAAa,KAAM,KAAK,SAAS,GAAG,EAAE,UAAU,EACrF,MAAMI,GAAMJ,EAAS,EAAIA,EAAS,GAAK,KAAQ,KAAK,SAAA,EACpD,KAAK,YAAY,aAAa,eAAkBI,EAAG,UAAU,EAC7D,KAAK,YAAY,aAAa,iBAAkB,GAAG,EACnD,KAAK,YAAY,aAAa,SAAkB,KAAK,SAAS,MAAM,UAAU,CAChF,CACF,CAEA,MAAO,WACD,KAAK,WAASxY,EAAA,KAAK,SAAL,MAAAA,EAAa,YAAY,KAAK,WAChDyC,EAAA,KAAK,SAAL,MAAAA,EAAa,YAAY,KAAK,aAC1B,KAAK,aACPE,EAAA,KAAK,SAAL,MAAAA,EAAa,YAAY,KAAK,WAElC,CACF,EArN0DlE,EAAAwZ,GAAA,UAAnD,IAAMY,GAANZ,GCnBA,MAAMa,GAAN,MAAMA,WAAgBnC,EAA8B,CAGzD,YACST,EACArY,EACA4Q,EACA0H,EAAwB,IAAIC,GACnC,CACA,MAAMF,EAAUrY,EAAQ4Q,EAAO0H,CAAY,EALpC,KAAA,SAAAD,EACA,KAAA,OAAArY,EACA,KAAA,MAAA4Q,EACA,KAAA,aAAA0H,EANT,KAAA,SAAmB,gBAUjB,KAAK,YAAc,KAAK,OAAA,CAC1B,CAEA,IAAI,GAAI,CACN,OAAO,KAAK,SAAS,WAAW,KAAK,MAAM,SAAS,QAAQ,MAAM,WAAW,CAAC,CAAC,CACjF,CACA,IAAI,GAAI,CACN,OAAO,KAAK,SAAS,WAAW,KAAK,MAAM,SAAS,QAAQ,MAAM,WAAW,CAAC,CAAC,CACjF,CAEA,IAAI,UAAoB,CACtB,OAAQ,KAAK,SAAiB,QAAU,MAC1C,CAGA,IAAI,WAAwD,CAC1D,MAAM9R,EAAK,KAAK,SAAiB,MACjC,OAAOA,IAAM,QAAUA,IAAM,SAAW,OACjCA,IAAM,YAAcA,IAAM,UAAYA,EAAI,QACnD,CAGA,IAAY,KAAc,CACxB,MAAMS,EAAI,KAAK,UACf,OAAOA,IAAM,SAAW,SAAWA,IAAM,OAAS,OAAS,MAC7D,CAGQ,YAAYoT,EAAgB3X,EAAiB,CACnD,MAAMiE,EAAI,KAAK,EAAGQ,EAAI,KAAK,EAC3B,OAAQ,KAAK,UAAA,CACX,IAAK,OACHkT,EAAG,aAAa,KAAM1T,EAAIjE,GAAG,UAAU,EAAG2X,EAAG,aAAa,KAAMlT,EAAIzE,GAAG,UAAU,EACjF2X,EAAG,aAAa,SAAU3X,EAAI,GAAG,UAAU,EAAG2X,EAAG,aAAa,UAAW3X,EAAI,GAAG,UAAU,EAC1F,MACF,IAAK,WAAY,CAEf,MAAM+D,EAAI/D,EAAI,KACd2X,EAAG,aAAa,IAAK,IAAI1T,CAAC,IAAIQ,EAAIV,CAAC,KAAKE,EAAIF,EAAI,IAAK,IAAIU,EAAIV,EAAI,EAAG,KAAKE,EAAIF,EAAI,IAAK,IAAIU,EAAIV,EAAI,EAAG,GAAG,EACxG,KACF,CACA,IAAK,UACH4T,EAAG,aAAa,IAAK,IAAI1T,CAAC,IAAIQ,EAAIzE,EAAI,GAAG,KAAKiE,EAAIjE,CAAC,IAAIyE,CAAC,KAAKR,CAAC,IAAIQ,EAAIzE,EAAI,GAAG,KAAKiE,EAAIjE,CAAC,IAAIyE,CAAC,GAAG,EAC/F,MACF,QACEkT,EAAG,aAAa,KAAM1T,EAAE,SAAA,CAAU,EAAG0T,EAAG,aAAa,KAAMlT,EAAE,SAAA,CAAU,EACvEkT,EAAG,aAAa,IAAK3X,EAAE,SAAA,CAAU,CAAA,CAEvC,CAMA,eAAwB,OACtB,MAAMA,EAAI,KAAK,WAAA,EAGT+R,GAAOtS,EAAA,KAAK,SAAiB,OAAtB,YAAAA,EAA4B,UACzC,OAAO,OAAOsS,GAAQ,UAAYA,EAAM,EAAI,KAAK,IAAI/R,EAAG+R,CAAG,EAAI/R,CACjE,CAEQ,YAAqB,aAC3B,MAAM6X,EAAU,KAAK,MAAM,SAAS,SAAS,OAAU,EACjDW,IAAa/Y,EAAA,KAAK,SAAiB,OAAtB,YAAAA,EAA4B,YAAa,EAK5D,IAAKyC,EAAA,KAAK,SAAiB,OAAtB,MAAAA,EAA4B,UAAW,CAC1C,MAAMuW,GAAQpW,GAAAD,EAAA,KAAK,MAAM,cAAX,YAAAA,EAA0C,wBAA1C,YAAAC,EAAA,KAAAD,GACRsW,EAAQ,KAAK,MAAc,YAAc,EACzCC,EAAYF,GAAQA,EAAK,MAAQ,EAAIA,EAAK,OAAS,EAAIZ,GAAU,EAEvE,OADiB,KAAK,SAAS,KAAO,EAAIW,EACvBG,EAAaD,CAClC,CACA,OAAOb,EAASb,GAA0B,KAAK,SAAS,KAAOwB,CACjE,CAKQ,YAAYb,EAAsB,OACxC,MAAMiB,GAAUnZ,EAAA,KAAK,SAAiB,OAAtB,YAAAA,EAA4B,OACvCmZ,IACLjB,EAAG,aAAa,SAAUiB,CAAM,EAChCjB,EAAG,aAAa,gBAAiB,KAAK,gBAAkB,KAAM,UAAU,EAC1E,CAEA,QAAS,CACP,MAAMA,EAAK,SAAS,gBAAgB,6BAA8B,KAAK,GAAG,EAE1EA,EAAG,aAAa,gBAAiB,KAAK,SAAS,EAAE,EAEjD,MAAMzK,EAAQ,KAAK,SAAiB,MAAQ,CAAA,EAC5C,OAAIA,EAAK,MAAOyK,EAAG,aAAa,YAAazK,EAAK,IAAI,EAClDA,EAAK,MAAQ,MAAOyK,EAAG,aAAa,YAAc,OAAOzK,EAAK,IAAI,CAAC,EACnEA,EAAK,OAAS,MAAMyK,EAAG,aAAa,aAAc,OAAOzK,EAAK,KAAK,CAAC,EACpEA,EAAK,MAAQ,MAAOyK,EAAG,aAAa,YAAc,OAAOzK,EAAK,IAAI,CAAC,EACvEyK,EAAG,aAAa,OAAQ,KAAK,SAAS,MAAM,UAAU,EACtD,KAAK,YAAYA,CAAE,EAEnB,KAAK,YAAYA,EAAI,KAAK,cAAA,CAAe,EAEzC,KAAK,YAAcA,EAEnBA,EAAG,iBAAiB,QAAS,IAAM,CAGjC,KAAK,SAAS,OAAS,CAAC,KAAK,SAAS,OACtC,KAAK,OAAA,EAEL,MAAMkB,EAAa,IAAI,YAAY,gBAAiB,CAClD,OAAQ,CAAE,UAAW,KAAK,QAAA,EAC1B,QAAS,GAAM,SAAU,EAAA,CAC1B,EACD,KAAK,YAAY,cAAcA,CAAU,CAC3C,CAAC,EAEDlB,EAAG,iBAAiB,YAAa,IAAM,CAIvC,CAAC,EAEMA,CACT,CAEA,QAAS,CACF,KAAK,aACP,KAAK,OAAe,SAAS,aAAa,KAAK,KAAK,QAAQ,EAE1D,KAAK,YAAY,eACpB,KAAK,OAAO,YAAY,KAAK,WAAW,EAG1C,KAAK,YAAY,aAAa,OAAQ,KAAK,SAAS,MAAM,UAAU,EACpE,KAAK,YAAY,KAAK,WAAW,EACjC,KAAK,YAAY,KAAK,YAAa,KAAK,eAAe,CACzD,CAEA,MAAO,QACLlY,EAAA,KAAK,SAAL,MAAAA,EAAa,YAAY,KAAK,YAChC,CACF,EA3J2DvB,EAAAqa,GAAA,WAApD,IAAMO,GAANP,GCDA,MAAMQ,GAAN,MAAMA,WAAqB3C,EAA8B,CAO9D,YACST,EACArY,EACA4Q,EACA0H,EAAwB,IAAIC,GACnC,CACA,MAAMF,EAAUrY,EAAQ4Q,EAAO0H,CAAY,EALpC,KAAA,SAAAD,EACA,KAAA,OAAArY,EACA,KAAA,MAAA4Q,EACA,KAAA,aAAA0H,EAVT,KAAA,SAAmB,aACnB,KAAQ,SAAkC,KAC1C,KAAQ,gBAAsC,KAC9C,KAAQ,QAAmC,KAC3C,KAAQ,cAAoC,KAS1C,KAAK,YAAc,KAAK,OAAA,CAC1B,CAIQ,oBAAoBoD,EAAwB,OAClD,MAAMnB,EAAS,KAAK,MAAM,SAAS,SAAS,OAAS,EAC/CoB,IAAQxZ,EAAA,KAAK,MAAM,cAAX,YAAAA,EAAwB,wBAAwB,QAAS,EACvE,OAAOwZ,EAAQ,EAAID,GAAU,EAAInB,EAASoB,GAASD,EAASnB,EAAS,IACvE,CAEA,QAAS,CACP,MAAMqB,EAAQ,SAAS,gBAAgB,6BAA8B,GAAG,EACxEA,EAAM,aAAa,QAAS,qBAAqB,EAEjD,MAAMtB,EAAO,SAAS,gBAAgB,6BAA8B,MAAM,EAC1EA,EAAK,aAAa,OAAQ,MAAM,EAChCA,EAAK,aAAa,SAAU,KAAK,SAAS,MAAM,UAAU,EAC1DA,EAAK,aAAa,eAAgB,KAAK,oBAAoB,KAAK,SAAS,WAAW,EAAE,UAAU,EAChGsB,EAAM,YAAYtB,CAAI,EACtB,KAAK,SAAWA,EAEhB,MAAMuB,EAAgB,SAAS,gBAAgB,6BAA8B,GAAG,EAChFA,EAAc,aAAa,QAAS,wBAAwB,EAC5DD,EAAM,YAAYC,CAAa,EAC/B,KAAK,gBAAkBA,EAEvB,MAAMC,EAAc,SAAS,gBAAgB,6BAA8B,GAAG,EAK9E,GAJAA,EAAY,aAAa,QAAS,sBAAsB,EACxDF,EAAM,YAAYE,CAAW,EAC7B,KAAK,cAAgBA,EAEjB,KAAK,SAAS,SAAU,CAC1B,MAAMC,EAAM,SAAS,gBAAgB,6BAA8B,QAAQ,EAC3EA,EAAI,aAAa,OAAQ,KAAK,SAAS,MAAM,UAAU,EACvDA,EAAI,aAAa,IAAK,KAAK,oBAAoB,CAAC,EAAE,UAAU,EAC5DA,EAAI,aAAa,SAAU,SAAS,EACpCA,EAAI,aAAa,eAAgB,KAAK,oBAAoB,GAAG,EAAE,UAAU,EACzEH,EAAM,YAAYG,CAAG,EACrB,KAAK,QAAUA,CACjB,CAEA,YAAK,YAAcH,EACZA,CACT,CAEA,QAAS,CACF,KAAK,aACR,KAAK,OAAA,EAEF,KAAK,YAAY,eACpB,KAAK,OAAO,YAAY,KAAK,WAAW,EAG1C,MAAMI,EAAO,KAAK,SAAS,KAQ3B,GAPI,KAAK,WACP,KAAK,SAAS,aAAa,IAAKA,CAAI,EACpC,KAAK,SAAS,aAAa,SAAU,KAAK,SAAS,MAAM,UAAU,EACnE,KAAK,SAAS,aAAa,eAAgB,KAAK,oBAAoB,KAAK,SAAS,WAAW,EAAE,SAAA,CAAU,EACzG,KAAK,SAAS,MAAM,QAAU,KAAK,SAAS,YAAc,UAAY,OAAS,SAG7E,KAAK,gBAEP,GADA,KAAK,gBAAgB,UAAY,GAC7B,KAAK,SAAS,YAAc,UAAW,CACzC,MAAMC,EAAU,KAAK,SAAS,WACxBC,EAAYD,EAAQ,OAAS,EAC7B,CAACE,EAAUC,CAAQ,EAAI,KAAK,SAAS,iBACrC,CAACC,EAAYC,CAAU,EAAI,KAAK,SAAS,aAE/C,QAAShb,EAAI,EAAGA,EAAI4a,EAAW5a,IAAK,CAClC,MAAMsX,EAAQqD,EAAQ3a,CAAC,EACjBib,EAAMN,EAAQ3a,EAAI,CAAC,EACnBkb,EAAWN,GAAa,EAAI,EAAI5a,GAAK4a,EAAY,GACjDP,EAAQQ,GAAYC,EAAWD,GAAYK,EAC3C/B,EAAU4B,GAAcC,EAAaD,GAAcG,EACnDC,EAAU,SAAS,gBAAgB,6BAA8B,MAAM,EAE7EA,EAAQ,aAAa,IAAK,IAAI7D,EAAM,CAAC,IAAIA,EAAM,CAAC,KAAK2D,EAAI,CAAC,IAAIA,EAAI,CAAC,EAAE,EACrEE,EAAQ,aAAa,OAAQ,MAAM,EACnCA,EAAQ,aAAa,SAAU,KAAK,SAAS,MAAM,UAAU,EAC7DA,EAAQ,aAAa,iBAAkB,OAAO,EAC9CA,EAAQ,aAAa,kBAAmB,OAAO,EAC/CA,EAAQ,aAAa,eAAgB,KAAK,oBAAoBd,CAAK,EAAE,UAAU,EAC/Ec,EAAQ,aAAa,UAAWhC,EAAQ,SAAA,CAAU,EAClD,KAAK,gBAAgB,YAAYgC,CAAO,CAC1C,CACA,KAAK,gBAAgB,MAAM,QAAU,OACvC,MACE,KAAK,gBAAgB,MAAM,QAAU,OAIzC,MAAMxY,EAAM,KAAK,SAAS,aAoB1B,GAlBI,KAAK,gBACH,KAAK,SAAS,YAAcA,EAAI,OAAS,GAC3C,KAAK,cAAc,UAAY,GAC/BA,EAAI,QAAQyR,GAAM,OAChB,MAAMnC,EAAM,SAAS,gBAAgB,6BAA8B,QAAQ,EAC3EA,EAAI,aAAa,KAAMmC,EAAG,EAAE,UAAU,EACtCnC,EAAI,aAAa,KAAMmC,EAAG,EAAE,UAAU,EACtCnC,EAAI,aAAa,IAAK,KAAK,oBAAoB,GAAG,EAAE,UAAU,EAC9DA,EAAI,aAAa,OAAQ,KAAK,SAAS,MAAM,UAAU,EACvDA,EAAI,aAAa,UAAW,KAAK,GACjCpR,EAAA,KAAK,gBAAL,MAAAA,EAAoB,YAAYoR,EAClC,CAAC,EACD,KAAK,cAAc,MAAM,QAAU,SAEnC,KAAK,cAAc,MAAM,QAAU,QAInC,KAAK,SAAW,KAAK,SAAS,SAChC,GAAItP,EAAI,OAAS,EAAG,CAClB,MAAMyY,EAASzY,EAAIA,EAAI,OAAS,CAAC,EACjC,KAAK,QAAQ,aAAa,KAAMyY,EAAO,EAAE,UAAU,EACnD,KAAK,QAAQ,aAAa,KAAMA,EAAO,EAAE,UAAU,EACnD,KAAK,QAAQ,aAAa,OAAQ,KAAK,SAAS,MAAM,UAAU,EAChE,KAAK,QAAQ,aAAa,IAAK,KAAK,oBAAoB,CAAC,EAAE,UAAU,EACrE,KAAK,QAAQ,aAAa,eAAgB,KAAK,oBAAoB,GAAG,EAAE,UAAU,EAClF,KAAK,QAAQ,MAAM,QAAU,OAC/B,MACE,KAAK,QAAQ,MAAM,QAAU,MAGnC,CAEA,MAAO,CACD,KAAK,aAAe,CAAC,KAAK,YAAY,eACxC,KAAK,OAAO,YAAY,KAAK,WAAW,EAE1C,KAAK,OAAA,CACP,CACF,EApJgE9b,EAAA6a,GAAA,gBAAzD,IAAMkB,GAANlB,GCMP,KAAM,CAAE,WAAAjQ,IAAenE,GACVuV,GAAN,MAAMA,WAAgB,KAAW,CACtC,eAAenZ,EAAa,CAC1B,MAAM,GAAGA,CAAI,CACf,CAEA,OAAOL,EAAapC,EAAqC,CACvD,IAAIkN,EAEJ,SAASC,EAAGzH,EAAqC,CAC/C,OAAOA,EAAE,OAAS1F,EAAO0F,EAAI,MAC/B,CAFS9F,EAAAuN,EAAA,MAIT,SAASC,EAAQvC,EAAUvK,EAAYtB,EAAc,KAA6B,CAChF,GAAIwL,GAAW,QAAQK,CAAG,GACxB,SAAW,CAACvK,EAAG4B,CAAC,IAAK2I,EAAI,UAEvB,GADAqC,EAAQE,EAAQlL,EAAG5B,EAAGtB,CAAM,EACxBkO,EACF,OAAOA,MAGN,CAEL,GADAA,EAAQC,EAAGtC,CAAG,EACTqC,EAUH,OAAOA,EATP,GAAIrC,GAAOL,GAAW,QAAQK,EAAIzI,CAAG,CAAC,GACpC,SAAW,CAAC9B,EAAG4B,CAAC,IAAK2I,EAAIzI,CAAG,EAAE,UAE5B,GADA8K,EAAQE,EAAQlL,EAAG5B,EAAGuK,CAAG,EACrBqC,EACF,OAAOA,EAOjB,CACA,OAAOA,CACT,CAxBS,OAAAtN,EAAAwN,EAAA,WA0BFA,EAAQ,IAAI,CACrB,CAEA,SAAuB,CACrB,OAAO,KAAK,OAAoB,CAAC1H,EAAG7E,KAClC6E,EAAE,KAAK7E,CAAC,EACJA,EAAE,QAAU,MAAM,QAAQA,EAAE,MAAM,GACpC6E,EAAE,KAAK,GAAG7E,EAAE,MAAM,EAEb6E,GACN,CAAA,CAAE,CACP,CACF,EAlDwC9F,EAAAgc,GAAA,WAAjC,IAAMrE,GAANqE,GA+DP,MACEC,GACE,CACE,UAAarB,GACb,SAAYR,GACZ,MAASQ,GACT,KAAQR,GACR,KAAQA,GACR,YAAeA,GACf,4BAA+BA,GAC/B,SAAYA,GACZ,WAAc2B,EAChB,EAGSG,GAAN,MAAMA,EAA6B,CAMxC,YACSzE,EACArY,EACA4Q,EACA0H,EAAwB,IAAIC,GACnC,CAJO,KAAA,SAAAF,EACA,KAAA,OAAArY,EACA,KAAA,MAAA4Q,EACA,KAAA,aAAA0H,EAEP,KAAK,SAAWD,EAAS,MAAQ,gBAEjCA,EAAS,UAAU,YAAY,gBAAiB,OAAQ,CAAC,CAAE,IAAAjV,EAAK,SAAA2K,EAAU,SAAAJ,KAAqB,CAC7F,MAAMoP,EAAUnc,EAACkQ,UAAsB,OAAA3O,EAAA2O,EAAM,WAAN,YAAA3O,EAAkC,IAAzD,WAEV6a,EAAW,KAAK,aAAa,OAAQlM,GACzC,CAAC/C,EAAS,QAAQ,IAAIgP,EAAQjM,CAAK,CAAC,CAAA,EAEhCmM,EAAW,KAAK,aAAa,OAAQnM,GACzC/C,EAAS,QAAQ,IAAIgP,EAAQjM,CAAK,CAAC,CAAA,EAEtB,CAAC,GAAG/C,EAAS,QAAQ,OAAA,CAAQ,EAAE,OAAQlC,GACpD,CAAC,KAAK,aAAa,KAAMiF,GAAqBiM,EAAQjM,CAAK,IAAMjF,EAAI,EAAE,CAAA,EAGlE,QAASA,GAAuB,CACrC,MAAMqR,EAAYrR,EAAY,WAAaA,EAAI,YAAY,KAC3D,IAAIsR,EAAcN,GAAsBK,CAAQ,EAC3CC,IACCtR,aAAe+J,GAAYuH,EAAcR,GACpC9Q,aAAenE,EAAOyV,EAAc3B,GACxC2B,EAAcnC,IAErB,MAAMoC,EAAyB,IAAID,EAAYtR,EAAK,KAAK,YAAa,KAAK,KAAK,EAChF,KAAK,aAAa,KAAKuR,CAAW,CACpC,CAAC,EAEDH,EAAS,QAASnM,GAAqB,CAIrC,MAAMuM,EAAUtP,EAAS,QAAQ,IAAIgP,EAAQjM,CAAK,CAAC,EAC/CuM,IAAUvM,EAAc,SAAWuM,GACvCvM,EAAM,OAAA,CACR,CAAC,EAEDkM,EAAS,QAASlM,GAAqB,CACjCA,EAAM,YAAY,eACpBA,EAAM,YAAY,cAAc,YAAYA,EAAM,WAAW,EAE/D,MAAM7O,EAAM,KAAK,aAAa,QAAQ6O,CAAK,EACvC7O,GAAO,GAAG,KAAK,aAAa,OAAOA,EAAK,CAAC,CAC/C,CAAC,EAED,KAAK,OAAA,CACP,CAAC,EAED,KAAK,YAAc,KAAK,OAAA,CAC1B,CAEA,IAAI,MAAO,CACT,OAAO,KAAK,QACd,CAEA,QAAqB,CACnB,GAAG,CAAC,KAAK,SACP,MAAM,IAAI,MAAM,eAAe,EAEjC,IAAIuM,EAAe,KAAK,SACxB,YAAK,YAAc,SAAS,gBAAgB,6BAA8BsO,GAAQ,OAAO,EACzF,KAAK,YAAY,aAAa,kBAAmBtO,EAAM,IAAI,EAC3D,KAAK,YAAY,aAAa,gBAAmBA,EAAM,EAAE,EAExD,KAAK,YAAoB,SAAWA,EAErC,KAAK,YAAY,UAAU,IAAI,WAAW,EAEvC,KAAK,SAAS,QAAU,KAAK,SAAS,OAAO,OAAS,GACvD,KAAK,SAAS,OAAO,QAAS8O,GAAwB,CACpD,MAAMC,EAAmB,IAAIT,GAAQQ,EAAiB,KAAK,YAAa,KAAK,KAAK,EAClF,KAAK,aAAa,KAAKC,CAAO,CAChC,CAAC,EAGI,KAAK,WACd,CAEA,QAAS,CACP,GAAG,CAAC,KAAK,SACP,MAAM,IAAI,MAAM,eAAe,EAG9B,KAAK,SAAS,UAEZ,KAAK,OAAO,SAAS,YAAA,EAQxB,KAAK,aAAa,QAASzM,GAAqB,CAC9CA,EAAM,OAAA,CACR,CAAC,EAEE,KAAK,SAAS,gBAAkB,IAC9B,KAAK,SAUd,CAEA,MAAa,QACX3O,EAAA,KAAK,SAAL,MAAAA,EAAa,YAAY,KAAK,aAE9B,KAAK,aAAa,QAAS2O,GAAqB,CAC9CA,EAAM,KAAA,CACR,CAAC,CACH,CAEA,IAAIA,EAAkB,CACpB,KAAK,aAAa,KAAKA,CAAK,CAC9B,CACF,EApI0ClQ,EAAAkc,GAAA,WACxCA,GAAO,QAAU,IADZ,IAAMU,GAANV,GCvEA,MAAMW,GAAN,MAAMA,EAAQ,CAQnB,YACkBC,EACA9V,EACA5H,EACA4Q,EACA+M,EAAsB3N,EAAM,cAAc,GAC1C4N,EAAsB5N,EAAM,SAAS,OAC9C6N,EACAC,EACP,CARgB,KAAA,KAAAJ,EACA,KAAA,MAAA9V,EACA,KAAA,OAAA5H,EACA,KAAA,MAAA4Q,EACA,KAAA,YAAA+M,EACA,KAAA,SAAAC,EACT,KAAA,QAAAC,EACA,KAAA,QAAAC,EAdT,KAAQ,SAAoB,GAE5B,KAAQ,SAAW,EACnB,KAAQ,SAAW,EACnB,KAAA,OAAS,GAYP,KAAK,YAAc,KAAK,QAAA,EAKpBH,IAAgB3N,EAAM,cAAc,IACtC,KAAK,SAAW,GAChB,KAAK,YAAY,aAAa,UAAW,OAAO,IAEhD,KAAK,SAAW,GAChB,KAAK,YAAY,aAAa,UAAW,MAAM,EAEnD,CAEQ,SAA0B,CAChC,MAAMqK,EAAK,SAAS,gBAAgB,6BAA8B,MAAM,EACxE,OAAAA,EAAG,YAAc,KAAK,KACtBA,EAAG,aAAa,iBAAkB,KAAK,MAAM,EAAE,EAC/CA,EAAG,aAAa,iBAAkB,MAAM,EACxCA,EAAG,MAAM,OAAS,OAClB,KAAK,YAAYA,CAAE,EACnB,KAAK,OAAO,YAAYA,CAAE,EACnBA,CACT,CAGQ,YAAYA,EAA0B,CAC5CA,EAAG,iBAAiB,YAAc0D,GAAmB,CACnDA,EAAG,eAAA,EACHA,EAAG,gBAAA,EACH,MAAMC,EAAM3D,EAAG,gBACf,GAAI,CAAC2D,EAAK,OACV,MAAMC,EAASrd,EAAA,CAACsP,EAAYC,IAAe,CACzC,MAAMjM,EAAI8Z,EAAI,eAAA,EAAkB9Z,EAAE,EAAIgM,EAAIhM,EAAE,EAAIiM,EAChD,MAAMvJ,EAAIoX,EAAI,aAAA,EACd,OAAOpX,EAAI1C,EAAE,gBAAgB0C,EAAE,SAAS,EAAK,CAAE,EAAG,EAAG,EAAG,CAAA,CAC1D,EAJe,UAKTgS,EAAQqF,EAAOF,EAAG,QAASA,EAAG,OAAO,EACrCG,EAAQ,KAAK,SAAUC,EAAQ,KAAK,SAC1C9D,EAAG,MAAM,OAAS,WAElB,MAAM+D,EAASxd,EAACwQ,GAAkB,CAChC,MAAMlN,EAAI+Z,EAAO7M,EAAE,QAASA,EAAE,OAAO,EACrC,KAAK,SAAW8M,GAASha,EAAE,EAAI0U,EAAM,GACrC,KAAK,SAAWuF,GAASja,EAAE,EAAI0U,EAAM,GACrC,KAAK,OAAS,GACd,KAAK,SAAW,GAChB,KAAK,YAAY,aAAa,UAAW,OAAO,EAChD,KAAK,OAAA,CACP,EARe,UASTyF,EAAOzd,EAAA,IAAM,CACjB,SAAS,oBAAoB,YAAawd,CAAM,EAChD,SAAS,oBAAoB,UAAWC,CAAI,EAC5ChE,EAAG,MAAM,OAAS,OAElB,KAAK,MAAM,cAAc,IAAI,YAAY,gBAAiB,CACxD,OAAQ,CAAE,GAAI,KAAK,MAAM,GAAI,UAAW,CAAE,EAAG,KAAK,SAAU,EAAG,KAAK,SAAS,EAC7E,QAAS,GAAM,SAAU,EAAA,CAC1B,CAAC,CACJ,EATa,QAUb,SAAS,iBAAiB,YAAa+D,CAAM,EAC7C,SAAS,iBAAiB,UAAWC,CAAI,CAC3C,CAAC,CACH,CAMA,QAAe,OACb,GAAI,CAAC,KAAK,SAAU,OAEpB,MAAM9D,EAAS,KAAK,MAAM,SAAS,SAAS,MAC5C,GAAIA,GAAU,EAAG,OAIjB,MAAM+D,EAAc,KAAK,MAAc,YAAc,CAAA,EAC/CC,EAAaD,EAAK,KAAOA,EAAK,KAAQ,KAAK,MAAc,gBAAkB/D,EAAS,IACpFiE,EAAaD,EAAW,IAE9B,IAAI5X,EAAWQ,EAAWsX,EAE1B,OAAQ,KAAK,SAAA,CAEX,KAAKzO,EAAM,SAAS,OAAQ,CAG1BrJ,EAAS,KAAK,MAAM,EACpBQ,EAAS,KAAK,MAAM,EAAIqX,EAAS,GACjCC,EAAS,SACT,KACF,CAEA,KAAKzO,EAAM,SAAS,UAAW,CAI7B,KAAM,CAAE,GAAAE,EAAI,GAAAC,CAAA,EAAO,KAAK,MAAM,SAAS,SACjCwH,EAAK,KAAK,MAAM,EAAIzH,EACpB0H,EAAK,KAAK,MAAM,EAAIzH,EACpBuO,EAAO,KAAK,KAAK/G,EAAKA,EAAKC,EAAKA,CAAE,GAAK,EACvCtF,EAASiI,EAAS,IAAQmE,EAChC/X,EAASuJ,EAAKyH,EAAKrF,EACnBnL,EAASgJ,EAAKyH,EAAKtF,EAAQkM,EAAS,GACpCC,EAAS9G,GAAM,EAAI,QAAU,MAC7B,KACF,CAEA,KAAK3H,EAAM,SAAS,OAElB,GAAI,KAAK,SAAW,MAAQ,KAAK,SAAW,KAAM,CAChDrJ,EAAS,KAAK,QACdQ,EAAS,KAAK,QACdsX,EAAS,QACT,KACF,CAIF,QACA,KAAKzO,EAAM,SAAS,OAAQ,CAE1B,MAAMwH,EAAK,KAAK,MAAM,GAAK,EAAIgH,EAAS,CAACA,EACzCC,EAAW,KAAK,MAAM,GAAK,EAAI,QAAU,MACzC9X,EAAW,KAAK,MAAM,EAAI6Q,EAC1BrQ,EAAW,KAAK,MAAM,EAAIqX,EAAS,GACnC,KACF,CAAA,CAGF,KAAK,YAAY,aAAa,IAAe7X,EAAE,UAAU,EACzD,KAAK,YAAY,aAAa,IAAeQ,EAAE,UAAU,GAErD,KAAK,UAAY,KAAK,WACxB,KAAK,YAAY,aAAa,YAAa,aAAa,KAAK,QAAQ,KAAK,KAAK,QAAQ,GAAG,EAE5F,KAAK,YAAY,aAAa,YAAeoX,EAAS,UAAU,EAChE,KAAK,YAAY,aAAa,cAAeD,EAAK,QAAU,uBAAuB,EACnF,KAAK,YAAY,aAAa,cAAe,KAAK,EAClD,KAAK,YAAY,aAAa,cAAeG,CAAM,EACnD,KAAK,YAAY,aAAa,OAAeH,EAAK,SAASnc,EAAA,KAAK,MAAM,QAAX,YAAAA,EAAkB,aAAc,SAAS,CACtG,CAGA,MAAa,CACX,KAAK,SAAW,GAChB,KAAK,YAAY,aAAa,UAAW,OAAO,EAChD,KAAK,OAAA,CACP,CAEA,MAAa,CACP,KAAK,SACT,KAAK,SAAW,GAChB,KAAK,YAAY,aAAa,UAAW,MAAM,EACjD,CAEA,QAAe,CACb,KAAK,SAAW,KAAK,KAAA,EAAS,KAAK,KAAA,CACrC,CAEA,IAAI,SAAmB,CAAE,OAAO,KAAK,QAAU,CAE/C,QAAe,CACb,KAAK,YAAY,OAAA,CACnB,CACF,EAxLqBvB,EAAA6c,GAAA,WAAd,IAAMkB,GAANlB,GCeA,MAAMmB,GAAN,MAAMA,WAAuB,WAAY,CAEhD,EAFgDhe,EAAAge,GAAA,kBAC9CA,GAAO,QAAU,WADZ,IAAMC,GAAND,GAgBA,MAAME,GAAN,MAAMA,WAAuB,WAAY,CAEhD,EAFgDle,EAAAke,GAAA,kBAC9CA,GAAO,QAAU,WADZ,IAAMC,GAAND,GAeA,MAAME,GAAN,MAAMA,WAAwB,WAAY,CAEjD,EAFiDpe,EAAAoe,GAAA,mBAC/CA,GAAO,QAAU,YADZ,IAAMC,GAAND,GAiCA,MAAME,GAAN,MAAMA,WAAuB,WAAY,CAEhD,EAFgDte,EAAAse,GAAA,kBAC9CA,GAAO,QAAU,WADZ,IAAMC,GAAND,GAwBA,MAAME,GAAN,MAAMA,WAA8B,WAAY,CAEvD,EAFuDxe,EAAAwe,GAAA,yBACrDA,GAAO,QAAU,kBADZ,IAAMC,GAAND,GAkBA,MAAME,GAAN,MAAMA,WAAsB,WAAY,CAE/C,EAF+C1e,EAAA0e,GAAA,iBAC7CA,GAAO,QAAU,UADZ,IAAMC,GAAND,GAIP,eAAe,OAAOT,GAAe,QAASA,EAAc,EAC5D,eAAe,OAAOE,GAAe,QAASA,EAAc,EAC5D,eAAe,OAAOE,GAAgB,QAASA,EAAe,EAC9D,eAAe,OAAOE,GAAe,QAASA,EAAc,EAC5D,eAAe,OAAOE,GAAsB,QAASA,EAAqB,EAC1E,eAAe,OAAOE,GAAc,QAASA,EAAa,ECrI1D,MAAMC,GAAgB,CACpB,UAAW,UAAW,UAAW,UACjC,UAAW,UAAW,UAAW,SACnC,EAYA,SAASC,GAAcC,EAAiBC,EAA0C,CAEhF,UAAW/d,KAAK+d,EACd,GAAID,IAAY,GAAG9d,CAAC,IAAIA,CAAC,GAAI,MAAO,CAACA,EAAGA,CAAC,EAG3C,UAAWge,KAAMD,EACf,GAAID,EAAQ,WAAWE,EAAK,GAAG,EAAG,CAChC,MAAMC,EAAKH,EAAQ,MAAME,EAAG,OAAS,CAAC,EACtC,GAAID,EAAM,SAASE,CAAE,EAAG,MAAO,CAACD,EAAIC,CAAE,CACxC,CAEF,OAAO,IACT,CAbSjf,EAAA6e,GAAA,iBAyBT,SAASK,GACPC,EAAcC,EAAcrc,EAAWsc,EACL,CAElC,MAAMC,EAAK,KAAK,IAAI,EAAGvc,EAAI,CAAC,EACtBwc,EAAMD,GAAM,IAAM,KACZA,GAAO,GAAK,EACZA,GAAO,GAAK,MACZA,GAAO,GAAK,MACZA,GAAO,GAAK,MACZA,GAAQ,EAAI,MACA,MAClBE,EAAM,KAAK,KAAK,KAAK,IAAI,EAAGL,CAAI,EAAIpc,CAAC,EAAIsc,EACzCI,EAAM,KAAK,KAAK,KAAK,IAAI,EAAGL,CAAI,EAAIrc,CAAC,EAAIsc,EAC/C,MAAO,CAAE,MAAOE,EAAMC,EAAK,MAAOD,EAAME,CAAA,CAC1C,CAfSzf,EAAAkf,GAAA,iBAoBT,MAAMQ,GAAgC,GAEtC,SAASC,GAAkBC,EAA2B9J,EAAe+J,EAAqB,CACxF,GAAI,CAACD,EAAQ,OACb,MAAME,EAAO,KAAK,IAAI,KAAK,IAAIhK,CAAK,EAAG,KAAK,IAAI+J,CAAK,CAAC,EAChDC,EAAO,IACZF,EAAe,KAAO,CAAE,GAAKA,EAAe,MAAQ,GAAK,UAAWE,EAAOJ,EAAA,EAC9E,CALS1f,EAAA2f,GAAA,qBAOT,SAASI,GACPhe,EAAmBie,EAAcC,EAAcC,EAAS,GACiB,CAEzE,MAAM/T,EAAMnM,EAACmB,GAAgB,CAC3B,MAAMT,EAAIqB,EAAI,MAAM,QAAQZ,CAAG,EACzBsC,EAAM/C,GAAK,EAAIqB,EAAIrB,CAAC,EAAI,KAC9B,GAAI+C,GAAO,MAAQA,IAAQ,GAAI,OAC/B,MAAM9C,EAAI,OAAO8C,CAAG,EACpB,OAAO,OAAO,SAAS9C,CAAC,EAAIA,EAAI,MAClC,EANY,OAONwf,EAAQhU,EAAI,GAAG6T,CAAI,IAAIE,CAAM,KAAK,GAAM/T,EAAI,GAAG6T,CAAI,IAAIE,CAAM,KAAK,EAClEE,EAAQjU,EAAI,GAAG6T,CAAI,IAAIE,CAAM,MAAM,GAAK/T,EAAI,GAAG6T,CAAI,IAAIE,CAAM,MAAM,EACnEG,EAAQlU,EAAI,GAAG8T,CAAI,IAAIC,CAAM,KAAK,GAAM/T,EAAI,GAAG8T,CAAI,IAAIC,CAAM,KAAK,EAClEI,EAAQnU,EAAI,GAAG8T,CAAI,IAAIC,CAAM,MAAM,GAAK/T,EAAI,GAAG8T,CAAI,IAAIC,CAAM,MAAM,EACzE,OAAIC,GAAQ,MAAQC,GAAS,MAAQC,GAAQ,MAAQC,GAAS,KAAa,KACpE,CAAE,MAAOH,EAAM,OAAQC,EAAO,MAAOC,EAAM,OAAQC,CAAA,CAC5D,CAjBStgB,EAAA+f,GAAA,sBAyCT,SAASQ,GAAe9G,EAA4B,SAClD,MAAM3T,EAAI9F,EAACqG,GAAcoT,EAAG,aAAapT,CAAC,EAAhC,KACJlE,IAAOZ,EAAAuE,EAAE,QAAQ,IAAV,YAAAvE,EAAa,MAAM,KAAK,IAAIP,GAAKA,EAAE,QAAQ,OAAO,WAAY,CAAA,EACrEwf,IAAOxc,EAAA8B,EAAE,WAAW,IAAb,YAAA9B,EAAgB,MAAM,KAAK,IAAI,QAAQ,OAAO,OAAO,YAAa,CAAA,EAC/E,MAAO,CACL,MAAO8B,EAAE,OAAO,EAAG,KAAMA,EAAE,MAAM,EAAG,QAASA,EAAE,SAAS,EAAG,KAAMA,EAAE,MAAM,EACzE,QAASA,EAAE,SAAS,EACpB,OAAQ3D,EAAK,OAAS,CAACA,EAAK,CAAC,EAAGA,EAAK,CAAC,GAAK,IAAI,EAAI,KACnD,UAAWqe,EAAI,OAAS,CAACA,EAAI,CAAC,EAAGA,EAAI,OAAS,EAAIA,EAAI,CAAC,EAAI,GAAQ,EAAI,KACvE,KAAM1a,EAAE,MAAM,CAAA,CAElB,CAXS9F,EAAAugB,GAAA,kBAcT,SAASE,GAAgBpb,EAAqB,CAC5C,KAAM,CAAE,EAAAvD,EAAG,EAAA+C,EAAG,EAAAC,GAAMG,GAAM,WAAWI,CAAG,EAClCqb,EAAK,KAAK,IAAI5e,EAAG+C,EAAGC,CAAC,EAAG6b,EAAK,KAAK,IAAI7e,EAAG+C,EAAGC,CAAC,EAC7CwU,EAAItZ,EAACgB,IAAe0f,EAAKC,EAAK3f,GAAG,SAAS,EAAE,EAAE,SAAS,EAAG,GAAG,EAAzD,KACV,MAAO,IAAIsY,EAAExX,CAAC,CAAC,GAAGwX,EAAEzU,CAAC,CAAC,GAAGyU,EAAExU,CAAC,CAAC,EAC/B,CALS9E,EAAAygB,GAAA,mBAOT,SAASG,GAAgB9I,EAAiC,CACxD,MAAMhS,EAAIgS,GAAA,YAAAA,EAAM,OAAO,cACvB,OAAOhS,IAAM,QAAUA,IAAM,WAAaA,EAAI,OAChD,CAHS9F,EAAA4gB,GAAA,mBAaT,SAASC,GAAe/I,EAAqBgJ,EAA6B,CACxE,OAAQhJ,GAAA,YAAAA,EAAM,cAAY,CACxB,IAAK,KAAS,MAAO,GACrB,IAAK,MAAS,MAAO,GACrB,IAAK,QAAS,MAAO,GACrB,IAAK,OAAS,MAAO,GACrB,QAAc,OAAOgJ,CAAA,CAEzB,CARS9gB,EAAA6gB,GAAA,kBAUF,MAAME,GAAN,MAAMA,WAAuBhP,EAAqC,CAmGvE,aAAc,CACZ,MAAA,EA9DF,KAAA,WAAqB,EAGrB,KAAA,aAAwB,IAAI4F,GAS5B,KAAQ,UAAiB,GACzB,KAAQ,eAAiB,GACzB,KAAQ,eAA0C,KAIlD,KAAQ,aAA4C,IACpD,KAAQ,kBAAiD,IACzD,KAAQ,aAA4C,IAIpD,KAAQ,aAAmC,KAG3C,KAAQ,gBAAyC,IACjD,KAAQ,gBAAyC,IACjD,KAAQ,iBAAyC,IAKjD,KAAQ,UAAa,GACrB,KAAQ,WAA4B,KACpC,KAAQ,WAA4B,KACpC,KAAQ,kBAAoD,IAE5D,KAAQ,aAA8B,KACtC,KAAQ,WAAoC,KAG5C,KAAQ,aAA8B,KACtC,KAAQ,WAAqD,KAE7D,KAAQ,eAAiB,GACzB,KAAQ,WAA4B,KACpC,KAAQ,SAAkC,KAC1C,KAAQ,WAAoC,KAC5C,KAAA,WACE,CAAE,KAAM,KAAM,OAAQ,KAAM,MAAO,IAAA,EAg4CrC,KAAQ,WAAa,EACrB,KAAQ,UAA2B,KA4InC,KAAQ,WAAyD,CAAE,MAAO,IAAI,IAAO,MAAO,IAAI,GAAI,EACpG,KAAQ,gBAAsC,KAmW9C,KAAQ,WAAoC,KAp2D1C,KAAK,MAAQ,KACb,KAAK,OAAS,KAEd,KAAK,SAAW,IAAI/F,GAAMjC,EAAmB,EAC7C,KAAK,SAAW,KAAK,SAAS,MAAQ,gBACtC,KAAK,YAAc,KAAK,OAAA,EAExB,QAAQ,IAAI,kCAAmC,KAAK,WAAW,EAK/D,SAAS,iBAAiB,gBAAkBa,GAAa,kDAOvD,MAAMnJ,IAAS9F,GAAAiP,EAAE,eAAF,YAAAjP,GAAA,KAAAiP,GAAmB,KAAMA,EAAE,OAC1C,GAAI,KAAK,SAAWnJ,IAAW,KAAK,QAAS,OAE7C,MAAM2Z,EAASxQ,EAAkB,OACjC,GAAI,CAACwQ,EAAO,OAIZ,KAAK,WAAa,KAAK,aAAa,SAAS,EACxC,SAAS,KAAK,aAAa,SAAS,GAAK,GAAI,EAAE,GAAK,IACrD,EACJ,MAAMC,EAAa,KAAK,WAAa,GAAK,KAAK,UAAa,KAAK,gBAAkB,KAEnF,KAAK,UAAY,GAEjB,MAAMC,EAAOF,EAAM,WAGbG,EAAaH,EAAM,YACnBI,EAAaJ,EAAM,YACnBK,EAAeL,EAAM,UAGrBM,EAAS,KAAK,iBAAA,EAKpB,KAAK,UAAaA,EAAO,SACzB,KAAK,WAAaA,EAAO,aAAe,KAAO,KAAQA,EAAO,YAAc,QAAOJ,GAAA,YAAAA,EAAO,KAAM,GAAG,EAInG,KAAK,aAAeI,EAAO,aAAe,KAAO,KAC7C,WAAWA,EAAO,YAAY,QAAQ,CAAC,CAAC,KAC5C,KAAK,WAAaA,EAAO,aAAe,KAAO,KAAQA,EAAO,YAAc,QAAOJ,GAAA,YAAAA,EAAO,KAAM,GAAG,EAInG,MAAMK,EAAwC,CAAA,EAExCC,GAAqBxd,GAAAgd,EAAc,UAAd,MAAAhd,GAAuB,OAAUgd,EAAc,QAAUpC,GACpF,GAAIyC,KAAgBnd,GAAA8c,EAAM,SAAN,MAAA9c,GAAc,OAAO,CACvC,MAAMud,EAAWT,EAAM,OAAO,IAAIK,CAAY,EAC1CI,GAC6B,CAAC,GAAG,IAAI,IAAI,CAAC,GAAGA,CAAQ,EAAE,IAAI,MAAM,CAAC,CAAC,EACxD,QAAQ,CAAC5c,EAAGnE,IAAM,CAC7B6gB,EAAc1c,CAAC,EAAI2c,EAAQ9gB,EAAI8gB,EAAQ,MAAM,CAC/C,CAAC,CAEL,EAIIrd,GAAA6c,EAAM,SAAN,MAAA7c,GAAc,MAAQ6c,EAAM,OAAO,KAAA,EAAO,OAAS,GACrDA,EAAM,OAAO,KAAA,EAAO,QAASjf,GAAsB,CACjD,MAAM8C,EAAI9C,EAAI,SAAW,OAAOA,EAAI,CAAC,CAAC,EAChC2f,EAAK3f,EAAI,MAAM,QAAQ,OAAO,EAC9Bf,EAAK0gB,GAAM,EAAI3f,EAAI2f,CAAE,EAAI,KAC3B1gB,GAAK,OAAOA,CAAC,IAAM,KAAMugB,EAAc1c,CAAC,EAAI,OAAO7D,CAAC,EAC9CugB,EAAc1c,CAAC,IACvB0c,EAAc1c,CAAC,EAAI2c,EAAQ,OAAO,KAAKD,CAAa,EAAE,OAASC,EAAQ,MAAM,EAEjF,CAAC,EAWH,MAAMG,EAAkB,OAAO,KAAKJ,CAAa,EAC3CK,EAAiCN,EAAO,kBAAoBA,EAAO,iBAAiB,KAAA,EACtF,IAAI,IACFA,EAAO,iBAAiB,MAAM,GAAG,EAC9B,IAAI1b,GAAKA,EAAE,KAAA,CAAM,EACjB,OAAOf,GAAK0c,EAAc1c,CAAC,CAAC,CAAA,EAEjC,IAAI,IAAI8c,CAAe,EAQrBE,EAAqBP,EAAO,YAE5BQ,EAAY9hB,EAACkC,GAAiC,CAClD,IAAIuD,EAAM,EACV,OAAAvD,EAAK,QAAQH,GAAO,CAClB,MAAMggB,EAAOhgB,EAAI,MAAM,QAAQmf,EAAK,CAAC,CAAC,EAChCc,EAAOd,EAAK,OAAS,EAAInf,EAAI,MAAM,QAAQmf,EAAK,CAAC,CAAC,EAAI,GACxDa,GAAQ,IAAGtc,EAAM,KAAK,IAAIA,EAAK,KAAK,IAAI,OAAO1D,EAAIggB,CAAI,CAAC,CAAC,CAAC,GAC1DC,GAAQ,IAAGvc,EAAM,KAAK,IAAIA,EAAK,KAAK,IAAI,OAAO1D,EAAIigB,CAAI,CAAC,CAAC,CAAC,EAChE,CAAC,EACMvc,CACT,EATkB,aAWZwc,GAAiBC,GAAAlB,EAAM,QAAN,MAAAkB,GAAa,KAAQJ,EAAUd,EAAM,MAAM,KAAA,CAAM,EAAK,EACvEmB,GAAiBC,GAAApB,EAAM,SAAN,MAAAoB,GAAc,KAAON,EAAUd,EAAM,OAAO,KAAA,CAAM,EAAI,EACvEqB,GAAiBC,GAAAtB,EAAM,eAAN,MAAAsB,GAAoB,KAAOR,EAAUd,EAAM,aAAa,KAAA,CAAM,EAAI,EACnFuB,EAAuBJ,EAAiB,EAAIA,EAAiBE,EAI7DhD,EAAaiC,EAAO,aAAe,KAAOA,EAAO,WAClDO,GAAsBU,EAAuB,GAAKN,EAAgB,EACnEA,EAAgBM,EAChB,EAKJ,KAAK,aACHjB,EAAO,QAAU,UAAYW,EAAgB,IAC3CX,EAAO,QAAU,SAAWiB,EAAuBlD,EAAa,IAChE,OAAOiC,EAAO,OAAU,SAAWA,EAAO,MAC1C,KACJ,KAAK,WAAaA,EAAO,QAAU,WAAaA,EAAO,QAAU,SAAWA,EAAO,MAC/E,OAAOA,EAAO,OAAU,SAAW,SAAW,KAClD,KAAK,eAAiBA,EAAO,cAC7B,KAAK,WAAaA,EAAO,UACzB,KAAK,WAAaA,EAAO,UAGzB,MAAMkB,EAAclB,EAAO,WACrBmB,GAAcnB,EAAO,WACrBoB,GAAcpB,EAAO,YAGrBqB,GAAW,KAAK,aAMhBC,GAAa5iB,EAAA,CAAC+B,EAAmB6B,EAAeif,EAAmBnR,EAAQ,IAAa,CAC5F,MAAMoR,EAAQ/gB,EAAI,MAAM,QAAQ6B,CAAK,EAC/Bme,EAAQhgB,EAAI,MAAM,QAAQmf,EAAK,CAAC,CAAC,EACjCc,EAAQd,EAAK,OAAS,EAAInf,EAAI,MAAM,QAAQmf,EAAK,CAAC,CAAC,EAAI,GACvDpM,EAAK,IAAIhO,EAAM,CACnB,GAAIgc,GAAS,EAAI,OAAO/gB,EAAI+gB,CAAK,CAAC,EAAK/gB,EAAI,SAAW,MAAM,KAAK,SAAS,SAAS,EAAE,EAAE,MAAM,CAAC,CAAC,GAC/F,WAAY,CACVggB,GAAQ,EAAI,OAAOhgB,EAAIggB,CAAI,CAAC,EAAIrQ,EAAQ,EACxCsQ,GAAQ,EAAI,CAAC,OAAOjgB,EAAIigB,CAAI,CAAC,EAAItQ,EAAQ,CAAA,EAE3C,KAAM,CAAA,CAAC,CACR,EACD,OAAImR,IAAU/N,EAAG,MAAQ,IAAI7P,GAAM4d,CAAQ,GACpC/N,CACT,EAdmB,cAmBbiO,EAGD,CAAA,EAICC,GAAiB1B,EAAO,WAKxB2B,GAAiBjC,EAAc,UACrC,GAAIM,EAAO,UAAU,SAAU2B,IAAA,MAAAA,GAAe,MAAM,CAClD,MAAMC,EAAU,KAAK,aAAa,OAAO,eAAgB,QAAQ,EAC3D/hB,EAAMnB,EAAA,CAAC8B,EAAiBuE,IAAc,CAAE,MAAM3F,EAAIoB,EAAE,MAAM,QAAQuE,CAAC,EAAG,OAAO3F,GAAK,EAAIoB,EAAEpB,CAAC,EAAI,IAAM,EAA7F,OACZ4gB,EAAO,UAAU,QAAQ,CAAC7Q,EAAI0S,IAAO,CACnCF,GAAc,KAAA,EAAO,QAASlhB,GAAsB,CAClD,GAAI,OAAOZ,EAAIY,EAAK,KAAK,CAAC,IAAM0O,EAAG,IAAK,OACxC,MAAMlO,EAAQ,OAAOpB,EAAIY,EAAK,IAAI,CAAC,EAC7BiZ,EAAQ7Z,EAAIY,EAAK,OAAO,GAAK,MAAQ,OAAOZ,EAAIY,EAAK,OAAO,CAAC,IAAM,KAAO,OAAOZ,EAAIY,EAAK,OAAO,CAAC,EAAI,KACtGgD,EAAQ5D,EAAIY,EAAK,OAAO,GAAK,OAAOZ,EAAIY,EAAK,OAAO,CAAC,IAAM,KAAO,OAAOZ,EAAIY,EAAK,OAAO,CAAC,EAClFiZ,GAASuG,EAAcvG,CAAK,EAAIuG,EAAcvG,CAAK,EACnDwG,EAAQ2B,EAAK3B,EAAQ,MAAM,EACnC1M,EAAK8N,GAAW7gB,EAAK,KAAMgD,EAAOsa,CAAU,EAClDvK,EAAG,GAAK,GAAGrE,EAAG,GAAG,KAAKlO,CAAE,GACxBuS,EAAG,KAAOrE,EAAG,MAAQ6Q,EAAO,WAAa,IACzC,MAAM8B,EAAQjiB,EAAIY,EAAK,OAAO,EAC1BqhB,GAAS,OAAOA,CAAK,IAAM,OAAMtO,EAAG,MAAQ,OAAOsO,CAAK,GAC5D,MAAMC,EAAQliB,EAAIY,EAAK,OAAO,EAC7B+S,EAAW,KAAO,CACjB,OAAQ,UAAW,KAAM,QACzB,KAAMuO,GAAS,MAAQ,OAAOA,CAAK,IAAM,KAAO,OAAOA,CAAK,EAAI9gB,EAChE,MAAOyY,GAAS,OAAW,KAAMzY,EAAI,IAAKkO,EAAG,IAC7C,UAAWA,EAAG,SAAA,EAEhB,KAAK,SAAS,OAAO,IAAIqE,EAAG,GAAIA,CAAE,EAClCoO,GAAA,MAAAA,EAAS,SAAS,QAAQ,IAAIpO,EAAG,GAAIA,EACvC,CAAC,CACH,CAAC,CACH,CAEA,IAAIwO,GAAAtC,EAAM,SAAN,MAAAsC,GAAc,KAAM,CACtB,MAAMC,EAAc,KAAK,aAAa,OAAO,eAAgB,QAAQ,EACrE,GAAIA,EAAa,CACfvC,EAAM,OAAO,KAAA,EAAO,QAASjf,GAAsB,CAEjD,MAAMyhB,EAAcnC,EAAetf,EAAI,MAAM,QAAQsf,CAAY,EAAI,GAC/DrG,EAAQwI,GAAe,EAAI,OAAOzhB,EAAIyhB,CAAW,CAAC,EAAI,KACtDX,EAAW7H,EAASuG,EAAcvG,CAAK,GAAK,UAAa,UAG/D,GAAIgI,GAAgB,CAClB,MAAMlO,EAAK8N,GAAW7gB,EAAKof,EAAW0B,EAAUxD,CAAU,EAG1DvK,EAAG,KAAOwM,EAAO,WAAa,IAG7BxM,EAAW,KAAO,CACjB,GAAKA,EAAW,MAAQ,CAAA,EACxB,OAAQ,UAAW,KAAM,QAAS,KAAMA,EAAG,GAC3C,MAAOkG,GAAS,OAAW,KAAMlG,EAAG,GACpC,UAAWwM,EAAO,cAAA,EAEpB,KAAK,SAAS,OAAO,IAAIxM,EAAG,GAAIA,CAAE,EAClCyO,EAAY,SAAS,QAAQ,IAAIzO,EAAG,GAAIA,CAAE,CAC5C,CAGA,GAAIkG,EAAO,CACT,MAAM+G,EAAOhgB,EAAI,MAAM,QAAQmf,EAAK,CAAC,CAAC,EAChCc,EAAOd,EAAK,OAAS,EAAInf,EAAI,MAAM,QAAQmf,EAAK,CAAC,CAAC,EAAI,GACvD6B,EAAU/H,CAAK,MAAaA,CAAK,EAAI,CAAE,EAAG,EAAG,EAAG,EAAG,GAAI,EAAG,GAAI,EAAG,GAAI,EAAG,EAAG,EAAG,MAAO6H,CAAA,GAC1F,MAAMY,EAAK1B,GAAQ,EAAI,OAAOhgB,EAAIggB,CAAI,CAAC,EAAI,EACrC2B,EAAK1B,GAAQ,EAAI,OAAOjgB,EAAIigB,CAAI,CAAC,EAAI,EAC3Ce,EAAU/H,CAAK,EAAE,GAAMyI,EACvBV,EAAU/H,CAAK,EAAE,GAAM0I,EACvBX,EAAU/H,CAAK,EAAE,IAAMyI,EAAKA,EAC5BV,EAAU/H,CAAK,EAAE,IAAM0I,EAAKA,EAC5BX,EAAU/H,CAAK,EAAE,IAAMyI,EAAKC,EAC5BX,EAAU/H,CAAK,EAAE,GAAM,CACzB,CACF,CAAC,EAgBD,MAAM2I,EAAiB,CAAC,GAAEC,GAAA5C,EAAM,SAAN,MAAA4C,GAAc,MAAQ5C,EAAM,OAAO,OAAO,OAAS,GAIvE6C,EAAmCvC,EAAO,WAAaqC,EACzD3C,EAAM,OAAO,KAAA,EAAO,OAAQlf,GAAoB,CAC9C,MAAM+C,EAAI/C,EAAE,SAAW,OAAOA,EAAE,CAAC,CAAC,EAClC,OAAO8f,EAAiB,OAAS,GAAKA,EAAiB,IAAI/c,CAAC,CAC9D,CAAC,EACD,CAAA,EAEJ,GAAIyc,EAAO,UAAW,CACtB,MAAMwC,EAAiBP,EAAY,YAC7BxJ,GAAMkI,EAAgB,EAAIA,EAAgB,GAAK,KAErD,GAAI0B,EAAgB,CAGlB,MAAMI,EAAc,IAAI,IAAIF,EAAgB,IAAK/hB,GAAoBA,EAAE,SAAW,OAAOA,EAAE,CAAC,CAAC,CAAC,CAAC,EAC/F,KAAK,SAAS,QAAQ,CAAC2X,EAAI5U,IAAM,CAAOkf,EAAY,IAAIlf,CAAC,IAAK4U,EAAG,OAAA,EAAU,KAAK,SAAS,OAAO5U,CAAC,EAAK,CAAC,EACvG,KAAK,cAAc,QAAQ,CAAC4U,EAAI5U,IAAM,CAAOkf,EAAY,IAAIlf,CAAC,IAAK4U,EAAG,OAAA,EAAU,KAAK,cAAc,OAAO5U,CAAC,EAAK,CAAC,EACjH,KAAK,SAAS,QAAQ,CAAC4U,EAAIpT,IAAM,CAAO0d,EAAY,IAAI1d,EAAE,MAAM,CAAC,CAAC,IAAKoT,EAAG,OAAA,EAAU,KAAK,SAAS,OAAOpT,CAAC,EAAK,CAAC,EAEhHwd,EAAgB,QAAS9hB,GAAsB,WAC7C,MAAMiZ,EAAQjZ,EAAI,SAAW,OAAOA,EAAI,CAAC,CAAC,EACpCgD,EAAQwc,EAAcvG,CAAK,GAAK,UAChC+G,EAAOhgB,EAAI,MAAM,QAAQmf,EAAK,CAAC,CAAC,EAChCc,EAAOd,EAAK,OAAS,EAAInf,EAAI,MAAM,QAAQmf,EAAK,CAAC,CAAC,EAAI,GACtDR,EAAKqB,GAAQ,EAAI,OAAOhgB,EAAIggB,CAAI,CAAC,EAAI1C,EAAa,EAClD2E,GAAKhC,GAAQ,EAAI,CAAC,OAAOjgB,EAAIigB,CAAI,CAAC,EAAI3C,EAAa,EAGnDO,GAAS,IAAI9Y,EAAM,CACvB,GAAI,QAAQkU,CAAK,GACjB,WAAY,CAAC0F,EAAIsD,EAAE,EACnB,KAAM,CAAE,KAAM,OAAQ,KAAMhJ,EAAO,MAAAA,EAAO,UAAWsG,EAAO,aAAA,CAAc,CAC3E,EACD1B,GAAO,MAAQ,IAAI3a,GAAMF,CAAK,EAC9B6a,GAAO,KAAQ,EACf,MAAMqE,GAAWliB,EAAI,MAAM,QAAQ,OAAO,EACpCmiB,EAAWD,IAAY,EAAIliB,EAAIkiB,EAAQ,EAAI,KACjDrE,GAAO,MAAQsE,GAAY,OAAOA,CAAQ,IAAM,KAAO,OAAOA,CAAQ,EAAI,OAC1E,KAAK,SAAS,OAAO,IAAItE,GAAO,GAAIA,EAAM,EAC1C2D,EAAY,SAAS,QAAQ,IAAI3D,GAAO,GAAIA,EAAM,EAKlD,MAAMuE,GAAOnkB,EAACI,GAAsB,CAClC,MAAMM,EAAIqB,EAAI,MAAM,QAAQ3B,CAAI,EAC1BO,EAAID,GAAK,EAAIqB,EAAIrB,CAAC,EAAI,KAC5B,OAAOC,GAAK,MAAQ,OAAOA,CAAC,IAAM,MAAQ,OAAOA,CAAC,IAAM,GAAK,KAAOA,CACtE,EAJa,QAKPyjB,GAAQD,GAAK,WAAW,EACxBE,GACJD,KAAU,OAASA,KAAU,cAAgBA,KAAU,OAASA,GAAQ9C,EAAO,UAC3EgD,GAASH,GAAK,SAAS,EAIvBI,GAHUD,IAAU,KAAOhD,EAAO,YAAegD,KAAW,IAAQ,OAAOA,EAAM,IAAM,QAIzFvE,GAAmBhe,EAAKmf,EAAK,CAAC,EAAaA,EAAK,CAAC,EAAa,GAAG,EACjE,KACJ,GAAI,CAACqD,GACHhjB,EAAA,KAAK,cAAc,IAAIyZ,CAAK,IAA5B,MAAAzZ,EAA+B,SAAU,KAAK,cAAc,OAAOyZ,CAAK,MACnE,CACL,IAAIwJ,EAAM,KAAK,cAAc,IAAIxJ,CAAK,EACjCwJ,IACHA,EAAM,SAAS,gBAAgB,6BAA8B,MAAM,EACnEA,EAAI,aAAa,qBAAsBxJ,CAAK,EAC5C,KAAK,cAAc,IAAIA,EAAOwJ,CAAG,GAEnCA,EAAI,aAAa,KAAMD,EAAG,MAAQlF,GAAY,UAAU,EACxDmF,EAAI,aAAa,KAAM,CAACD,EAAG,OAASlF,GAAY,UAAU,EAC1DmF,EAAI,aAAa,UAAYD,EAAG,OAASA,EAAG,OAASlF,GAAY,UAAU,EAC3EmF,EAAI,aAAa,WAAYD,EAAG,OAASA,EAAG,OAASlF,GAAY,UAAU,EAC3EmF,EAAI,aAAa,OAAQ,MAAM,EAC/BA,EAAI,aAAa,SAAUzf,CAAK,EAChCyf,EAAI,aAAa,eAAgBzK,EAAG,SAAA,CAAU,EAC9CyK,EAAI,aAAa,iBAAkB,KAAK,EACxCA,EAAI,aAAa,mBAAoB,GAAGzK,EAAK,CAAC,IAAIA,EAAK,CAAC,EAAE,EACtD+J,GAAkB,CAACU,EAAI,iBAA8B,aAAaA,EAAKV,EAAe,UAAU,CACtG,CAKA,MAAMW,GAASJ,KAAO,OAClBtE,GAAmBhe,EAAKmf,EAAK,CAAC,EAAaA,EAAK,CAAC,CAAW,EAC5D,KACEwD,EAAW,KAAK1J,CAAK,GAI3B,IAHI,CAACyJ,IAAUJ,KAAO,iBACpBrgB,EAAA,KAAK,SAAS,IAAI0gB,CAAQ,IAA1B,MAAA1gB,EAA6B,SAAU,KAAK,SAAS,OAAO0gB,CAAQ,GAElED,IAAUJ,KAAO,aAAc,EACjCngB,EAAA,KAAK,SAAS,IAAI8W,CAAK,IAAvB,MAAA9W,EAA0B,SAAU,KAAK,SAAS,OAAO8W,CAAK,EAG9D,MAAM2J,EAAKF,GAAO,MAAQpF,EAAY5V,EAAKgb,GAAO,OAASpF,EACrDuF,EAAK,CAACH,GAAO,OAASpF,EAAY3V,EAAK,CAAC+a,GAAO,MAAQpF,EAC7DM,GAAkBC,IAASnW,EAAKkb,GAAM,GAAIjb,EAAKkb,GAAM,CAAC,EACtD,IAAIC,EAAM,KAAK,SAAS,IAAIH,CAAQ,EAC/BG,IACHA,EAAM,SAAS,gBAAgB,6BAA8B,MAAM,EACnEA,EAAI,aAAa,gBAAiB7J,CAAK,EACvC6J,EAAI,aAAa,eAAgB,YAAY,EAC7C,KAAK,SAAS,IAAIH,EAAUG,CAAG,GAEjCA,EAAI,aAAa,IAAK,IAAIF,CAAE,IAAIX,EAAE,KAAKva,CAAE,IAAIua,EAAE,KAAKtD,CAAE,IAAIkE,CAAE,KAAKlE,CAAE,IAAIhX,CAAE,EAAE,EAC3Emb,EAAI,aAAa,OAAQ,MAAM,EAC/BA,EAAI,aAAa,SAAU9f,CAAK,EAChC8f,EAAI,aAAa,gBAAiB9K,EAAK,MAAM,UAAU,EACvD8K,EAAI,aAAa,iBAAkB,KAAK,EACpCf,GAAkB,CAACe,EAAI,iBAA8B,aAAaA,EAAKf,EAAe,UAAU,CACtG,SAAYW,GAGL,CACL,MAAMK,EAAcL,GAAO,MAASpF,EAC9B0F,EAAc,CAACN,GAAO,OAASpF,EAC/B2F,GAAeP,GAAO,OAASA,GAAO,OAASpF,EAC/C4F,GAAeR,GAAO,OAASA,GAAO,OAASpF,EACrDM,GAAkBC,GAAQoF,EAAa,EAAGC,EAAc,CAAC,EAEzD,IAAIxL,EAAK,KAAK,SAAS,IAAIuB,CAAK,EAC3BvB,IACHA,EAAK,SAAS,gBAAgB,6BAA8B,MAAM,EAClEA,EAAG,aAAa,gBAAiBuB,CAAK,EACtC,KAAK,SAAS,IAAIA,EAAOvB,CAAE,GAE7BA,EAAG,aAAa,IAAkBqL,EAAO,SAAA,CAAU,EACnDrL,EAAG,aAAa,IAAkBsL,EAAO,SAAA,CAAU,EACnDtL,EAAG,aAAa,QAAkBuL,EAAW,SAAA,CAAU,EACvDvL,EAAG,aAAa,SAAkBwL,EAAY,SAAA,CAAU,EACxDxL,EAAG,aAAa,OAAkB,MAAM,EACxCA,EAAG,aAAa,SAAkB1U,CAAK,EACvC0U,EAAG,aAAa,eAAkBM,EAAG,SAAA,CAAU,EAC/CN,EAAG,aAAa,iBAAkB,KAAK,EACvCA,EAAG,aAAa,mBAAoB,GAAGM,EAAK,CAAC,IAAIA,EAAK,CAAC,EAAE,EACrD+J,GAAkB,CAACrK,EAAG,eACxBqK,EAAe,aAAarK,EAAIqK,EAAe,UAAU,CAE7D,KA5BoB,CAClB,MAAMoB,EAAQ,KAAK,SAAS,IAAIlK,CAAK,EACjCkK,IAASA,EAAM,OAAA,EAAU,KAAK,SAAS,OAAOlK,CAAK,EACzD,CA0BF,CAAC,CAEH,MAGE,OAAO,QAAQ+H,CAAS,EAAE,QAAQ,CAAC,CAAC/H,EAAO,CAAE,EAAAjV,EAAG,EAAAQ,EAAG,EAAAxD,EAAG,MAAAgC,CAAA,CAAO,IAAM,CACjE,MAAM6a,EAAS,IAAI9Y,EAAM,CACvB,GAAI,QAAQkU,CAAK,GACjB,WAAY,CAACjV,EAAIhD,EAAIsc,EAAY,EAAE9Y,EAAIxD,GAAKsc,CAAU,EACtD,KAAM,CAAE,KAAM,OAAQ,KAAMrE,EAAO,MAAAA,EAAO,UAAWsG,EAAO,aAAA,CAAc,CAC3E,EACD1B,EAAO,MAAQ,IAAI3a,GAAMF,CAAK,EAC9B6a,EAAO,KAAQ,EACfA,EAAO,MAAQ,OACf,KAAK,SAAS,OAAO,IAAIA,EAAO,GAAIA,CAAM,EAC1C2D,EAAY,SAAS,QAAQ,IAAI3D,EAAO,GAAIA,CAAM,CACpD,CAAC,EAGc0B,EAAO,SAEpB,KAAK,SAAS,QAAQ,CAAC7H,EAAI5U,IAAM,CAC1Bke,EAAUle,CAAC,IAAK4U,EAAG,OAAA,EAAU,KAAK,SAAS,OAAO5U,CAAC,EAC1D,CAAC,GAEGsgB,GAAAnE,EAAM,aAAN,MAAAmE,GAAkB,KAEpBnE,EAAM,WAAW,KAAA,EAAO,QAASjf,GAAsB,CACrD,MAAMqjB,EAAWrjB,EAAI,MAAM,QAAQsf,GAAgB,OAAO,EACpDrG,EAAQoK,GAAY,EAAI,OAAOrjB,EAAIqjB,CAAQ,CAAC,EAAKrjB,EAAI,SAAW,KACtE,GAAI,CAACiZ,EAAO,OACZ,MAAMjW,EAAQwc,EAAcvG,CAAK,GAAK,UAChCyJ,EAAS1E,GAAmBhe,EAAKmf,EAAK,CAAC,EAAaA,EAAK,CAAC,CAAW,EAC3E,GAAI,CAACuD,EAAQ,OACb,MAAMK,EAAcL,EAAO,MAASpF,EAC9B0F,GAAc,CAACN,EAAO,OAASpF,EAC/B2F,IAAeP,EAAO,OAASA,EAAO,OAASpF,EAC/C4F,IAAeR,EAAO,OAASA,EAAO,OAASpF,EACrDM,GAAkB,KAAK,SAAS,OAAO,IAAI,QAAQ3E,CAAK,EAAE,EACxCgK,GAAa,EAAGC,GAAc,CAAA,EAChD,IAAIxL,EAAK,KAAK,SAAS,IAAIuB,CAAK,EAC3BvB,IACHA,EAAK,SAAS,gBAAgB,6BAA8B,MAAM,EAClEA,EAAG,aAAa,gBAAiBuB,CAAK,EACtC,KAAK,SAAS,IAAIA,EAAOvB,CAAE,GAE7BA,EAAG,aAAa,IAAkBqL,EAAO,SAAA,CAAU,EACnDrL,EAAG,aAAa,IAAkBsL,GAAO,SAAA,CAAU,EACnDtL,EAAG,aAAa,QAAkBuL,GAAW,SAAA,CAAU,EACvDvL,EAAG,aAAa,SAAkBwL,GAAY,SAAA,CAAU,EACxDxL,EAAG,aAAa,OAAkB,MAAM,EACxCA,EAAG,aAAa,SAAkB1U,CAAK,EACvC0U,EAAG,aAAa,eAAkBM,EAAG,SAAA,CAAU,EAC/CN,EAAG,aAAa,iBAAkB,KAAK,EACvCA,EAAG,aAAa,mBAAoB,GAAGM,EAAK,CAAC,IAAIA,EAAK,CAAC,EAAE,EACrD+J,GAAkB,CAACrK,EAAG,eACxBqK,EAAe,aAAarK,EAAIqK,EAAe,UAAU,CAE7D,CAAC,EAGD,OAAO,QAAQf,CAAS,EAAE,QAAQ,CAAC,CAAC/H,EAAO,CAAE,EAAAjV,EAAG,EAAAQ,EAAG,GAAAoD,EAAI,GAAAC,EAAI,EAAA7G,EAAG,MAAAgC,EAAA,CAAO,IAAM,CACzE,GAAIhC,EAAI,EAAG,OACX,MAAMsiB,GAAKtf,EAAIhD,EAAGuiB,GAAK/e,EAAIxD,EACrBwiB,EAAU5b,EAAK5G,EAAIsiB,GAAKA,GACxBG,GAAU5b,EAAK7G,EAAIuiB,GAAKA,GACxB,CAAE,MAAAxP,GAAO,MAAA+J,IAAUX,GAAcqG,EAASC,GAASziB,EAAGsc,CAAU,EAChE/P,GAAK+V,GAAKhG,EAAY9P,GAAK,CAAE+V,GAAMjG,EACzCM,GAAkB,KAAK,SAAS,OAAO,IAAI,QAAQ3E,CAAK,EAAE,EACxClF,GAAO+J,EAAA,EACzB,IAAIpG,EAAK,KAAK,SAAS,IAAIuB,CAAK,EAC3BvB,IACHA,EAAK,SAAS,gBAAgB,6BAA8B,MAAM,EAClEA,EAAG,aAAa,gBAAiBuB,CAAK,EACtC,KAAK,SAAS,IAAIA,EAAOvB,CAAE,GAE7BA,EAAG,aAAa,KAAmBnK,GAAKwG,IAAO,UAAU,EACzD2D,EAAG,aAAa,KAAmBlK,GAAKsQ,IAAO,UAAU,EACzDpG,EAAG,aAAa,SAAmB3D,GAAQ,GAAG,UAAU,EACxD2D,EAAG,aAAa,UAAmBoG,GAAQ,GAAG,UAAU,EACxDpG,EAAG,aAAa,OAAkB,MAAM,EACxCA,EAAG,aAAa,SAAkB1U,EAAK,EACvC0U,EAAG,aAAa,eAAkBM,EAAG,SAAA,CAAU,EAC/CN,EAAG,aAAa,iBAAkB,KAAK,EACvCA,EAAG,aAAa,mBAAoB,GAAGM,EAAK,CAAC,IAAIA,EAAK,CAAC,EAAE,EACrD+J,GAAkB,CAACrK,EAAG,eACxBqK,EAAe,aAAarK,EAAIqK,EAAe,UAAU,CAE7D,CAAC,IAMc2B,GAAAzE,EAAM,UAAN,MAAAyE,GAAe,OAChC,KAAK,cAAc,QAAQ,CAAChM,EAAI5U,IAAM,CAC/B0c,EAAc1c,CAAC,IAAK4U,EAAG,OAAA,EAAU,KAAK,cAAc,OAAO5U,CAAC,EACnE,CAAC,EACDmc,EAAM,QAAQ,KAAA,EAAO,QAASjf,GAAsB,CAClD,MAAMqjB,EAAWrjB,EAAI,MAAM,QAAQsf,GAAgB,OAAO,EACpDrG,EAAQoK,GAAY,EAAI,OAAOrjB,EAAIqjB,CAAQ,CAAC,EAAKrjB,EAAI,SAAW,KACtE,GAAI,CAACiZ,EAAO,OACZ,MAAMjW,EAAQwc,EAAcvG,CAAK,GAAK,UAChCyJ,EAAS1E,GAAmBhe,EAAKmf,EAAK,CAAC,EAAaA,EAAK,CAAC,CAAW,EAC3E,GAAI,CAACuD,EAAQ,OACb,MAAMK,EAAcL,EAAO,MAASpF,EAC9B0F,GAAc,CAACN,EAAO,OAASpF,EAC/B2F,IAAeP,EAAO,OAASA,EAAO,OAASpF,EAC/C4F,IAAeR,EAAO,OAASA,EAAO,OAASpF,EACrD,IAAI5F,EAAK,KAAK,cAAc,IAAIuB,CAAK,EAChCvB,IACHA,EAAK,SAAS,gBAAgB,6BAA8B,MAAM,EAClEA,EAAG,aAAa,qBAAsBuB,CAAK,EAC3C,KAAK,cAAc,IAAIA,EAAOvB,CAAE,GAElCA,EAAG,aAAa,IAAkBqL,EAAO,SAAA,CAAU,EACnDrL,EAAG,aAAa,IAAkBsL,GAAO,SAAA,CAAU,EACnDtL,EAAG,aAAa,QAAkBuL,GAAW,SAAA,CAAU,EACvDvL,EAAG,aAAa,SAAkBwL,GAAY,SAAA,CAAU,EACxDxL,EAAG,aAAa,OAAkB,MAAM,EACxCA,EAAG,aAAa,SAAkB1U,CAAK,EACvC0U,EAAG,aAAa,eAAkBM,EAAG,SAAA,CAAU,EAC/CN,EAAG,aAAa,iBAAkB,KAAK,EACvCA,EAAG,aAAa,mBAAoB,GAAGM,EAAK,CAAC,IAAIA,EAAK,CAAC,EAAE,EACrD+J,GAAkB,CAACrK,EAAG,eACxBqK,EAAe,aAAarK,EAAIqK,EAAe,UAAU,CAE7D,CAAC,EAGL,CAGInB,KAEF,KAAK,aAAa,QAAQ,CAAC+C,EAAKnjB,IAAO,CAChCghB,EAAY,SAAS,QAAQ,IAAIhhB,CAAE,IAAKmjB,EAAI,OAAA,EAAU,KAAK,aAAa,OAAOnjB,CAAE,EACxF,CAAC,EACD,KAAK,YAAY,QAAQ,CAACmjB,EAAKnjB,IAAO,CAC/BghB,EAAY,SAAS,QAAQ,IAAI,QAAQhhB,CAAE,EAAE,IAAKmjB,EAAI,OAAA,EAAU,KAAK,YAAY,OAAOnjB,CAAE,EACjG,CAAC,EAGGmgB,KAAgB,GAClB1B,EAAM,OAAO,KAAA,EAAO,QAASjf,GAAsB,CACjD,MAAM4jB,EAAO5jB,EAAI,MAAM,QAAQof,CAAS,EAClCld,EAAS0hB,GAAQ,EAAI,OAAO5jB,EAAI4jB,CAAI,CAAC,EAAI,KAC/C,GAAI,CAAC1hB,EAAQ,OACb,MAAM6Q,EAAKyO,EAAY,SAAS,QAAQ,IAAItf,CAAM,EAClD,GAAI,CAAC6Q,EAAI,OAKT,MAAM8Q,EAAc3hB,EACpB,IAAIyhB,EAAM,KAAK,aAAa,IAAIzhB,CAAM,EACjCyhB,EAIHhD,KAAgBtT,EAAM,cAAc,GAAKsW,EAAI,KAAA,EAASA,EAAI,KAAA,GAH1DA,EAAM,IAAI3H,GAAQ6H,EAAa9Q,EAAI6N,GAAU,KAAMD,EAAW,EAC9D,KAAK,aAAa,IAAIze,EAAQyhB,CAAG,EAIrC,CAAC,EAICjD,KAAe,IACgBkB,EAC7BE,EAAgB,IAAK/hB,GAAoBA,EAAE,SAAW,OAAOA,EAAE,CAAC,CAAC,CAAC,EAClE,OAAO,KAAKihB,CAAS,GAEV,QAAS/H,GAAkB,CACxC,MAAM6K,EAAS,QAAQ7K,CAAK,GACtBlG,EAAKyO,EAAY,SAAS,QAAQ,IAAIsC,CAAM,EAClD,GAAI,CAAC/Q,EAAI,OACT,IAAI4Q,EAAM,KAAK,YAAY,IAAI1K,CAAK,EAC/B0K,EAIHjD,KAAerT,EAAM,cAAc,GAAKsW,EAAI,KAAA,EAASA,EAAI,KAAA,GAHzDA,EAAM,IAAI3H,GAAQ/C,EAAOlG,EAAI6N,GAAU,KAAMF,EAAU,EACvD,KAAK,YAAY,IAAIzH,EAAO0K,CAAG,EAInC,CAAC,GAILnC,EAAY,SAAS,UAAU,YAAY,gBAAiBA,EAAY,QAAQ,CAClF,CACF,CAGA,MAAMuC,GAAoB,KAAK,aAAa,OAAO,eAAgB,cAAc,EAEjF,GAD4BxE,EAAO,kBACRwE,GAAmB,CAC5CA,GAAkB,SAAS,QAAQ,MAAA,EACnC,KAAK,SAAS,aAAa,MAAA,EAE3B,MAAMC,GAAaC,GAAAhF,EAAM,eAAN,MAAAgF,GAAoB,KAAOhF,EAAM,aAAeA,EAAM,OACzE,GAAI+E,GAAA,MAAAA,EAAY,KAAM,CACpB,MAAME,EAA0E,CAAA,EAC1EC,EAAgB5E,EAAO,gBAAkBA,EAAO,gBAAgB,MAAM,GAAG,EAAE,IAAI1b,GAAKA,EAAE,KAAA,CAAM,EAAI,KAEtGmgB,EAAW,KAAA,EAAO,QAAShkB,GAAsB,CAC/C,MAAMokB,EAAOpkB,EAAI,MAAM,QAAQof,CAAS,GAAK,EAAIpf,EAAI,MAAM,QAAQof,CAAS,EAAKpf,EAAI,MAAM,QAAQ,MAAM,GAAK,EAAIA,EAAI,MAAM,QAAQ,MAAM,EAAKA,EAAI,MAAM,QAAQ,UAAU,GAAK,EAAIA,EAAI,MAAM,QAAQ,UAAU,EAAI,GAC9MqkB,EAAOD,GAAQ,EAAI,OAAOpkB,EAAIokB,CAAI,CAAC,EAAKpkB,EAAI,SAAW,SAE7D,GAAImkB,GAAiB,CAACA,EAAc,SAASE,CAAI,EAAG,OAEpD,MAAMrE,EAAOhgB,EAAI,MAAM,QAAQmf,EAAK,CAAC,CAAC,EAChCc,EAAOd,EAAK,OAAS,EAAInf,EAAI,MAAM,QAAQmf,EAAK,CAAC,CAAC,EAAI,GACtDmF,EAAOtkB,EAAI,MAAM,QAAQ,MAAM,GAAK,EAAIA,EAAI,MAAM,QAAQ,MAAM,EAAKA,EAAI,MAAM,QAAQ,gBAAgB,GAAK,EAAIA,EAAI,MAAM,QAAQ,gBAAgB,EAAKA,EAAI,MAAM,QAAQ,OAAO,GAAK,EAAIA,EAAI,MAAM,QAAQ,OAAO,EAAI,GAEtNukB,EAAOD,GAAQ,EAAI,OAAOtkB,EAAIskB,CAAI,CAAC,EAAKJ,EAASG,CAAI,EAAIH,EAASG,CAAI,EAAE,OAAS,EAAI,EAKvFrE,GAAQ,GAAKC,GAAQ,IAClBiE,EAASG,CAAI,IAAGH,EAASG,CAAI,EAAI,CAAA,GACtCH,EAASG,CAAI,EAAE,KAAK,CAClB,EAAG,OAAOrkB,EAAIggB,CAAI,CAAC,EAAI1C,EACvB,EAAG,CAAC,OAAOtd,EAAIigB,CAAI,CAAC,EAAI3C,EACxB,KAAAiH,CAAA,CACD,EAEL,CAAC,EAEgB,OAAO,KAAKL,CAAQ,EAC5B,QAAQ,CAACM,EAASJ,IAAS,CAClC,MAAMK,EAASP,EAASM,CAAO,EAC/B,GAAIC,EAAO,SAAW,EAAG,OAEzB,MAAM3D,EAAWrB,EAAQ2E,EAAO3E,EAAQ,MAAM,EAExCiF,EAAU,IAAIzR,GAAW,CAC7B,GAAI,QAAQuR,CAAO,GACnB,OAAQA,EACR,MAAO,IAAIthB,GAAM4d,CAAQ,EACzB,UAAWvB,EAAO,oBAClB,YAAaA,EAAO,sBACpB,iBAAkBA,EAAO,2BACzB,aAAcA,EAAO,uBACrB,OAAQA,EAAO,iBACf,UAAWA,EAAO,oBAClB,gBAAiBA,EAAO,0BACxB,YAAaA,EAAO,oBAAsB,IAC1C,WAAYA,EAAO,qBACnB,SAAUA,EAAO,mBACjB,OAAQkF,EAAO,IAAIljB,IAAM,CAAE,EAAGA,EAAE,EAAG,EAAGA,EAAE,EAAG,KAAMA,EAAE,MAAO,CAAA,CAC3D,EAED,KAAK,SAAS,aAAa,IAAIijB,EAASE,CAAO,EAC/CX,GAAkB,SAAS,QAAQ,IAAIW,EAAQ,GAAIA,CAAO,CAC5D,CAAC,CACH,CACAX,GAAkB,SAAS,UAAU,YAAY,gBAAiBA,GAAkB,QAAQ,CAC9F,CAKA,MAAMY,GAAgB,KAAK,aAAa,OAAO,eAAgB,SAAS,EAClEC,GAAgBD,IAAA,YAAAA,GAAc,aAAa,OAAO,eAAgB,SAClEE,GAAgBF,IAAA,YAAAA,GAAc,aAAa,OAAO,eAAgB,SAGlEG,GAAgBH,IAAA,YAAAA,GAAc,aAAa,OAAO,eAAgB,aAElEI,GAAexF,EAAO,UAC5B,IAAIyF,GAAA/F,EAAM,QAAN,MAAA+F,GAAa,MAAQH,GAAW,CAiBlC,GAZA5F,EAAM,MAAM,KAAA,EAAO,QAASjf,GAAsB,CAChD,MAAM+S,EAAK8N,GAAW7gB,EAAKqf,EAAW,SAAS,EAC/CtM,EAAG,KAAO,EAGV,MAAMkS,EAAKjlB,EAAI,MAAM,QAAQ,OAAO,EAC9BklB,EAAKD,GAAM,EAAIjlB,EAAIilB,CAAE,EAAI,KAC9BlS,EAAW,KAAO,CAAE,GAAKA,EAAW,MAAQ,CAAA,EAAK,KAAM,OACnC,KAAMmS,GAAM,MAAQ,OAAOA,CAAE,IAAM,MAAQ,OAAOA,CAAE,IAAM,GAAK,OAAOA,CAAE,EAAInS,EAAG,EAAA,EACpG8R,GAAU,SAAS,QAAQ,IAAI9R,EAAG,GAAIA,CAAE,CAC1C,CAAC,EAEGgS,IAAgBH,MAAaO,GAAAlG,EAAM,QAAN,MAAAkG,GAAa,MAAM,CAElD,MAAMC,EAAuC,CAAA,EACzC9F,KAAgB+F,GAAApG,EAAM,SAAN,MAAAoG,GAAc,OAChCpG,EAAM,OAAO,KAAA,EAAO,QAASjf,GAAsB,CACjD,MAAM4jB,EAAO5jB,EAAI,MAAM,QAAQof,CAAS,EAClCkG,EAAOtlB,EAAI,MAAM,QAAQsf,CAAa,EACxCsE,GAAQ,GAAK0B,GAAQ,MAAgB,OAAOtlB,EAAI4jB,CAAI,CAAC,CAAC,EAAI,OAAO5jB,EAAIslB,CAAI,CAAC,EAChF,CAAC,EAIH,MAAMC,EAAsBtG,EAAM,MAAM,OAAO,IAAKlf,GAAoB,CACtE,MAAMT,EAAMS,EAAE,MAAM,QAAQsf,CAAS,EACrC,OAAO/f,GAAO,EAAI,OAAOS,EAAET,CAAG,CAAC,EAAI,EACrC,CAAC,EAAE,OAAO,OAAO,EAEXkmB,EAA4D,CAAA,GACjEvG,EAAM,MAAM,OAAS,CAAA,GAAI,QAAS7f,GAAgB,CACjD,MAAMqmB,EAAO3I,GAAc1d,EAAKmmB,CAAS,EACrCE,GAAMD,EAAU,KAAK,CAAE,IAAApmB,EAAK,KAAAqmB,EAAM,CACxC,CAAC,EAMD,MAAMC,EAAeznB,EAACiE,GAAgC,CACpD,MAAM4J,EAAsB,CAAA,EAC5B,OAAAmT,EAAM,MAAM,KAAA,EAAO,QAASjf,GAAsB,CAChD,MAAM4jB,EAAO5jB,EAAI,MAAM,QAAQof,CAAS,EACpCwE,EAAO,GAAK,OAAO5jB,EAAI4jB,CAAI,CAAC,IAAM1hB,GACtCsjB,EAAU,QAAQ,CAAC,CAAE,IAAApmB,KAAU,CAC7B,MAAMumB,EAAS3lB,EAAI,MAAM,QAAQZ,CAAG,EAChCumB,GAAU,IAAG7Z,EAAO1M,CAAG,EAAI,OAAOY,EAAI2lB,CAAM,CAAC,GAAK,EACxD,CAAC,CACH,CAAC,EACM7Z,CACT,EAXqB,gBAcf8Z,EAAgB3nB,EAAC4nB,GAAmC,CACxD,MAAMC,EAAoB,CAAA,EAC1B,IAAIC,EAAQ,EAaZ,GAZA9G,EAAM,MAAM,KAAA,EAAO,QAASjf,GAAsB,CAChD,MAAM4jB,EAAQ5jB,EAAI,MAAM,QAAQof,CAAS,EACnCld,EAAS0hB,GAAQ,EAAI,OAAO5jB,EAAI4jB,CAAI,CAAC,EAAI,KACzCoC,EAAU1G,EAAetf,EAAI,MAAM,QAAQsf,CAAY,EAAI,IACjD0G,GAAW,EAAI,OAAOhmB,EAAIgmB,CAAO,CAAC,EAAK9jB,EAASkjB,EAAaljB,CAAM,EAAI,QACzE2jB,IACdE,IACAP,EAAU,QAAQ,CAAC,CAAE,IAAApmB,MAAU,CAC7B,MAAMumB,GAAS3lB,EAAI,MAAM,QAAQZ,EAAG,EACpC,GAAIumB,IAAU,EAAG,CAAE,MAAM/mB,EAAI,OAAOoB,EAAI2lB,EAAM,CAAC,EAAQ,MAAM/mB,CAAC,IAAGknB,EAAK1mB,EAAG,GAAK0mB,EAAK1mB,EAAG,GAAK,GAAKR,EAAG,CACrG,CAAC,EACH,CAAC,EACGmnB,IAAU,EAAG,MAAO,CAAA,EACxB,MAAMja,EAAsB,CAAA,EAC5B,OAAA0Z,EAAU,QAAQ,CAAC,CAAE,IAAApmB,KAAU,CAAE0M,EAAO1M,CAAG,GAAK0mB,EAAK1mB,CAAG,GAAK,GAAK2mB,CAAO,CAAC,EACnEja,CACT,EAnBsB,iBAuBhBma,EAAUhoB,EAACuC,GAAuE,CACtF,GAAIgf,EAAchf,CAAE,EAClB,MAAO,CAAE,QAASolB,EAAcplB,CAAE,EAAG,MAAOgf,EAAchf,CAAE,EAAG,MAAOA,CAAA,EAGxE,MAAM0lB,EAAcd,EAAa5kB,CAAE,GAAK,KAClCwC,EAAQkjB,EAAe1G,EAAc0G,CAAW,GAAK,UAAa,UACxE,MAAO,CAAE,QAASR,EAAallB,CAAE,EAAG,MAAAwC,EAAO,MAAOxC,CAAA,CACpD,EARgB,WAwBV2lB,EAAwB,CAAA,EAExBC,EAAanoB,EAACI,GAAqC,OACvD,MAAMgoB,EAASpH,EAAc,SACvBjf,GAAMR,EAAA6mB,GAAA,YAAAA,EAAO,OAAP,YAAA7mB,EAAA,KAAA6mB,GAAgB,KAAMtmB,GAAoBA,EAAE,UAAY1B,GACpE,GAAI,CAAC2B,EAAK,OAAO,KACjB,MAAMkE,EAAiB,CAAA,EACvB,OAAAshB,EAAU,QAAQ,CAAC,CAAE,IAAApmB,KAAU,CAC7B,MAAMT,EAAIqB,EAAI,MAAM,QAAQZ,CAAG,EAC/B,GAAIT,GAAK,EAAG,CAAE,MAAMC,EAAI,OAAOoB,EAAIrB,CAAC,CAAC,EAAO,OAAO,SAASC,CAAC,IAAGsF,EAAE9E,CAAG,EAAIR,EAAG,CAC9E,CAAC,EACMsF,CACT,EAVmB,cAWboiB,EAAcroB,EAAA,CAACiG,EAAWua,IAAyC,CACvE,GAAI,CAACA,EAAK,OAAOva,EACjB,MAAMH,EAAI,KAAK,IAAIG,CAAC,EACpB,OAAIH,EAAI0a,EAAI,CAAC,EAAU,EAChB1a,EAAI0a,EAAI,CAAC,EAAI,KAAK,KAAKva,CAAC,EAAIua,EAAI,CAAC,EAAIva,CAC9C,EALoB,eAOpBqb,EAAO,WAAW,QAAQ,CAAC3L,EAAGqR,IAAO,CACnC,MAAMsB,EAAOtoB,EAAA,CAACmB,EAAaqmB,GAAwBvhB,GAAWlB,GAChDiK,KAA2D,CACvE/I,GAAIoiB,EAAYpiB,GAAG0P,EAAE,SAAS,EAC1B,OAAK,IAAI1P,EAAC,EAAI,OAClBiiB,EAAU,KAAK,CAAE,IAAK,GAAGlB,CAAE,IAAI7lB,CAAG,GAAI,KAAAqmB,GAAM,OAAQ,KAAK,IAAIvhB,EAAC,EAAG,MAAAlB,GAAO,MAAOiiB,EAAI,GAAGhY,GAAM,CAC9F,EALa,QAMPuZ,EAAavoB,EAAA,CAACwoB,EAAaC,KAC1B9S,EAAE,OACA,CAACA,EAAE,OAAO,CAAC,EAAGA,EAAE,OAAO,CAAC,GAAK8K,GAAgB9K,EAAE,OAAO,CAAC,CAAC,CAAC,EAD1C,CAAC6S,EAAKC,EAAG,EADd,cAKnB,GAAI9S,EAAE,QAAS,CAEb,MAAM1P,EAAIkiB,EAAWxS,EAAE,OAAO,EAC9B,GAAI,CAAC1P,EAAG,OACR,KAAM,CAACuiB,GAAKC,EAAG,EAAIF,EAAW/G,EAAQ,CAAC,EAAGA,EAAQ,CAAC,CAAC,EAC9CxS,GAAO,CAAE,KAAM2G,EAAE,MAAQA,EAAE,OAAA,EACjC4R,EAAU,QAAQ,CAAC,CAAE,IAAApmB,GAAK,KAAAqmB,MAAW,CACnC,MAAM7mB,GAAIsF,EAAE9E,EAAG,GAAK,EACpBmnB,EAAKnnB,GAAKqmB,GAAM7mB,GAAGA,IAAK,EAAI6nB,GAAMC,GAAKzZ,EAAI,CAC7C,CAAC,EACD,MACF,CAGA,MAAM0Z,EAAY/S,EAAE,MAAQA,EAAE,OAAS,KACvC,GAAI,CAAC+S,EAAW,OAChB,MAAMC,EAAYX,EAAQU,CAAS,EAC7BE,EAAcjT,EAAE,SAAWA,EAAE,MAAQ,KACrCkT,EAAYD,EAAcZ,EAAQY,CAAW,EAAI,KACjD5Z,EAAO,CAAE,KAAM2G,EAAE,MAAQ+S,EAAW,MAAO/S,EAAE,OAAS,OAAW,KAAMA,EAAE,MAAQ,MAAA,EACjF,CAAC6S,GAAKC,EAAG,EAAIF,EAAWI,EAAQ,OAAOE,GAAA,YAAAA,EAAW,QAASF,EAAQ,KAAK,EAE1EE,GAAalT,EAAE,QAEjB4R,EAAU,QAAQ,CAAC,CAAE,IAAApmB,EAAK,KAAAqmB,MAAW,CACnC,MAAM7hB,IAAKgjB,EAAQ,QAAQxnB,CAAG,GAAK,IAAM0nB,EAAU,QAAQ1nB,CAAG,GAAK,GACnEmnB,EAAKnnB,EAAKqmB,GAAM7hB,GAAGA,GAAI,EAAI6iB,GAAMC,GAAKzZ,CAAI,CAC5C,CAAC,EACQ6Z,GAAalT,EAAE,KAExB4R,EAAU,QAAQ,CAAC,CAAE,IAAApmB,EAAK,KAAAqmB,MAAW,CACnC,MAAMsB,GAAKH,EAAQ,QAAQxnB,CAAG,GAAK,EAAG4nB,GAAKF,EAAU,QAAQ1nB,CAAG,GAAK,EACjE2nB,GAAK,GAAGR,EAAKnnB,EAAM,KAAMqmB,GAAMsB,GAAIN,GAAKxZ,CAAI,EAC5C+Z,GAAK,GAAGT,EAAKnnB,EAAM,KAAMqmB,GAAMuB,GAAIN,GAAK,CAAE,GAAGzZ,EAAM,KAAM2G,EAAE,MAAQ,OAAW,MAAOA,EAAE,MAAQ,OAAW,CAChH,CAAC,EAED4R,EAAU,QAAQ,CAAC,CAAE,IAAApmB,EAAK,KAAAqmB,MAAW,CACnC,MAAMvhB,GAAI0iB,EAAQ,QAAQxnB,CAAG,GAAK,EAC9B8E,GAAI,GAAGqiB,EAAKnnB,EAAKqmB,GAAMvhB,GAAGuiB,GAAKxZ,CAAI,CACzC,CAAC,CAEL,CAAC,EAIDkZ,EAAU,KAAK,CAACpiB,EAAGhB,IAAMA,EAAE,OAASgB,EAAE,MAAM,EAM5C,MAAMkjB,EAAgB,CAAC,CAAEhI,EAAc,SAIjC5H,EAAgBJ,GAAesI,EAAO,SAAS,GAAKA,EAAO,aAAe,GAO1E2H,GAAUjpB,EAACkpB,GAAmC,CAClD,MAAMC,EAAKD,EAAG,IAAI,KAAK,GAAG,EAAE,OAAOvoB,GAAKA,EAAI,CAAC,EAC7C,OAAOwoB,EAAG,OAAS,CAAC,KAAK,IAAI,GAAGA,CAAE,EAAG,KAAK,IAAI,GAAGA,CAAE,CAAC,EAAI,CAAC,EAAG,CAAC,CAC/D,EAHgB,WAIVC,GAAappB,EAACqpB,GAAoC,CACtD,MAAMjjB,EAAiB,CAAA,EACvB,OAAAmhB,EAAU,QAAQ,CAAC,CAAE,IAAApmB,EAAK,KAAAqmB,KAAW,CACnC,GAAKA,EAAK,CAAC,IAAMA,EAAK,CAAC,IAAO6B,EAAM,OACpC,MAAMhpB,EAAS2gB,EAAM,MAAM,IAAI7f,CAAG,EAClC,GAAId,YAAmBM,KAAKN,IAAa,KAAK,OAAOM,CAAC,CAAC,CACzD,CAAC,EACMsoB,GAAQ7iB,CAAI,CACrB,EARmB,cASbkjB,GAAYtpB,EAACqpB,GACjBJ,GAAQf,EAAU,OAAO1X,GAAMA,EAAE,KAAK,CAAC,IAAMA,EAAE,KAAK,CAAC,IAAO6Y,CAAI,EAAE,IAAI7Y,GAAKA,EAAE,MAAM,CAAC,EADpE,aAEZ+Y,EAASjI,EAAO,eAChBkI,GAAcxpB,EAACqpB,GACnBE,IAAW,OAASD,GAAUD,CAAI,EAAID,GAAWC,CAAI,EADnC,eAEdI,GAAYD,GAAY,EAAK,EAAGE,GAAYF,GAAY,EAAI,EAC5DG,GAAW3pB,EAAA,CAACiG,EAAWojB,IAAkB,CAC7C,GAAIE,IAAW,WAAY,CAAE,MAAMzjB,EAAI,KAAK,IAAI,EAAG,KAAK,IAAIG,CAAC,CAAC,EAAG,MAAO,CAAE,WAAYH,EAAG,QAASA,CAAA,CAAK,CACvG,KAAM,CAACyS,EAAIC,CAAE,EAAI6Q,EAAOK,GAAYD,GACpC,MAAO,CAAE,WAAYnR,GAAQrS,EAAGsS,EAAIC,EAAIJ,EAAgB,EAAG,QAASE,GAAQrS,EAAGsS,EAAIC,EAAIH,EAAa,CAAA,CACtG,EAJiB,YAWXuR,GAAwC,CAAA,EAC9C1B,EAAU,QAAQ,CAAC,CAAE,KAAAV,EAAM,OAAAriB,KAAa,CAEtC,GADeqiB,EAAK,CAAC,IAAMA,EAAK,CAAC,GACnB,CAACwB,EAAY,OAC3B,MAAMa,EAAM7pB,EAACuC,GAAe,CAAEqnB,GAAcrnB,CAAE,GAAKqnB,GAAcrnB,CAAE,GAAK,GAAK,KAAK,IAAI4C,CAAM,CAAG,EAAnF,OACZ,GAAI6jB,EAAY,CAAEa,EAAIrC,EAAK,CAAC,CAAC,EAAG,MAAQ,CACxCqC,EAAIrC,EAAK,CAAC,CAAC,EAAGqC,EAAIrC,EAAK,CAAC,CAAC,CAC3B,CAAC,EAKDxG,EAAM,MAAM,KAAA,EAAO,QAASjf,GAAsB,CAChD,MAAM+nB,EAAU/nB,EAAI,MAAM,QAAQqf,CAAS,EACrC7e,EAAKunB,GAAW,EAAI,OAAO/nB,EAAI+nB,CAAO,CAAC,EAAI,GACjD,GAAI,CAACvnB,EAAI,OACT,MAAMuS,EAAK8R,GAAU,SAAS,QAAQ,IAAIrkB,CAAE,EAC5C,GAAI,CAACuS,EAAI,OACT,MAAM7O,EAAI2jB,GAAcrnB,CAAE,GAAK,EACzBwnB,EAAc,EAAE9jB,EAAI,GAC1B6O,EAAG,KAAOiV,EAAezI,EAAO,qBAAuB,EAAIvI,GACjDG,GAAiBjT,EAAGmT,CAAS,EACtCtE,EAAW,KAAO,CAAE,GAAKA,EAAW,MAAQ,CAAA,EACxB,OAAQiV,GAAezI,EAAO,oBAAA,CACrD,CAAC,EAQD,MAAM0I,EAA4C,CAAA,EAC5CC,GAAUjqB,EAAA,CAAC4N,EAAesc,EAAyBpkB,EAAWhB,IAClE,GAAG8I,CAAK,IAAIsc,GAAO,EAAE,IAAIpkB,CAAC,IAAIhB,CAAC,GADjB,WAEZkkB,GACFd,EAAU,QAAQ,CAAC,CAAE,KAAAV,EAAM,OAAAriB,EAAQ,MAAAyI,EAAO,KAAAxN,KAAW,CACnD,MAAMoC,EAAMynB,GAAQrc,EAAOxN,EAAMonB,EAAK,CAAC,EAAGA,EAAK,CAAC,CAAC,EACjDwC,EAAkBxnB,CAAG,GAAKwnB,EAAkBxnB,CAAG,GAAK,GAAK2C,CAC3D,CAAC,EAGH+iB,EAAU,QAAQ,CAAC,CAAE,IAAA/mB,EAAK,KAAAqmB,EAAM,OAAAriB,EAAQ,MAAAJ,EAAO,MAAA6I,EAAO,KAAAxN,EAAM,MAAA4a,EAAO,KAAAoL,CAAA,IAAW,CAC5E,MAAM+D,EAAWvD,GAAU,SAAS,QAAQ,IAAIY,EAAK,CAAC,CAAC,EACjD4C,GAAWxD,GAAU,SAAS,QAAQ,IAAIY,EAAK,CAAC,CAAC,EACvD,GAAI,CAAC2C,GAAY,CAACC,GAAQ,OAE1B,MAAMC,GAAU7C,EAAK,CAAC,IAAMA,EAAK,CAAC,EAClC,GAAI6C,IAAU,CAACrB,EAAY,OAI3B,KAAM,CAAE,WAAA/O,EAAY,QAAAJ,EAAA,EAAY8P,GAASxkB,EAAQklB,EAAM,EACjDC,GAAS,IAAIxjB,EAAM,CAAE,GAAI,GAAG0gB,EAAK,CAAC,CAAC,OAAQ,WAAY,CAAC2C,EAAS,EAAGA,EAAS,CAAC,EAAG,KAAM,CAAA,EAAI,EAC3FI,GAAS,IAAIzjB,EAAM,CAAE,GAAI,GAAG0gB,EAAK,CAAC,CAAC,OAAQ,WAAY,CAAC4C,GAAO,EAAKA,GAAO,CAAC,EAAK,KAAM,CAAA,EAAI,EAOjG,IAAII,GACJ,GAAIH,GACFG,GAAW,IAAIjT,GAAS,GAAI+S,GAAeC,EAAW,EAIrDC,GAAiB,OAAS,UAClBxB,EAAY,CACrB,MAAMyB,GAAMT,EAAkBC,GAAQrc,EAAOxN,EAAMonB,EAAK,CAAC,EAAGA,EAAK,CAAC,CAAC,CAAC,GAAKriB,EACnEulB,GAAMV,EAAkBC,GAAQrc,EAAOxN,EAAMonB,EAAK,CAAC,EAAGA,EAAK,CAAC,CAAC,CAAC,GAAK,EACnEmD,GAAcF,GAAMC,GAC1BF,GAAW,IAAIrT,GACb,CAAE,OAAAhS,EAAQ,YAAAwlB,EAAA,EACVL,GACAC,EAAA,CAEJ,MACEC,GAAW,IAAIhjB,GAAK,GAAI8iB,GAAQC,EAAI,EAEtCC,GAAS,GAAQ,QAAQrpB,CAAG,GAC5BqpB,GAAS,MAAQ,IAAIvlB,GAAMF,CAAK,EAC/BylB,GAAiB,KAAO,CACvB,WAAc,GACd,OAAArlB,EAEA,UAAAiU,EACA,WAAAa,EACA,QAAAJ,GACA,WAAAmP,EACA,OAAAqB,GAEA,OAAc7C,EAAK,CAAC,EACpB,OAAcA,EAAK,CAAC,EACpB,MAAAxM,EACA,KAAAoL,EACA,MAAchmB,CAAA,GAIIiqB,GAAUxD,IAAiBF,GAAaA,IAChD,SAAS,QAAQ,IAAI6D,GAAS,GAAIA,EAAQ,CACxD,CAAC,EAED7D,GAAU,SAAS,UAAU,YAAY,gBAAiBA,GAAU,QAAQ,EACxEE,IAAeA,GAAc,SAAS,UAAU,YAAY,gBAAiBA,GAAc,QAAQ,CACzG,CAOA,MAAM+D,EAAetJ,EAAO,UACxBsF,GAAU,cACXA,GAAU,YAA2B,MAAM,QAAUgE,EAAe,GAAK,QAEvEA,IACH,KAAK,YAAY,QAAQlF,GAAOA,EAAI,QAAQ,EAC5C,KAAK,YAAY,MAAA,GAIf/C,IAAYH,IAAe,GAAKoI,IAElC,KAAK,YAAY,QAAQ,CAAClF,EAAKnjB,IAAO,CAC/BqkB,GAAU,SAAS,QAAQ,IAAIrkB,CAAE,IAAKmjB,EAAI,OAAA,EAAU,KAAK,YAAY,OAAOnjB,CAAE,EACrF,CAAC,EACDye,EAAM,MAAM,KAAA,EAAO,QAASjf,GAAsB,WAChD,MAAM+nB,EAAU/nB,EAAI,MAAM,QAAQqf,CAAS,EACrC7e,EAAKunB,GAAW,EAAI,OAAO/nB,EAAI+nB,CAAO,CAAC,EAAI,GACjD,GAAI,CAACvnB,EAAI,OACT,MAAMuS,EAAK8R,GAAU,SAAS,QAAQ,IAAIrkB,CAAE,EAC5C,GAAI,CAACuS,EAAI,OACT,IAAKvT,EAAAuT,EAAW,OAAX,MAAAvT,EAAiB,OAAQ,EAC5ByC,EAAA,KAAK,YAAY,IAAIzB,CAAE,IAAvB,MAAAyB,EAA0B,SAC1B,KAAK,YAAY,OAAOzB,CAAE,EAC1B,MACF,CACA,MAAMua,EAAO,SAAQ5Y,EAAA4Q,EAAW,OAAX,YAAA5Q,EAAiB,OAAQ3B,CAAE,EAChD,IAAImjB,EAAM,KAAK,YAAY,IAAInjB,CAAE,EAC7BmjB,GAAOA,EAAI,OAAS5I,IAAQ4I,EAAI,OAAA,EAAU,KAAK,YAAY,OAAOnjB,CAAE,EAAGmjB,EAAM,QAC5EA,EAIHlD,IAAepT,EAAM,cAAc,GAAKsW,EAAI,KAAA,EAASA,EAAI,KAAA,GAHzDA,EAAM,IAAI3H,GAAQjB,EAAMhI,EAAI6N,GAAU,KAAMH,CAAU,EACtD,KAAK,YAAY,IAAIjgB,EAAImjB,CAAG,EAIhC,CAAC,GAIHkB,GAAU,SAAS,UAAU,YAAY,gBAAiBA,GAAU,QAAQ,CAC9E,CAGA,MAAMiE,GAAkB,KAAK,aAAa,OAAO,eAAgB,aAAa,EACxEC,GAAkB,KAAK,aAAa,OAAO,eAAgB,YAAY,EACzED,SAAsB,SAAS,UAAU,YAAY,4BAA6BA,GAAgB,SAAS,OAAO,EAClHC,SAAsB,SAAS,UAAU,YAAY,2BAA6BA,GAAe,SAAS,OAAO,EAErH,KAAK,OAAA,EAGD7J,GAAW,KAAK,UAAUA,CAAS,CACzC,CAAC,CACH,CA/pCA,WAAW,oBAA+B,CAKxC,MAAO,CACL,QAAS,SAAU,MACnB,eAAgB,cAAe,SAC/B,SAAU,cAAe,cAAe,cAAA,CAE5C,CAiCA,IAAI,QAAS,CACX,OAAO,KAAK,OACd,CA4CA,eAAwB,SACtB,MAAMtH,EAAS,KAAK,SAAS,SAAS,OAAS,EACzCY,GAAOvW,GAAAzC,EAAA,KAAK,cAAL,YAAAA,EAAkB,wBAAlB,YAAAyC,EAAA,KAAAzC,GACPiZ,EAAQ,KAAa,YAAc,EACzC,OAAOD,GAAQA,EAAK,MAAQ,EAAK,EAAIZ,EAASY,EAAK,MAASC,EAAOb,EAAS,IAC9E,CAukCQ,mBAA0B,CAC5B,CAAC,KAAK,SAAW,CAAC,KAAK,WACvB,KAAK,iBACT,KAAK,eAAiB,GACtB,eAAe,IAAM,OACnB,KAAK,eAAiB,IACtBpY,EAAA,KAAK,UAAL,MAAAA,EAAc,cAAc,IAAI,YAAY,gBAAiB,CAC3D,OAAQ,KAAK,QAAQ,MACrB,QAAS,GACT,SAAU,EAAA,CACX,EACH,CAAC,EACH,CAMQ,kBAgDN,OACA,MAAMwpB,EAAW,KAAK,cAAc,UAAU,EACxCC,EAAW,KAAK,cAAc,UAAU,EAExCC,EAAe,CAAC,GAAG,KAAK,iBAAiB,WAAW,CAAC,EACrDC,EAAWD,EAAa,KAAKza,GAAK,CAACA,EAAE,aAAa,KAAK,CAAC,GAAK,KAC7D2a,EAAWF,EAAa,UAAYza,EAAE,aAAa,KAAK,CAAC,EAGzD4a,EAAW,CAAC,GAAG,KAAK,iBAAiB,UAAU,CAAC,EAChDC,EAAYrrB,EAAC8F,GAAA,OAAc,QAAAvE,EAAA6pB,EAAQ,KAAK5a,GAAKA,EAAE,aAAa1K,CAAC,CAAC,IAAnC,YAAAvE,EAAsC,aAAauE,KAAM,MAAxE,aACZwlB,EAAYF,EAAQ,QAAU5a,EAAE,aAAa,SAAS,CAAC,EACvD+a,EAAiB,KAAK,cAAc,iBAAiB,EACrDC,EAAW,KAAK,cAAc,SAAS,EACvCC,EAAkB,KAAK,aAAa,QAAQ,EAElD,MAAO,CAGL,WAAY5K,IACVkK,GAAA,YAAAA,EAAS,aAAa,WAAY,KAAK,aAAa,aAAa,GAAKU,EACtErc,EAAM,cAAc,EAAA,EAEtB,UAAW,CAAC,CAAC2b,EACb,OAAQ,IAAM,CACZ,MAAMpqB,EAAI,KAAK,aAAa,OAAO,EACnC,GAAIA,IAAM,WAAaA,IAAM,SAAU,OAAOA,EAC9C,MAAMoC,EAAI,OAAOpC,CAAC,EAClB,OAAOA,GAAK,MAAQ,OAAO,SAASoC,CAAC,GAAKA,EAAI,EAAIA,EAAI,IACxD,GAAA,EACA,UAAW,KAAK,aAAa,YAAY,GAAK,KAC9C,UAAW,CACT,MAAO,IAAM,CAAE,MAAMA,EAAI,OAAO,KAAK,aAAa,iBAAiB,CAAC,EACrD,OAAO,OAAO,SAASA,CAAC,GAAKA,EAAI,EAAIA,EAAI,IAAM,GAAA,EAC9D,OAAQ,KAAK,aAAa,mBAAmB,GAAK,KAClD,MAAQ,KAAK,aAAa,kBAAkB,GAAK,IAAA,EAEnD,WAAY,IAAM,CAChB,MAAMpC,EAAI,OAAO,KAAK,aAAa,YAAY,CAAC,EAChD,OAAO,OAAO,SAASA,CAAC,GAAKA,EAAI,GAAKA,GAAK,EAAIA,EAAIwX,EACrD,GAAA,EACA,uBAAsB5W,EAAAwpB,GAAA,YAAAA,EAAS,aAAa,iBAAtB,YAAAxpB,EAAsC,iBAAkB,OAC9E,YAAa,KAAK,aAAa,cAAc,IAAM,QACnD,YAAa,IAAM,CACjB,MAAMZ,EAAI,OAAO,KAAK,aAAa,aAAa,CAAC,EACjD,OAAO,KAAK,aAAa,aAAa,GAAK,OAAO,SAASA,CAAC,GAAKA,EAAI,EAAIA,EAAI,IAC/E,GAAA,EACA,cAAe,KAAK,aAAa,QAAQ,IAAM,UAG/C,UAAkB,CAAC,CAACqqB,EACpB,kBAAkBA,GAAA,YAAAA,EAAS,aAAa,YAAa,KACrD,OAAkB,CAAC,CAACA,GAAWA,EAAQ,aAAa,YAAY,EAEhE,WAAY,IAAM,CAChB,MAAMrqB,EAAIqqB,GAAA,YAAAA,EAAS,aAAa,aAChC,OAAIrqB,IAAM,OAASA,IAAM,cAAgBA,IAAM,OAAeA,EACvDqqB,GAAA,MAAAA,EAAS,aAAa,cAAgB,MAAQ,MACvD,GAAA,EACA,YAAkB,CAAC,CAACA,GAAWA,EAAQ,aAAa,SAAS,EAC7D,WAAYnK,IACVmK,GAAA,YAAAA,EAAS,aAAa,WAAY,KAAK,aAAa,aAAa,GAAKS,EACtErc,EAAM,cAAc,EAAA,EAGtB,cAAe,CAAC,CAAC4b,GAAWA,EAAQ,aAAa,YAAY,EAG7D,WAAY,CAAC,CAACE,EACd,UAAWC,EAAO,IAAI3a,IAAM,CAC1B,IAAKA,EAAE,aAAa,KAAK,EACzB,KAAMA,EAAE,aAAa,MAAM,EAAI,WAAWA,EAAE,aAAa,MAAM,CAAE,EAAI,KACrE,UAAWA,EAAE,aAAa,YAAY,CAAA,EACtC,EACF,YAAaqQ,IACXqK,GAAA,YAAAA,EAAU,aAAa,WAAY,KAAK,aAAa,cAAc,GAAKO,EACxErc,EAAM,cAAc,GAAA,EAEtB,UAAW8b,GAAA,MAAAA,EAAU,aAAa,QAAU,WAAWA,EAAS,aAAa,MAAM,CAAE,EAAI,KAEzF,eAAgB,CAAC,CAACA,GAAYA,EAAS,aAAa,YAAY,EAGhE,UAAaE,EAAQ,OAAS,EAC9B,WAAaA,EAAQ,IAAI7K,EAAc,EAEvC,eAAgBK,GAAgByK,EAAU,aAAa,CAAC,EACxD,YAAaC,GAAa,IAAM,CAC9B,MAAM3qB,EAAI,OAAO2qB,EAAU,aAAa,SAAS,CAAC,EAClD,OAAO,OAAO,SAAS3qB,CAAC,GAAKA,EAAI,EAAIA,EAAI,CAC3C,KAAO,KAGP,iBAAuB,CAAC,CAAC4qB,EACzB,iBAAuBA,GAAA,YAAAA,EAAgB,aAAa,WAAY,KAChE,kBAAwBA,GAAA,YAAAA,EAAgB,aAAa,YAAiC,OACtF,oBAAuBA,GAAA,MAAAA,EAAgB,aAAa,cAAgB,SAASA,EAAe,aAAa,YAAY,EAAI,EAAE,EAAI,EAC/H,2BAA4BA,GAAA,YAAAA,EAAgB,aAAa,sBAAgD,WACzG,sBAAuBA,GAAA,YAAAA,EAAgB,aAAa,aAAc,QAClE,oBAAuBA,GAAA,YAAAA,EAAgB,aAAa,WAAY,QAChE,mBAAuBA,GAAA,MAAAA,EAAgB,aAAa,YAAc,WAAWA,EAAe,aAAa,UAAU,CAAE,EAAI,KACzH,qBAAwBA,GAAA,YAAAA,EAAgB,aAAa,gBAA2C,UAChG,sBAAuBA,GAAA,MAAAA,EAAgB,aAAa,gBAAkB,WAAWA,EAAe,aAAa,cAAc,CAAE,EAAI,EACjI,2BAA4B,KAAK,iBAAiBA,GAAA,YAAAA,EAAgB,aAAa,sBAAuB,CAAC,EAAG,CAAC,CAAC,EAC5G,uBAAwB,KAAK,iBAAiBA,GAAA,YAAAA,EAAgB,aAAa,iBAAkB,CAAC,GAAK,CAAC,CAAC,EAMrG,SAAY,CAAC,CAACC,EACd,WAAYA,GAAA,MAAAA,EAAQ,aAAa,KAAQA,EAAO,aAAa,GAAG,GAAK,GAAM,KAC3E,WAAYA,GAAA,MAAAA,EAAQ,aAAa,KAAQA,EAAO,aAAa,GAAG,GAAK,GAAM,IAAA,CAE/E,CAEQ,iBAAiB/oB,EAAkCipB,EAA8C,CACvG,GAAI,CAACjpB,EAAO,OAAOipB,EACnB,MAAM9f,EAAQnJ,EAAM,MAAM,GAAG,EAAE,IAAI4J,GAAQ,OAAOA,EAAK,KAAA,CAAM,CAAC,EAC9D,OAAIT,EAAM,OAAS,GAAK,CAACA,EAAM,MAAM,OAAO,QAAQ,EAAU8f,EACvD,CAAC9f,EAAM,CAAC,EAAGA,EAAM,CAAC,CAAC,CAC5B,CAEA,yBAAyBrL,EAAewM,EAAyBI,EAA+B,CAC1FJ,IAAaI,GACjB,KAAK,kBAAA,CACP,CAEA,mBAA0B,OAGxB,MAAMlH,EAAI,KAAK,aAAa,OAAO,EAC7BJ,EAAI,KAAK,aAAa,QAAQ,EACpC,KAAK,MAAM,QAAU,QACjBI,IAAG,KAAK,MAAM,MAAS,MAAM,OAAOA,CAAC,CAAC,EAAIA,EAAI,GAAGA,CAAC,MAClDJ,IAAG,KAAK,MAAM,OAAS,MAAM,OAAOA,CAAC,CAAC,EAAIA,EAAI,GAAGA,CAAC,MAEtD,KAAK,YAAY,KAAK,WAAW,EACjCkb,GAAe,WAAW,IAAI,IAAI,EAKlC,KAAK,eAAiB,IAAI,iBAAiB,IAAM,KAAK,mBAAmB,EACzE,KAAK,eAAe,QAAQ,KAAM,CAChC,UAAiB,GACjB,WAAiB,GACjB,QAAiB,GACjB,gBAAiB,CACf,QAAS,OAAQ,UAAW,OAAQ,cAAe,UACnD,UAAW,SAAU,YAAa,OAClC,SAAU,aAAc,QAAS,YAAa,UAAW,MAAO,cAChE,eAAgB,cAAe,aAAc,SAAU,QAAS,SAAU,aAC1E,kBAAmB,oBAAqB,mBAAoB,cAAe,cAAe,eAC1F,QAAS,SAAU,SAAU,SAAU,OAAQ,WAC/C,aAAc,eAAgB,qBAAsB,gBACpD,IAAK,IAAK,OAAQ,YAAA,CACpB,CACD,EAID,MAAM4K,EAAQ,KAAK,aAAa,KAAK,EACrC,KAAK,SACFA,EAAQ,SAAS,eAAeA,CAAK,EAAI,OAC1C,KAAK,QAAQ,WAAW,KACxBpqB,EAAA,KAAK,gBAAL,YAAAA,EAAoB,QAAQ,eAC5B,SAAS,cAAc,WAAW,EAEpC,KAAK,KAAA,EAKL,MAAMqqB,EAAc,KAAK,aAAa,OAAO,eAAgB,QAAQ,EACrE,GAAIA,GAAA,MAAAA,EAAa,YACf,KAAK,aAAeA,EAAY,gBAC3B,CAEL,QAAQ,KAAK,yEAAyE,EACtF,MAAMC,EAAa,KAAK,aAAa,CAAC,EAClCA,GAAA,MAAAA,EAAY,cACd,KAAK,aAAe,SAAS,gBAAgB,6BAA8B,GAAG,EAC9E,KAAK,aAAa,aAAa,kBAAmB,iBAAiB,EACnEA,EAAW,YAAY,YAAY,KAAK,YAAY,EAExD,CACF,CAEA,sBAA6B,YAC3BtqB,EAAA,KAAK,iBAAL,MAAAA,EAAqB,aACrB,KAAK,eAAiB,MACtByC,EAAA,KAAK,aAAL,MAAAA,EAAiB,aACjB,KAAK,WAAa,KAClB+c,GAAe,WAAW,OAAO,IAAI,GAErC7c,EAAA,KAAK,aAAL,MAAAA,EAAiB,SACjB,KAAK,WAAa,IACpB,CAMA,OAAO,WAA8B,CAAE,MAAO,CAAC,GAAG6c,GAAe,UAAU,CAAG,CAG9E,OAAO,SAASve,EAAoC,CAClD,UAAWqC,KAAKkc,GAAe,WAC7B,GAAIlc,EAAE,KAAOrC,GAAOqC,EAAE,aAAa,YAAY,IAAMrC,EAAK,OAAOqC,EAEnE,OAAO,IACT,CAGA,UAAsE,CACpE,MAAM+I,EAAQ,KAAK,aAAa,OAAO,eAAgB,OAAO,EAC9D,OAAKA,EACE,CAAC,GAAGA,EAAM,SAAS,QAAQ,QAAQ,EAAE,IAAKtL,GAAA,OAAY,OAC3D,GAAIA,EAAE,GAAI,OAAMf,EAAAe,EAAE,OAAF,YAAAf,EAAQ,OAAQe,EAAE,GAAI,EAAGA,EAAE,EAAG,EAAGA,EAAE,CAAA,EACnD,EAHiB,CAAA,CAIrB,CAGA,UAAwG,CACtG,MAAMwpB,EAAU9rB,EAACI,GAAiB,CAChC,MAAMa,EAAI,KAAK,aAAa,OAAO,eAAgBb,CAAI,EACvD,OAAOa,EAAI,CAAC,GAAGA,EAAE,SAAS,QAAQ,OAAA,CAAQ,EAAI,CAAA,CAChD,EAHgB,WAIhB,MAAO,CAAC,GAAG6qB,EAAQ,OAAO,EAAG,GAAGA,EAAQ,WAAW,CAAC,EACjD,IAAKxpB,GAAW,CACf,MAAM0D,EAAI1D,EAAE,MAAQ,CAAA,EACpB,MAAO,CAAE,OAAQ0D,EAAE,OAAQ,OAAQA,EAAE,OAAQ,OAAQA,EAAE,QAAU,EACxD,SAAU,CAAC,CAACA,EAAE,WAAY,KAAM,CAAC,CAACA,EAAE,MAAA,CAC/C,CAAC,EACA,OAAO,GAAK,EAAE,QAAU,MAAQ,EAAE,QAAU,IAAI,CACrD,CAYQ,eAA8B,CACpC,MAAO,CAAC,GAAG,KAAK,YAAY,iBAC1B,4FAAA,CACD,CACH,CAEQ,YAAYyT,EAAqB,CACvC,MAAMsS,EAAMtS,EAAG,QAAQ,YAAA,EACjB1W,EAAI/C,EAAC8F,GAAc,WAAW2T,EAAG,aAAa3T,CAAC,GAAK,GAAG,EAAnD,KACV,GAAIimB,IAAQ,SAAU,MAAO,CAAE,EAAG,IAAK,GAAIhpB,EAAE,IAAI,EAAG,GAAIA,EAAE,IAAI,CAAA,EAC9D,GAAIgpB,IAAQ,OAAU,MAAO,CAAE,EAAG,IAAK,EAAGhpB,EAAE,GAAG,EAAG,EAAGA,EAAE,GAAG,CAAA,EAC1D,GAAIgpB,IAAQ,OAAU,MAAO,CAAE,EAAG,IAAK,GAAIhpB,EAAE,IAAI,EAAG,GAAIA,EAAE,IAAI,EAAG,GAAIA,EAAE,IAAI,EAAG,GAAIA,EAAE,IAAI,CAAA,EACxF,GAAIgpB,IAAQ,OAAQ,CAClB,MAAMpmB,EAAI8T,EAAG,aAAa,GAAG,GAAK,GAClC,MAAO,CAAE,EAAG,IAAK,EAAA9T,EAAG,MAAOA,EAAE,MAAMob,GAAe,YAAY,GAAK,CAAA,GAAI,IAAI,MAAM,CAAA,CACnF,CACA,OAAO,IACT,CAGQ,eAAsC,CAC5C,MAAM/a,MAAQ,IACd,YAAK,cAAA,EAAgB,QAAQyT,GAAM,CAAE,MAAMzY,EAAI,KAAK,YAAYyY,CAAE,EAAOzY,GAAGgF,EAAE,IAAIyT,EAAIzY,CAAC,CAAG,CAAC,EACpFgF,CACT,CAGQ,UAAU6I,EAAkC,CAC9C,KAAK,YAAc,OAAQ,qBAAqB,KAAK,SAAS,EAAG,KAAK,UAAY,MACtF,MAAMC,MAAS,IAEf,GADA,KAAK,cAAA,EAAgB,QAAQ2K,GAAM,CAAE,GAAI5K,EAAK,IAAI4K,CAAE,EAAG,CAAE,MAAMzY,EAAI,KAAK,YAAYyY,CAAE,EAAOzY,GAAG8N,EAAG,IAAI2K,EAAIzY,CAAC,CAAG,CAAE,CAAC,EAC9G,CAAC8N,EAAG,KAAM,OAEd,MAAMkd,EAAM,KAAK,WACXC,EAAK,YAAY,IAAA,EACjBC,EAAOlsB,EAACyK,GAAeA,EAAI,GAAM,EAAIA,EAAIA,EAAI,EAAI,KAAK,IAAI,GAAKA,EAAI,EAAG,CAAC,EAAI,EAApE,QACP0hB,EAAOnsB,EAAA,CAAC8F,EAAWhB,EAAWuB,IAAcP,GAAKhB,EAAIgB,GAAKO,EAAnD,QAEP+lB,EAAOpsB,EAACiY,GAAgB,CAC5B,MAAMxN,EAAI,KAAK,IAAI,GAAIwN,EAAMgU,GAAMD,CAAG,EAChC3lB,EAAI6lB,EAAKzhB,CAAC,EAChBqE,EAAG,QAAQ,CAACud,EAAI5S,IAAO,CACrB,MAAM6S,EAAKzd,EAAK,IAAI4K,CAAE,EACtB,GAAI,GAAC6S,GAAMA,EAAG,IAAMD,EAAG,GACvB,GAAIA,EAAG,IAAM,IACX5S,EAAG,aAAa,KAAM,OAAO0S,EAAKG,EAAG,GAAID,EAAG,GAAIhmB,CAAC,CAAC,CAAC,EACnDoT,EAAG,aAAa,KAAM,OAAO0S,EAAKG,EAAG,GAAID,EAAG,GAAIhmB,CAAC,CAAC,CAAC,UAC1CgmB,EAAG,IAAM,IAClB5S,EAAG,aAAa,IAAK,OAAO0S,EAAKG,EAAG,EAAGD,EAAG,EAAGhmB,CAAC,CAAC,CAAC,EAChDoT,EAAG,aAAa,IAAK,OAAO0S,EAAKG,EAAG,EAAGD,EAAG,EAAGhmB,CAAC,CAAC,CAAC,UACvCgmB,EAAG,IAAM,IAClB5S,EAAG,aAAa,KAAM,OAAO0S,EAAKG,EAAG,GAAID,EAAG,GAAIhmB,CAAC,CAAC,CAAC,EACnDoT,EAAG,aAAa,KAAM,OAAO0S,EAAKG,EAAG,GAAID,EAAG,GAAIhmB,CAAC,CAAC,CAAC,EACnDoT,EAAG,aAAa,KAAM,OAAO0S,EAAKG,EAAG,GAAID,EAAG,GAAIhmB,CAAC,CAAC,CAAC,EACnDoT,EAAG,aAAa,KAAM,OAAO0S,EAAKG,EAAG,GAAID,EAAG,GAAIhmB,CAAC,CAAC,CAAC,MAC9C,CAIL,GAAI,CAACimB,EAAG,MAAQA,EAAG,KAAK,SAAWD,EAAG,KAAK,OAAQ,OACnD,IAAI3rB,EAAI,EACR,MAAMiF,EAAI0mB,EAAG,EAAE,QAAQtL,GAAe,aACpC,IAAM,OAAOoL,EAAKG,EAAG,KAAK5rB,CAAC,EAAG2rB,EAAG,KAAK3rB,GAAG,EAAG2F,CAAC,CAAC,CAAA,EAChDoT,EAAG,aAAa,IAAK9T,CAAC,CACxB,CACF,CAAC,EACD,KAAK,UAAY8E,EAAI,EAAI,sBAAsB2hB,CAAI,EAAI,IACzD,EA7Ba,QA8Bb,KAAK,UAAY,sBAAsBA,CAAI,CAC7C,CAGA,OAAgB,CACd,MAAMhP,EAAM,KAAK,YAAY,UAAU,EAAI,EAC3CA,EAAI,aAAa,QAAS,4BAA4B,EACtDA,EAAI,aAAa,cAAe,8BAA8B,EAC9D,MAAM7C,EAAO,KAAK,YAAY,sBAAA,EAC9B,OAAIA,EAAK,OAAQ6C,EAAI,aAAa,QAAU,OAAO,KAAK,MAAM7C,EAAK,KAAK,CAAC,CAAC,EACtEA,EAAK,QAAQ6C,EAAI,aAAa,SAAU,OAAO,KAAK,MAAM7C,EAAK,MAAM,CAAC,CAAC,EACpE,IAAI,cAAA,EAAgB,kBAAkB6C,CAAG,CAClD,CAIA,MAAM1L,EAAQ,EAAoB,CAChC,MAAM6a,EAAS,KAAK,MAAA,EACdhS,EAAO,KAAK,YAAY,sBAAA,EACxBtU,EAAI,KAAK,IAAI,EAAG,KAAK,MAAMsU,EAAK,KAAK,CAAC,EACtC1U,EAAI,KAAK,IAAI,EAAG,KAAK,MAAM0U,EAAK,MAAM,CAAC,EAC7C,OAAO,IAAI,QAAQ,CAACyN,EAASwE,IAAW,CACtC,MAAMC,EAAO,IAAI,KAAK,CAACF,CAAM,EAAG,CAAE,KAAM,8BAA+B,EACjEG,EAAM,IAAI,gBAAgBD,CAAI,EAC9BE,EAAM,IAAI,MAChBA,EAAI,OAAS,IAAM,CACjB,GAAI,CACF,MAAMC,EAAS,SAAS,cAAc,QAAQ,EAC9CA,EAAO,MAAQ3mB,EAAIyL,EACnBkb,EAAO,OAAS/mB,EAAI6L,EACpB,MAAMmb,EAAMD,EAAO,WAAW,IAAI,EAClC,GAAI,CAACC,EAAK,CAAE,IAAI,gBAAgBH,CAAG,EAAGF,EAAO,IAAI,MAAM,eAAe,CAAC,EAAG,MAAQ,CAClFK,EAAI,MAAMnb,EAAOA,CAAK,EACtBmb,EAAI,UAAUF,EAAK,EAAG,EAAG1mB,EAAGJ,CAAC,EAC7B,IAAI,gBAAgB6mB,CAAG,EACvB1E,EAAQ4E,EAAO,UAAU,WAAW,CAAC,CACvC,OAASE,EAAK,CAAE,IAAI,gBAAgBJ,CAAG,EAAGF,EAAOM,CAAG,CAAG,CACzD,EACAH,EAAI,QAAWnc,GAAM,CAAE,IAAI,gBAAgBkc,CAAG,EAAGF,EAAOhc,CAAC,CAAG,EAC5Dmc,EAAI,IAAMD,CACZ,CAAC,CACH,CAGA,WAAuF,CACrF,MAAM9e,EAAQ,KAAK,aAAa,OAAO,eAAgB,QAAQ,EAC/D,OAAKA,EACE,CAAC,GAAGA,EAAM,SAAS,QAAQ,OAAA,CAAQ,EACvC,OAAQtL,GAAA,OAAW,QAAAf,EAAAe,EAAE,OAAF,YAAAf,EAAQ,QAAS,QAAO,EAC3C,IAAKe,GAAA,WAAY,OAAE,KAAIf,EAAAe,EAAE,OAAF,YAAAf,EAAQ,OAAQe,EAAE,GAAI,OAAO0B,EAAA1B,EAAE,OAAF,YAAA0B,EAAQ,MAAO,KAAKE,EAAA5B,EAAE,OAAF,YAAA4B,EAAQ,IAC7D,EAAG5B,EAAE,EAAG,EAAGA,EAAE,CAAA,EAAI,EAJpB,CAAA,CAKrB,CAGA,aAAaiY,EAAgE,CAC3E,OAAO,KAAK,UAAA,EACT,OAAOjX,GAAKA,EAAE,GAAKiX,EAAK,GAAKjX,EAAE,GAAKiX,EAAK,EAAIA,EAAK,GACtCjX,EAAE,GAAKiX,EAAK,GAAKjX,EAAE,GAAKiX,EAAK,EAAIA,EAAK,CAAC,EACnD,IAAIjX,GAAKA,EAAE,EAAE,CAClB,CASQ,SAASwC,EAAWhB,EAAmB,CAC7C,OAAOgB,GAAKhB,EAAI,GAAGgB,CAAC,KAAIhB,CAAC,GAAK,GAAGA,CAAC,KAAIgB,CAAC,EACzC,CAGA,aAAainB,EAAyF,CACpG,KAAK,WAAW,MAAQ,IAAI,KAAKA,EAAI,OAAS,IAAI,IAAI,GAAK,KAAK,SAAS,EAAE,OAAQ,EAAE,MAAM,CAAC,CAAC,EAC7F,KAAK,WAAW,MAAQ,IAAI,KAAKA,EAAI,OAAS,CAAA,GAAI,IAAI,MAAM,CAAC,EAC7D,KAAK,iBAAA,CACP,CAGA,gBAAuB,CACrB,KAAK,WAAW,MAAM,MAAA,EACtB,KAAK,WAAW,MAAM,MAAA,EACtB,KAAK,iBAAA,CACP,CAEQ,kBAAyB,CAC/B,GAAI,CAAC,KAAK,YAAa,OAClB,KAAK,kBACR,KAAK,gBAAkB,SAAS,gBAAgB,6BAA8B,GAAG,EACjF,KAAK,gBAAgB,aAAa,kBAAmB,WAAW,EAChE,KAAK,gBAAgB,aAAa,iBAAkB,MAAM,GAG5D,KAAK,YAAY,YAAY,KAAK,eAAe,EACjD,MAAMloB,EAAI,KAAK,gBACfA,EAAE,YAAc,GAEhB,MAAM8U,EAAU,KAAK,SAAmB,SAAS,OAAS,EACpDqT,EAAK,UACLC,EAAKjtB,EAAA,CAAC+rB,EAAamB,IAA2C,CAClE,MAAMzT,EAAK,SAAS,gBAAgB,6BAA8BsS,CAAG,EACrE,UAAW1lB,KAAK6mB,EAAOzT,EAAG,aAAapT,EAAG,OAAO6mB,EAAM7mB,CAAC,CAAC,CAAC,EAC1D,OAAOoT,CACT,EAJW,MAOX,GAAI,KAAK,WAAW,MAAM,KAAM,CAC9B,MAAM0T,EAA+C,CAAA,EACrD,KAAK,SAAA,EAAW,QAAQpqB,GAAK,CAAEoqB,EAAGpqB,EAAE,EAAE,EAAI,CAAE,EAAGA,EAAE,EAAG,EAAGA,EAAE,CAAA,CAAK,CAAC,EAC/D,KAAK,WAAW,MAAM,QAAQP,GAAO,CACnC,KAAM,CAAC,EAAGsC,CAAC,EAAItC,EAAI,MAAM,IAAG,EACtBgQ,EAAI2a,EAAG,CAAC,EAAGC,EAAID,EAAGroB,CAAC,EACrB,CAAC0N,GAAK,CAAC4a,GACXvoB,EAAE,YAAYooB,EAAG,OAAQ,CACvB,GAAIza,EAAE,EAAG,GAAIA,EAAE,EAAG,GAAI4a,EAAE,EAAG,GAAIA,EAAE,EACjC,OAAQJ,EAAI,eAAgBrT,EAAS,IAAM,iBAAkB,GAAK,iBAAkB,OAAA,CACrF,CAAC,CACJ,CAAC,CACH,CAGA,KAAK,WAAW,MAAM,QAAQpX,GAAM,OAClC,MAAMkX,EAAK,KAAK,YAAY,cAAc,oBAAoBlY,EAAA,OAAe,MAAf,MAAAA,EAAoB,OAAS,IAAI,OAAOgB,CAAE,EAAIA,CAAE,IAAI,EAClH,GAAI,CAACkX,EAAI,OACT,MAAMsS,EAAMtS,EAAG,QAAQ,YAAA,EACvB,IAAInK,EAAYC,EAAYzN,EAC5B,GAAIiqB,IAAQ,OAAQ,CAClB,MAAM9lB,EAAI,WAAWwT,EAAG,aAAa,OAAO,GAAK,GAAG,EACpDnK,EAAK,WAAWmK,EAAG,aAAa,GAAG,GAAK,GAAG,EAAIxT,EAAI,EACnDsJ,EAAK,WAAWkK,EAAG,aAAa,GAAG,GAAK,GAAG,EAAI,WAAWA,EAAG,aAAa,QAAQ,GAAK,GAAG,EAAI,EAC9F3X,EAAKmE,EAAI,CACX,MACEqJ,EAAK,WAAWmK,EAAG,aAAa,IAAI,GAAK,GAAG,EAC5ClK,EAAK,WAAWkK,EAAG,aAAa,IAAI,GAAK,GAAG,EAC5C3X,EAAK,WAAW2X,EAAG,aAAa,GAAG,GAAK,GAAG,EAE7C5U,EAAE,YAAYooB,EAAG,SAAU,CACzB,GAAA3d,EAAI,GAAAC,EAAI,EAAGzN,EAAI,IAAM6X,EAAS,KAAO,KAAM,OAAQ,OAAQqT,EAAI,eAAgBrT,EAAS,IAAA,CACzF,CAAC,CACJ,CAAC,CACH,CAEA,QAAqB,CACnB,MACEyD,EAAM,SAAS,gBAAgB,6BAA8B,KAAK,EAEpEA,EAAI,UAAU,IAAI,OAAO,EAIzBA,EAAI,MAAM,QAAU,QACpBA,EAAI,MAAM,MAAU,OACpBA,EAAI,MAAM,OAAU,OACpBA,EAAI,aAAa,sBAAuB,eAAe,EACvDA,EAAI,aAAa,UAAY,KAAK,SAAmB,SAAS,YAAY,EAC1EA,EAAI,aAAa,YAAc,KAAK,SAAmB,UAAU,UAAU,EAC3EA,EAAI,aAAa,OAAQ,QAAQ,EACjCA,EAAI,aAAa,kBAAmB,GAAG,KAAK,IAAK,KAAK,SAAmB,SAAS,MAAQ,KAAK,SAAmB,SAAS,MAAM,CAAC,EAAE,EACpI,KAAK,YAAcA,EAMnB,MAAMiQ,EAAO,SAAS,gBAAgB,6BAA8B,MAAM,EAMpEC,EAAK,IAAMC,EAAK,IAChBC,EAAYxtB,EAAA,CAACuC,EAAYkrB,IAAiB,CAC9C,MAAMznB,EAAI,SAAS,gBAAgB,6BAA8B,QAAQ,EACzEA,EAAE,aAAa,KAAezD,CAAE,EAChCyD,EAAE,aAAa,cAAe,OAAOsnB,CAAE,CAAC,EACxCtnB,EAAE,aAAa,eAAe,OAAOunB,CAAE,CAAC,EACxCvnB,EAAE,aAAa,OAAe,OAAOsnB,CAAE,CAAC,EACxCtnB,EAAE,aAAa,OAAe,OAAOunB,EAAK,CAAC,CAAC,EAC5CvnB,EAAE,aAAa,SAAe,MAAM,EACpCA,EAAE,aAAa,cAAe,gBAAgB,EAC9C,MAAM1C,EAAI,SAAS,gBAAgB,6BAA8B,MAAM,EACvEA,EAAE,aAAa,IAAQ,WAAWiqB,CAAE,KAAKD,CAAE,IAAIC,EAAG,CAAC,IAAI,EACvDjqB,EAAE,aAAa,OAAQmqB,CAAI,EAC3BznB,EAAE,YAAY1C,CAAC,EACf+pB,EAAK,YAAYrnB,CAAC,CACpB,EAdkB,aAgBlB,OAAA4Y,GAAc,QAAQ7Z,GAASyoB,EAAU,YAAYzoB,EAAM,MAAM,CAAC,CAAC,GAAIA,CAAK,CAAC,EAC7EqY,EAAI,YAAYiQ,CAAI,EAEpB,KAAK,SAAS,OAAO,QAASzf,GAAqB,CACjD,MAAM+O,EAAmB,IAAIC,GAAQhP,EAAc,KAAK,YAAa,IAAI,EACzE,KAAK,aAAa,KAAK+O,CAAO,CAChC,CAAC,EAED,KAAK,SAAS,UAAU,YAAY,gBAAiB,KAAK,QAAS,EAEnE,KAAK,cAAA,EAEES,CACT,CAEA,eAAgB,CAEd,KAAK,YAAY,iBAAiB,QAAUD,GAAmB,CAC7D,QAAQ,IAAI,gBAAiBA,CAAE,EAC/BA,EAAG,eAAA,EACW,KAAK,KAAKA,EAAG,MAAM,EACrB,EACV,KAAK,YAAc,IAEnB,KAAK,YAAc,IAErB,KAAK,SAAS,UAAU,KAAK,KAAK,UAAU,EAC5C,KAAK,OAAA,CACP,CAAC,EAGD,IAAIuQ,EAAY,GACZC,EAAgBC,EAEpB,KAAK,YAAY,iBAAiB,YAAczQ,GAAmB,CACjEuQ,EAAY,GACZC,EAASxQ,EAAG,QACZyQ,EAASzQ,EAAG,OACd,CAAC,EACD,IAAI0Q,EAAmC,KACnCC,EAAgD,KAEpD,MAAMC,EAAY/tB,EAAA,IAAM,CAClB8tB,IACF,KAAK,SAAS,UAAU,IAAIA,EAAW,GAAIA,EAAW,EAAE,EACxD,KAAK,aAAa,CAAC,EAAE,YAAY,aAAa,YAAa,KAAK,SAAS,UAAU,SAAA,CAAU,EAC7FA,EAAa,MAEfD,EAAoB,IACtB,EAPkB,aASlB,KAAK,YAAY,iBAAiB,YAAc1Q,GAAmB,CACjE,GAAI,CAACuQ,EAAW,OAChB,MACE9W,EAAKuG,EAAG,QAAUwQ,EAClB9W,EAAKsG,EAAG,QAAUyQ,EAEpBE,EAAa,CAAE,GAAIlX,EAAK,IAAK,GAAIC,EAAK,GAAA,EACtC8W,EAASxQ,EAAG,QACZyQ,EAASzQ,EAAG,QAER0Q,IAAsB,OACxBA,EAAoB,sBAAsBE,CAAS,EAEvD,CAAC,EAED,KAAK,YAAY,iBAAiB,UAAY5Q,GAAmB,CAC/DuQ,EAAY,EACd,CAAC,EAID,KAAK,YAAY,iBAAiB,iBAAmBvQ,GAAoB,SACvE,MAAM5a,GAAKyB,GAAAzC,EAAA4b,EAAG,SAAH,YAAA5b,EAAW,YAAX,YAAAyC,EAAsB,GACjC,GAAI,CAACzB,EAAI,OACT,MAAMmjB,EAAM,KAAK,aAAa,IAAInjB,CAAE,GACxB,KAAK,YAAY,IAAIA,EAAG,QAAQ,QAAS,EAAE,CAAC,GAC5C,KAAK,YAAY,IAAIA,CAAE,EAC/BmjB,GAAOA,EAAI,cAAgBtW,EAAM,cAAc,SAAW,OAAA,CAChE,EAAA,EAKA,MAAM4e,EAAchuB,EAACyZ,GAAyC,OAC5D,KAAOA,GAAMA,IAAO,KAAK,aAAa,CACpC,MAAMlX,GAAKhB,EAAAkY,EAAG,eAAH,YAAAlY,EAAA,KAAAkY,EAAkB,iBAC7B,GAAIlX,EAAI,OAAOA,EACfkX,EAAKA,EAAG,aACV,CACA,OAAO,IACT,EAPoB,eASdwU,EAAejuB,EAACuC,GACb,KAAK,aAAa,IAAIA,CAAE,GACxB,KAAK,YAAY,IAAIA,EAAG,QAAQ,SAAU,EAAE,CAAC,GAC7C,KAAK,YAAY,IAAIA,CAAE,EAHX,gBAMrB,KAAK,YAAY,iBAAiB,YAAc4a,GAAmB,CACjE,MAAM5a,EAAKyrB,EAAY7Q,EAAG,MAAoB,EAC9C,GAAI,CAAC5a,EAAI,OACT,MAAMmjB,EAAMuI,EAAa1rB,CAAE,GACvBmjB,GAAA,YAAAA,EAAK,eAAgBtW,EAAM,cAAc,QAAU,KAAA,CACzD,CAAC,EAED,KAAK,YAAY,iBAAiB,WAAa+N,GAAmB,CAGhE,MAAM5a,EAAKyrB,EAAY7Q,EAAG,MAAoB,EAC9C,GAAI,CAAC5a,EAAI,OAGT,MAAM2rB,EAAU/Q,EAAG,cAEnB,GADkB6Q,EAAYE,CAAO,IACnB3rB,EAAI,OACtB,MAAMmjB,EAAMuI,EAAa1rB,CAAE,GACvBmjB,GAAA,YAAAA,EAAK,eAAgBtW,EAAM,cAAc,QAAU,KAAA,CACzD,CAAC,EAKD,KAAK,yBAAA,CACP,CAGQ,MAAMhP,EAAc+tB,EAAmC,CAC7D,KAAK,cAAc,IAAI,YAAY/tB,EAAM,CAAE,OAAA+tB,EAAQ,QAAS,GAAM,SAAU,EAAA,CAAM,CAAC,CACrF,CAGQ,aAAa1U,EAAuB3B,EAAiC,SAC3E,KAAO2B,GAAMA,IAAO,KAAK,aAAa,CACpC,KAAIlY,EAAAkY,EAAG,eAAH,YAAAlY,EAAA,KAAAkY,EAAkB3B,KAAS,QAAQ9T,EAAAyV,EAAG,eAAH,MAAAzV,EAAA,KAAAyV,EAAkB3B,IAAO,OAAO2B,EACvEA,EAAKA,EAAG,aACV,CACA,OAAO,IACT,CAGQ,YAAYA,EAAmD,CACrE,MAAM,EAAI,KAAK,aAAaA,EAAI,kBAAkB,EAClD,GAAI,CAAC,EAAG,OAAO,KACf,MAAM9T,EAAyB,CAC7B,OAAU,EAAE,aAAa,kBAAkB,EAC3C,OAAU,EAAE,aAAa,kBAAkB,EAC3C,OAAU,WAAW,EAAE,aAAa,kBAAkB,GAAK,GAAG,EAC9D,SAAU,EAAE,aAAa,oBAAoB,IAAM,OACnD,KAAU,EAAE,aAAa,gBAAgB,IAAM,MAAA,EAEjD,OAAI,EAAE,aAAa,iBAAiB,MAAK,MAAQ,EAAE,aAAa,iBAAiB,GAC7E,EAAE,aAAa,gBAAgB,MAAM,KAAQ,EAAE,aAAa,gBAAgB,GACzEA,CACT,CAGQ,YAAY8T,EAAmD,CACrE,MAAM1W,EAAI,KAAK,aAAa0W,EAAI,eAAe,EAC/C,GAAI,CAAC1W,EAAG,OAAO,KACf,MAAMgpB,EAAMhpB,EAAE,QAAQ,YAAA,EACtB,IAAIgD,EAAWQ,EACXwlB,IAAQ,QACVhmB,EAAI,WAAWhD,EAAE,aAAa,GAAG,GAAK,GAAG,EAAI,WAAWA,EAAE,aAAa,OAAO,GAAM,GAAG,EAAI,EAC3FwD,EAAI,WAAWxD,EAAE,aAAa,GAAG,GAAK,GAAG,EAAI,WAAWA,EAAE,aAAa,QAAQ,GAAK,GAAG,EAAI,IAE3FgD,EAAI,WAAWhD,EAAE,aAAa,IAAI,GAAK,GAAG,EAC1CwD,EAAI,WAAWxD,EAAE,aAAa,IAAI,GAAK,GAAG,GAE5C,MAAMR,EAAKQ,EAAE,aAAa,eAAe,EACnC4C,EAAyB,CAC7B,GAAApD,EACA,KAAMQ,EAAE,aAAa,WAAW,GAAK,QACrC,KAAMA,EAAE,aAAa,WAAW,GAAKR,EACrC,EAAAwD,EAAG,EAAAQ,CAAA,EAEL,OAAIxD,EAAE,aAAa,YAAY,MAAK,MAAQA,EAAE,aAAa,YAAY,GACnEA,EAAE,aAAa,WAAW,MAAM,KAAQA,EAAE,aAAa,WAAW,GAC/D4C,CACT,CAEQ,0BAAiC,CACvC,MAAMyX,EAAM,KAAK,YAEjBA,EAAI,iBAAiB,QAAUD,GAAmB,CAChD,MAAMxY,EAASwY,EAAG,OACZ9H,EAAO,KAAK,YAAY1Q,CAAM,EACpC,GAAI0Q,EAAM,CAAE,KAAK,MAAM,gBAAiB,CAAE,GAAGA,EAAM,cAAe8H,EAAI,EAAG,MAAQ,CACjF,MAAMiR,EAAO,KAAK,YAAYzpB,CAAM,EAChCypB,QAAW,MAAM,gBAAiB,CAAE,GAAGA,EAAM,cAAejR,EAAI,CACtE,CAAC,EAGD,IAAIkR,EAAyD,KAC7D,MAAMC,EAAQtuB,EAAA,CAACyK,EAAoB9E,IACjC8E,IAAM,OAAS,GAAG9E,EAAE,MAAM,KAAIA,EAAE,MAAM,GAAK,OAAOA,EAAE,EAAE,EAD1C,SAGdyX,EAAI,iBAAiB,YAAcD,GAAmB,CACpD,MAAMxY,EAASwY,EAAG,OACZ9H,EAAO,KAAK,YAAY1Q,CAAM,EAC9BypB,EAAO/Y,EAAO,KAAO,KAAK,YAAY1Q,CAAM,EAC5C4pB,EAAOlZ,EAAO,CAAE,KAAM,OAAiB,OAAQA,CAAA,EACxC+Y,EAAO,CAAE,KAAM,OAAiB,OAAQA,GACxC,KACPI,EAAUD,EAAOD,EAAMC,EAAK,KAAMA,EAAK,MAAM,EAAI,KACnDF,IAAY,CAACE,GAAQF,EAAQ,MAAQG,KACvC,KAAK,MAAMH,EAAQ,OAAS,OAAS,kBAAoB,kBAAmB,CAAE,IAAKA,EAAQ,GAAA,CAAK,EAChGA,EAAU,MAERE,IAAS,CAACF,GAAWA,EAAQ,MAAQG,KACvC,KAAK,MAAMD,EAAK,OAAS,OAAS,gBAAkB,gBAAiB,CAAE,GAAGA,EAAK,OAAQ,cAAepR,CAAA,CAAI,EAC1GkR,EAAU,CAAE,KAAME,EAAK,KAAM,IAAKC,CAAA,GAIhC,KAAK,aAAa,SAAS,GAAKD,EAClC,KAAK,aAAa,KAAK,aAAaA,EAAK,KAAMA,EAAK,MAAM,EAAGpR,EAAG,QAASA,EAAG,OAAO,EAEnF,KAAK,aAAA,CAET,CAAC,EAEDC,EAAI,iBAAiB,aAAc,IAAM,CACnCiR,IACF,KAAK,MAAMA,EAAQ,OAAS,OAAS,kBAAoB,kBAAmB,CAAE,IAAKA,EAAQ,GAAA,CAAK,EAChGA,EAAU,MAEZ,KAAK,aAAA,CACP,CAAC,CACH,CAMQ,aAAarhB,EAAuBrH,EAAgC,CAC1E,GAAIqH,IAAS,OAAQ,CACnB,MAAM/G,EAAI,OAAON,EAAE,MAAM,EACnB8oB,EAAO,OAAO,SAASxoB,CAAC,EAAI,KAAM,CAACA,EAAE,QAAQ,CAAC,CAAE,IAAM,GAC5D,MAAO,GAAGN,EAAE,MAAM,MAAMA,EAAE,MAAM,GAAG8oB,CAAI,EACzC,CACA,OAAO,OAAO9oB,EAAE,MAAQA,EAAE,EAAE,CAC9B,CAEQ,aAAamX,EAAc4R,EAAiBC,EAAuB,CACzE,GAAI,CAAC,KAAK,WAAY,CACpB,MAAMlV,EAAK,SAAS,cAAc,KAAK,EACvCA,EAAG,aAAa,kBAAmB,EAAE,EACrC,OAAO,OAAOA,EAAG,MAAO,CACtB,SAAU,QAAS,OAAQ,aAAc,cAAe,OACxD,WAAY,sBAAuB,MAAO,OAC1C,KAAM,iCAAkC,QAAS,UACjD,aAAc,MAAO,WAAY,SACjC,UAAW,oCAAA,CACW,EACxB,SAAS,KAAK,YAAYA,CAAE,EAC5B,KAAK,WAAaA,CACpB,CACA,KAAK,WAAW,YAAcqD,EAC9B,KAAK,WAAW,MAAM,KAAO,GAAG4R,CAAO,KACvC,KAAK,WAAW,MAAM,IAAO,GAAGC,CAAO,KACvC,KAAK,WAAW,MAAM,QAAU,OAClC,CAEQ,cAAqB,CACvB,KAAK,aAAY,KAAK,WAAW,MAAM,QAAU,OACvD,CAEA,MAAO,OACL,GAAG,CAAC,KAAK,YAAa,CACpB,QAAQ,MAAM,0BAA2B,IAAI,EAC7C,MACF,CAUA,IARAptB,EAAA,KAAK,UAAL,MAAAA,EAAc,YAAY,KAAK,aAE9B,KAAK,aAA2B,QAASqtB,GAAsB,CAC9DA,EAAS,KAAA,CACX,CAAC,EAIG,CAAC,KAAK,YAAc,OAAO,eAAmB,KAAe,KAAK,YAAa,CACjF,IAAIC,EAAQ,EACZ,KAAK,WAAa,IAAI,eAAeC,GAAW,OAC9C,MAAM7oB,IAAI1E,EAAAutB,EAAQ,CAAC,IAAT,YAAAvtB,EAAY,YAAY,QAAS,EACvC0E,EAAI,GAAK,KAAK,IAAIA,EAAI4oB,CAAK,EAAI,KACjCA,EAAQ5oB,EACR,KAAK,cAAA,EACL,KAAK,YAAA,EAET,CAAC,EACD,KAAK,WAAW,QAAQ,KAAK,WAAW,CAC1C,CACF,CAEA,QAAS,CAGP,KAAK,gBAAA,EACL,KAAK,cAAA,EACL,KAAK,cAAA,EACL,KAAK,gBAAA,EACL,KAAK,YAAA,EACL,KAAK,iBAAA,CACP,CAOA,aAAoB,SAElB,MAAM8oB,EAAY,KAAK,aAAa,OAAO,eAAgB,MAAM,EAC7DA,GAAA,MAAAA,EAAW,cACZA,EAAU,YAA2B,MAAM,QAAU,KAAK,UAAY,GAAK,QAG9E,MAAM3vB,EAAS,KAAK,aACdua,EAAS,KAAK,SAAS,SAAS,MAChC,CAAE,GAAArK,EAAI,GAAAC,CAAA,EAAO,KAAK,SAAS,SACjC,GAAI,CAACnQ,GAAUua,GAAU,EAAG,OAE5B,MAAMgE,EAAWhE,EAAS,IACpBqV,EAAWrR,EAAW,GAEtBsR,EAAQjvB,EAAA,CAACkvB,EAAiBpS,IAAwB,CACtD,IAAIrD,EAAK,KAAK,cAAc,IAAIyV,CAAI,EACpC,GAAI,CAAC,KAAK,WAAapS,GAAQ,KAAM,CAC/BrD,IAAMA,EAAG,OAAA,EAAU,KAAK,cAAc,OAAOyV,CAAI,GACrD,MACF,CACKzV,IACHA,EAAK,SAAS,gBAAgB,6BAA8B,MAAM,EAClEA,EAAG,aAAa,kBAAmByV,CAAI,EACvCzV,EAAG,aAAa,iBAAkB,MAAM,EACxCra,EAAO,YAAYqa,CAAE,EACrB,KAAK,cAAc,IAAIyV,EAAMzV,CAAE,GAEjCA,EAAG,YAAcqD,EACjBrD,EAAG,aAAa,YAAekE,EAAS,SAAA,CAAU,EAClDlE,EAAG,aAAa,cAAe,uBAAuB,EACtDA,EAAG,aAAa,cAAe,KAAK,EACpCA,EAAG,aAAa,OAAe,MAAM,EACjCyV,IAAS,KAGXzV,EAAG,aAAa,KAAMnK,EAAKqK,EAASqV,GAAK,UAAU,EACnDvV,EAAG,aAAa,KAAM,CAACuV,GAAK,UAAU,EACtCvV,EAAG,aAAa,cAAe,KAAK,IAGpCA,EAAG,aAAa,IAAMuV,EAAK,SAAA,CAAU,EACrCvV,EAAG,aAAa,KAAMlK,EAAKoK,EAASgE,EAAWqR,GAAK,UAAU,EAC9DvV,EAAG,aAAa,cAAe,OAAO,EAE1C,EA9Bc,SAoCd,GAJAwV,EAAM,IAAK,KAAK,UAAU,EAC1BA,EAAM,IAAK,KAAK,UAAU,EAGtB,KAAK,cAAgB,MACvB1tB,EAAA,KAAK,aAAL,MAAAA,EAAiB,SACjB,KAAK,WAAa,SACb,CACA,KAAK,aACR,KAAK,WAAa,SAAS,gBAAgB,6BAA8B,MAAM,EAC/E,KAAK,WAAW,aAAa,qBAAsB,EAAE,EACrD,KAAK,WAAW,aAAa,iBAAkB,MAAM,GAElD,KAAK,WAAW,eAAenC,EAAO,YAAY,KAAK,UAAU,EACtE,MAAMqa,EAAK,KAAK,WAChBA,EAAG,YAAc,KAAK,aACtBA,EAAG,aAAa,aAAgBkE,EAAW,KAAM,UAAU,EAC3DlE,EAAG,aAAa,cAAe,uBAAuB,EACtDA,EAAG,aAAa,aAAe,QAAQ,EACvCA,EAAG,aAAa,OAAe,MAAM,EACrCA,EAAG,aAAa,KAAMnK,EAAKqK,EAASqV,GAAK,UAAU,EACnDvV,EAAG,aAAa,KAAMlK,EAAKoK,EAASgE,EAAWqR,GAAK,UAAU,EAC9DvV,EAAG,aAAa,cAAe,OAAO,CACxC,CAIA,GAAI,CAAC,KAAK,YACRzV,EAAA,KAAK,WAAL,MAAAA,EAAe,SAAU,KAAK,SAAW,SACpC,CACA,KAAK,WACR,KAAK,SAAW,SAAS,gBAAgB,6BAA8B,MAAM,EAC7E,KAAK,SAAS,aAAa,kBAAmB,EAAE,EAChD,KAAK,SAAS,aAAa,iBAAkB,MAAM,GAEhD,KAAK,SAAS,eAAe5E,EAAO,YAAY,KAAK,QAAQ,EAElE,MAAM+vB,GADM,KAAK,WAAW,MAAQ,IAAM,KAC1B,KAAK,cAAA,EACf1kB,EAAI,KAAK,SACfA,EAAE,YAAc,KAAK,WACrBA,EAAE,aAAa,YAAa0kB,EAAG,SAAA,CAAU,EACzC1kB,EAAE,aAAa,cAAe,KAAK,WAAW,QAAU,uBAAuB,EAC/EA,EAAE,aAAa,cAAe,KAAK,EACnCA,EAAE,aAAa,OAAQ,KAAK,WAAW,OAAS,MAAM,EACtDA,EAAE,aAAa,IAAK6E,EAAG,SAAA,CAAU,EACjC7E,EAAE,aAAa,KAAM8E,EAAKoK,EAASwV,EAAK,KAAK,UAAU,EACvD1kB,EAAE,aAAa,cAAe,QAAQ,CACxC,CACF,CAEA,eAAsB,CACpB,KAAK,YAAY,QAAQib,GAAQA,EAAI,QAAQ,EAC7C,KAAK,YAAY,QAAQA,GAAQA,EAAI,QAAQ,EAC7C,KAAK,aAAa,QAAQA,GAAOA,EAAI,QAAQ,CAC/C,CAEA,iBAAkB,OAChB,MAAM1V,EAAQ,KAAK,SAEnB,GADAA,EAAM,gBAAgB,KAAK,cAAc,EACrC,KAAK,cAAgB,KAAK,aAAe,EAAG,CAE9C,KAAM,CAAE,GAAAV,EAAI,GAAAC,CAAA,EAAOS,EAAM,SACnB,EAAI,KAAK,gBAAkB,KAAK,aAAe,UACjDA,EAAM,eAAeV,EAAIC,CAAE,EAAI,IAC/B,KAAK,aACTS,EAAM,SAAW,IAAIR,GAAS,EAAG,EAAGF,EAAIC,CAAE,CAC5C,CAEA,MAAM6f,GAAU7tB,EAAA,KAAK,cAAL,YAAAA,EAAkB,wBAClC,GAAG,KAAK,aAAe6tB,EAAS,CAC9B,QAAQ,IAAI,aAAcA,CAAO,EACjC,IAAInpB,EAAGJ,EACJupB,EAAQ,QAAU,GAAKA,EAAQ,SAAW,GAC3CnpB,EAAI,EACJJ,EAAI,IAGJI,EAAImpB,EAAQ,MACZvpB,EAAIupB,EAAQ,QAEd,KAAK,SAAS,QAAU,GAAKnpB,GAAM,EAAI,KAAK,SAAS,SAAS,QAC9D,KAAK,SAAS,QAAU,GAAKJ,GAAK,EAAI,KAAK,SAAS,SAAS,QAG7D,KAAK,aAAa,CAAC,EAAE,YAAY,aAAa,YAAa,KAAK,SAAS,UAAU,SAAA,CAAU,EAE7F,KAAK,YAAY,aAAa,UAAY,KAAK,SAAmB,SAAS,YAAY,EAEvF,IAAIuK,EAAuC,KAAK,SAAS,OAAO,OAAO,SAAU,YAAY,EAC7F,GAAIA,EAAe,CACjB,IACEE,EAASF,EAAc,QAAQ,IAAI,QAAQ,EAC3CG,EAASH,EAAc,QAAQ,IAAI,QAAQ,EAE7C,GAAIE,GAAUC,EAAQ,CACpB,MAAMgD,EAAK,KAAK,SAAS,SACzBjD,EAAO,KAAO,IAAIxJ,EAAM,CAAE,GAAI,eAAgB,WAAY,CAACyM,EAAG,GAAKA,EAAG,MAAO,CAAC,EAAG,QAAS,CAAC,gBAAiB,eAAe,EAAG,EAC9HjD,EAAO,GAAK,IAAIxJ,EAAM,CAAE,GAAI,aAAc,WAAY,CAACyM,EAAG,GAAKA,EAAG,MAAO,CAAC,EAAG,QAAS,CAAC,gBAAiB,eAAe,EAAG,EAC1HhD,EAAO,KAAO,IAAIzJ,EAAM,CAAE,GAAI,eAAgB,WAAY,CAAC,EAAGyM,EAAG,GAAKA,EAAG,KAAK,EAAG,QAAS,CAAC,gBAAiB,eAAe,EAAG,EAC9HhD,EAAO,GAAK,IAAIzJ,EAAM,CAAE,GAAI,aAAc,WAAY,CAAC,EAAGyM,EAAG,GAAKA,EAAG,KAAK,EAAG,QAAS,CAAC,gBAAiB,eAAe,EAAG,CAC5H,CACF,CACF,CACF,CAEA,eAAgB,CACb,KAAK,aAA2B,QAASqb,GAAsB,CAC9DA,EAAS,OAAA,CACX,CAAC,CACH,CACF,EAvrEyE5uB,EAAA+gB,GAAA,kBACvEA,GAAO,QAAkB,WAczBA,GAAO,MAAgB;AAAA,MACnBhP,GAAgB,KAAK;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAm6CzBgP,GAAe,eAAsC,IA2CrDA,GAAe,aAAe,8BA99CzB,IAAMsO,GAANtO,GAwrEP,eAAe,OAAOsO,GAAe,QAASA,EAAc,EC31ErD,MAAMC,GAAWtvB,EAACwC,GAAgB+sB,GAAS,SAAS/sB,CAAG,EAAtC,YAEXgtB,GAAYxvB,EAAA,IAAMuvB,GAAS,UAAA,EAAf"}
|
|
1
|
+
{"version":3,"file":"qeviz.umd.js","sources":["../src/types/DataFrame.ts","../src/objects/Model.ts","../src/utils/debug.ts","../src/elements/QEVisual.ts","../src/objects/Color.ts","../src/objects/Transform.ts","../src/utils/Tools.ts","../src/types/EventBus.ts","../src/objects/Layers.ts","../src/objects/PlottedObject.ts","../src/objects/Extremes.ts","../src/objects/AxisPoint.ts","../src/objects/Graph.ts","../src/elements/DrawableElement.ts","../src/objects/polyfit.ts","../src/objects/Trajectory.ts","../src/objects/Edges.ts","../src/elements/Drawable.ts","../src/objects/Sizing.ts","../src/elements/QELine.ts","../src/elements/QEPoint.ts","../src/elements/QETrajectory.ts","../src/elements/QELayer.ts","../src/elements/QELabel.ts","../src/elements/QEChildElements.ts","../src/elements/QEGraph.ts","../src/index.ts"],"sourcesContent":["export interface DataFrameRowInterface {\n get names(): string[];\n get rowName(): string | undefined;\n get types(): DataFrameColumnType[];\n get parent(): DataFrame | undefined;\n}\n\nexport class DataFrameRow extends Array<any> implements DataFrameRowInterface {\n #rowNumber?: number;\n #rowName?: string;\n #names: string[];\n #parent?: DataFrame;\n #classes: string[] | undefined;\n\n constructor(names: string[], values: any[], rowName?: string, parent?: DataFrame, index?: number) {\n super(...values);\n this.#names = names;\n this.#rowName = rowName;\n this.#parent = parent;\n this.#classes = parent?.classes;\n this.#rowNumber = index;\n }\n\n get parent(): DataFrame | undefined {\n return this.#parent;\n }\n get names(): string[] {\n return this.#names;\n }\n get rowName(): string | undefined {\n return this.#rowName;\n }\n get types(): DataFrameColumnType[] {\n if (!this.#parent) throw new Error(\"No parent DataFrame attached to this row.\");\n return this.#parent.types;\n }\n get classes(): string[] | undefined {\n return this.#classes;\n }\n\n get rowNumber(): number | undefined {\n return this.#rowNumber;\n }\n\n col(wh: string | number): DataFrameColumn | undefined {\n if (!this.#parent) throw new Error(\"No parent DataFrame attached to this row.\");\n return this.#parent.col(wh);\n }\n cols(...wh: (string | number)[]): DataFrame {\n if (!this.#parent) throw new Error(\"No parent DataFrame attached to this row.\");\n return this.#parent.cols(...wh);\n }\n\n filter(predicate: (value: any, index: number, array: any[]) => boolean): any {\n console.error(\"DataFrameRow does not currently support filtering.\");\n // This method is intentionally left empty to prevent filtering on DataFrameRow.\n }\n}\n\nexport enum DataFrameColumnType {\n Character = 'character',\n Double = 'double',\n Logical = 'logical',\n Integer = 'integer'\n}\n\nexport interface DataFrameColumnInterface {\n get name(): string;\n get type(): DataFrameColumnType;\n get rowNames(): string[] | undefined;\n}\n\nexport class DataFrameColumn extends Array<any> implements DataFrameColumnInterface {\n #name: string;\n #type: DataFrameColumnType;\n #rowNames: string[] | undefined;\n #parent?: DataFrame;\n\n constructor(name: string, column: any, rowNames?: string[], parent?: DataFrame) {\n super(column.length);\n for (let i = 0; i < column.length; i++) {\n this[i] = column[i];\n }\n this.#name = name;\n\n if (column.type !== undefined) {\n this.#type = column.type;\n }\n // If undefined, infer type\n else {\n if (column.every((v: any) => typeof v === 'string' || v === null || v === undefined)) {\n this.#type = DataFrameColumnType.Character;\n }\n else if (column.every((v: any) => Number.isInteger(v) || v === null || v === undefined)) {\n // If only 1 and 0, consider as logical\n if (column.every((v: any) => v === 0 || v === 1 || v === null || v === undefined)) {\n this.#type = DataFrameColumnType.Logical;\n }\n else {\n this.#type = DataFrameColumnType.Integer;\n }\n }\n else if (column.every((v: any) => typeof v === 'number' || v === null || v === undefined)) {\n this.#type = DataFrameColumnType.Double;\n }\n else if (column.every((v: any) => typeof v === 'boolean' || v === null || v === undefined)) {\n this.#type = DataFrameColumnType.Logical;\n }\n\n // Default to character if mixed types\n else {\n this.#type = DataFrameColumnType.Character;\n }\n }\n this.#parent = parent;\n\n if (rowNames && rowNames.length !== this.length) {\n throw new Error(\"Row names length must match the number of rows in the DataFrameColumn.\");\n }\n if (rowNames && rowNames.length > 0) {\n this.#rowNames = rowNames;\n }\n else {\n this.#rowNames = undefined;\n }\n }\n\n get name(): string {\n return this.#name;\n }\n get type(): DataFrameColumnType {\n return this.#type;\n }\n get rowNames(): string[] | undefined {\n return this.#rowNames;\n }\n\n\n row(wh: string | number): DataFrameRow | undefined {\n if (!this.#parent) throw new Error(\"No parent DataFrame attached to this column.\");\n return this.#parent.row(wh);\n }\n rows(...wh: (string | number)[]): DataFrameRow[] {\n if (!this.#parent) throw new Error(\"No parent DataFrame attached to this column.\");\n return this.#parent.rows(...wh);\n }\n}\n\nexport interface DataFrameInterface {\n // Methods\n getColumnByName(name: string): DataFrameColumn | undefined;\n getRowByIndex(index: number): any[];\n getRowByName(name: string): any[] | undefined;\n row(wh: string | number): any[] | undefined;\n type(wh: string | number): DataFrameColumnType | undefined;\n\n get names(): string[];\n get rowNames(): string[] | undefined;\n get types(): string[];\n\n // Properties\n nrow: number;\n ncol: number;\n}\n\nexport class DataFrame extends Array<DataFrameColumn> implements DataFrameInterface {\n #names: string[];\n #rowNames: string[] | undefined;\n #classes: string[] | undefined;\n\n constructor(names?: string[], colValues?: any[], rowNames?: string[], classes?: string[]) {\n if (!names || !colValues) {\n colValues = [];\n names = [];\n }\n if (colValues.map( (c: any) => c.length ).every( (l: any) => l === names.length )) {\n // Transpose if needed\n const transposed: any[] = [];\n for (let i = 0; i < names.length; i++) {\n const col: any[] = [];\n for (let j = 0; j < colValues.length; j++) {\n col.push(colValues[j][i]);\n }\n transposed.push(col);\n }\n colValues = transposed;\n }\n\n super(colValues.length);\n\n colValues.forEach((col, index) => {\n if (col instanceof DataFrameColumn) {\n // If col is already a DataFrameColumn, just assign it\n this[index] = col as DataFrameColumn;\n } else {\n // Otherwise, create a new DataFrameColumn\n this[index] = new DataFrameColumn(names[index], col, rowNames, this) as DataFrameColumn;\n }\n });\n this.#names = names;\n if (rowNames && this[0] && rowNames.length !== this[0].length) {\n throw new Error(\"Row names length must match the number of rows in the DataFrame.\");\n }\n if (rowNames && rowNames.length > 0) {\n this.#rowNames = rowNames;\n }\n if (classes && classes.length !== this.length) {\n throw new Error(\"Classes length must match the number of columns in the DataFrame.\");\n }\n if (classes && classes.length > 0) {\n this.#classes = classes;\n }\n }\n\n get classes(): string[] | undefined {\n return this.#classes;\n }\n\n getColumnByName(name: string): DataFrameColumn | undefined {\n const idx = this.#names.indexOf(name);\n return idx >= 0 ? this[idx] : undefined;\n }\n getRowByIndex(index: number): DataFrameRow {\n if (this && this.length === 0) {\n console.warn(\"DataFrame is empty, cannot get row by index\", index);\n return new DataFrameRow(this.#names, [], undefined, this, index);\n }\n const result_vals: any[] = [];\n for (let col of this) {\n let v = col[index];\n result_vals.push(v);\n }\n return new DataFrameRow(this.#names, result_vals, this.#rowNames ? this.#rowNames[index] : undefined, this, index);\n }\n getRowByName(name: string): DataFrameRow | undefined {\n if (!this.#rowNames) return undefined;\n\n const index = this.#rowNames.indexOf(name);\n if (index === -1) return undefined;\n return this.getRowByIndex(index);\n }\n\n get types(): DataFrameColumnType[] {\n return this.map(col => col.type);\n }\n type(wh: string | number): DataFrameColumnType | undefined {\n if (typeof wh === 'number') {\n return this[wh]?.type;\n }\n else if (typeof wh === 'string') {\n const col = this.getColumnByName(wh);\n return col ? col.type : undefined;\n }\n return undefined;\n }\n\n // row(wh: string | number): DataFrameRow | undefined {\n\n row(wh: string | number): DataFrameRow | undefined {\n if (typeof wh === 'number') {\n return this.getRowByIndex(wh);\n }\n else if (typeof wh === 'string') {\n return this.getRowByName(wh);\n }\n return undefined;\n }\n // rows(...wh: (string | number)[]): DataFrame {\n rows(...wh: (string | number)[]): DataFrameRow[] {\n // Support: rows(\"Data\"), rows(\"Data\", \"Design\"), rows([\"Data\", \"Design\"]), rows()\n let\n selectors: (string | number)[],\n selectedRows: DataFrameRow[] = [],\n selectedRowNames: string[] | undefined = []\n ;\n\n // No arguments: return all rows\n if (wh.length === 0) {\n if (!this[0] || this.length === 0) {\n return [];\n }\n const numRows = this[0].length;\n selectedRows = Array.from({ length: numRows }, (_, i) => this.getRowByIndex(i));\n selectedRowNames = this.#rowNames;\n }\n\n else {\n // Single array argument\n if (wh.length === 1 && Array.isArray(wh[0])) {\n selectors = wh[0] as (string | number)[];\n }\n else {\n // Rest arguments\n selectors = wh;\n }\n\n selectedRows = selectors.map((item, i: number) => {\n let r = this.row(item);\n if (this.#rowNames && r) {\n selectedRowNames?.push(this.#rowNames[i]);\n }\n return r;\n }).filter((row): row is DataFrameRow => row !== undefined);\n }\n\n // Build columns from selected rows\n // const\n // colNames = this.#names,\n // columns = colNames.map((name, colIdx) => selectedRows.map(row => row[colIdx])),\n // colObjs = colNames.map((name, idx) => new DataFrameColumn(name, { values: columns[idx], type: this[idx].type }, selectedRowNames, this))\n // ;\n\n // return new DataFrame(\n // colNames,\n // colObjs,\n // selectedRowNames\n // );\n\n return selectedRows;\n }\n\n col(wh: string | number): DataFrameColumn | undefined {\n if (typeof wh === 'number') {\n return this[wh];\n } else if (typeof wh === 'string') {\n return this.getColumnByName(wh);\n }\n return undefined;\n }\n\n cols(...wh: (string | number)[]): DataFrame {\n // Support: cols(\"Data\"), cols(\"Data\", \"Design\"), cols([\"Data\", \"Design\"]), cols()\n let\n selectors: (string | number)[],\n selectedCols: DataFrameColumn[],\n selectedNames: string[] = []\n ;\n\n // No arguments: return all columns\n if (wh.length === 0) {\n selectedCols = this.slice();\n selectedNames = this.#names;\n }\n else {\n // Single array argument\n if (wh.length === 1 && Array.isArray(wh[0])) {\n selectors = wh[0] as (string | number)[];\n }\n // Rest arguments\n else {\n selectors = wh;\n }\n\n selectedCols = selectors.map((item) => this.col(item)).filter((col): col is DataFrameColumn => col !== undefined);\n selectedNames = selectedCols.map(col => col.name);\n }\n\n return new DataFrame(selectedNames, selectedCols, this.#rowNames);\n }\n\n subset(rows?: (string | number)[], cols?: (string | number)[]): DataFrame {\n const selectedCols: DataFrameColumn[] = (cols && cols.length > 0)\n ? this.cols(...cols)\n : this.slice();\n\n return new DataFrame(\n selectedCols.map(col => col.name),\n selectedCols.map(col => col.values),\n this.#rowNames\n );\n }\n\n get names(): string[] {\n return this.#names;\n }\n\n get rowNames(): string[] | undefined {\n return this.#rowNames;\n }\n\n get nrow(): number {\n return this[0] ? this[0].length : 0;\n }\n\n get ncol(): number {\n return this.length;\n }\n}\n","import { DataFrame, DataFrameRow } from \"../types/DataFrame\";\n\n/** Internal key union for Model.setByKey */\nexport type ModelKey =\n | \"updated\" | \"points\" | \"nodes\" | \"edges\"\n | \"dimensions\" | \"confidence\" | \"outlier\" | \"groups\" | \"trajectories\" | \"networks\" | \"pointsets\";\n\n/** Internal shape of the Model class — used by setByKey */\nexport interface ModelSpec {\n updated?: number;\n points: DataFrame;\n nodes: DataFrame;\n edges: DataFrame;\n dimensions: (string | number)[];\n confidence?: DataFrame;\n outlier?: DataFrame;\n groups?: DataFrame;\n trajectories?: DataFrame;\n networks?: DataFrame;\n pointsets?: DataFrame;\n}\n\nexport class Model implements ModelSpec {\n private _updated: number | undefined;\n private _points: DataFrame;\n private _nodes: DataFrame;\n private _edges: DataFrame;\n private _dimensions: (string | number)[];\n private _params: any;\n private _confidence: DataFrame | undefined;\n private _outlier: DataFrame | undefined;\n private _groups: DataFrame | undefined;\n private _trajectories: DataFrame | undefined;\n private _networks: DataFrame | undefined;\n private _pointsets: DataFrame | undefined;\n\n // Resolved column names — set by QEVisual.setModelData() via auto-detection\n // or caller-supplied overrides. Renderers read these instead of hardcoding.\n /** ID column in the points and edges frames */\n unit_id_col: string = 'id';\n /** ID column in the nodes frame */\n node_id_col: string = 'id';\n /** Group column in the points frame (null = no grouping) */\n group_col: string | null = null;\n /** Directed network mode — true renders arrowheads; false (default) undirected */\n directed: boolean = false;\n /** Group palette override (ModelData.palette); empty = qeviz default. */\n palette: string[] = [];\n\n constructor(o: Partial<ModelSpec> = {}) {\n this._points = o.points ?? new DataFrame();\n this._nodes = o.nodes ?? new DataFrame();\n this._edges = o.edges ?? new DataFrame();\n this._dimensions = o.dimensions ?? [];\n this._confidence = undefined;\n this._outlier = undefined;\n this._groups = undefined;\n }\n\n get updated(): number | undefined { return this._updated; }\n set updated(v: number | undefined) { this._updated = v; }\n\n get points(): DataFrame { return this._points; }\n set points(v: DataFrame) { this._points = v; }\n\n get nodes(): DataFrame { return this._nodes; }\n set nodes(v: DataFrame) { this._nodes = v; }\n\n get edges(): DataFrame { return this._edges; }\n set edges(v: DataFrame) { this._edges = v; }\n\n get confidence(): DataFrame | undefined { return this._confidence; }\n set confidence(v: DataFrame | undefined) { this._confidence = v; }\n\n get outlier(): DataFrame | undefined { return this._outlier; }\n set outlier(v: DataFrame | undefined) { this._outlier = v; }\n\n get groups(): DataFrame | undefined { return this._groups; }\n set groups(v: DataFrame | undefined) { this._groups = v; }\n\n get trajectories(): DataFrame | undefined { return this._trajectories; }\n set trajectories(v: DataFrame | undefined) { this._trajectories = v; }\n\n /** Explicit networks (one row per named layer, edge columns as in `edges`),\n * drawn by <qe-edges network=\"name\">. */\n get networks(): DataFrame | undefined { return this._networks; }\n set networks(v: DataFrame | undefined) { this._networks = v; }\n\n /** Explicit point sets (rows: set, id, x, y, group?, color?, shape?, label?),\n * drawn by <qe-points set=\"name\">. */\n get pointsets(): DataFrame | undefined { return this._pointsets; }\n set pointsets(v: DataFrame | undefined) { this._pointsets = v; }\n\n get dimensions(): (string | number)[] { return this._dimensions; }\n set dimensions(v: (string | number)[]) { this._dimensions = v; }\n\n get params(): any { return this._params; }\n set params(v: any) { this._params = v; }\n\n point(id: string): DataFrameRow | undefined {\n return this._points.row(id);\n }\n\n setByKey<K extends keyof ModelSpec>(key: K, value: ModelSpec[K]): void {\n (this as any)[key] = value;\n }\n}\n\nexport default Model;\n","export const DEBUG: boolean = (globalThis as any).__QEVIZ_DEBUG__ === true;\n\nexport function dbg(...args: any[]): void {\n if (DEBUG) console.log(...args);\n}\n","import { Label, Point } from \"../objects/PlottedObject\";\nimport { Edge } from \"../objects/Edges\";\nimport Model, { ModelKey } from \"../objects/Model\";\nimport { DataFrame } from \"../types/DataFrame.js\";\nimport { dbg } from \"../utils/debug.js\";\nimport { ModelData } from \"../types/ModelData.js\";\n\nexport const vizENA = {\n get: (n: number) => {\n const elements = [...(document as any).querySelectorAll(\"qe-graph\")];\n if (typeof n === \"number\" && n >= 0) {\n return elements[n];\n }\n return elements;\n },\n}\n\nexport class QEVisualElement extends HTMLElement {\n static tagName = 'qe-visual';\n\n static get observedAttributes() {\n return ['updated'];\n }\n\n static styles = `\n :host { display: block; width: 100%; }\n :host(.hidden) { display: none !important; }\n /* The output wrapper and the slotted graph fill the host so the plot\n stretches to its container instead of collapsing to intrinsic size. */\n div { display: block; width: 100%; height: 100%; }\n ::slotted(qe-graph) { display: block; width: 100%; height: 100%; }\n `;\n\n protected _outputElement!: HTMLElement;\n protected _isVisible: boolean = true;\n protected output: string = '';\n\n private _model: Model;\n /** Public accessor so ena-graph (and external code) can read the model. */\n get model(): Model {\n return this._model;\n }\n\n private _updated: string = '';\n get updated(): string {\n return this._updated;\n }\n set updated(val: string) {\n this._updated = val;\n this.setAttribute('updated', val);\n // Notify via CustomEvent instead of directly coupling to StateManager.\n // RQEVisualElement (and any other arbor consumer) listens for this and\n // forwards to globalStateManager.\n this.dispatchEvent(new CustomEvent('model-updated', {\n detail: this._model,\n bubbles: true,\n composed: true,\n }));\n }\n\n private _active_points: Point[] = [];\n private _points: Map<any, Point> = new Map();\n get points(): Map<any, Point> {\n return this._points;\n }\n set points(pts: Map<any, Point> | Point[]) {\n this._points.clear();\n if (pts instanceof Map) {\n this._points = pts;\n } else if (Array.isArray(pts)) {\n pts.forEach(p => this._points.set(p.ID, p));\n }\n }\n get active_points(): Point[] {\n return Array.from(this._active_points.values());\n }\n\n private _edges: Map<any, Edge> = new Map();\n get edges(): Map<any, Edge> {\n return this._edges;\n }\n set edges(edges: Map<any, Edge> | Edge[]) {\n this._edges.clear();\n if (edges instanceof Map) {\n this._edges = edges;\n } else if (Array.isArray(edges)) {\n this._edges = new Map();\n edges.forEach(e => this._edges.set(e.ID, e));\n }\n }\n\n private _labels: Map<any, Label> = new Map();\n get labels(): Map<any, Label> {\n return this._labels;\n }\n\n constructor() {\n super();\n\n this._model = new Model();\n\n const shadow = this.attachShadow({ mode: 'open' });\n\n const style = document.createElement('style');\n style.textContent = QEVisualElement.styles;\n shadow.appendChild(style);\n\n this._outputElement = document.createElement('div');\n shadow.appendChild(this._outputElement);\n }\n\n connectedCallback(): void {\n dbg(\"QEVisualElement connected\");\n this.render();\n }\n\n /**\n * Accept pre-fetched ENA model data and update the visualization.\n * Call this directly when data is available from any source —\n * rENA R package, Python package, or static JSON.\n */\n setModelData(data: ModelData): void {\n const frameKeys: ModelKey[] = ['nodes', 'edges', 'points', 'groups', 'confidence', 'outlier', 'trajectories', 'networks', 'pointsets'] as ModelKey[];\n\n // ── Step 1: ingest all frames into DataFrames ──────────────────────────\n frameKeys.forEach((name) => {\n const raw = (data as any)[name];\n if (!raw?.data?.length) return;\n\n const\n rows: any[] = raw.data,\n types: any = raw.types || {},\n colNames: string[] = Object.keys(rows[0]),\n colValues: any[][] = rows.map((v: any) => Object.values(v)),\n classes: string[] = colNames.map(col => (types[col] ?? 'character') as string);\n\n // Determine which column is the row-identifier (stored as DataFrame.rowName).\n // The caller can supply overrides; otherwise we auto-detect.\n let idCol: string | undefined;\n if (name === 'networks') {\n idCol = 'name'; // one row per explicit network layer\n } else if (name === 'pointsets') {\n idCol = 'id'; // point id within its set\n } else if (name === 'nodes') {\n idCol = data.node_id_col\n ?? colNames.find(c => (types[c] ?? 'character') === 'character');\n } else if (name === 'edges' || name === 'points' || name === 'trajectories') {\n idCol = data.id_col\n ?? colNames.find(c => (types[c] ?? 'character') === 'character');\n } else {\n // groups / confidence / outlier: first character column is the group id\n idCol = data.group_col\n ?? colNames.find(c => (types[c] ?? 'character') === 'character');\n }\n\n const removalCol = idCol ? colNames.indexOf(idCol) : 0;\n const rowNames = colValues.map((v: any) => String(v[removalCol]));\n this._model.setByKey(name, new DataFrame(colNames, colValues, rowNames, classes));\n });\n\n // ── Step 2: ingest scalar fields ─────────────────────────────────────\n if (data.updated !== undefined) this._model.setByKey('updated', data.updated);\n if (data.directed !== undefined) this._model.directed = data.directed;\n if (Array.isArray((data as any).palette)) this._model.palette = (data as any).palette.map(String);\n\n // ── Step 3: resolve and store column names on the model ───────────────\n // These are read by QEGraph at render time instead of hardcoded strings.\n\n // node id col — first character column in nodes, or override\n const nodesDF = this._model.nodes;\n this._model.node_id_col = data.node_id_col\n ?? nodesDF?.names?.find(n => nodesDF.col(n)?.type === 'character')\n ?? 'id';\n\n // unit id col — first character column in points, or override\n const pointsDF = this._model.points;\n this._model.unit_id_col = data.id_col\n ?? pointsDF?.names?.find(n => pointsDF.col(n)?.type === 'character')\n ?? 'id';\n\n // group col — caller override, or first non-unit-id character col in points\n const unitId = this._model.unit_id_col;\n this._model.group_col = data.group_col\n ?? pointsDF?.names?.find(n => n !== unitId && pointsDF.col(n)?.type === 'character')\n ?? null;\n\n // ── Step 4: auto-detect dimension (x/y) columns from nodes ───────────\n // Numeric columns that aren't the node id. Caller can override via\n // x_col / y_col but those are passed in ModelData for the renderer to use\n // directly; here we just set model.dimensions as the default.\n if (nodesDF?.names?.length) {\n const nodeId = this._model.node_id_col;\n const xColOvr = data.x_col;\n const yColOvr = data.y_col;\n if (xColOvr && yColOvr) {\n this._model.dimensions = [xColOvr, yColOvr];\n } else {\n const numCols = nodesDF.names.filter(n => {\n if (n === nodeId) return false;\n const col = nodesDF.col(n);\n return col && col.type !== 'character' && col.type !== 'logical';\n });\n if (numCols.length >= 2) {\n this._model.dimensions = [xColOvr ?? numCols[0], yColOvr ?? numCols[1]];\n }\n }\n }\n\n this.updated = this._model.updated !== undefined ? String(this._model.updated) : String(Date.now());\n dbg(\"Model updated via setModelData:\", this.updated);\n this.render();\n }\n\n /**\n * Base implementation is a no-op. Subclasses (e.g. RQEVisualElement) override\n * this to fetch data from a backend and call setModelData().\n */\n async calculate(): Promise<void> {}\n\n render(): void {\n if (!this._isVisible) {\n this.classList.add('hidden');\n } else {\n this.classList.remove('hidden');\n }\n\n if (this._model?.updated !== undefined && this._model.updated !== null) {\n this._outputElement.innerHTML = `${this.output}<slot></slot>`;\n } else {\n this._outputElement.innerHTML = \"Define the model on the left.\";\n }\n }\n}\ncustomElements.define(QEVisualElement.tagName, QEVisualElement);\n\nexport default QEVisualElement;\n","export class Color {\n base: string;\n\n constructor(base: Color | string) {\n this.base = typeof base === \"string\" ? base : base.base;\n\n // Return a Proxy to allow 0-based indexing for r, g, b\n return new Proxy(this, {\n get(target, prop) {\n if (typeof prop === \"string\" && /^[0-2]$/.test(prop)) {\n const { r, g, b } = Color.parseColor(target.base);\n return [r, g, b][Number(prop)];\n }\n return (target as any)[prop];\n }\n });\n }\n\n toString(): string {\n return this.base;\n }\n\n setBase(base: string): void {\n this.base = base;\n }\n\n static parseColor(color: string): { r: number; g: number; b: number } {\n const c = String(color).trim();\n // \"#RRGGBB\" (fast path), \"#RGB\", \"#RRGGBBAA\" (alpha dropped)\n if (/^#[0-9a-f]{6}([0-9a-f]{2})?$/i.test(c)) {\n const n = parseInt(c.slice(1, 7), 16);\n return { r: (n >> 16) & 255, g: (n >> 8) & 255, b: n & 255 };\n }\n if (/^#[0-9a-f]{3}$/i.test(c)) {\n const [r, g, b] = [1, 2, 3].map(i => parseInt(c[i] + c[i], 16));\n return { r, g, b };\n }\n const m = c.match(/^rgba?\\(\\s*([\\d.]+)[,\\s]+([\\d.]+)[,\\s]+([\\d.]+)/i);\n if (m) return { r: Math.round(+m[1]), g: Math.round(+m[2]), b: Math.round(+m[3]) };\n // Anything else CSS understands (\"red\", \"steelblue\", hsl(), …), as the\n // adapters pass colour names through: let the browser resolve it.\n const resolved = Color.resolveCss(c);\n if (resolved) return Color.parseColor(resolved);\n throw new Error(`Unsupported color format: ${color}`);\n }\n\n private static _ctx: CanvasRenderingContext2D | null | undefined;\n private static _cssCache = new Map<string, string | null>();\n\n /** A CSS colour as \"#rrggbb\" / \"rgba(...)\", or null if it isn't one. */\n static resolveCss(color: string): string | null {\n if (Color._cssCache.has(color)) return Color._cssCache.get(color)!;\n if (Color._ctx === undefined) {\n Color._ctx = typeof document !== 'undefined'\n ? document.createElement('canvas').getContext('2d') : null;\n }\n let out: string | null = null;\n const ctx = Color._ctx;\n if (ctx) {\n // An invalid value leaves fillStyle unchanged, so test against two sentinels.\n ctx.fillStyle = '#000000'; ctx.fillStyle = color; const a = ctx.fillStyle;\n ctx.fillStyle = '#ffffff'; ctx.fillStyle = color; const b = ctx.fillStyle;\n if (a === b) out = String(a);\n }\n Color._cssCache.set(color, out);\n return out;\n }\n\n static rgb(r: number, g: number, b: number): string {\n return `rgb(${r}, ${g}, ${b})`;\n }\n}\n\nexport class WeightedColor extends Color {\n weight: number;\n /** Optional alpha; defaults to `weight` (saturation and alpha together). */\n alpha: number | undefined;\n\n constructor(base: Color | string, weight: number, alpha?: number) {\n super(base);\n this.weight = weight;\n this.alpha = alpha;\n }\n\n // Parse hex → HSV (h in [0, 360), s/v in [0, 1]).\n static toHSV(hex: string): { h: number; s: number; v: number } {\n const { r, g, b } = Color.parseColor(hex);\n const rn = r / 255, gn = g / 255, bn = b / 255;\n const max = Math.max(rn, gn, bn), min = Math.min(rn, gn, bn);\n const d = max - min;\n const v = max;\n const s = max === 0 ? 0 : d / max;\n let h = 0;\n if (d > 0) {\n switch (max) {\n case rn: h = ((gn - bn) / d + (gn < bn ? 6 : 0)) / 6; break;\n case gn: h = ((bn - rn) / d + 2) / 6; break;\n default: h = ((rn - gn) / d + 4) / 6;\n }\n }\n return { h: h * 360, s, v };\n }\n\n // Convert HSV + alpha → rgba() CSS string.\n static hsvToRgba(h: number, s: number, v: number, a: number): string {\n const c = v * s;\n const x = c * (1 - Math.abs((h / 60) % 2 - 1));\n const m = v - c;\n let r = 0, g = 0, b = 0;\n if (h < 60) { r = c; g = x; b = 0; }\n else if (h < 120) { r = x; g = c; b = 0; }\n else if (h < 180) { r = 0; g = c; b = x; }\n else if (h < 240) { r = 0; g = x; b = c; }\n else if (h < 300) { r = x; g = 0; b = c; }\n else { r = c; g = 0; b = x; }\n return `rgba(${Math.round((r + m) * 255)},${Math.round((g + m) * 255)},${Math.round((b + m) * 255)},${a.toFixed(4)})`;\n }\n\n // Returns rgba(...) matching rENA's edge-color convention (ena.plot.network):\n // • hue and value (brightness) are preserved from the base color\n // • HSV saturation is set to |weight| directly (0 = grey, 1 = fully vivid)\n // • alpha is also set to |weight|\n //\n // rENA converts the input color to HSV, replaces the S component with the\n // normalized edge weight, and additionally sets plotly element opacity to the\n // same value. Working in HSV (not HSL) is essential: palette colors like\n // #EE6677 have HSL lightness ≈ 67%, so 100% HSL saturation still looks\n // washed-out, whereas HSV value ≈ 0.93 gives the expected vivid output.\n toString(): string {\n const { h, v } = WeightedColor.toHSV(this.base);\n const w = Math.min(1, Math.abs(this.weight));\n const a = this.alpha === undefined ? w : Math.min(1, Math.max(0, this.alpha));\n return WeightedColor.hsvToRgba(h, w, v, a);\n }\n}","export class Transform {\n private _values: number[] = [1, 0, 0, 1, 0, 0];\n private _keys: string[] = [\"a\", \"b\", \"c\", \"d\", \"e\", \"f\"];\n\n get values() {\n return this._values;\n }\n set values(vals: number[]) {\n if (vals && vals.length === 6) {\n this._values = vals;\n }\n }\n get keys() {\n return this._keys;\n }\n set keys(vals: string[]) {\n if (vals && vals.length === 6) {\n this._keys = vals;\n }\n }\n\n constructor(vals: number[] | null = null) {\n if (vals) {\n this.values = vals;\n }\n }\n\n toString() {\n let matrix_str = this.keys.map((k, i) => this.values[i]).join(\" \")\n ;\n\n return `matrix(${matrix_str})`;\n }\n\n toMatrix() {\n return Object.fromEntries(this._keys.map((k, i) => [k, this._values[i]]));\n }\n\n toArray() {\n return this._values;\n }\n\n set(wh: string, val: number) {\n if (val !== 0.0075 && val !== 0) {\n this._values[this._keys.findIndex(k => k === wh)] = val;\n }\n }\n get(wh: string) {\n return this._values[this._keys.findIndex(k => k === wh)];\n }\n\n scale(a: number, d: number = a) {\n this.a = a;\n this.d = d;\n }\n\n zoom(z: number) {\n this.a = z;\n this.d = z;\n }\n\n pan(x: number, y: number) {\n this.e = this.e + x;\n this.f = this.f + y;\n }\n\n set a(x: number) { this.set(\"a\", x); }\n set b(x: number) { this.set(\"b\", x); }\n set c(x: number) { this.set(\"c\", x); }\n set d(x: number) { this.set(\"d\", x); }\n set e(x: number) { this.set(\"e\", x); }\n set f(x: number) { this.set(\"f\", x); }\n\n get a() { return this.get(\"a\"); }\n get b() { return this.get(\"b\"); }\n get c() { return this.get(\"c\"); }\n get d() { return this.get(\"d\"); }\n get e() { return this.get(\"e\"); }\n get f() { return this.get(\"f\"); }\n}","// const __ = {\n// matrix_string: (matrix) => {\n// let matrix_str = ['a','b','c','d','e','f'].map( l => matrix[l] ).join(\" \")\n// return `matrix(${matrix_str})`\n// },\n// isArray: (obj) => {\n// return typeof Array.isArray === \"function\" ? Array.isArray(obj) :\n// (obj && typeof obj === \"object\" && obj.constructor.name === \"Array\");\n// },\n// recurse: (obj, opt, iterator) => {\n// function recurse(obj, i, parent = null) {\n// if (__.isArray(obj)) {\n// for (const [i, o] of obj.entries()) {\n// recurse(o, i, parent);\n// }\n// } else {\n// iterator(obj, i, parent);\n// if (obj && __.isArray(obj[opt.children])) {\n// for (const [i, o] of obj[opt.children].entries()) {\n// recurse(o, i, obj);\n// }\n// }\n// }\n// }\n\n// recurse(obj);\n// },\n// geom: {\n// point: {\n// // source https://github.com/HarryStevens/geometric/\n// translate: (point, angle, distance) => {\n// const r = __.geom.angle.torad(angle);\n// return [point[0] + distance * Math.cos(r), point[1] + distance * Math.sin(r)];\n// },\n\n// // source https://github.com/HarryStevens/geometric/\n// rotate: (point, angle, origin) => {\n\n// // See: https://en.wikipedia.org/wiki/Cartesian_coordinate_system#Rotation\n// function rotate(point, angle){\n// return [\n// (point[0] * Math.cos(angle)) - point[1] * Math.sin(angle),\n// (point[0] * Math.sin(angle)) + point[1] * Math.cos(angle)\n// ];\n// }\n\n// const r = __.geom.angle.torad(angle);\n\n// if (!origin || (origin[0] === 0 && origin[1] === 0)){\n// return rotate(point, r);\n// }\n// else {\n// // See: https://math.stackexchange.com/questions/1964905/rotation-around-non-zero-point\n// const p0 = point.map((c, i) => c - origin[i]);\n// const rotated = rotate(p0, r);\n// return rotated.map((c, i) => c + origin[i]);\n// }\n// }\n// },\n// line: {\n// slope: (p1, p2) => {\n// let\n// m = (p2[1] - p1[1])/(p2[0] - p1[0]),\n// n = p1[0] - m * p1[0]\n// ;\n// return m;\n// },\n// intercept: (p1, p2) => {\n// let\n// m = __.geom.line.slope(p1, p2),\n// n = p1[1] - m * p1[0]\n// ;\n// return n;\n// },\n// slope_intercept: (p1, p2) => {\n// return {\n// slope: __.geom.line.slope(p1, p2),\n// intercept: __.geom.line.intercept(p1, p2)\n// };\n// },\n// midpoint: (p1, p2, w = 0.5) => {\n// if(Array.isArray(p1[0])) {\n// p2 = (p1[1]);\n// p1 = (p1[0]);\n// }\n// return [0, 1].map( i => (parseFloat(p1[i]) + parseFloat(p2[i])) * w );\n// },\n// length: (p1, p2) => {\n// if(Array.isArray(p1[0])) {\n// p2 = p1[1];\n// p1 = p1[0];\n// }\n// return Math.sqrt([0, 1].map( i => Math.pow(p2[i] - p1[i], 2) ).reduce( (a,b) => a + b, 0))\n// },\n// interpolate: (line) => {\n// // source https://github.com/HarryStevens/geometric/\n// return t =>\n// t === 0 ?\n// line[0] :\n// t === 1 ?\n// line[1] :\n// __.geom.point.translate(line[0], __.geom.angle.line(line), __.geom.line.length(line) * t)\n// ;\n// },\n// point_along: (line, distance = 0) => {\n// let\n// len = __.geom.line.length(line),\n// ratio = distance / len,\n// Xt = ((1 - ratio) * line[0][0] + (ratio * line[1][0])),\n// Yt = ((1 - ratio) * line[0][1] + (ratio * line[1][1]))\n// ;\n// return [Xt, Yt];\n// },\n// rotate: (line, by = [0, 0]) => {\n// let\n// translated = [line[1][0] - by[0], line[1][1] - by[1]],\n// rotated = [-(translated[1]), translated[0]],\n// rotated_reflection = [-(rotated[0]), -(rotated[1])],\n// untranslated = [rotated[0] + by[0], rotated[1] + by[1]],\n// untranslated2 = [rotated_reflection[0] + by[0], rotated_reflection[1] + by[1]]\n// ;\n// return [untranslated, untranslated2];\n// },\n// rotate2: (line, fixed, angle = 90) => {\n// let\n// line_si = __.geom.line.slope_intercept(line[0], line[1]),\n// P = [0, line_si.intercept],\n// Q = [1, line_si.slope + line_si.intercept]\n// ;\n// line = [P, Q];\n\n// let\n// xx = [line[0][0], line[1][0]],\n// yy = [line[0][1], line[1][1]],\n// x_fixed = fixed[0],\n// y_fixed = fixed[1],\n// angle_rad = -2 * Math.PI * angle/360,\n// xx_new = xx.map( (x, i) => (x - x_fixed) * Math.cos(angle_rad) - (yy[i] - y_fixed) * Math.sin(angle_rad) + x_fixed ),\n// yy_new = yy.map( (y, i) => (xx[i] - x_fixed) * Math.sin(angle_rad) - (y - y_fixed) * Math.cos(angle_rad) + y_fixed ),\n// object_new = [\n// [xx_new[0], yy_new[0]],\n// [xx_new[1], yy_new[1]]\n// ]\n// ;\n\n// return(object_new);\n// },\n// intersection: (lineA, lineB) => {\n// const\n// [[x1, y1], [x2, y2]] = lineA,\n// [[x3, y3], [x4, y4]] = lineB,\n// D = ( (x1 - x2) * (y3 - y4) ) - ( (y1 - y2) * (x3 - x4) ),\n// num1 = ( ((x1 * y2) - (y1 * x2)) * (x3 - x4) ) -\n// ( (x1 - x2) * ((x3 * y4) - (y3 * x4)) ),\n// num2 = ( ((x1 * y2) - (y1 * x2)) * (y3 - y4) ) -\n// ( (y1 - y2) * ((x3 * y4) - (y3 * x4)) )\n// ;\n// return [num1 / D, num2 / D];\n// },\n// intersect_circle(line, circle_xy, circle_r) {\n// let { slope: m, intercept: n } = __.geom.line.slope_intercept(line[0], line[1]);\n// let\n// a = 1 + Math.pow(m,2),\n// b = 2 * m * n - 2 * circle_xy[1] * m - 2 * circle_xy[0],\n// c = Math.pow(circle_xy[0], 2) + Math.pow(n, 2) + Math.pow(circle_xy[1], 2) - 2 * circle_xy[1] * n - Math.pow(circle_r, 2),\n// int\n// ;\n// if (Math.sqrt( Math.pow(b, 2) - (4 * a * c)) >= 0) {\n// let\n// x1 = (-b + Math.sqrt( Math.pow(b, 2) - (4 * a * c)))/(2 * a),\n// x2 = (-b - Math.sqrt( Math.pow(b, 2) - (4 * a * c)))/(2 * a),\n// y1 = m * x1 + n,\n// y2 = m * x2 + n\n// ;\n// int = [[x1, y1], [x2, y2]];\n// }\n// else {\n// int = \"The line and the circumference do not intersect\"\n// }\n// return(int)\n// }\n// },\n// angle: {\n// torad: (a) => a / 180 * Math.PI,\n// todeg: (a) => a * 180 / Math.PI,\n// line: (line) => {\n// // source https://github.com/HarryStevens/geometric/\n// return __.geom.angle.todeg(\n// Math.atan2(line[1][1] - line[0][1], line[1][0] - line[0][0])\n// );\n// }\n// }\n// },\n// object: {\n// proxy(obj, handler, deep = false) {\n// if(deep === false) {\n// return new Proxy(obj, handler);\n// }\n// else {\n// if (typeof obj !== 'object' || obj === null) {\n// return obj;\n// }\n\n// for (const key in obj) {\n// if (obj.hasOwnProperty(key)) {\n// obj[key] = __.object.proxy(obj[key], handler, deep);\n// }\n// }\n\n// return new Proxy(obj, handler);\n// }\n// },\n// handler: {\n// set: function(target, property, value) {\n// target[property] = value;\n// window.dispatchEvent(__.event(\"settingUpdate\", this, { target, property, value }))\n\n// return true;\n// },\n// get: function(target, property) {\n// return target[property];\n// }\n// },\n// get: (obj, key) => {\n// const parts = key.split(\".\");\n// let current = obj;\n// for (const part of parts) {\n// if (current && typeof current === \"object\" && current.hasOwnProperty(part)) {\n// current = current[part];\n// }\n// else {\n// return undefined;\n// }\n// }\n// return current;\n// },\n// set: (obj, key, value) => {\n// const parts = key.split(\".\");\n// let current = obj,\n// i\n// ;\n\n// for (i = 0; i < parts.length - 1; i++) {\n// const part = parts[i];\n// if (current && typeof current === \"object\") {\n// if (!current.hasOwnProperty(part)) {\n// current[part] = {};\n// }\n// current = current[part];\n// }\n// else {\n// return false;\n// }\n// }\n\n// if (current && typeof current === \"object\") {\n// current[parts[i]] = value;\n// return true;\n// }\n// else {\n// return false;\n// }\n// }\n// },\n// array: {\n// unique: (x) => [...new Set(x)],\n// divide: (a, b) => {\n// let ret;\n\n// if(Array.isArray(a)) {\n// if(Array.isArray(b)) {\n// if(a.length === b.length) {\n// ret = a.map( (a_,i) => a_ / b[i] )\n// }\n// else {\n// console.error(\"If both are arrays, they must be equal length.\")\n// }\n// }\n// else {\n// ret = a.map( a_ => a_ / b );\n// }\n// }\n// else {\n// ret = a / b;\n// }\n\n// return(ret);\n// },\n// multiply: (a, b) => {\n// let ret;\n\n// if(Array.isArray(a)) {\n// if(Array.isArray(b)) {\n// if(a.length === b.length) {\n// ret = a.map( (a_,i) => a_ * b[i] )\n// }\n// else {\n// console.error(\"If both are arrays, they must be equal length.\")\n// }\n// }\n// else {\n// ret = a.map( a_ => a_ * b );\n// }\n// }\n// else {\n// ret = a * b;\n// }\n\n// return(ret);\n// },\n// subtract: (a, b) => {\n// let ret;\n\n// if(Array.isArray(a)) {\n// if(Array.isArray(b)) {\n// if(a.length === b.length) {\n// ret = a.map( (a_,i) => a_ - b[i] )\n// }\n// else {\n// console.error(\"If both are arrays, they must be equal length.\")\n// }\n// }\n// else {\n// ret = a.map( a_ => a_ - b );\n// }\n// }\n// else {\n// ret = a - b;\n// }\n\n// return(ret);\n// },\n// shift: () => {\n// return Array.from(a, (b, i) => a[i + 1]);\n// }\n// },\n// math: {\n// sum: (a) => a.reduce( (a,b) => a + b, 0),\n// mean: (a) => __.math.sum(a) / a.length,\n// round: (a, b) => {\n// const factor = Math.pow(10, b);\n// return Math.round(a * factor) / factor;\n// }\n// },\n// event: (nm, elm, data) => {\n// return new CustomEvent(nm, {\n// bubbles: true,\n// cancelable: true,\n// detail: {\n// element: elm,\n// data: data || (elm ? elm.__data__ : undefined)\n// }\n// })\n// },\n// hash: {\n// parts: () => location.hash.replace(/#/,'').split(/\\//).filter(a => a).map(a => a.split(/:/)),\n// exists: (x) => __.hash.parts().flat().findIndex(a => a === x) >= 0\n// },\n// url: {\n// parse: (l = window.location) => {\n// },\n// query: {\n// parse: (l = window.location.search) =>\n// Object.fromEntries(l.replace(/^\\?/,'').split(/&/).map( i => i.split(/=/) ))\n// ,\n// keys: (l = window.location.search) =>\n// l.replace(/^\\?/,'').split(/&/).map( i => i.split(/=/)[0] )\n// ,\n// has: (k, l = window.location.search) =>\n// __.url.query.keys(l).findIndex(i => i == k) >= 0\n// }\n// }\n// };\n\nexport namespace Tools {\n export namespace Matrix {\n export function matrixString(matrix: Record<string, number>): string {\n const matrixStr = ['a', 'b', 'c', 'd', 'e', 'f'].map(l => matrix[l]).join(' ');\n return `matrix(${matrixStr})`;\n }\n }\n\n export namespace Geometry {\n export namespace Point {\n export function translate(point: [number, number], angle: number, distance: number): [number, number] {\n const r = Angle.toRad(angle);\n return [point[0] + distance * Math.cos(r), point[1] + distance * Math.sin(r)];\n }\n\n export function rotate(point: [number, number], angle: number, origin?: [number, number]): [number, number] {\n const r = Angle.toRad(angle);\n\n function rotatePoint(p: [number, number], a: number): [number, number] {\n return [\n p[0] * Math.cos(a) - p[1] * Math.sin(a),\n p[0] * Math.sin(a) + p[1] * Math.cos(a),\n ];\n }\n\n if (!origin || (origin[0] === 0 && origin[1] === 0)) {\n return rotatePoint(point, r);\n } else {\n const p0 = point.map((c, i) => c - origin[i]) as [number, number];\n const rotated = rotatePoint(p0, r);\n return rotated.map((c, i) => c + origin[i]) as [number, number];\n }\n }\n }\n\n export namespace Line {\n export function slope(p1: [number, number], p2: [number, number]): number {\n return (p2[1] - p1[1]) / (p2[0] - p1[0]);\n }\n export function intercept(p1: [number, number], p2: [number, number]): number {\n const m = slope(p1, p2);\n return p1[1] - m * p1[0];\n }\n export function slopeIntercept(p1: [number, number], p2: [number, number]): { slope: number; intercept: number } {\n return {\n slope: slope(p1, p2),\n intercept: intercept(p1, p2),\n };\n }\n export function point_along(line: [[number, number], [number, number]], distance: number = 0): [number, number] {\n const ratio = distance;\n const Xt = ((1 - ratio) * line[0][0] + (ratio * line[1][0]));\n const Yt = ((1 - ratio) * line[0][1] + (ratio * line[1][1]));\n return [Xt, Yt];\n }\n export function midpoint(p1: [number, number], p2: [number, number], w = 0.5): [number, number] {\n if (Array.isArray(p1[0])) {\n p2 = (p1[1] as any);\n p1 = (p1[0] as any);\n }\n\n return [0, 1].map(i => (parseFloat(p1[i] as any) + parseFloat(p2[i] as any)) * w) as [number, number];\n }\n export function length(\n p1: [number, number] | [[number, number], [number, number]],\n p2?: [number, number]\n ): number {\n if (Array.isArray((p1 as any)[0])) {\n p2 = (p1 as [[number, number], [number, number]])[1];\n p1 = (p1 as [[number, number], [number, number]])[0];\n }\n return Math.sqrt(\n [0, 1].map(i => Math.pow((p2 as [number, number])[i] - (p1 as [number, number])[i], 2)).reduce((a, b) => a + b, 0)\n );\n }\n export function rotate(\n line: [[number, number], [number, number]],\n by: [number, number] = [0, 0]\n ): [[number, number], [number, number]] {\n const translated: [number, number] = [\n line[1][0] - by[0],\n line[1][1] - by[1]\n ];\n const rotated: [number, number] = [\n -translated[1],\n translated[0]\n ];\n const rotated_reflection: [number, number] = [\n -rotated[0],\n -rotated[1]\n ];\n const untranslated: [number, number] = [\n rotated[0] + by[0],\n rotated[1] + by[1]\n ];\n const untranslated2: [number, number] = [\n rotated_reflection[0] + by[0],\n rotated_reflection[1] + by[1]\n ];\n return [untranslated, untranslated2];\n }\n export function rotate2(\n line: [[number, number], [number, number]],\n fixed: [number, number],\n angle: number = 90\n ): [[number, number], [number, number]] {\n // Calculate slope and intercept\n const m = Tools.Geometry.Line.slope(line[0], line[1]);\n const n = Tools.Geometry.Line.intercept(line[0], line[1]);\n const P: [number, number] = [0, n];\n const Q: [number, number] = [1, m + n];\n line = [P, Q];\n\n const xx = [line[0][0], line[1][0]];\n const yy = [line[0][1], line[1][1]];\n const x_fixed = fixed[0];\n const y_fixed = fixed[1];\n const angle_rad = -2 * Math.PI * angle / 360;\n const xx_new = xx.map((x, i) =>\n (x - x_fixed) * Math.cos(angle_rad) - (yy[i] - y_fixed) * Math.sin(angle_rad) + x_fixed\n );\n const yy_new = yy.map((y, i) =>\n (xx[i] - x_fixed) * Math.sin(angle_rad) - (y - y_fixed) * Math.cos(angle_rad) + y_fixed\n );\n const object_new: [[number, number], [number, number]] = [\n [xx_new[0], yy_new[0]],\n [xx_new[1], yy_new[1]]\n ];\n\n return object_new;\n }\n export function intersection(\n lineA: [[number, number], [number, number]],\n lineB: [[number, number], [number, number]]\n ): [number, number] {\n const\n [[x1, y1], [x2, y2]] = lineA,\n [[x3, y3], [x4, y4]] = lineB,\n D = ((x1 - x2) * (y3 - y4)) - ((y1 - y2) * (x3 - x4)),\n num1 = (((x1 * y2) - (y1 * x2)) * (x3 - x4)) -\n ((x1 - x2) * ((x3 * y4) - (y3 * x4))),\n num2 = (((x1 * y2) - (y1 * x2)) * (y3 - y4)) -\n ((y1 - y2) * ((x3 * y4) - (y3 * x4)));\n return [num1 / D, num2 / D];\n }\n export function intersect_circle(line: [[number, number], [number, number]], circle_xy: [number, number], circle_r: number): [[number, number], [number, number]] {\n let { slope: m, intercept: n } = Tools.Geometry.Line.slopeIntercept(line[0], line[1]);\n let\n a = 1 + Math.pow(m, 2),\n b = 2 * m * n - 2 * circle_xy[1] * m - 2 * circle_xy[0],\n c = Math.pow(circle_xy[0], 2) + Math.pow(n, 2) + Math.pow(circle_xy[1], 2) - 2 * circle_xy[1] * n - Math.pow(circle_r, 2),\n int: [[number, number], [number, number]] = [[Infinity, Infinity], [Infinity, Infinity]]\n ;\n\n if (Math.sqrt(Math.pow(b, 2) - (4 * a * c)) >= 0) {\n let\n x1 = (-b + Math.sqrt(Math.pow(b, 2) - (4 * a * c))) / (2 * a),\n x2 = (-b - Math.sqrt(Math.pow(b, 2) - (4 * a * c))) / (2 * a),\n y1 = m * x1 + n,\n y2 = m * x2 + n\n ;\n int = [[x1, y1], [x2, y2]];\n }\n else {\n console.error(\"The line and the circumference do not intersect\");\n }\n\n return (int)\n }\n export function interpolate(line: [[number, number], [number, number]]): (t: number) => [number, number] {\n // source https://github.com/HarryStevens/geometric/\n return t =>\n t === 0 ?\n line[0] :\n t === 1 ?\n line[1] :\n Tools.Geometry.Point.translate(line[0], Tools.Geometry.Angle.line(line), Tools.Geometry.Line.length(line) * t)\n ;\n }\n }\n\n export namespace Angle {\n export function toRad(angle: number): number {\n return (angle / 180) * Math.PI;\n }\n\n export function toDeg(angle: number): number {\n return (angle * 180) / Math.PI;\n }\n // source https://github.com/HarryStevens/geometric/\n export function line(line: [[number, number], [number, number]]): number {\n if (line.length !== 2 || !Array.isArray(line[0]) || !Array.isArray(line[1]) || line[0].length !== 2 || line[1].length !== 2) {\n throw new Error('Invalid line format. Expected [[x1, y1], [x2, y2]].');\n }\n //console.log(\"line: \", line)\n return Tools.Geometry.Angle.toDeg(\n Math.atan2(line[1][1] - line[0][1], line[1][0] - line[0][0])\n );\n }\n }\n }\n\n export namespace ArrayTools {\n export function unique<T>(arr: T[]): T[] {\n return [...new Set(arr)];\n }\n\n export function divide(a: number | number[], b: number | number[]): number | number[] {\n if (Array.isArray(a)) {\n if (Array.isArray(b)) {\n if (a.length !== b.length) throw new Error('Arrays must be of equal length');\n return a.map((val, i) => val / b[i]);\n }\n return a.map(val => val / (b as number));\n }\n return (a as number) / (b as number);\n }\n\n export function isArray(obj: any): boolean {\n return typeof Array.isArray === \"function\" ? Array.isArray(obj) :\n (obj && typeof obj === \"object\" && obj.constructor.name === \"Array\");\n }\n }\n\n export namespace Mathematics {\n export function sum(arr: number[]): number {\n return arr.reduce((a, b) => a + b, 0);\n }\n\n export function mean(arr: number[]): number {\n return sum(arr) / arr.length;\n }\n\n export function round(value: number, decimals: number): number {\n const factor = Math.pow(10, decimals);\n return Math.round(value * factor) / factor;\n }\n }\n\n export namespace Events {\n export function createEvent(name: string, element?: HTMLElement, data?: any): CustomEvent {\n return new CustomEvent(name, {\n bubbles: true,\n cancelable: true,\n detail: {\n element,\n data: data || (element ? (element as any).__data__ : undefined),\n },\n });\n }\n }\n\n export namespace Hash {\n export function parts(): string[][] {\n return location.hash\n .replace(/#/, '')\n .split(/\\//)\n .filter(a => a)\n .map(a => a.split(/:/));\n }\n\n export function exists(key: string): boolean {\n return parts().flat().findIndex(a => a === key) >= 0;\n }\n }\n\n\n export namespace Objects {\n export function proxy<T extends object>(obj: T, handler: ProxyHandler<any>, deep = false): T {\n if (!deep) {\n return new Proxy(obj, handler);\n } else {\n if (typeof obj !== 'object' || obj === null) {\n return obj;\n }\n\n for (const key in obj) {\n if (Object.prototype.hasOwnProperty.call(obj, key)) {\n (obj as any)[key] = proxy((obj as any)[key], handler, deep);\n }\n }\n\n return new Proxy(obj, handler);\n }\n }\n\n export const handler: ProxyHandler<any> = {\n set(target, property, value) {\n target[property] = value;\n window.dispatchEvent(\n Tools.Events.createEvent(\"settingUpdate\", window as any, { target, property, value })\n );\n return true;\n },\n get(target, property) {\n return target[property];\n }\n };\n\n export function get(obj: any, key: string): any {\n const parts = key.split(\".\");\n let current = obj;\n for (const part of parts) {\n if (current && typeof current === \"object\" && Object.prototype.hasOwnProperty.call(current, part)) {\n current = current[part];\n } else {\n return undefined;\n }\n }\n return current;\n }\n\n export function set(obj: any, key: string, value: any): boolean {\n const parts = key.split(\".\");\n let current = obj;\n let i: number;\n\n for (i = 0; i < parts.length - 1; i++) {\n const part = parts[i];\n if (current && typeof current === \"object\") {\n if (!Object.prototype.hasOwnProperty.call(current, part)) {\n current[part] = {};\n }\n current = current[part];\n } else {\n return false;\n }\n }\n\n if (current && typeof current === \"object\") {\n current[parts[i]] = value;\n return true;\n } else {\n return false;\n }\n }\n }\n\n export namespace URL {\n export function parse(location: Location = window.location): Record<string, string> {\n return Object.fromEntries(new URLSearchParams(location.search));\n }\n\n export namespace Query {\n export function parse(location: string = window.location.search): Record<string, string> {\n return Object.fromEntries(\n location.replace(/^\\?/, '').split(/&/).map(i => i.split(/=/))\n );\n }\n\n export function keys(location: string = window.location.search): string[] {\n return location.replace(/^\\?/, '').split(/&/).map(i => i.split(/=/)[0]);\n }\n\n export function has(key: string, location: string = window.location.search): boolean {\n return keys(location).findIndex(i => i === key) >= 0;\n }\n }\n }\n}\n\n","export type EventBusListener = (details: { key: string, newValue: any, oldValue: any }) => any;\n\n/**\n * Minimal local pub/sub used by vizena Graph and Layer objects.\n * Has the same API surface as arbor's StateManager but carries no R/arbor deps.\n */\nexport class EventBus {\n private _state: Map<string, any> = new Map();\n private listeners: Map<string, Map<string, Set<EventBusListener>>> = new Map();\n\n get state(): Map<string, any> {\n return this._state;\n }\n\n hasVariable(key: string): boolean {\n return this._state.has(key);\n }\n\n getVariable(key: string): any {\n return this._state.get(key);\n }\n\n setVariable(key: string, value: any, options?: { lazy?: boolean }): void {\n const oldValue = this._state.get(key);\n this._state.set(key, value);\n if (!options?.lazy) {\n this.notifyListeners(key, value, oldValue);\n }\n }\n\n addListener(key: string, type: string, listener: EventBusListener): void {\n if (!this.listeners.has(key)) this.listeners.set(key, new Map());\n const typeMap = this.listeners.get(key)!;\n if (!typeMap.has(type)) typeMap.set(type, new Set());\n typeMap.get(type)!.add(listener);\n }\n\n removeListener(key: string, type: string, listener: EventBusListener): void {\n this.listeners.get(key)?.get(type)?.delete(listener);\n }\n\n getListeners(key: string, type: string): EventBusListener[] {\n return Array.from(this.listeners.get(key)?.get(type) ?? []);\n }\n\n notifyListeners(key: string, newValue: any, oldValue: any): void {\n const typeMap = this.listeners.get(key);\n if (!typeMap) return;\n for (const set of typeMap.values()) {\n set.forEach((listener) => {\n if (typeof listener === 'function') {\n listener({ key, newValue, oldValue });\n } else if (typeof (listener as any).calculate === 'function') {\n (listener as any).calculate.call(listener, { key, newValue, oldValue });\n }\n });\n }\n }\n}\n","import { Transform } from \"./Transform.js\";\nimport { Tools } from \"../utils/Tools.js\";\nconst { ArrayTools } = Tools;\nimport { Graph } from \"./Graph.js\";\nimport { PlottedObject } from \"./PlottedObject.js\";\nimport { EventBus as StateManager } from \"../types/EventBus.js\";\n\nexport type LayerLike = {\n name?: string;\n layers?: LayerArray;\n [key: string]: any;\n};\n\nexport class LayerArray extends Array<LayerLike> {\n constructor(...args: any[]) {\n super(...args);\n }\n\n search(key: string, name: string): LayerLike | undefined {\n let found: LayerLike | undefined;\n\n function fn(a: LayerLike): LayerLike | undefined {\n return a.name === name ? a : undefined;\n }\n\n function recurse(obj: any, i?: number, parent: any = null): LayerLike | undefined {\n if (ArrayTools.isArray(obj)) {\n for (const [i, o] of obj.entries()) {\n found = recurse(o, i, parent);\n if (found) {\n return found;\n }\n }\n } else {\n found = fn(obj);\n if (!found) {\n if (obj && ArrayTools.isArray(obj[key])) {\n for (const [i, o] of obj[key].entries()) {\n found = recurse(o, i, obj);\n if (found) {\n return found;\n }\n }\n }\n } else {\n return found;\n }\n }\n return found;\n }\n\n return recurse(this);\n }\n\n flatten(): LayerLike[] {\n return this.reduce<LayerLike[]>((a, l: LayerLike) => {\n a.push(l);\n if (l.layers && Array.isArray(l.layers)) {\n a.push(...l.layers);\n }\n return a;\n }, []);\n }\n \n recurse(\n key: string,\n callback: (layer: LayerLike, parent?: LayerLike | null, depth?: number) => any, \n parent: LayerLike | null = null, \n depth: number = 0\n ): any {\n let results: any[] = new LayerArray();\n for (const layer of this) {\n let result = callback(layer, parent, depth);\n \n if (layer[key] && Array.isArray(layer[key])) {\n let r = new LayerArray(...layer[key]).recurse(key, callback, layer, depth + 1);\n if (r !== undefined) {\n results.push(...r);\n }\n }\n\n results.push(result);\n }\n console.log(\"Recurse results: \", results);\n return results;\n }\n}\n\nexport class Layer {\n __state__: StateManager = new StateManager();\n\n name: string;\n ID: string;\n scale_x: number = 1;\n scale_y: number = 1;\n tabindex?: number;\n _transform: Transform;\n scale_objects: boolean = true;\n layers: LayerArray = new LayerArray();\n objects: Map<string, PlottedObject> = new Map();\n parent?: Layer | Graph;\n visible: boolean = true;\n\n constructor(ID: string, o: any, parent?: Graph | Layer) {\n this.ID = ID;\n this.name = o.name || `layer-${ID}`;\n this.tabindex = o.tabindex;\n this.parent = parent;\n this._transform = new Transform();\n\n parent?.__state__.addListener(\"graph_updated\", \"live\", ({ key, newValue, oldValue }) => {\n // console.log(`Graph updated, updating layer: ${this.name}`);\n });\n \n parent?.__state__.addListener(`graph_updated_${this.name}`, \"live\", ({ key, newValue, oldValue }) => {\n // console.log(`Graph updated, updating layer: ${this.name}, Key: ${key}`, \"New Value: \", newValue, \"Old Value: \", oldValue);\n this.objects = newValue;\n this.__state__.setVariable(`layer_updated`, this );\n });\n }\n\n get transform(): Transform {\n return this._transform;\n }\n set transform(t: Transform) {\n this._transform = t;\n }\n}","import { Transform } from './Transform';\nimport { Color } from './Color';\nimport { Edge } from './Edges';\nimport { DataFrameRow } from '../types/DataFrame';\n\nexport type DimensionType = DimensionVector | DataFrameRow | number[];\n\nexport interface DimensionVectorInterface extends Array<number> {\n\n [index: number]: number;\n flipped: boolean;\n flip(): DimensionVector;\n get names(): string[];\n get(wh: string | number): number | undefined;\n}\nexport class DimensionVector extends Array<number> implements DimensionVectorInterface {\n #flipped: boolean = false;\n #names: string[] | undefined;\n\n constructor(...args: number[]) {\n super(arguments.length);\n for (let i = 0; i < args.length; i++) {\n this[i] = args[i];\n }\n this.#flipped = false;\n }\n\n static fromArray(arr: DataFrameRow): DimensionVector {\n const vec = new DimensionVector();\n arr.forEach((v, i) => {\n vec.push(v);\n });\n vec.#names = arr.names;\n\n return vec;\n }\n\n flip(): DimensionVector {\n this.#flipped = !this.#flipped;\n for (let i = 0; i < this.length; i++) {\n this[i] = -this[i];\n }\n return this;\n }\n\n get(wh: string | number): number | undefined {\n if (typeof wh === 'number') {\n return this[wh];\n } else if (this.#names && this.#names.includes(wh)) {\n return this[this.#names.indexOf(wh)];\n } else {\n return undefined;\n }\n }\n\n get flipped(): boolean {\n return this.#flipped;\n }\n\n get names(): string[] {\n if (this.#names) {\n return this.#names;\n } else {\n return this.map((_, i) => `V${i + 1}`);\n }\n }\n}\n\nexport interface PlottedObjectOptions {\n ID: string;\n dimensions?: DimensionVector;\n x?: number | number[];\n y?: number | number[];\n size: number | 0;\n color: Color;\n highlight: Color | null;\n shape?: any;\n active: boolean;\n meta: any;\n\n [key: string]: any;\n}\n\nexport class PlottedObject implements PlottedObjectOptions {\n private readonly _original: PlottedObjectOptions;\n private readonly _dimensions: DimensionVector;\n\n ID: string;\n scale_x: number = 1;\n scale_y: number = 1;\n scale_size: number = 0.05;\n active: boolean = false;\n visible: boolean = false;\n highlighting: boolean = false;\n meta: any = {};\n \n _transform: Transform;\n _x: any = 0;\n _y: any = 0;\n _color: Color;\n _highlight: Color;\n _highlight_default: Color = new Color('#000000');\n _size: number = 0;\n\n shape?: any;\n\n // graph: Graph;\n parent: any;\n\n get dimensions(): DimensionVector {\n return this._dimensions;\n }\n\n get color(): Color {\n return (\n // This was expecting hightight to be an object with a color property\n // but now it is just a Color object, so we can simplify this.\n (this.highlighting && this._highlight) ? this._highlight : this._color\n );\n }\n set color(c: Color) {\n this._color = c;\n }\n get highlight(): Color {\n return this._highlight || this._highlight_default;\n }\n set highlight(h: Color) {\n this._highlight = h;\n }\n\n get size(): number {\n return this._size;\n }\n set size(s: number) {\n this._size = s;\n }\n\n get original(): PlottedObjectOptions {\n return this._original;\n }\n\n get x() {\n return this._x; // * this.graph.x_mirror();\n }\n get y() {\n return this._y; // * this.graph.y_mirror();\n }\n set x(x_: any) { this._x = x_; }\n set y(y_: any) { this._y = y_; }\n dimension(wh: string | number): number | undefined {\n return this._dimensions.get(wh);\n }\n\n get transform() { return this._transform; }\n set transform(t: any) { this._transform = t; }\n\n constructor(dimensions: DimensionType, o: PlottedObjectOptions) {\n this.ID = o.ID;\n // this.graph = graph;\n this._transform = new Transform();\n\n // If dimensions is already a DimensionVector, use it directly\n if (dimensions instanceof DimensionVector) {\n this._dimensions = dimensions;\n }\n else if (dimensions instanceof DataFrameRow) {\n // If dimensions is a DataFrameRow, convert it to a DimensionVector\n this._dimensions = DimensionVector.fromArray(dimensions);\n }\n\n // If dimensions is an array, convert it to a DimensionVector\n else if (Array.isArray(dimensions)) {\n this._dimensions = new DimensionVector(...dimensions);\n }\n\n // Else is a warning and fallback to a default DimensionVector\n else {\n console.warn(\"Invalid dimensions provided, using default DimensionVector(0, 0)\");\n this._dimensions = new DimensionVector(0, 0);\n }\n\n // make a copy of the object to avoid mutating the original\n let data: PlottedObjectOptions = { ...o };\n\n // keep the original data for reference\n this._original = { ...data };\n\n this.ID = data.ID;\n this.x = data.x || this._dimensions[0];\n this.y = data.y || this._dimensions[1];\n this._size = data.size || 1;\n this._color = data.color || new Color('#000000');\n this.active = data.active || false;\n this.shape = data.shape || null;\n this.meta = data.meta || {};\n\n this._highlight = this._highlight_default;\n if (data.highlight) {\n this._highlight = data.highlight;\n }\n // else if (graph && graph.options && graph.options[this.constructor.name.toUpperCase()]) {\n // this._highlight = graph.options[this.constructor.name.toUpperCase()].highlight;\n // }\n }\n}\n\nexport interface LineOptions extends PlottedObjectOptions {\n x1: number | string;\n y1: number | string;\n x2: number | string;\n y2: number | string;\n width?: number;\n color: Color;\n shape: string | null;\n [key: string]: any;\n}\n\nexport class Line extends PlottedObject {\n from: Point;\n to: Point;\n width?: number;\n _color!: Color;\n shape!: string;\n\n // constructor(x: LineOptions) {\n // super([], x);\n // // const data = Object.assign({}, x);\n // const { x1, y1, x2, y2, width, color, shape } = x;\n\n // // console.log(\"Line constructor data:\", data);\n // // console.warn(\" this was using `meta` but it is deprecated now - should be using `original` instead\");\n // // this.meta = Object.keys(data)\n // // .filter(k => ['ID', 'x1', 'y1', 'x2', 'y2', 'size', 'color'].indexOf(k) < 0)\n // // .reduce((n: any, k: string) => { n[k] = data[k]; return n; }, {});\n\n // this.x1 = parseFloat(x1 as string);\n // this.y1 = parseFloat(y1 as string);\n // this.x2 = parseFloat(x2 as string);\n // this.y2 = parseFloat(y2 as string);\n // this.width = width;\n // this._color = color || new Color('#000000');\n // this.shape = shape || 'line';\n // }\n\n constructor(data: DataFrameRow | any, from: Point, to: Point) {\n // let\n // // dimensions: DimensionType = data.classes.map( (c: string, i: number) => c === \"ena.co.occurrence\" ? data[i] : -1).filter(a => a !== -1),\n // // meta: any = data.classes.map( (c: string, i: number) => c === \"ena.metadata\" ? [data.names[i], data[i]] : null).filter(a => a !== null).reduce((n: any, c: any) => { n[c[0]] = c[1]; return n; }, {}),\n // // ID: string = data.rowName || `point-${Math.random().toString(36).substring(2, 9)}`\n // ;\n\n super([], {} as any);\n\n this.from = from;\n this.to = to;\n }\n\n get line(): [[number, number], [number, number]] {\n return [[this.from.x, this.from.y], [this.to.x, this.to.y]];\n }\n get midpoint(): [number, number] {\n return [\n (this.from.x + this.to.x) / 2,\n (this.from.y + this.to.y) / 2\n ];\n }\n get length(): number {\n return Math.sqrt(\n Math.pow(this.to.x - this.from.x, 2) +\n Math.pow(this.to.y - this.from.y, 2)\n );\n }\n get color(): Color { return this._color; }\n set color(c: Color) { this._color = c; }\n}\n\nexport interface PointOptions extends PlottedObjectOptions {\n shape?: string;\n label?: string;\n [key: string]: any;\n}\n\nexport class Point extends PlottedObject {\n static SHAPES = { CIRCLE: 'circle', SQUARE: 'rect' };\n\n private _label: Label | undefined;\n edges: Map<any, Edge> = new Map();\n shape: string = Point.SHAPES.CIRCLE;\n\n // constructor(dimensions: DimensionType, o: PointOptions) { //, graph?: any) {\n // super(dimensions, o);\n // this.active = o.active || false;\n // this.visible = o.visible || false;\n // this.size = o.size || 1;\n // this.color = o.color || new Color('#000000');\n // this.shape = o.shape ? o.shape : \"circle\";\n // this.scale_size = 2;\n // this._x = dimensions[0];\n // this._y = dimensions[1];\n // this.label = new Label(this.ID, this);\n // }\n constructor(data: DataFrameRow | any) {\n let\n dimensions: DimensionType | undefined, // = data.classes.map( (c, i) => (c === \"ena.co.occurrence\" || c === \"ena.dimension\") ? data[i] : -1).filter(a => a !== -1),\n meta: any, // = data.classes.map( (c, i) => c === \"ena.metadata\" ? [data.names[i], data[i]] : null).filter(a => a !== null).reduce((n: any, c: any) => { n[c[0]] = c[1]; return n; }, {}),\n ID: string // = data.rowName || `point-${Math.random().toString(36).substring(2, 9)}`\n ;\n\n if(data) {\n if(data instanceof DataFrameRow) {\n dimensions = data.classes?.map( (c, i) => (c === \"ena.co.occurrence\" || c === \"ena.dimension\") ? data[i] : -1).filter(a => a !== -1);\n meta = data.classes?.map( (c, i) => c === \"ena.metadata\" ? [data.names[i], data[i]] : null).filter(a => a !== null).reduce((n: any, c: any) => { n[c[0]] = c[1]; return n; }, {});\n ID = data.rowName || `point-${Math.random().toString(36).substring(2, 9)}`;\n }\n else if(typeof data === \"object\") {\n dimensions = data.dimensions || [];\n meta = data.meta || {};\n ID = data.ID || `point-${Math.random().toString(36).substring(2, 9)}`;\n }\n else {\n console.warn(\"Invalid data provided for Point, using default values\");\n dimensions = [];\n meta = {};\n ID = `point-${Math.random().toString(36).substring(2, 9)}`;\n }\n }\n else {\n dimensions = [];\n meta = {};\n ID = `point-${Math.random().toString(36).substring(2, 9)}`;\n }\n\n super(dimensions ?? [], { meta, ID } as any);\n }\n\n set label(l: Label | undefined) {\n this._label = l;\n }\n get label(): Label | undefined {\n return this._label;\n }\n get x(): number {\n // const dims = this.graph.options.GRAPH.dimensions;\n // const _ = this.meta[dims[0]];\n // const mult = 1;\n // return parseFloat(_) * mult;\n return this._x;\n }\n get y(): number {\n // const dims = this.graph.options.GRAPH.dimensions;\n // const _ = this.meta[dims[1]];\n // const mult = 1;\n // return parseFloat(_) * mult;\n return this._y;\n }\n set x(x_: number) { this._x = parseFloat(x_ as any); }\n set y(y_: number) { this._y = parseFloat(y_ as any); }\n}\n\nexport class ConfidenceInterval extends PlottedObject {\n width?: number;\n z: number = 1.959964;\n // meta: any;\n\n private _mean: any;\n\n constructor(mean: any) {\n super(mean.dimensions, mean);\n this.ID = \"mean_ci_\" + mean.ID;\n this._mean = mean;\n }\n\n get line(): [[number, number], [number, number]] {\n // x1, y1, x2, y2 should be defined on mean or this\n return [\n [this._mean.x1, this._mean.y1],\n [this._mean.x2, this._mean.y2]\n ];\n }\n get variance(): [number, number] {\n const points = [...this._mean.points.values()];\n return [\n points.length > 1 ? points.map(p => Math.pow(p.x - this._mean.x, 2)).reduce((a, b) => a + b, 0) / (points.length - 1) : 0,\n points.length > 1 ? points.map(p => Math.pow(p.y - this._mean.y, 2)).reduce((a, b) => a + b, 0) / (points.length - 1) : 0\n ];\n }\n get std(): [number, number] {\n return this.variance.map(Math.sqrt) as [number, number];\n }\n get value(): [number, number] {\n const pointsSize = this._mean.points.size;\n return this.std.map(s => this.z * (s / Math.sqrt(pointsSize))) as [number, number];\n }\n get length(): number {\n const [a, b] = this.line;\n return Math.sqrt(Math.pow(b[0] - a[0], 2) + Math.pow(b[1] - a[1], 2));\n }\n\n get path(): string {\n const x_ = this._mean.x;\n const y_ = this._mean.y;\n const v = this.value;\n const x = v[0];\n const y = v[1];\n const xl = x_ - x;\n const xr = x_ + x;\n const yt = y_ - y;\n const yb = y_ + y;\n return `M${xl},${yt} ${xr},${yt} ${xr},${yb} ${xl},${yb}z`;\n }\n}\n\nexport class Label extends PlottedObject {\n object: PlottedObject;\n _visible: boolean = false;\n text: string;\n offset: number = 0;\n dragging?: boolean;\n\n constructor(txt: string, object: PlottedObject) {\n // super(object.ID);\n super(object.dimensions, object);\n this.text = txt;\n this.ID = object.ID;\n this.object = object;\n this.x = this.dimensions[0]; //object.x;\n this.y = this.dimensions[1]; //object.y;\n this.offset = object.size || 0;\n this.size = this.offset / 4;\n this.visible = false;\n\n this._transform.set(\"e\", 1); // this.object.size * this.graph.SIZE_EFFECT * 2);\n this._transform.set(\"f\", 1); // this.object.size * this.graph.SIZE_EFFECT * 2);\n }\n\n get x(): number {\n return parseFloat(this._x);\n }\n get y(): number {\n return parseFloat(this._y);\n }\n set x(x_: number) { this._x = x_; }\n set y(y_: number) { this._y = y_; }\n\n get transform(): Transform {\n console.warn(\"transform is disabled - need updated reference for the graph options\")\n // if (\n // !this.dragging &&\n // this.graph.options[this.object.constructor.name.toUpperCase()].labelposition === Label.POSITION.OBJECT\n // ) {\n // const s = this.object.size;\n // const effect = 1; // this.graph.object.SIZE_EFFECT\n // this._transform.set(\"e\", s * effect / 2 / this._transform.a);\n // this._transform.set(\"f\", s * effect / 2 / this._transform.a);\n // } else if (\n // !this.dragging &&\n // this.graph.options[this.object.constructor.name.toUpperCase()].labelposition === Label.POSITION.STATIC\n // ) {\n // const eVal = this.graph.extremes[this.graph.options.LABEL.position[1] as keyof typeof this.graph.extremes];\n // const fVal = this.graph.extremes[this.graph.options.LABEL.position[0] as keyof typeof this.graph.extremes];\n // this._transform.set(\"e\", typeof eVal === \"number\" ? eVal : 0);\n // this._transform.set(\"f\", typeof fVal === \"number\" ? fVal : 0);\n // }\n return this._transform;\n }\n set transform(t: Transform) { this._transform = t; }\n\n static DISPLAY_TYPES = { OFF: 0, AUTO: 1, CLICK: 2, ON: 3 };\n static HIGHLIGHT = { OFF: 0, ON: 2 };\n static POSITION = { OBJECT: 1, STATIC: 2, CONTAINER: 3, CUSTOM: 4 };\n}\n","\nclass Extremes {\n x_max: number;\n y_max: number;\n // _point_max?: Point;\n // _node_max?: Point;\n\n /** Centre of the view; (0, 0) — the ENA origin — unless centred on the content */\n cx: number;\n cy: number;\n\n constructor(x: number, y: number, cx: number = 0, cy: number = 0) { //, n?: Point, p?: Point) {\n this.x_max = x;\n this.y_max = y;\n this.cx = cx;\n this.cy = cy;\n // this._point_max = p;\n // this._node_max = n;\n }\n as_viewBox(p: number = 1.2): string {\n let x = this.x_max * p;\n let y = this.y_max * p;\n return (`${this.cx - x} ${this.cy - y} ${x * 2} ${y * 2}`);\n }\n\n // get point_max(): Point {\n // return this._point_max || { x: 1, y: 1 };\n // }\n // get node_max(): Point {\n // return this._node_max || { x: 1, y: 1 };\n // }\n\n get height(): number {\n return this.y_max * 2;\n } \n get width(): number {\n return this.x_max * 2;\n }\n get top(): number {\n return this.y_max * -1;\n }\n get bottom(): number {\n return this.y_max;\n }\n get left(): number {\n return this.x_max * -1;\n }\n get right(): number {\n return this.x_max;\n }\n}\n\nexport { Extremes };","import { DimensionVector, PlottedObject } from \"./PlottedObject\";\n\nexport class AxisPoint extends PlottedObject {\n\n constructor(dimensions: DimensionVector, o: any) {\n super(dimensions, o);\n\n this.visible = true;\n\n this.size = o.size;\n }\n\n set size(s: number) {\n this._size = s;\n }\n get size(): number {\n return this._size;\n }\n\n get x(): number {\n return this._x;\n }\n get y(): number {\n return this._y;\n }\n set x(x_: number) { this._x = x_; }\n set y(y_: number) { this._y = y_; }\n\n get transform() {\n return this._transform;\n }\n}","import { Color } from \"./Color\";\nimport { Layer, LayerArray, LayerLike } from \"./Layers\";\nimport { DimensionVector, Label, Line, Point } from \"./PlottedObject\";\nimport { Transform } from \"./Transform\";\nimport { Extremes } from \"./Extremes\";\nimport { Node } from \"./Points\";\nimport { Edge } from \"./Edges\";\nimport { AxisPoint } from \"./AxisPoint\";\nimport { DataFrame, DataFrameRow } from \"../types/DataFrame\";\nimport { EventBus as StateManager } from \"../types/EventBus\";\n\nexport let DefaultGraphOptions = {\n GRAPH: {\n ratio: 1,\n x_max: 1,\n y_max: 1,\n selector: \"body\",\n width: 1,\n height: 1,\n axes: true,\n SIZE_EFFECT: 1,\n dimensions: [ 0, 1 ]\n },\n NODE: {\n size: 1,\n highlight: {\n color: 'yellow',\n labels: Label.DISPLAY_TYPES.ON,\n },\n labels: Label.DISPLAY_TYPES.ON,\n labelposition: Label.POSITION.OBJECT\n },\n POINT: {\n active: 2,\n size: 0.05,\n color: \"#000\",\n shape: Point.SHAPES.CIRCLE,\n labels: Label.DISPLAY_TYPES.AUTO,\n labelposition: Label.POSITION.OBJECT\n },\n MEAN: {\n shape: Point.SHAPES.SQUARE,\n labels: Label.DISPLAY_TYPES.AUTO,\n },\n LABEL: {\n highlight: Label.HIGHLIGHT.OFF,\n position: ['top', 'left'],\n container: \"#label-container\"\n },\n EDGE: {\n multiplier: 1\n }\n};\n\nexport class Graph {\n __state__: StateManager = new StateManager();\n\n name: string = \"unnamed-graph\";\n origin: AxisPoint | undefined = undefined;\n\n options: typeof DefaultGraphOptions;\n\n points: Map<string, Point | AxisPoint> = new Map();\n nodes: Map<string, Node> = new Map();\n edges: Map<string, Edge> = new Map();\n trajectories: Map<string, any> = new Map();\n labels: Map<string, Label> = new Map();\n transform: Transform = new Transform();\n\n scale_x: number = 1;\n scale_y: number = 1;\n\n _extremes!: Extremes;\n SIZE_EFFECT: number = 1;\n _mirror_y: boolean = true;\n _mirror_x: boolean = false;\n\n layers: LayerArray;\n _layers: LayerArray = new LayerArray(\n { name: \"graph\", tabindex: 0, layers: [\n { \n name: \"axes\",\n layers: [\n { \n name: \"axis_lines\", tabindex: 0, layers: [], \n objects: [\n\n ]\n },\n { \n name: \"axis_labels\", tabindex: 0, layers: [], objects: []\n },\n {\n name: \"axis_points\", \n tabindex: 0, \n layers: [], \n objects: [\n this.origin\n ]\n }\n ]\n },\n\n {\n name: \"network\",\n layers: [\n { name: \"edges\", layers: [], tabindex: 0 },\n { name: \"nodes\", layers: [], tabindex: 0 },\n { name: \"edgenodes\", layers: [], tabindex: 0 },\n ]\n },\n { name: \"trajectories\", layers: [], tabindex: 0 },\n { name: \"points\", layers: [], tabindex: 0 },\n\n { name: \"labels\", layers: [], tabindex: 0 },\n ] },\n );\n\n constructor(\n options: typeof DefaultGraphOptions = { ...DefaultGraphOptions }\n ) {\n this.options = options;\n \n this.origin = new AxisPoint(\n new DimensionVector(0, 0),\n {\n ID: \"origin\",\n x: 0, y: 0,\n size: 0,\n meta: {},\n graph: this,\n color: new Color(\"#FFFFFF\"),\n highlight: new Color(\"#FFFFFF\"),\n active: false\n }\n );\n\n let layer_id = 1;\n function buildLayerTree(layerData: any, parent: Layer | null, graph: Graph): Layer {\n const new_layer = new Layer(`${layer_id}`, layerData, graph);\n layer_id += 1;\n new_layer.parent = parent || undefined;\n if (layerData.layers && Array.isArray(layerData.layers)) {\n new_layer.layers = new LayerArray(...layerData.layers.map((child: any) => buildLayerTree(child, new_layer, graph)));\n }\n return new_layer;\n }\n\n this.layers = new LayerArray(...this._layers.map((l: any) => buildLayerTree(l, null, this)));\n\n let axisPointLayer: LayerLike | undefined = this.layers.search(\"layers\", \"axis_points\");\n if (axisPointLayer) {\n axisPointLayer.objects.set(this.origin.ID, this.origin);\n }\n \n let axisLineLayer: LayerLike | undefined = this.layers.search(\"layers\", \"axis_lines\");\n if (axisLineLayer) {\n let extremes = this.extremes || new Extremes(1, 1);\n let axis_x = new Line(\n {}, \n new Point({ ID: \"axis-x-start\", dimensions: [-extremes.x_max, 0], classes: [\"ena.dimension\", \"ena.dimension\"] }), \n new Point({ ID: \"axis-x-end\", dimensions: [extremes.x_max, 0], classes: [\"ena.dimension\", \"ena.dimension\"] })\n );\n axis_x.ID = \"axis-x\";\n axisLineLayer.objects.set(axis_x.ID, axis_x);\n let axis_y = new Line(\n {}, \n new Point({ ID: \"axis-y-start\", dimensions: [0, -extremes.y_max], classes: [\"ena.dimension\", \"ena.dimension\"] }),\n new Point({ ID: \"axis-y-end\", dimensions: [0, extremes.y_max], classes: [\"ena.dimension\", \"ena.dimension\"] })\n );\n axis_y.ID = \"axis-y\";\n axisLineLayer.objects.set(axis_y.ID, axis_y);\n console.log(\"Added axis lines to layer: \", axisLineLayer);\n }\n\n // Define extremes based on options\n this.extremes = new Extremes(options.GRAPH.x_max, options.GRAPH.y_max);\n }\n\n set extremes(e: Extremes) {\n this._extremes = e;\n }\n get extremes(): Extremes {\n return this._extremes;\n }\n get mirror_x(): boolean {\n return this._mirror_x;\n }\n set mirror_x(m: boolean) {\n this._mirror_x = m;\n }\n get mirror_y(): boolean {\n return this._mirror_y;\n }\n set mirror_y(m: boolean) {\n this._mirror_y = m;\n }\n\n x_mirror(): number {\n return (this.mirror_x ? -1 : 1);\n }\n y_mirror(): number {\n return (this.mirror_y ? -1 : 1);\n }\n\n add_point(p: DataFrameRow) {\n const point: Point = new Point(p);\n this.points.set(point.ID, point);\n\n // if (g_.options.POINT && g_.options.POINT.label) {\n // p.label = new Label(p.meta[g_.options.POINT.label], p, g_);\n // g_.labels.set(p.label.ID, p.label);\n // }\n // g_.points.set(p.ID, p);\n // const pointsLayer = g_.layers.search(\"layers\", \"points\");\n // if (pointsLayer) {\n // pointsLayer.objects.push(p);\n // }\n // g_.update_extremes();\n }\n add_points(ps: DataFrame) {\n let g_ = this;\n ps.rows().forEach((p: DataFrameRow) => {\n g_.add_point(p);\n });\n }\n\n add_nodes(ns: any[]) {\n let\n g_ = this\n ;\n\n ns.forEach((new_node) => {\n // if (g_.options.NODE && g_.options.NODE.label) {\n // new_node.label = new Label(new_node.meta[g_.options.NODE.label], new_node, g_);\n new_node.label = new Label(new_node.ID, new_node);\n g_.labels.set(new_node.label.ID, new_node.label);\n // }\n g_.nodes.set(new_node.ID, new_node);\n const nodesLayer = g_.layers.search(\"layers\", \"nodes\");\n if (nodesLayer) {\n nodesLayer.objects.push(new_node);\n }\n });\n g_.update_extremes();\n }\n add_edge(e: any, from?: any, to?: any) {\n let g_ = this;\n g_.edges.set(e.ID, e);\n\n this.add_nodes([from || e.from, to || e.to]);\n\n return (e);\n }\n add_edges(es: any[]) {\n let added = es.map(e => this.add_edge(e));\n const edgesLayer = this.layers.search(\"layers\", \"edges\");\n if (edgesLayer) {\n edgesLayer.objects.push(...added);\n }\n return (added);\n }\n\n /**\n * The visible extent: 1.3 × the farthest point or node. Centred on the\n * origin (the ENA convention: (0, 0) is the mean of the points), or with\n * `centerContent`, on the middle of the points' and nodes' bounding box, so\n * a network that sits off to one side of the origin fills the plot.\n */\n update_extremes(centerContent: boolean = false) {\n // let\n // dim1 = this.options.GRAPH.dimensions[0],\n // dim2 = this.options.GRAPH.dimensions[1],\n // // Get all points and nodes to calculate extremes\n // all_points = [...this.points.values(), ...this.nodes.values()].flat(),\n // x_max = Math.max(...all_points.map((p: PlottedObject) => Math.abs(p.dimension(dim1) || 0))),\n // y_max = Math.max(...all_points.map((p: PlottedObject) => Math.abs(p.dimension(dim2) || 0))),\n // max = Math.max(x_max, y_max)\n // ;\n // this.extremes = new Extremes(Math.ceil(max), Math.ceil(max), { x: 1, y: 1 }, { x: 1, y: 1 });\n\n const search_layers = [\n this.layers.search(\"layers\", \"points\"),\n this.layers.search(\"layers\", \"nodes\")\n ].filter((l): l is LayerLike => l !== undefined);\n if (search_layers.length === 0) {\n this.extremes = new Extremes(1, 1);\n }\n else {\n // Bound = largest |x|/|y| across points and nodes, plus a modest margin\n // for peripheral node labels. The previous Math.ceil() snapped this up to\n // the next integer, which — for ENA's small coordinate ranges (≈1–2) —\n // left the network floating in a lot of dead space. Keep the raw value so\n // the drawing fills the canvas.\n let minX = Infinity, maxX = -Infinity, minY = Infinity, maxY = -Infinity;\n search_layers.forEach(l => l.objects.forEach((o: any) => {\n if (Number.isFinite(o.x)) { minX = Math.min(minX, o.x); maxX = Math.max(maxX, o.x); }\n if (Number.isFinite(o.y)) { minY = Math.min(minY, o.y); maxY = Math.max(maxY, o.y); }\n }));\n const found = Number.isFinite(minX) && Number.isFinite(minY);\n const cx = centerContent && found ? (minX + maxX) / 2 : 0;\n const cy = centerContent && found ? (minY + maxY) / 2 : 0;\n const content_max = found\n ? Math.max(Math.abs(minX - cx), Math.abs(maxX - cx), Math.abs(minY - cy), Math.abs(maxY - cy))\n : 0;\n const found_max = (content_max > 0 ? content_max : 1) * 1.3;\n this.extremes = new Extremes(found_max, found_max, cx, cy);\n }\n }\n\n /** Farthest node from (cx, cy), on either axis */\n nodeExtentFrom(cx: number, cy: number): number {\n const nodes = this.layers.search(\"layers\", \"nodes\");\n let max = 0;\n nodes?.objects.forEach((o: any) => {\n if (Number.isFinite(o.x) && Number.isFinite(o.y)) max = Math.max(max, Math.abs(o.x - cx), Math.abs(o.y - cy));\n });\n return max;\n }\n\n base_point_size(scale = 8): number {\n let minDim = Math.min(this.extremes.x_max, this.extremes.y_max);\n let n = this.points.size + this.nodes.size;\n return Math.min(1, minDim / (Math.sqrt(n) * scale));\n }\n}\n","import { Graph } from \"../objects/Graph\";\nimport { Layer } from \"../objects/Layers\";\nimport { PlottedObject } from \"../objects/PlottedObject\";\n\nexport abstract class DrawableElement extends HTMLElement {\n \n static style: string = `\n :host {\n max-width: 100%;\n display: block;\n }\n .wrapper {\n height: 100%;\n display: flex;\n justify-content: center;\n }\n `;\n\n element: Element | null = null;\n object: PlottedObject | Graph | Layer | null = null;\n\n get wrapper() {\n const\n element = this,\n shadow = element.shadowRoot,\n wrapper = shadow?.querySelector(\".wrapper\")\n ;\n return wrapper;\n }\n\n constructor() {\n super();\n\n const\n element = this,\n shadow = element.attachShadow({ mode: 'open' }),\n style = document.createElement('style'),\n wrapper = document.createElement('div')\n ;\n\n style.textContent = (this.constructor as any).style;\n shadow.appendChild(style);\n\n wrapper.setAttribute('class', 'wrapper');\n shadow.appendChild(wrapper);\n }\n}","// Pure, DOM-free polynomial trajectory fitting.\n//\n// Ported from `ena.plot.trajectory()` in the ETM Explorer (RescuShell) R kit:\n// - near-origin filtering of the fit set (points at the cumulative origin are\n// drawn but excluded from the fit),\n// - `loocv_2d` degree selection (joint 2D leave-one-out CV via the hat-matrix\n// shortcut), with a `fixed` escape hatch,\n// - least-squares polynomial fit solved by QR for numerical parity with R's\n// `lm(y ~ poly(t, deg))`.\n//\n// Leverages and residuals depend only on the column space of the design, so a\n// raw monomial basis solved by QR reproduces R's selected degree and fitted\n// curve to floating-point tolerance despite R using orthogonal `poly()`.\n\n/** Near-origin tolerance; hardcoded to match the R kit's `zero_eps` default. */\nexport const TRAJECTORY_ZERO_EPS = 1e-8;\n\nexport interface XY {\n x: number;\n y: number;\n}\n\nexport type DegreeSelection = 'loocv_2d' | 'fixed';\n\nexport interface TrajectoryFit {\n degree: number;\n coeffsX: number[];\n coeffsY: number[];\n}\n\n/** Drop near-origin points (both coords within eps of 0) from the fit set. */\nexport function nearOriginFilter(pts: XY[], eps: number = TRAJECTORY_ZERO_EPS): XY[] {\n return pts.filter(p => Math.abs(p.x) > eps || Math.abs(p.y) > eps);\n}\n\n/** Evenly spaced parameter t in [0,1] by index — matches R's seq(0,1,length.out=n). */\nfunction normalizedT(n: number): number[] {\n if (n <= 0) return [];\n if (n === 1) return [0];\n const t = new Array(n);\n for (let i = 0; i < n; i++) t[i] = i / (n - 1);\n return t;\n}\n\n/** Vandermonde design [1, t, t^2, ..., t^deg], n×(deg+1). */\nfunction design(t: number[], degree: number): number[][] {\n return t.map(ti => {\n const row = new Array(degree + 1);\n let p = 1;\n for (let k = 0; k <= degree; k++) {\n row[k] = p;\n p *= ti;\n }\n return row;\n });\n}\n\n/**\n * Modified Gram-Schmidt QR. `A` is n×m (n >= m). Returns Q (n×m, orthonormal\n * columns) and R (m×m upper triangular). More stable than raw normal equations,\n * matching what R's `lm` does internally.\n */\nfunction qr(A: number[][]): { Q: number[][]; R: number[][] } {\n const n = A.length;\n const m = A[0].length;\n const Q = A.map(row => row.slice());\n const R = Array.from({ length: m }, () => new Array(m).fill(0));\n for (let j = 0; j < m; j++) {\n let norm = 0;\n for (let i = 0; i < n; i++) norm += Q[i][j] * Q[i][j];\n norm = Math.sqrt(norm);\n R[j][j] = norm;\n if (norm > 1e-300) {\n for (let i = 0; i < n; i++) Q[i][j] /= norm;\n }\n for (let k = j + 1; k < m; k++) {\n let dot = 0;\n for (let i = 0; i < n; i++) dot += Q[i][j] * Q[i][k];\n R[j][k] = dot;\n for (let i = 0; i < n; i++) Q[i][k] -= dot * Q[i][j];\n }\n }\n return { Q, R };\n}\n\n/** Qᵀy (length m). */\nfunction qtY(Q: number[][], y: number[]): number[] {\n const n = Q.length;\n const m = Q[0].length;\n const out = new Array(m).fill(0);\n for (let j = 0; j < m; j++) {\n let s = 0;\n for (let i = 0; i < n; i++) s += Q[i][j] * y[i];\n out[j] = s;\n }\n return out;\n}\n\n/** Back-substitution for R c = b, R upper triangular m×m. */\nfunction backSolve(R: number[][], b: number[]): number[] {\n const m = b.length;\n const c = new Array(m).fill(0);\n for (let i = m - 1; i >= 0; i--) {\n let s = b[i];\n for (let j = i + 1; j < m; j++) s -= R[i][j] * c[j];\n c[i] = Math.abs(R[i][i]) > 1e-12 ? s / R[i][i] : 0;\n }\n return c;\n}\n\n/** Leverages h_ii = sum_j Q[i][j]^2 (diagonal of the hat matrix). */\nfunction leverages(Q: number[][]): number[] {\n return Q.map(row => {\n let s = 0;\n for (let j = 0; j < row.length; j++) s += row[j] * row[j];\n return s;\n });\n}\n\n/** Least-squares monomial coefficients for y ~ poly(t, degree). */\nfunction fitCoeffs(t: number[], y: number[], degree: number): number[] {\n const X = design(t, degree);\n const { Q, R } = qr(X);\n return backSolve(R, qtY(Q, y));\n}\n\n/** Evaluate a monomial polynomial (ascending coeffs) at t. */\nexport function evalPoly(coeffs: number[], t: number): number {\n let v = 0;\n let p = 1;\n for (let k = 0; k < coeffs.length; k++) {\n v += coeffs[k] * p;\n p *= t;\n }\n return v;\n}\n\n/**\n * Joint 2D leave-one-out CV PRESS for a candidate degree. x(t) and y(t) share\n * one design (hence one hat matrix), so LOO residuals are e_i / (1 - h_ii).\n * Returns Infinity for a degenerate (saturated) fit so it is never selected.\n */\nfunction loocv2d(t: number[], x: number[], y: number[], degree: number): number {\n const X = design(t, degree);\n const { Q, R } = qr(X);\n const h = leverages(Q);\n const cx = backSolve(R, qtY(Q, x));\n const cy = backSolve(R, qtY(Q, y));\n let press = 0;\n for (let i = 0; i < t.length; i++) {\n const denom = 1 - h[i];\n if (denom <= 0) return Infinity;\n const ex = x[i] - evalPoly(cx, t[i]);\n const ey = y[i] - evalPoly(cy, t[i]);\n press += (ex / denom) ** 2 + (ey / denom) ** 2;\n }\n return press;\n}\n\n/**\n * Select a degree in 1..min(maxDegree, n-1). For `loocv_2d`, minimises the joint\n * 2D LOOCV PRESS; ties resolve to the smallest degree (matching R's which.min).\n * For `fixed`, or when there are too few points to run CV, returns the cap.\n */\nexport function selectDegree(fitPts: XY[], maxDegree: number, mode: DegreeSelection): number {\n const n = fitPts.length;\n const cap = Math.min(Math.max(1, Math.floor(maxDegree)), Math.max(1, n - 1));\n if (mode === 'fixed' || n < 3) return cap;\n const t = normalizedT(n);\n const x = fitPts.map(p => p.x);\n const y = fitPts.map(p => p.y);\n let best = 1;\n let bestVal = Infinity;\n for (let deg = 1; deg <= cap; deg++) {\n const v = loocv2d(t, x, y, deg);\n if (v < bestVal) {\n bestVal = v;\n best = deg;\n }\n }\n return best;\n}\n\n/**\n * Fit a trajectory polynomial. The near-origin filter is applied to both the\n * per-frame points and the (optional) full-trajectory `selectionSet`. The degree\n * is chosen on `selectionSet` when given — so it stays constant as a playhead\n * scrubs a growing prefix — then clamped to what the current frame can support,\n * and the coefficients are re-fit on the current frame's points.\n *\n * Returns null when fewer than three non-origin points are available (matching\n * the R kit's n_fit < 3 guard); callers should fall back to raw steps.\n */\nexport function fitTrajectory(\n activePts: XY[],\n opts: { maxDegree: number; degreeSelection: DegreeSelection; selectionSet?: XY[] | null }\n): TrajectoryFit | null {\n const fitPts = nearOriginFilter(activePts);\n if (fitPts.length < 3) return null;\n\n const selBasis = opts.selectionSet ? nearOriginFilter(opts.selectionSet) : fitPts;\n const basis = selBasis.length >= 3 ? selBasis : fitPts;\n let degree = selectDegree(basis, opts.maxDegree, opts.degreeSelection);\n\n // A growing playhead prefix may hold fewer points than the held degree needs.\n degree = Math.min(degree, Math.max(1, fitPts.length - 1));\n\n const t = normalizedT(fitPts.length);\n const coeffsX = fitCoeffs(t, fitPts.map(p => p.x), degree);\n const coeffsY = fitCoeffs(t, fitPts.map(p => p.y), degree);\n return { degree, coeffsX, coeffsY };\n}\n\n/** Sample the fitted curve at steps+1 evenly spaced points over t in [0,1]. */\nexport function sampleCurve(fit: TrajectoryFit, steps = 100): XY[] {\n const out: XY[] = [];\n for (let s = 0; s <= steps; s++) {\n const t = s / steps;\n out.push({ x: evalPoly(fit.coeffsX, t), y: evalPoly(fit.coeffsY, t) });\n }\n return out;\n}\n","import { PlottedObject, PlottedObjectOptions, Point } from './PlottedObject';\nimport { Color } from './Color';\nimport { DegreeSelection, fitTrajectory, sampleCurve } from './polyfit';\n\nexport interface TrajectoryOptions {\n ID?: string;\n unitId?: string;\n points?: Point[] | { x: number; y: number; time?: number; label?: string }[];\n color?: Color | string;\n smooth?: 'none' | 'poly' | 'spline';\n maxDegree?: number;\n degreeSelection?: DegreeSelection;\n polyCoeffsX?: number[];\n polyCoeffsY?: number[];\n currentTime?: number;\n showPoints?: boolean;\n showTips?: boolean;\n lineStyle?: 'uniform' | 'tapered';\n strokeWidth?: number;\n strokeWidthRange?: [number, number];\n opacityRange?: [number, number];\n size?: number;\n active?: boolean;\n meta?: any;\n [key: string]: any;\n}\n\nconst TRAJECTORY_CURVE_STEPS = 100;\n\nexport class Trajectory extends PlottedObject {\n readonly _typeName: string = 'Trajectory';\n trajPoints: Point[] = [];\n smooth: 'none' | 'poly' | 'spline' = 'none';\n maxDegree: number = 3;\n degreeSelection: DegreeSelection = 'loocv_2d';\n /** Degree chosen at the most recent fit; -1 until a poly curve is built. */\n selectedDegree: number = -1;\n polyCoeffsX: number[] = [];\n polyCoeffsY: number[] = [];\n currentTime: number = Infinity;\n showPoints: boolean = true;\n showTips: boolean = true;\n lineStyle: 'uniform' | 'tapered' = 'uniform';\n strokeWidth: number = 2;\n strokeWidthRange: [number, number] = [1, 6];\n opacityRange: [number, number] = [0.3, 1];\n\n constructor(options: TrajectoryOptions = {}) {\n const defaultColor = options.color instanceof Color ? options.color : new Color(typeof options.color === 'string' ? options.color : '#000000');\n super([], {\n ID: options.ID || `traj-${Math.random().toString(36).substring(2, 9)}`,\n size: options.size || 1,\n color: defaultColor,\n highlight: null,\n active: options.active || false,\n meta: options.meta || {},\n ...options\n } as PlottedObjectOptions);\n\n this.smooth = options.smooth || 'none';\n this.maxDegree = options.maxDegree !== undefined ? options.maxDegree : 3;\n this.degreeSelection = options.degreeSelection || 'loocv_2d';\n this.polyCoeffsX = options.polyCoeffsX || [];\n this.polyCoeffsY = options.polyCoeffsY || [];\n this.currentTime = options.currentTime !== undefined ? options.currentTime : Infinity;\n this.showPoints = options.showPoints !== undefined ? options.showPoints : true;\n this.showTips = options.showTips !== undefined ? options.showTips : true;\n this.lineStyle = options.lineStyle || 'uniform';\n this.strokeWidth = options.strokeWidth || 2;\n this.strokeWidthRange = options.strokeWidthRange || [1, 6];\n this.opacityRange = options.opacityRange || [0.3, 1];\n\n if (options.points && Array.isArray(options.points)) {\n this.trajPoints = options.points.map(p => {\n if (p instanceof Point) return p;\n const pt = new Point({ dimensions: [p.x, p.y], meta: { time: p.time, label: p.label } });\n pt.x = p.x;\n pt.y = p.y;\n return pt;\n });\n }\n }\n\n get activePoints(): Point[] {\n if (this.currentTime === Infinity) {\n return this.trajPoints;\n }\n return this.trajPoints.filter(p => {\n const t = (p.meta && typeof p.meta.time === 'number') ? p.meta.time : 0;\n return t <= this.currentTime;\n });\n }\n\n get path(): string {\n return this.pathPoints.reduce((acc, pt, idx) => {\n return idx === 0 ? `M${pt.x},${pt.y}` : `${acc} L${pt.x},${pt.y}`;\n }, '');\n }\n\n get pathPoints(): Array<{ x: number; y: number }> {\n const pts = this.activePoints;\n if (pts.length < 2) return [];\n\n if (this.smooth === 'poly') {\n // Precomputed coefficients override the fit (caller-supplied curve).\n if (this.polyCoeffsX.length > 0 && this.polyCoeffsY.length > 0) {\n return sampleCurve(\n { degree: this.polyCoeffsX.length - 1, coeffsX: this.polyCoeffsX, coeffsY: this.polyCoeffsY },\n TRAJECTORY_CURVE_STEPS\n );\n }\n\n // Select the degree on the full trajectory so it stays constant while a\n // playhead scrubs a growing prefix; fit coefficients on the visible frame.\n const fit = fitTrajectory(\n pts.map(p => ({ x: p.x, y: p.y })),\n {\n maxDegree: this.maxDegree,\n degreeSelection: this.degreeSelection,\n selectionSet: this.trajPoints.map(p => ({ x: p.x, y: p.y }))\n }\n );\n if (fit) {\n this.selectedDegree = fit.degree;\n return sampleCurve(fit, TRAJECTORY_CURVE_STEPS);\n }\n // Too few non-origin points to fit — fall back to raw steps below.\n }\n\n return pts.map(pt => ({ x: pt.x, y: pt.y }));\n }\n}\n","import { PlottedObject, Line, PlottedObjectOptions } from './PlottedObject.js';\nimport { Node } from './Points.js';\nimport { Color, WeightedColor } from './Color.js';\nimport { Tools } from '../utils/Tools.js';\nimport { DataFrameRow } from '../types/DataFrame.js';\n\n// Placeholder for zoom level, should be defined in the context of the application\nconst zoom_level = 1;\n\nexport class Edge extends Line {\n declare from: Node;\n declare to: Node;\n _totalweight: number = 0;\n _weight: number;\n declare _color: WeightedColor;\n\n constructor(data: DataFrameRow | any, from: Node, to: Node, weight: number = 0) {\n super(data, from, to);\n this._weight = weight;\n }\n\n get base_color(): Color { return this._color };\n get color(): WeightedColor {\n const base = this._color || new Color(\"#000000\");\n return new WeightedColor(base, Math.abs(this.weight));\n }\n set color(c: Color) { this._color = c as any; }\n\n base_weight() { return this._weight };\n get weight() {\n // let w = Array.isArray(this.#weight) ? this.#weight.reduce( (a, b) => a - b, 0) : this.#weight;\n let w = Array.isArray(this._weight) ? (this._weight[0] - this._weight[1]) : this._weight;\n return w; // * this.graph.options.EDGE.multiplier\n }\n set weight(w) {\n this._weight = w;\n }\n\n get totalweight(): number {\n return this.weight;\n }\n set totalweight(w: number) {\n this._totalweight = w;\n }\n}\n\nexport class SubtractedEdges extends Edge {\n edge_one: Edge;\n edge_two: Edge;\n\n #weight: number;\n #color: WeightedColor;\n\n constructor(e1: Edge, e2: Edge) {\n super(e1, e1.from, e1.to);\n\n this.edge_one = e1;\n this.edge_two = e2;\n\n this.#weight = this.edge_one.weight - this.edge_two.weight;\n\n let\n color_type_fn: new (color: Color | string, weight: number) => WeightedColor = this.edge_one.color.constructor as any,\n color: string = this.edge_one.color.base\n ;\n if (this.weight > 0) {\n color = this.edge_one.color.base;\n }\n else {\n color = this.edge_two.color.base;\n }\n\n this.#color = new color_type_fn(color, this.#weight);\n }\n\n get weight() {\n return this.#weight;\n }\n set weight(w) {\n this.#weight = w;\n }\n\n get color() {\n return this.#color;\n }\n set color(c) {\n this.#color = c;\n }\n}\n\nexport class MeanEdge extends Edge {\n edges: Set<Edge> = new Set<Edge>();\n\n constructor(o: any) {\n super(o, o.from, o.to);\n\n this.visible = true;\n // this.meta = o.meta || { ID: this.ID };\n }\n\n // get weight() { return __.math.mean([...this.edges.values()].map( e => e.weight )) * this.graph.options.EDGE.multiplier; }\n get weight() {\n let wt = Tools.Mathematics.mean([...this.edges.values()].map((e: Edge) => e.weight)) * 1;\n return wt;\n }\n set weight(w) { this._weight = w; }\n\n get path() {\n return `M${this.from.x} ${this.from.y} L${this.to.x} ${this.to.y}z`;\n }\n\n get totalweight() {\n return Array.from(this.edges).reduce((acc, edge) => acc + edge.totalweight, 0);\n }\n}\n\nexport class EdgeArrow extends PlottedObject {\n #edge;\n\n constructor(edge: PlottedObjectOptions) {\n super(edge.dimensions || [], edge);\n this.#edge = edge;\n }\n\n get edge() {\n return this.#edge;\n }\n\n get path(): string {\n /**\n *\n * mid_int0 nock_int0\n * --------------*-----*-------------- <- edge of arrow from midpoint to base_pt0\n * / /\n * / /\n * / /\n * / /\n * / /\n * / /\n * <-- edge node head--> * * * <-- nock ---> edge midpoint this way ---->\n * \\ ^-mid |\n * \\ | \\ |\n * \\ | \\ | <---- showing line from nock to edge used to find\n * \\ | \\ | intersection with edge\n * \\| \\|\n * --------------*-----*-------------- <- edge of arrow from midpoint to base_pt1\n * mid_int1---^ ^----nock_int1\n *\n */\n // Pure vector geometry on the tapered edge: T = target (wide end, base\n // points B0/B1), A = apex. The chevron sits 20% of the way from T toward\n // A, but its length follows the triangle's local width (≈ a constant\n // shape) rather than a fixed share of the edge length — on long, thin\n // edges the old fractional sizing stretched it into a sliver. (The old\n // slope-intercept intersections also misbehaved on near-vertical edges.)\n const _this = this.#edge;\n const T: [number, number] = [_this.to.x, _this.to.y];\n const A: [number, number] = _this.from_point;\n const [B0, B1] = _this.base_pts as [[number, number], [number, number]];\n const L = Math.hypot(A[0] - T[0], A[1] - T[1]);\n const W = Math.hypot(B0[0] - B1[0], B0[1] - B1[1]);\n if (!(L > 0) || !(W > 0)) return '';\n const u = [(A[0] - T[0]) / L, (A[1] - T[1]) / L]; // along the edge, T → A\n const b = Math.hypot(B0[0] - T[0], B0[1] - T[1]);\n const v = [(B0[0] - T[0]) / b, (B0[1] - T[1]) / b]; // across, toward B0\n const halfW = (d: number) => (W / 2) * Math.max(0, 1 - d / L);\n const at = (d: number, s: number) => `${T[0] + u[0] * d + v[0] * s} ${T[1] + u[1] * d + v[1] * s}`;\n\n const dh = 0.2 * L; // head\n const c = Math.min(0.15 * L, 0.8 * 2 * halfW(dh)); // length ≈ local width\n const dm = dh + c / 2, dn = dh + c; // notch, back\n const p = `M${at(dh, 0)} L${at(dm, halfW(dm))} L${at(dn, halfW(dn))} ` +\n `L${at(dm, 0)} L${at(dn, -halfW(dn))} L${at(dm, -halfW(dm))}z`;\n return p;\n }\n}\n\nexport enum EdgeDirection {\n FROM = 'from',\n TO = 'to'\n}\n\nexport class TaperedEdge extends Edge {\n // base_pts = [];\n _path: string = '';\n // Arrowheads are off by default — the tapered triangle shape already\n // communicates direction. Enabling #with_arrow currently throws because\n // EdgeArrow.constructor passes the edge as the lone super() arg.\n #with_arrow = false;\n #arrow;\n\n _directions: EdgeDirection[] = [EdgeDirection.FROM, EdgeDirection.TO];\n towards: EdgeDirection = EdgeDirection.TO;\n\n constructor(data: any, from: Node, to: Node) {\n super(data, from, to);\n\n if (this.#with_arrow === true) {\n this.#arrow = new EdgeArrow(this);\n }\n }\n\n get path(): string {\n return `M${this.from.x} ${this.from.y} L${this.base_pts[0].join(' ')} L${this.base_pts[1].join(' ')}z`;\n }\n static calculate_base_points(edg: TaperedEdge): [[number, number], [number, number]] {\n // Find the two endpoints of the tapered edge based on its `towards` direction.\n const top: EdgeDirection = edg.towards;\n const base: EdgeDirection = edg._directions.find(d => d !== edg.towards) as EdgeDirection;\n\n const bx = edg[base].x, by = edg[base].y;\n const tx = edg[top].x, ty = edg[top].y;\n const dx = tx - bx, dy = ty - by;\n const L = Math.hypot(dx, dy);\n\n // Degenerate: zero-length edge or unset weight — collapse to a point at `top`.\n const wt = (edg.weight ?? 0) * zoom_level;\n if (L === 0 || !isFinite(wt) || wt === 0) {\n return [[tx, ty], [tx, ty]];\n }\n\n // Unit perpendicular to the edge direction; offset both sides by wt/2.\n // Pure vector math here avoids the slope-intercept form used by\n // Tools.Geometry, which produces NaN for vertical edges and ill-conditioned\n // values for horizontal ones.\n const px = -dy / L, py = dx / L;\n const halfW = wt / 2;\n return [\n [tx + px * halfW, ty + py * halfW],\n [tx - px * halfW, ty - py * halfW],\n ];\n }\n get base_pts() {\n return TaperedEdge.calculate_base_points(this);\n }\n get arrow() {\n return this.#arrow;\n }\n get with_arrow() {\n return this.#with_arrow;\n }\n get from_point() {\n return [this.from.x, this.from.y];\n }\n}\n\nexport class TaperedMidpointEdge extends TaperedEdge {\n constructor(data: any, from: Node, to: Node) {\n super(data, from, to);\n }\n\n get path(): string {\n return `M${this.midpoint[0]} ${this.midpoint[1]} L${this.base_pts[0].join(' ')} L${this.base_pts[1].join(' ')}z`;\n }\n get from_point(): [number, number] {\n return this.midpoint;\n }\n}\n\nexport class TaperedWeightedMidpointEdge extends TaperedEdge {\n // Preserve the original data weight so that QELine.update()'s\n // `edge.weight = sw * 4` (which sets _weight for display sizing) doesn't\n // corrupt the midpoint calculation.\n private _dataWeight: number = 0;\n\n constructor(data: any, from: Node, to: Node) {\n super(data, from, to);\n this._totalweight = data.totalweight ?? 0;\n this._dataWeight = data.weight ?? this._weight;\n }\n\n get weighted_midpoint(): [number, number] {\n return Tools.Geometry.Line.interpolate(this.line)(1 - (this._dataWeight / this._totalweight));\n }\n\n get base_pts(): [[number, number], [number, number]] {\n return TaperedEdge.calculate_base_points(this);\n }\n\n static build_path(edg: TaperedWeightedMidpointEdge | MeanTaperedWeightedMidpointEdge): string {\n if (edg._totalweight > 0) {\n let p = `M${edg.weighted_midpoint[0]} ${edg.weighted_midpoint[1]} L${edg.base_pts[0].join(' ')} L${edg.base_pts[1].join(' ')}z`;\n\n return p\n }\n else {\n console.error(\"TaperedWeightedMidpointEdge: No totalweight, returning empty path\");\n return '';\n }\n }\n get path(): string {\n return TaperedWeightedMidpointEdge.build_path(this);\n }\n\n get from_point() {\n return this.weighted_midpoint;\n }\n}\n\nexport class MeanNodeEdge extends MeanEdge {\n constructor(o: any) {\n super(o);\n }\n get path() {\n return NodeEdge.build_path(this.weight, [...this.edges.values()][0].to)\n }\n get weight() {\n return Tools.Mathematics.mean([...this.edges.values()].map(e => e.weight)) * 1;\n }\n set weight(w) { this._weight = w; }\n}\n\nexport class MeanTaperedEdge extends MeanEdge {\n #with_arrow = true;\n #arrow;\n\n constructor(o: PlottedObjectOptions) {\n super(o);\n\n if (this.#with_arrow === true) {\n this.#arrow = new EdgeArrow(this);\n }\n }\n\n get with_arrow() {\n return this.#with_arrow;\n }\n get arrow() {\n return this.#arrow;\n }\n get from_point() {\n return [this.from.x, this.from.y];\n }\n}\n\nexport class MeanTaperedMidpointEdge extends MeanTaperedEdge {\n constructor(o: PlottedObjectOptions) {\n super(o);\n }\n\n get base_pts(): [[number, number], [number, number]] {\n const\n top = EdgeDirection.TO,\n base = EdgeDirection.FROM\n ;\n\n let\n edge_line: [[number, number], [number, number]] = [[this[base].x, this[base].y], [this[top].x, this[top].y]],\n perp_line = Tools.Geometry.Line.rotate2(edge_line, edge_line[1], 90),\n ints = Tools.Geometry.Line.intersect_circle(perp_line, edge_line[1], this.weight / 2)\n ;\n\n return ints;\n }\n get path(): string {\n return `M${this.midpoint[0]} ${this.midpoint[1]} L${this.base_pts[0].join(' ')} L${this.base_pts[1].join(' ')}z`;\n }\n get weight(): number {\n return Tools.Mathematics.mean([...this.edges.values()].map(e => e.weight)) * 1;\n }\n set weight(w) { this._weight = w; }\n}\n\nexport class MeanTaperedWeightedMidpointEdge extends MeanTaperedEdge {\n constructor(o: PlottedObjectOptions) {\n super(o);\n }\n\n get totalweight(): number {\n // debugger;\n // console.error(\"THIS NEEDS THE MEAN WEIGHT OF ITS COUNTERPART (FROM -> TO -- TO --> FROM)\")\n // or does the mean of the edges.totalweight equal to the same?\n return Tools.Mathematics.mean([...this.edges.values()].map(e => e.totalweight));\n }\n\n get weighted_midpoint() {\n // console.log(\"Weighted: \", this.weight, this.totalweight)\n return Tools.Geometry.Line.interpolate(this.line)(1 - (this.weight / this.totalweight))\n }\n\n get base_pts() {\n const\n top = EdgeDirection.TO, //this.#directions[this.#directions.findIndex( d => d === this.towards )],\n base = EdgeDirection.FROM //this.#directions[this.#directions.findIndex( d => d !== this.towards )]\n ;\n\n let\n edge_line: [[number, number], [number, number]] = [[this[base].x, this[base].y], [this[top].x, this[top].y]],\n perp_line = Tools.Geometry.Line.rotate2(edge_line, edge_line[1], 90),\n ints = Tools.Geometry.Line.intersect_circle(perp_line, edge_line[1], this.weight / 2)\n ;\n\n return ints;\n }\n\n get path() {\n let p = TaperedWeightedMidpointEdge.build_path(this)\n // console.log(\"Static p: \", p);\n return p;\n }\n get weight() {\n return Tools.Mathematics.mean([...this.edges.values()].map(e => e.weight)) * 1;\n }\n set weight(w) { this._weight = w; }\n}\n\nexport class NodeEdge extends Edge {\n\n constructor(data: any, from: Node, to: Node) {\n super(data, from, to);\n }\n\n static build_path(weight: number, to: Node) {\n let\n R = weight / 2,\n CX = to.x - R,\n R2 = R * 2,\n p = `M ${CX}, ${to.y} a ${R},${R} 0 1,0 ${R2},0 a ${R},${R} 0 1,0 -${R2},0`\n ;\n\n return p;\n }\n\n get path() {\n let wt = this.weight * zoom_level; //this.graph.get_graphs()[0].object.SIZE_EFFECT;\n return NodeEdge.build_path(wt, this.to);\n }\n}\n","import { PlottedObject } from \"../objects/PlottedObject\";\nimport { QEArray, } from \"./QELayer\";\nimport { QEGraphElement } from \"./QEGraph\";\n\nexport abstract class Drawable {\n abstract create(): SVGElement;\n \n svg_element: SVGElement;\n\n constructor(\n public __data__: PlottedObject, \n public parent: SVGElement, \n public graph: QEGraphElement,\n public __children__: QEArray = new QEArray()\n ) {\n this.svg_element = this.create();\n }\n\n get_size() {\n return this.__data__.size;\n }\n\n draw() {\n this.parent?.appendChild(this.svg_element);\n }\n\n update(elem: SVGElement, animate = true) {\n // this.update(elem);\n }\n\n animateSVGAttribute(elem: SVGElement, attr: string, to: number) {\n const from = parseFloat(elem.getAttribute(attr) || '0');\n if (from === to) return;\n\n const duration = 5000;\n const start = performance.now();\n function animate(now: number) {\n const t = Math.min(1, (now - start) / duration);\n const value = from + (to - from) * t;\n elem.setAttribute(attr, value.toString());\n if (t < 1) requestAnimationFrame(animate);\n else elem.setAttribute(attr, to.toString());\n }\n requestAnimationFrame(animate);\n }\n}\n","// Shared mark-size and colour rules, sizes in units of the coordinate extent.\n//\n// Width follows webENA: absolute, raw weight × a constant (`edge-width`, as a\n// fraction of the plot width), so equal weights draw equally wide in graphs of\n// the same size. That one width-per-weight drives undirected strokes, the\n// wide ends of directed edges, self-connection dots, and code nodes (whose\n// diameter is the sum of their edges' widths).\n//\n// Colour follows webENA's ramps (saturation 0.25–1, opacity 0.3–1), but the\n// rescaling range is taken across the whole model rather than per network.\n\n/** Default `<qe-graph edge-width>`: the width of an edge of weight 1 as a\n * fraction of the plot width. Width is absolute — raw weight × this — as in\n * webENA, so equal weights get equal widths in graphs of the same size. */\nexport const DEFAULT_EDGE_WIDTH = 0.04;\n\n/** webENA's colour ramps: non-zero weights are rescaled linearly from the\n * reference [min, max] onto these saturation and opacity ranges. */\nexport const SATURATION_RANGE: [number, number] = [0.25, 1];\nexport const OPACITY_RANGE: [number, number] = [0.3, 1];\n\n/** Linear map of |w| from [lo, hi] onto `range`; 0 stays 0 (not drawn). */\nexport function rampFor(w: number, lo: number, hi: number, range: [number, number]): number {\n const a = Math.abs(w);\n if (!(a > 0)) return 0;\n if (!(hi > lo)) return range[1];\n const t = Math.min(1, Math.max(0, (a - lo) / (hi - lo)));\n return range[0] + t * (range[1] - range[0]);\n}\n\n/** Edge stroke width for edges drawn outside the network rule (fallback). */\nexport const EDGE_WIDTH_PER_EXTENT = 0.011;\n\n/** On-screen width (CSS px) of the outline drawn around directed (tapered)\n * edges so long, thin triangles stay legible along their whole length. */\nexport const TAPERED_OUTLINE_PX = 0.75;\n\n/** Direction chevrons on directed edges: RGB multiplier applied to the\n * (opaque, white-flattened) edge colour, and the white halo's on-screen\n * width in CSS px. */\nexport const CHEVRON_DARKEN = 0.8;\nexport const CHEVRON_HALO_PX = 0.75;\n\n/** Point radius per unit of `size` (QEPoint). */\nexport const POINT_RADIUS_PER_EXTENT = 0.006;\n\n/** `size` for a code node with no drawn edges: a tiny dot that still marks\n * where the code sits (hide it with <qe-nodes unconnected=\"hide\">). */\nexport const UNCONNECTED_NODE_SIZE = 0.6;\n\n/** Width per unit of weight in extent units (plot width = 2 × extent). */\nexport function widthPerWeight(edgeWidth: number): number {\n return 2 * edgeWidth;\n}\n\n/** QEPoint `size` for a node whose diameter equals the summed widths of its\n * edges, `weightSum × widthFrac` (both in extent units). */\nexport function nodeSizeForEdges(weightSum: number, widthFrac: number): number {\n return (weightSum * widthFrac) / (2 * POINT_RADIUS_PER_EXTENT);\n}\n","import { Line } from \"../objects/PlottedObject\";\nimport { NodeEdge, TaperedEdge, EdgeArrow } from \"../objects/Edges\";\nimport { Color, WeightedColor } from \"../objects/Color\";\nimport { Drawable } from \"./Drawable\";\nimport { QEArray, QEElement } from \"./QELayer\";\nimport { QEGraphElement } from \"./QEGraph\";\nimport { CHEVRON_DARKEN, CHEVRON_HALO_PX, EDGE_WIDTH_PER_EXTENT, TAPERED_OUTLINE_PX } from \"../objects/Sizing\";\n\n/** Composite an rgba() colour over white, returning an opaque rgb(). */\nfunction flattenOnWhite(col: string): string {\n const m = /rgba?\\(([^)]+)\\)/.exec(col);\n if (!m) return col;\n const [r, g, b, a = 1] = m[1].split(',').map(Number);\n const f = (c: number) => Math.round(255 + (c - 255) * a);\n return `rgb(${f(r)},${f(g)},${f(b)})`;\n}\n\n/** Scale an rgba()/rgb() colour's RGB channels by `k` (alpha unchanged). */\nfunction darkenRgba(col: string, k: number): string {\n const m = /rgba?\\(([^)]+)\\)/.exec(col);\n if (!m) return col;\n const [r, g, b, a = 1] = m[1].split(',').map(Number);\n return `rgba(${Math.round(r * k)},${Math.round(g * k)},${Math.round(b * k)},${a})`;\n}\n\nexport class QELine extends Drawable implements QEElement {\n __name__: string = \"unnamed-line\";\n // Optional second element for the direction-indicator chevron on directed edges.\n private _arrow_el: SVGPathElement | null = null;\n // Invisible wide companion line giving thin undirected edges a clickable/\n // hoverable hit target for the qe-edge-* interaction events.\n private _hit_el: SVGLineElement | null = null;\n\n /** Stamp edge identity onto an element so <qe-graph> delegation can resolve\n * qe-edge-* events. No-op for non-edges (e.g. axis lines). */\n private _stampEdge(el: SVGElement): void {\n const meta = (this.__data__ as any).meta ?? {};\n if (!meta.isMeanEdge) return;\n el.setAttribute('data-edge-source', String(meta.source ?? ''));\n el.setAttribute('data-edge-target', String(meta.target ?? ''));\n el.setAttribute('data-edge-weight', String(meta.weight ?? 0));\n el.setAttribute('data-edge-directed', meta.isDirected ? 'true' : 'false');\n if (meta.isSelf) el.setAttribute('data-edge-self', 'true');\n if (meta.group != null) el.setAttribute('data-edge-group', String(meta.group));\n if (meta.unit != null) el.setAttribute('data-edge-unit', String(meta.unit));\n }\n\n constructor(\n public __data__: Line,\n public parent: SVGElement,\n public graph: QEGraphElement,\n public __children__: QEArray = new QEArray(),\n ) {\n super(__data__, parent, graph, __children__);\n\n this.svg_element = this.create();\n }\n\n create() {\n if (this.__data__ instanceof NodeEdge) {\n // Self-connection: filled circle inside the node, sized by weight.\n const path = document.createElementNS('http://www.w3.org/2000/svg', 'path');\n path.setAttribute('fill', this.__data__.color.toString());\n path.setAttribute('stroke', 'none');\n this.svg_element = path;\n return path;\n }\n\n if (this.__data__ instanceof TaperedEdge) {\n // Directed edges render as filled triangles via TaperedEdge.path.\n // A second SVG path is reserved for the direction-indicator chevron;\n // it is populated lazily in update() once meta.isDirected is known.\n const path = document.createElementNS('http://www.w3.org/2000/svg', 'path');\n path.setAttribute('fill', this.__data__.color.toString());\n path.setAttribute('stroke', 'none');\n this.svg_element = path;\n return path;\n }\n\n const line = document.createElementNS('http://www.w3.org/2000/svg', 'line');\n line.setAttribute('x1', this.__data__.from.x.toString());\n line.setAttribute('y1', this.__data__.from.y.toString());\n line.setAttribute('x2', this.__data__.to.x.toString());\n line.setAttribute('y2', this.__data__.to.y.toString());\n line.setAttribute('stroke-width', this.get_size().toString());\n line.setAttribute('stroke', this.__data__.color.toString());\n\n this.svg_element = line;\n return line;\n }\n\n update() {\n if (!this.svg_element) {\n this.create();\n }\n if (!this.svg_element.parentElement) {\n this.parent.appendChild(this.svg_element);\n }\n\n const extent = (this.graph.__data__ as any).extremes?.x_max ?? 1;\n const meta = (this.__data__ as any).meta ?? {};\n\n if (meta.isMeanEdge) {\n this._stampEdge(this.svg_element);\n const weight = typeof meta.weight === 'number' ? meta.weight : 0;\n const maxW = typeof meta.maxWeight === 'number' ? meta.maxWeight : 1;\n const opacity = typeof meta.opacity === 'number' ? meta.opacity : Math.min(1, weight / (maxW || 1));\n // Target ≈ multiplier×5 in plotly-px to match rENA (ena.plot.network\n // default: multiplier=5, width = raw_weight × 5). For a ±2.66-extent\n // coordinate space rendered at ~460px, 1 data-unit ≈ 86px, so\n // rENA's max stroke (0.47 × 5 ≈ 2.4px) ≈ 0.028 data units.\n // Factor 0.011 × extent(2.66) × 1.0 ≈ 0.029 → ~2.5px at 86px/unit.\n // Width = weight × the plot's shared width-per-weight (objects/Sizing.ts);\n // the fallback keeps edges visible if an edge arrives without one.\n const ext = extent > 0 ? extent : 1;\n const sw = typeof meta.widthFrac === 'number'\n ? ext * meta.widthFrac * weight\n : ext * EDGE_WIDTH_PER_EXTENT * (weight / (maxW || 1));\n\n // Build a WeightedColor from the stored base color + normalized weight so\n // that toString() produces hsla(h, s*w%, l%, w) — matching the Web ENA\n // convention of scaling both saturation and alpha together with weight.\n const baseColor = (this.__data__ as any)._color || new Color('#000000');\n // Saturation and opacity come from the graph's colour ramps\n // (<qe-edges color-scale>); older edges carry only opacity.\n const saturation = typeof meta.saturation === 'number' ? meta.saturation : opacity;\n const edgeColor = new WeightedColor(baseColor, saturation, opacity).toString();\n\n if (this.__data__ instanceof NodeEdge) {\n // Diameter = the self weight's width (same width-per-weight as edges\n // and nodes), matching ona. The node's diameter includes this self\n // weight, so the dot always fits inside it. Computed here because the\n // live extent is not known when the edge objects are built.\n (this.__data__ as NodeEdge).weight = sw;\n (this.svg_element as SVGPathElement).setAttribute('d', (this.__data__ as NodeEdge).path);\n this.svg_element.setAttribute('fill', edgeColor);\n this.svg_element.setAttribute('stroke', 'none');\n } else if (this.__data__ instanceof TaperedEdge) {\n // TaperedEdge.path uses .weight as the total base width (the wide end,\n // at the target node); node sizes sum these base widths.\n (this.__data__ as TaperedEdge).weight = sw;\n (this.svg_element as SVGPathElement).setAttribute('d', (this.__data__ as TaperedEdge).path);\n this.svg_element.setAttribute('fill', edgeColor);\n // Hairline outline (constant on-screen width, same weighted colour as\n // the fill). A long, thin triangle tapers below a pixel for most of its\n // length; the outline keeps the whole connection legible without\n // changing its width or colour encoding (ona draws a similar halo).\n this.svg_element.setAttribute('stroke', edgeColor);\n this.svg_element.setAttribute('stroke-width', String(TAPERED_OUTLINE_PX));\n this.svg_element.setAttribute('vector-effect', 'non-scaling-stroke');\n this.svg_element.setAttribute('stroke-linejoin', 'round');\n\n // ── Direction-indicator chevron ──────────────────────────────────────\n // For directed mean edges, overlay an EdgeArrow chevron filled with a\n // more-opaque/saturated version of the edge colour. Rendered over the\n // semi-transparent triangle body, the fully-opaque fill reads as a\n // visibly darker notch that indicates the direction without introducing\n // a foreign colour.\n if (meta.isDirected) {\n try {\n const arrow = new EdgeArrow(this.__data__ as any);\n const arrowPath = arrow.path;\n // Discard degenerate paths that contain NaN or Infinity (geometry\n // collapsed — zero-length edge, parallel lines, etc.).\n if (arrowPath && !arrowPath.includes('NaN') && !arrowPath.includes('Infinity')) {\n if (!this._arrow_el) {\n this._arrow_el = document.createElementNS('http://www.w3.org/2000/svg', 'path');\n this._arrow_el.setAttribute('stroke', 'none');\n }\n if (!this._arrow_el.parentElement) {\n this.parent.appendChild(this._arrow_el);\n }\n this._arrow_el.setAttribute('d', arrowPath);\n // As ona draws arrows: the edge's weighted colour flattened onto\n // white (\"fake alpha\", so it is opaque and weak edges still get\n // lighter chevrons), then darkened — plus ona's optional white\n // halo, at a constant on-screen width, so it stands out from the\n // triangle it sits on.\n this._arrow_el.setAttribute('fill', darkenRgba(flattenOnWhite(edgeColor), CHEVRON_DARKEN));\n this._arrow_el.setAttribute('stroke', '#ffffff');\n this._arrow_el.setAttribute('stroke-width', String(CHEVRON_HALO_PX));\n this._arrow_el.setAttribute('vector-effect', 'non-scaling-stroke');\n this._arrow_el.setAttribute('stroke-linejoin', 'round');\n }\n } catch (_) {\n // EdgeArrow geometry degenerates for very short or zero-weight edges —\n // silently skip rather than crashing the render loop.\n }\n }\n } else {\n // Regular undirected edge\n const x1 = this.__data__.from.x, y1 = this.__data__.from.y;\n const x2 = this.__data__.to.x, y2 = this.__data__.to.y;\n (this.svg_element as SVGLineElement).setAttribute('x1', x1.toString());\n (this.svg_element as SVGLineElement).setAttribute('y1', y1.toString());\n (this.svg_element as SVGLineElement).setAttribute('x2', x2.toString());\n (this.svg_element as SVGLineElement).setAttribute('y2', y2.toString());\n this.svg_element.setAttribute('stroke-width', sw.toString());\n this.svg_element.setAttribute('stroke', edgeColor);\n this.svg_element.setAttribute('pointer-events', 'stroke');\n this.svg_element.removeAttribute('marker-end');\n\n // Transparent wide hit target so thin edges are clickable/hoverable.\n // Sized to a comfortable minimum regardless of the visible stroke width.\n if (!this._hit_el) {\n this._hit_el = document.createElementNS('http://www.w3.org/2000/svg', 'line');\n this._hit_el.setAttribute('stroke', 'transparent');\n this._hit_el.setAttribute('stroke-linecap', 'round');\n this._hit_el.setAttribute('pointer-events', 'stroke');\n }\n if (!this._hit_el.parentElement) this.parent.appendChild(this._hit_el);\n this._hit_el.setAttribute('x1', x1.toString());\n this._hit_el.setAttribute('y1', y1.toString());\n this._hit_el.setAttribute('x2', x2.toString());\n this._hit_el.setAttribute('y2', y2.toString());\n this._hit_el.setAttribute('stroke-width', Math.max(sw, extent * 0.03).toString());\n this._stampEdge(this._hit_el);\n }\n } else {\n // Thin axis lines: ~0.4% of coordinate extent\n (this.svg_element as SVGLineElement).setAttribute('x1', this.__data__.from.x.toString());\n (this.svg_element as SVGLineElement).setAttribute('y1', this.__data__.from.y.toString());\n (this.svg_element as SVGLineElement).setAttribute('x2', this.__data__.to.x.toString());\n (this.svg_element as SVGLineElement).setAttribute('y2', this.__data__.to.y.toString());\n const sw = (extent > 0 ? extent : 1) * 0.004 * this.get_size();\n this.svg_element.setAttribute('stroke-width', sw.toString());\n this.svg_element.setAttribute('stroke-opacity', '1');\n this.svg_element.setAttribute('stroke', this.__data__.color.toString());\n }\n }\n\n draw() {\n if (this._hit_el) this.parent?.appendChild(this._hit_el);\n this.parent?.appendChild(this.svg_element);\n if (this._arrow_el) {\n this.parent?.appendChild(this._arrow_el);\n }\n }\n}\n","import { PlottedObject } from \"../objects/PlottedObject\";\nimport { Drawable } from \"./Drawable\";\nimport { QEArray, QEElement } from \"./QELayer\";\nimport { QEGraphElement } from \"./QEGraph\";\nimport { POINT_RADIUS_PER_EXTENT } from \"../objects/Sizing\";\n\nexport class QEPoint extends Drawable implements QEElement {\n __name__: string = \"unnamed-point\";\n\n constructor(\n public __data__: PlottedObject,\n public parent: SVGElement,\n public graph: QEGraphElement,\n public __children__: QEArray = new QEArray(),\n ) {\n super(__data__, parent, graph, __children__);\n\n this.svg_element = this.create();\n }\n\n get x() {\n return this.__data__.dimensions[this.graph.__data__.options.GRAPH.dimensions[0]];\n }\n get y() {\n return this.__data__.dimensions[this.graph.__data__.options.GRAPH.dimensions[1]];\n }\n\n get isSquare(): boolean {\n return (this.__data__ as any).shape === 'rect';\n }\n\n /** \"circle\" (default) | \"rect\" | \"triangle\" | \"diamond\". */\n get shapeKind(): 'circle' | 'rect' | 'triangle' | 'diamond' {\n const s = (this.__data__ as any).shape;\n return s === 'rect' || s === 'square' ? 'rect'\n : s === 'triangle' || s === 'diamond' ? s : 'circle';\n }\n\n /** SVG tag for the current shape. */\n private get tag(): string {\n const k = this.shapeKind;\n return k === 'circle' ? 'circle' : k === 'rect' ? 'rect' : 'path';\n }\n\n /** Position / size the element for its shape (r = half-size). */\n private setGeometry(el: SVGElement, r: number): void {\n const x = this.x, y = this.y;\n switch (this.shapeKind) {\n case 'rect':\n el.setAttribute('x', (x - r).toString()); el.setAttribute('y', (y - r).toString());\n el.setAttribute('width', (r * 2).toString()); el.setAttribute('height', (r * 2).toString());\n break;\n case 'triangle': {\n // Equilateral, pointing up (SVG y-down), centred on the point.\n const h = r * 1.15;\n el.setAttribute('d', `M${x} ${y - h} L${x + h * 0.866} ${y + h * 0.5} L${x - h * 0.866} ${y + h * 0.5}Z`);\n break;\n }\n case 'diamond':\n el.setAttribute('d', `M${x} ${y - r * 1.2} L${x + r} ${y} L${x} ${y + r * 1.2} L${x - r} ${y}Z`);\n break;\n default:\n el.setAttribute('cx', x.toString()); el.setAttribute('cy', y.toString());\n el.setAttribute('r', r.toString());\n }\n }\n\n /** Half-side length for squares / radius for circles, in SVG user units.\n * Factor 0.006 keeps code-node diameters in the same visual range as rENA\n * (≈ 1–2 % of the coordinate half-extent for a typical ENA network).\n */\n computeRadius(): number {\n const r = this.baseRadius();\n // Optional ceiling (user units): group means are capped to their CI box so\n // a tight interval is never hidden under the marker.\n const cap = (this.__data__ as any).meta?.maxRadius;\n return typeof cap === 'number' && cap > 0 ? Math.min(r, cap) : r;\n }\n\n private baseRadius(): number {\n const extent = (this.graph.__data__.extremes.x_max) || 1;\n const sizeScale = (this.__data__ as any).meta?.sizeScale ?? 1;\n // Fixed-on-screen mode (webENA size decoupling): keep a constant pixel size\n // regardless of data extent / container size / wheel-zoom, by converting a\n // target px into user units via the current px-per-unit and zoom. Otherwise\n // size scales with the coordinate space (default — nodes/edges do the same).\n if ((this.__data__ as any).meta?.fixedSize) {\n const rect = (this.graph.svg_element as SVGSVGElement)?.getBoundingClientRect?.();\n const zoom = (this.graph as any).zoom_level || 1;\n const pxPerUnit = rect && rect.width > 0 ? rect.width / (2 * extent) : 1;\n const targetPx = this.__data__.size * 2 * sizeScale; // size 2.5 → 5px radius\n return (targetPx / pxPerUnit) / zoom;\n }\n return extent * POINT_RADIUS_PER_EXTENT * this.__data__.size * sizeScale;\n }\n\n /** Optional halo stroke (e.g. white outline on unit points to separate\n * overlapping dots in dense clusters). Width scales with the dot so it holds\n * up at any zoom. No-op unless the object requests it via meta.stroke. */\n private applyStroke(el: SVGElement): void {\n const stroke = (this.__data__ as any).meta?.stroke;\n if (!stroke) return;\n el.setAttribute('stroke', stroke);\n el.setAttribute('stroke-width', (this.computeRadius() * 0.22).toString());\n }\n\n create() {\n const el = document.createElementNS('http://www.w3.org/2000/svg', this.tag) as SVGElement;\n\n el.setAttribute('data-point-id', this.__data__.ID);\n // Identity for <qe-graph> delegation → qe-node-* interaction events.\n const meta = (this.__data__ as any).meta ?? {};\n if (meta.kind) el.setAttribute('data-kind', meta.kind);\n if (meta.name != null) el.setAttribute('data-name', String(meta.name));\n if (meta.group != null) el.setAttribute('data-group', String(meta.group));\n if (meta.unit != null) el.setAttribute('data-unit', String(meta.unit));\n el.setAttribute('fill', this.__data__.color.toString());\n this.applyStroke(el);\n\n this.setGeometry(el, this.computeRadius());\n\n this.svg_element = el;\n\n el.addEventListener('click', () => {\n // Note: do NOT stopPropagation — the click must bubble to <qe-graph>'s\n // delegation so it can emit the public qe-node-click event.\n this.__data__.active = !this.__data__.active;\n this.update();\n\n const pointEvent = new CustomEvent('point-clicked', {\n detail: { pointData: this.__data__ },\n bubbles: true, composed: true\n });\n this.svg_element.dispatchEvent(pointEvent);\n });\n\n el.addEventListener('mouseover', () => {\n // Do not stopPropagation — the parent SVG uses mouseover delegation\n // to show AUTO-mode labels. The fill is already set; this handler is\n // retained as a hook for future hover-highlight logic.\n });\n\n return el;\n }\n\n update() {\n if (!this.svg_element) {\n (this.parent as any).__data__.__children__.push(this.create());\n }\n if (!this.svg_element.parentElement) {\n this.parent.appendChild(this.svg_element);\n }\n\n this.svg_element.setAttribute('fill', this.__data__.color.toString());\n this.applyStroke(this.svg_element);\n this.setGeometry(this.svg_element, this.computeRadius());\n }\n\n draw() {\n this.parent?.appendChild(this.svg_element);\n }\n}\n","import { Trajectory } from '../objects/Trajectory';\nimport { Drawable } from './Drawable';\nimport { QEArray, QEElement } from './QELayer';\nimport { QEGraphElement } from './QEGraph';\n\nexport class QETrajectory extends Drawable implements QEElement {\n __name__: string = 'trajectory';\n private _path_el: SVGPathElement | null = null;\n private _segments_group: SVGGElement | null = null;\n private _tip_el: SVGCircleElement | null = null;\n private _points_group: SVGGElement | null = null;\n\n constructor(\n public __data__: Trajectory,\n public parent: SVGElement,\n public graph: QEGraphElement,\n public __children__: QEArray = new QEArray()\n ) {\n super(__data__, parent, graph, __children__);\n this.svg_element = this.create();\n }\n\n // Trajectory styling is specified in display pixels, while SVG paths use\n // graph coordinates. Convert at render time so marks stay legible at any scale.\n private graphUnitsForPixels(pixels: number): number {\n const extent = this.graph.__data__.extremes.x_max || 1;\n const width = this.graph.svg_element?.getBoundingClientRect().width || 0;\n return width > 0 ? pixels * (2 * extent / width) : pixels * extent * 0.006;\n }\n\n create() {\n const group = document.createElementNS('http://www.w3.org/2000/svg', 'g');\n group.setAttribute('class', 'qe-trajectory-group');\n\n const path = document.createElementNS('http://www.w3.org/2000/svg', 'path');\n path.setAttribute('fill', 'none');\n path.setAttribute('stroke', this.__data__.color.toString());\n path.setAttribute('stroke-width', this.graphUnitsForPixels(this.__data__.strokeWidth).toString());\n group.appendChild(path);\n this._path_el = path;\n\n const segmentsGroup = document.createElementNS('http://www.w3.org/2000/svg', 'g');\n segmentsGroup.setAttribute('class', 'qe-trajectory-segments');\n group.appendChild(segmentsGroup);\n this._segments_group = segmentsGroup;\n\n const pointsGroup = document.createElementNS('http://www.w3.org/2000/svg', 'g');\n pointsGroup.setAttribute('class', 'qe-trajectory-points');\n group.appendChild(pointsGroup);\n this._points_group = pointsGroup;\n\n if (this.__data__.showTips) {\n const tip = document.createElementNS('http://www.w3.org/2000/svg', 'circle');\n tip.setAttribute('fill', this.__data__.color.toString());\n tip.setAttribute('r', this.graphUnitsForPixels(4).toString());\n tip.setAttribute('stroke', '#ffffff');\n tip.setAttribute('stroke-width', this.graphUnitsForPixels(1.5).toString());\n group.appendChild(tip);\n this._tip_el = tip;\n }\n\n this.svg_element = group;\n return group;\n }\n\n update() {\n if (!this.svg_element) {\n this.create();\n }\n if (!this.svg_element.parentElement) {\n this.parent.appendChild(this.svg_element);\n }\n\n const dStr = this.__data__.path;\n if (this._path_el) {\n this._path_el.setAttribute('d', dStr);\n this._path_el.setAttribute('stroke', this.__data__.color.toString());\n this._path_el.setAttribute('stroke-width', this.graphUnitsForPixels(this.__data__.strokeWidth).toString());\n this._path_el.style.display = this.__data__.lineStyle === 'tapered' ? 'none' : 'block';\n }\n\n if (this._segments_group) {\n this._segments_group.innerHTML = '';\n if (this.__data__.lineStyle === 'tapered') {\n const pathPts = this.__data__.pathPoints;\n const nSegments = pathPts.length - 1;\n const [minWidth, maxWidth] = this.__data__.strokeWidthRange;\n const [minOpacity, maxOpacity] = this.__data__.opacityRange;\n\n for (let i = 0; i < nSegments; i++) {\n const start = pathPts[i];\n const end = pathPts[i + 1];\n const progress = nSegments <= 1 ? 1 : i / (nSegments - 1);\n const width = minWidth + (maxWidth - minWidth) * progress;\n const opacity = minOpacity + (maxOpacity - minOpacity) * progress;\n const segment = document.createElementNS('http://www.w3.org/2000/svg', 'path');\n\n segment.setAttribute('d', `M${start.x},${start.y} L${end.x},${end.y}`);\n segment.setAttribute('fill', 'none');\n segment.setAttribute('stroke', this.__data__.color.toString());\n segment.setAttribute('stroke-linecap', 'round');\n segment.setAttribute('stroke-linejoin', 'round');\n segment.setAttribute('stroke-width', this.graphUnitsForPixels(width).toString());\n segment.setAttribute('opacity', opacity.toString());\n this._segments_group.appendChild(segment);\n }\n this._segments_group.style.display = 'block';\n } else {\n this._segments_group.style.display = 'none';\n }\n }\n\n const pts = this.__data__.activePoints;\n\n if (this._points_group) {\n if (this.__data__.showPoints && pts.length > 0) {\n this._points_group.innerHTML = '';\n pts.forEach(pt => {\n const dot = document.createElementNS('http://www.w3.org/2000/svg', 'circle');\n dot.setAttribute('cx', pt.x.toString());\n dot.setAttribute('cy', pt.y.toString());\n dot.setAttribute('r', this.graphUnitsForPixels(2.5).toString());\n dot.setAttribute('fill', this.__data__.color.toString());\n dot.setAttribute('opacity', '0.7');\n this._points_group?.appendChild(dot);\n });\n this._points_group.style.display = 'block';\n } else {\n this._points_group.style.display = 'none';\n }\n }\n\n if (this._tip_el && this.__data__.showTips) {\n if (pts.length > 0) {\n const lastPt = pts[pts.length - 1];\n this._tip_el.setAttribute('cx', lastPt.x.toString());\n this._tip_el.setAttribute('cy', lastPt.y.toString());\n this._tip_el.setAttribute('fill', this.__data__.color.toString());\n this._tip_el.setAttribute('r', this.graphUnitsForPixels(4).toString());\n this._tip_el.setAttribute('stroke-width', this.graphUnitsForPixels(1.5).toString());\n this._tip_el.style.display = 'block';\n } else {\n this._tip_el.style.display = 'none';\n }\n }\n }\n\n draw() {\n if (this.svg_element && !this.svg_element.parentElement) {\n this.parent.appendChild(this.svg_element);\n }\n this.update();\n }\n}\n","import { Tools } from \"../utils/Tools\";\nimport { Graph } from \"../objects/Graph\";\nimport { Layer, LayerLike } from \"../objects/Layers\";\nimport { PlottedObject, Point } from \"../objects/PlottedObject\";\nimport { Trajectory } from \"../objects/Trajectory\";\nimport { QELine } from \"./QELine\";\nimport { QEPoint } from \"./QEPoint\";\nimport { QETrajectory } from \"./QETrajectory\";\nimport { QEGraphElement } from \"./QEGraph\";\n\n\nconst { ArrayTools } = Tools;\nexport class QEArray extends Array<any> {\n constructor(...args: any[]) {\n super(...args);\n }\n\n search(key: string, name: string): LayerLike | undefined {\n let found: LayerLike | undefined;\n\n function fn(a: LayerLike): LayerLike | undefined {\n return a.name === name ? a : undefined;\n }\n\n function recurse(obj: any, i?: number, parent: any = null): LayerLike | undefined {\n if (ArrayTools.isArray(obj)) {\n for (const [i, o] of obj.entries()) {\n found = recurse(o, i, parent);\n if (found) {\n return found;\n }\n }\n } else {\n found = fn(obj);\n if (!found) {\n if (obj && ArrayTools.isArray(obj[key])) {\n for (const [i, o] of obj[key].entries()) {\n found = recurse(o, i, obj);\n if (found) {\n return found;\n }\n }\n }\n } else {\n return found;\n }\n }\n return found;\n }\n\n return recurse(this);\n }\n\n flatten(): LayerLike[] {\n return this.reduce<LayerLike[]>((a, l: LayerLike) => {\n a.push(l);\n if (l.layers && Array.isArray(l.layers)) {\n a.push(...l.layers);\n }\n return a;\n }, []);\n }\n}\n\nexport interface QEElement {\n svg_element: SVGElement;\n graph: QEGraphElement;\n parent: SVGElement | null;\n __name__: string;\n __data__: Graph | PlottedObject | LayerLike;\n __children__: QEArray;\n draw(): void;\n update(): void;\n}\n\nconst\n QEElementConstructors: Record<string, new (d: any, p: SVGElement, g: QEGraphElement) => QEElement> =\n {\n \"AxisPoint\": QEPoint,\n \"AxisLine\": QELine,\n \"Point\": QEPoint,\n \"Line\": QELine,\n \"Edge\": QELine,\n \"TaperedEdge\": QELine,\n \"TaperedWeightedMidpointEdge\": QELine,\n \"NodeEdge\": QELine,\n \"Trajectory\": QETrajectory,\n }\n;\n\nexport class QELayer implements QEElement {\n static tagName = 'g';\n\n svg_element: SVGElement; \n __name__: string;\n\n constructor(\n public __data__: Layer, \n public parent: SVGElement, \n public graph: QEGraphElement,\n public __children__: QEArray = new QEArray(),\n ) {\n this.__name__ = __data__.name || \"unnamed-layer\";\n\n __data__.__state__.addListener(`layer_updated`, \"live\", ({ key, newValue, oldValue } : any) => {\n const childId = (child: QEElement) => (child.__data__ as PlottedObject)?.ID;\n\n const removing = this.__children__.filter((child: QEElement) =>\n !newValue.objects.has(childId(child))\n );\n const updating = this.__children__.filter((child: QEElement) =>\n newValue.objects.has(childId(child))\n );\n const adding = [...newValue.objects.values()].filter((obj: PlottedObject) =>\n !this.__children__.some((child: QEElement) => childId(child) === obj.ID)\n );\n\n adding.forEach((obj: PlottedObject) => {\n const obj_name = (obj as any)._typeName || obj.constructor.name;\n let constructor = QEElementConstructors[obj_name];\n if (!constructor) {\n if (obj instanceof Trajectory) constructor = QETrajectory;\n else if (obj instanceof Point) constructor = QEPoint;\n else constructor = QELine;\n }\n const ena_element: QEElement = new constructor(obj, this.svg_element, this.graph);\n this.__children__.push(ena_element);\n });\n\n updating.forEach((child: QEElement) => {\n // Pull the *new* PlottedObject from the updated layer data so that any\n // changed properties (e.g. weight, color, meta flags) are picked up by\n // the child's update() call.\n const newData = newValue.objects.get(childId(child)) as PlottedObject;\n if (newData) (child as any).__data__ = newData;\n child.update();\n });\n\n removing.forEach((child: QEElement) => {\n if (child.svg_element.parentElement) {\n child.svg_element.parentElement.removeChild(child.svg_element);\n }\n const idx = this.__children__.indexOf(child);\n if (idx >= 0) this.__children__.splice(idx, 1);\n });\n\n this.update();\n });\n\n this.svg_element = this.create();\n }\n\n get name() {\n return this.__name__;\n }\n\n create(): SVGElement {\n if(!this.__data__) {\n throw new Error(\"Layer is null\");\n }\n let layer: Layer = this.__data__ as Layer;\n this.svg_element = document.createElementNS(\"http://www.w3.org/2000/svg\", QELayer.tagName);\n this.svg_element.setAttribute('data-layer-name', layer.name);\n this.svg_element.setAttribute('data-layer-id', layer.ID);\n\n (this.svg_element as any).__data__ = layer;\n\n this.svg_element.classList.add('ena-layer');\n\n if(this.__data__.layers && this.__data__.layers.length > 0) {\n this.__data__.layers.forEach((sublayer: LayerLike) => {\n const layer_g: QELayer = new QELayer(sublayer as any, this.svg_element, this.graph);\n this.__children__.push(layer_g);\n });\n }\n\n return this.svg_element;\n }\n\n update() {\n if(!this.__data__) {\n throw new Error(\"Layer is null\");\n }\n\n if(this.__data__.visible) {\n // Update layer properties here\n if(this.parent.nodeName.toLowerCase() === \"svg\") {\n // Compute the transform string based on the size of the parent SVG elemet. \n // -- a circle with radius 1 should be scaled to the size of the parent SVG element, \n // so that as the graph is zoomed in and out, the circle scales with it.\n // this.svg_element.style.transform = `scale(${this.parent.clientWidth / 100}, ${this.parent.clientHeight / 100})`;\n }\n\n // Update sublayers\n this.__children__.forEach((child: QEElement) => {\n child.update();\n });\n\n if(this.__data__.scale_objects === true) {\n if(this.__name__ === \"points\") {\n // this.svg_element.setAttribute('transform', `\n // scale(${this.graph.__data__.scale_x}, ${this.graph.__data__.scale_y})\n // `);\n }\n }\n else {\n // this.svg_element.setAttribute('transform', `scale(${this.graph.x_mirror()}, ${this.graph.y_mirror()})`); \n }\n }\n }\n\n draw(): void {\n this.parent?.appendChild(this.svg_element);\n\n this.__children__.forEach((child: QEElement) => {\n child.draw();\n });\n }\n\n add(child: QEElement) {\n this.__children__.push(child);\n }\n}","import { Label, Point } from \"../objects/PlottedObject\";\nimport { QEGraphElement } from \"./QEGraph\";\n\n/**\n * SVG <text> drawable for a single ENA label.\n *\n * ── Display modes (Label.DISPLAY_TYPES) ──────────────────────────────────────\n * OFF (0) — never shown\n * AUTO (1) — shown on mouseover of the associated point, hidden on mouseout\n * CLICK (2) — toggled by clicking the associated point\n * ON (3) — always shown\n *\n * ── Position modes (Label.POSITION) ─────────────────────────────────────────\n * OBJECT (1) — offset near the point (quadrant-aware, default)\n * STATIC (2) — centered directly on the point (no offset; label overlaps point)\n * CONTAINER (3) — projected to the viewBox boundary in the point's direction;\n * useful for code-node labels that appear at the outer ring\n * CUSTOM (4) — caller provides explicit (customX, customY) coordinates\n */\nexport class QELabel {\n svg_element: SVGTextElement;\n private _visible: boolean = false;\n // Drag offset (graph-space units) and pin state for host-repositionable labels.\n private _offsetX = 0;\n private _offsetY = 0;\n pinned = false;\n\n constructor(\n public readonly text: string,\n public readonly point: Point,\n public readonly parent: SVGElement,\n public readonly graph: QEGraphElement,\n public readonly displayMode: number = Label.DISPLAY_TYPES.ON,\n public readonly position: number = Label.POSITION.OBJECT,\n public customX?: number,\n public customY?: number,\n ) {\n this.svg_element = this._create();\n\n // Set initial visibility without calling update() yet.\n // The QEGraphElement calls update_labels() after update_extremes() so that\n // the first real positioning uses the correct graph extent, not the default 1.\n if (displayMode === Label.DISPLAY_TYPES.ON) {\n this._visible = true;\n this.svg_element.setAttribute('display', 'block');\n } else {\n this._visible = false;\n this.svg_element.setAttribute('display', 'none');\n }\n }\n\n private _create(): SVGTextElement {\n const el = document.createElementNS('http://www.w3.org/2000/svg', 'text') as SVGTextElement;\n el.textContent = this.text;\n el.setAttribute('data-label-for', this.point.ID);\n el.setAttribute('pointer-events', 'auto'); // draggable\n el.style.cursor = 'grab';\n this._attachDrag(el);\n this.parent.appendChild(el);\n return el;\n }\n\n /** Drag to reposition; pins the label open and emits qe-label-move on drop. */\n private _attachDrag(el: SVGTextElement): void {\n el.addEventListener('mousedown', (ev: MouseEvent) => {\n ev.preventDefault();\n ev.stopPropagation(); // don't start a graph pan\n const svg = el.ownerSVGElement;\n if (!svg) return;\n const toUser = (cx: number, cy: number) => {\n const p = svg.createSVGPoint(); p.x = cx; p.y = cy;\n const m = svg.getScreenCTM();\n return m ? p.matrixTransform(m.inverse()) : ({ x: 0, y: 0 } as DOMPoint);\n };\n const start = toUser(ev.clientX, ev.clientY);\n const baseX = this._offsetX, baseY = this._offsetY;\n el.style.cursor = 'grabbing';\n\n const onMove = (e: MouseEvent) => {\n const p = toUser(e.clientX, e.clientY);\n this._offsetX = baseX + (p.x - start.x);\n this._offsetY = baseY + (p.y - start.y);\n this.pinned = true; // keep it shown once moved\n this._visible = true;\n this.svg_element.setAttribute('display', 'block');\n this.update();\n };\n const onUp = () => {\n document.removeEventListener('mousemove', onMove);\n document.removeEventListener('mouseup', onUp);\n el.style.cursor = 'grab';\n // Public event so the host can persist / mirror across coordinated plots.\n this.graph.dispatchEvent(new CustomEvent('qe-label-move', {\n detail: { id: this.point.ID, transform: { x: this._offsetX, y: this._offsetY } },\n bubbles: true, composed: true,\n }));\n };\n document.addEventListener('mousemove', onMove);\n document.addEventListener('mouseup', onUp);\n });\n }\n\n /**\n * Recompute position and font-size from current graph extents.\n * No-ops when the label is hidden (AUTO/CLICK modes while not hovered/clicked).\n */\n update(): void {\n if (!this._visible) return;\n\n const extent = this.graph.__data__.extremes.x_max;\n if (extent <= 0) return; // graph not initialised yet\n\n // qe_labels(font_size =) is in CSS pixels (constant on screen); default\n // scales with the plot extent.\n const font = (this.graph as any)._labelFont ?? {};\n const fontSize = font.size ? font.size * (this.graph as any).unitsPerPixel() : extent * 0.06;\n const offset = fontSize * 1.2;\n\n let x: number, y: number, anchor: string;\n\n switch (this.position) {\n\n case Label.POSITION.STATIC: {\n // Centered on the point — label sits at exactly the point's coordinates.\n // Useful when the caller wants to control offset manually via customX/Y.\n x = this.point.x;\n y = this.point.y - offset * 0.3;\n anchor = 'middle';\n break;\n }\n\n case Label.POSITION.CONTAINER: {\n // Project from the view's centre (the origin, unless center=\"content\")\n // through the point onto the viewBox boundary. Labels ring the outer\n // edge of the plot, one per code/group direction.\n const { cx, cy } = this.graph.__data__.extremes;\n const px = this.point.x - cx;\n const py = this.point.y - cy;\n const dist = Math.sqrt(px * px + py * py) || 1;\n const scale = (extent * 0.93) / dist;\n x = cx + px * scale;\n y = cy + py * scale - offset * 0.3;\n anchor = px >= 0 ? 'start' : 'end';\n break;\n }\n\n case Label.POSITION.CUSTOM: {\n // Caller-provided coordinates; fall back to OBJECT behaviour if unset.\n if (this.customX != null && this.customY != null) {\n x = this.customX;\n y = this.customY;\n anchor = 'start';\n break;\n }\n // fall through to OBJECT\n }\n\n default:\n case Label.POSITION.OBJECT: {\n // Quadrant-aware offset: push label away from origin.\n const dx = this.point.x >= 0 ? offset : -offset;\n anchor = this.point.x >= 0 ? 'start' : 'end';\n x = this.point.x + dx;\n y = this.point.y - offset * 0.4;\n break;\n }\n }\n\n this.svg_element.setAttribute('x', x.toString());\n this.svg_element.setAttribute('y', y.toString());\n // Host drag offset (graph-space units) composes on top of the computed spot.\n if (this._offsetX || this._offsetY) {\n this.svg_element.setAttribute('transform', `translate(${this._offsetX}, ${this._offsetY})`);\n }\n this.svg_element.setAttribute('font-size', fontSize.toString());\n this.svg_element.setAttribute('font-family', font.family ?? 'system-ui, sans-serif');\n this.svg_element.setAttribute('font-weight', '500');\n this.svg_element.setAttribute('text-anchor', anchor);\n this.svg_element.setAttribute('fill', font.color ?? this.point.color?.toString() ?? '#333333');\n }\n\n /** Make the label visible and position it immediately. */\n show(): void {\n this._visible = true;\n this.svg_element.setAttribute('display', 'block');\n this.update();\n }\n\n hide(): void {\n if (this.pinned) return; // a dragged/pinned label stays visible\n this._visible = false;\n this.svg_element.setAttribute('display', 'none');\n }\n\n toggle(): void {\n this._visible ? this.hide() : this.show();\n }\n\n get visible(): boolean { return this._visible; }\n\n remove(): void {\n this.svg_element.remove();\n }\n}\n","/**\n * Declarative child layer elements for <qe-graph>.\n *\n * Each element is an inert configuration holder — no shadow DOM, no rendering\n * logic. <qe-graph> reads their presence and attributes via querySelector() to\n * configure each rendering layer.\n *\n * Presence = the layer is rendered.\n * Absence = the layer is hidden. (Code-node positions come from the\n * model and anchor the coordinate space whether or not\n * <qe-nodes> is present; the element only controls drawing.)\n *\n * HTML authoring example:\n *\n * <qe-graph width=\"100%\" height=\"440\">\n * <qe-nodes label=\"on\"></qe-nodes>\n * <qe-means groups=\"FirstGame,SecondGame\" confidence></qe-means>\n * <qe-points label=\"auto\"></qe-points>\n * <qe-edges group=\"FirstGame\" compare=\"SecondGame\"></qe-edges>\n * </qe-graph>\n */\n\n/**\n * <qe-nodes> — renders the code nodes.\n * Presence = draw nodes; absence = hide them (positions still set the extent).\n * A node's diameter equals the summed widths of its drawn edges: every edge\n * touching it (undirected), or the wide ends of the edges directed at it,\n * including its self-connection (directed / ONA).\n *\n * Attributes:\n * label \"on\" | \"off\" | \"click\" | \"auto\" (default \"on\")\n * unconnected \"dot\" (default) — nodes with no drawn edges show as a tiny\n * dot; \"hide\" — hide them (and their labels).\n */\nexport class QENodesElement extends HTMLElement {\n static tagName = 'qe-nodes' as const;\n}\n\n/**\n * <qe-means> — renders group mean markers and optional CI boxes.\n * Presence = show means; absence = hide means.\n *\n * Attributes:\n * groups Comma-separated group names to show. Omit for all groups.\n * confidence Boolean — show 95% CI rectangles.\n * label \"on\" | \"off\" | \"click\" | \"auto\" (default \"on\")\n * fixed-size Boolean — keep mean markers a constant on-screen pixel size\n * regardless of data extent, container size, or zoom (default:\n * markers scale with the coordinate space, like nodes and edges).\n */\nexport class QEMeansElement extends HTMLElement {\n static tagName = 'qe-means' as const;\n}\n\n/**\n * <qe-points> — renders individual unit scatter dots.\n * Presence = show unit points; absence = hide unit points.\n *\n * Attributes:\n * label \"on\" | \"off\" | \"click\" | \"auto\" (default \"auto\")\n * size Numeric dot size (default 2.5), relative to the code-node size.\n * fixed-size Boolean — keep unit dots a constant on-screen pixel size\n * regardless of data extent, container size, or zoom (default:\n * dots scale with the coordinate space, like nodes and edges).\n */\nexport class QEPointsElement extends HTMLElement {\n static tagName = 'qe-points' as const;\n}\n\n/**\n * <qe-edges> — renders an edge network.\n * Presence = draw edges; absence = no edge network.\n *\n * Attributes:\n * group Group name whose mean network to draw.\n * unit Individual unit ID whose personal network to draw\n * (e.g. \"FirstGame::steven z\"). Mutually exclusive with `group`.\n * compare Second group to subtract (group − compare).\n * also Second group to overlay alongside `group`.\n * scale Reference node weight for mark sizes — the node drawn at\n * <qe-graph mark-size> × the plot width (edge widths follow):\n * \"model\" (default) — the largest node among the model's\n * group-mean networks, so separate plots of\n * one model are comparable;\n * \"plot\" — this plot's own largest node;\n * <number> — a fixed node weight.\n * magnify Multiply this plot's edge widths and node sizes (not colour),\n * e.g. to read a faint subtraction. Whenever the attribute is\n * present — any value, including \"1\" — the plot is labelled\n * \"(scaled N.Nx)\", so exported plots state their scaling.\n * color-scale How |weight| maps onto webENA's colour ramps (saturation\n * 0.25–1, opacity 0.3–1):\n * \"model\" (default) — rescaled from the model's smallest to largest\n * non-zero weight (every unit), so plots of one\n * model share a colour scale;\n * \"plot\" — rescaled within this plot (webENA);\n * \"absolute\" — no ramps: saturation = opacity = |weight|.\n */\nexport class QEEdgesElement extends HTMLElement {\n static tagName = 'qe-edges' as const;\n}\n\n/**\n * <qe-trajectories> — renders epistemic cognitive trajectory curves and steps.\n * Presence = draw trajectories; absence = no trajectories.\n *\n * Attributes:\n * units Comma-separated unit IDs to show. Omit for all.\n * smooth \"none\" | \"poly\" (default \"none\")\n * max-degree Upper bound on polynomial degree if smooth=\"poly\" (default 3)\n * degree-selection \"loocv_2d\" | \"fixed\" (default \"loocv_2d\"). \"loocv_2d\"\n * picks the degree in 1..max-degree by joint 2D leave-one-out CV;\n * \"fixed\" always uses max-degree. Near-origin points are excluded\n * from the fit (still drawn).\n * points \"true\" | \"false\" — show discrete point markers along trajectory\n * tips \"true\" | \"false\" — show leading tip marker\n * playhead Number — current turn / time index for filtering/animation\n * line-style \"uniform\" | \"tapered\" (default \"uniform\")\n * stroke-width Number (default 2)\n * stroke-width-range \"min,max\" for tapered lines (default \"1,6\")\n * opacity-range \"min,max\" for tapered lines (default \"0.3,1\")\n */\nexport class QETrajectoriesElement extends HTMLElement {\n static tagName = 'qe-trajectories' as const;\n}\n\n/**\n * <qe-axes> — renders the x/y axis lines and, per axis, an optional title.\n * Presence = draw axes; absence = no axes.\n *\n * Attributes:\n * x Show the x-axis label. A value sets custom text; an empty/boolean\n * attribute defaults to the x dimension name (e.g. \"SVD1\").\n * y Show the y-axis label. Same rule with the y dimension name.\n *\n * Examples:\n * <qe-axes></qe-axes> lines only, no labels\n * <qe-axes x y></qe-axes> \"SVD1\" / \"SVD2\"\n * <qe-axes x=\"Task focus\" y> \"Task focus\" / \"SVD2\"\n */\nexport class QEAxesElement extends HTMLElement {\n static tagName = 'qe-axes' as const;\n}\n\ncustomElements.define(QENodesElement.tagName, QENodesElement);\ncustomElements.define(QEMeansElement.tagName, QEMeansElement);\ncustomElements.define(QEPointsElement.tagName, QEPointsElement);\ncustomElements.define(QEEdgesElement.tagName, QEEdgesElement);\ncustomElements.define(QETrajectoriesElement.tagName, QETrajectoriesElement);\ncustomElements.define(QEAxesElement.tagName, QEAxesElement);\n","import { DefaultGraphOptions, Graph } from \"../objects/Graph\";\nimport { DrawableElement } from \"./DrawableElement\";\nimport { QEArray, QEElement, QELayer } from \"./QELayer\";\nimport QEVisualElement from \"./QEVisual\";\nimport { DataFrameRow } from \"../types/DataFrame\";\nimport { NodeEdge, TaperedWeightedMidpointEdge } from \"../objects/Edges\";\nimport { Label, Line, Point } from \"../objects/PlottedObject\";\nimport { Trajectory } from \"../objects/Trajectory\";\nimport { LayerLike } from \"../objects/Layers\";\nimport { Color } from \"../objects/Color\";\nimport { Extremes } from \"../objects/Extremes\";\nimport { QELabel } from \"./QELabel\";\nimport { DEFAULT_EDGE_WIDTH, OPACITY_RANGE, SATURATION_RANGE, UNCONNECTED_NODE_SIZE, nodeSizeForEdges, rampFor, widthPerWeight } from \"../objects/Sizing\";\nimport \"./QEChildElements.js\";\n\n// Accessible color palette for group assignment (Paul Tol's bright scheme)\nconst GROUP_PALETTE = [\n '#4477AA', '#EE6677', '#228833', '#CCBB44',\n '#66CCEE', '#AA3377', '#BBBBBB', '#000000',\n];\n\n/**\n * Parse an edge column name into the two code IDs it connects.\n * Edge columns use \".\" as separator between the two codes, but codes can\n * themselves contain \".\" (e.g. \"Technical.Constraints\"). We resolve the\n * ambiguity by trying every prefix that matches a known code.\n *\n * Self-connections (\"A.A\") are detected first — they return [A, A].\n * In directed (ONA) mode the full unfolded matrix is expected, so A→B and\n * B→A are distinct columns; both resolve correctly as ordered pairs.\n */\nfunction parseEdgePair(colName: string, codes: string[]): [string, string] | null {\n // Self-connections first: exact match \"code.code\"\n for (const c of codes) {\n if (colName === `${c}.${c}`) return [c, c];\n }\n // Directed or undirected pairs: longest-prefix wins to handle dotted code names\n for (const c1 of codes) {\n if (colName.startsWith(c1 + '.')) {\n const c2 = colName.slice(c1.length + 1);\n if (codes.includes(c2)) return [c1, c2];\n }\n }\n return null;\n}\n\n/**\n * Compute half-width and half-height for a 95% CI rectangle on the group mean.\n *\n * Each axis is treated independently: half-extent = t(df,0.975) × SE,\n * where SE = sqrt(variance / n) and df = n − 1. This matches the standard\n * ENA rectangular CI displayed in the rENA / Web ENA tools.\n *\n * Inputs are the *raw* (un-scaled) variances; pointScale is applied here so\n * the returned values are in SVG coordinate space.\n */\nfunction computeCIRect(\n varX: number, varY: number, n: number, pointScale: number\n): { halfW: number; halfH: number } {\n // t(df, 0.975) — rough approximation good to ±0.02 for df ≥ 3\n const df = Math.max(1, n - 1);\n const t95 = df >= 120 ? 1.960\n : df >= 60 ? 2.000\n : df >= 30 ? 2.042\n : df >= 20 ? 2.086\n : df >= 10 ? 2.228\n : df >= 5 ? 2.571\n : 4.303; // df = 1\n const seX = Math.sqrt(Math.max(0, varX) / n) * pointScale;\n const seY = Math.sqrt(Math.max(0, varY) / n) * pointScale;\n return { halfW: t95 * seX, halfH: t95 * seY };\n}\n\n/** Mean markers never exceed this fraction of their interval box's shorter\n * half-side. Marker size is otherwise arbitrary (extent- or pixel-based), so\n * without a cap a tight CI disappears underneath the mean square. */\nconst MEAN_MAX_FRACTION_OF_INTERVAL = 0.5;\n\nfunction capMeanToInterval(meanPt: Point | undefined, halfW: number, halfH: number): void {\n if (!meanPt) return;\n const half = Math.min(Math.abs(halfW), Math.abs(halfH));\n if (!(half > 0)) return; // degenerate interval (n = 1, zero variance): keep default size\n (meanPt as any).meta = { ...((meanPt as any).meta ?? {}), maxRadius: half * MEAN_MAX_FRACTION_OF_INTERVAL };\n}\n\nfunction readIntervalBounds(\n row: DataFrameRow, dim0: string, dim1: string, prefix = ''\n): { x_low: number; x_high: number; y_low: number; y_high: number } | null {\n // prefix '' → CI ({dim}.low / .high); 'o' → outlier ({dim}.olow / .ohigh).\n const get = (col: string) => {\n const i = row.names.indexOf(col);\n const raw = i >= 0 ? row[i] : null;\n if (raw == null || raw === '') return undefined; // Number(null) would be 0\n const v = Number(raw);\n return Number.isFinite(v) ? v : undefined;\n };\n const xLow = get(`${dim0}.${prefix}low`) ?? get(`${dim0}_${prefix}low`);\n const xHigh = get(`${dim0}.${prefix}high`) ?? get(`${dim0}_${prefix}high`);\n const yLow = get(`${dim1}.${prefix}low`) ?? get(`${dim1}_${prefix}low`);\n const yHigh = get(`${dim1}.${prefix}high`) ?? get(`${dim1}_${prefix}high`);\n if (xLow == null || xHigh == null || yLow == null || yHigh == null) return null;\n return { x_low: xLow, x_high: xHigh, y_low: yLow, y_high: yHigh };\n}\n\n/**\n * <qe-edges color-scale>: the range that edge weights are rescaled from onto\n * webENA's saturation (0.25–1) and opacity (0.3–1) ramps.\n * \"model\" (default) — min / max non-zero |weight| across the whole model\n * (every unit), so separate plots of one model share\n * one colour scale.\n * \"plot\" — this plot's own min / max (webENA's per-network\n * behaviour).\n * \"absolute\" — no rescaling: saturation = opacity = |weight|.\n */\ntype ColorScale = 'model' | 'plot' | 'absolute';\n\n/** One <qe-edges> element: a named network or an explicit `network` row. */\ntype EdgeLayerSpec = {\n group: string | null; unit: string | null;\n compare: string | null; also: string | null;\n network: string | null;\n colors: [string, string | null] | null; // positive, negative (null → complement)\n threshold: [number, number] | null; // min, max (max = Infinity when omitted)\n name: string | null;\n};\n\nfunction parseEdgeLayer(el: Element): EdgeLayerSpec {\n const a = (k: string) => el.getAttribute(k);\n const cols = a('colors')?.split(',').map(c => c.trim()).filter(Boolean) ?? [];\n const thr = a('threshold')?.split(',').map(Number).filter(Number.isFinite) ?? [];\n return {\n group: a('group'), unit: a('unit'), compare: a('compare'), also: a('also'),\n network: a('network'),\n colors: cols.length ? [cols[0], cols[1] ?? null] : null,\n threshold: thr.length ? [thr[0], thr.length > 1 ? thr[1] : Infinity] : null,\n name: a('name'),\n };\n}\n\n/** Complementary hue (rENA: one colour → negatives use hue + 180°). */\nfunction complementColor(hex: string): string {\n const { r, g, b } = Color.parseColor(hex);\n const mx = Math.max(r, g, b), mn = Math.min(r, g, b);\n const f = (c: number) => (mx + mn - c).toString(16).padStart(2, '0');\n return `#${f(r)}${f(g)}${f(b)}`;\n}\n\nfunction parseColorScale(attr: string | null): ColorScale {\n const a = attr?.trim().toLowerCase();\n return a === 'plot' || a === 'absolute' ? a : 'model';\n}\n\n/**\n * Parse a label-mode attribute string into a Label.DISPLAY_TYPES integer.\n * \"on\" → 3 (ON)\n * \"off\" → 0 (OFF)\n * \"click\" → 2 (CLICK)\n * \"auto\" → 1 (AUTO)\n * Returns `defaultMode` for any unrecognized value or null.\n */\nfunction parseLabelMode(attr: string | null, defaultMode: number): number {\n switch (attr?.toLowerCase()) {\n case 'on': return 3;\n case 'off': return 0;\n case 'click': return 2;\n case 'auto': return 1;\n default: return defaultMode;\n }\n}\n\nexport class QEGraphElement extends DrawableElement implements QEElement {\n static tagName: string = \"qe-graph\";\n\n static get observedAttributes(): string[] {\n // Only layout / shorthand attributes live on <qe-graph> itself.\n // Layer-specific config (group, unit, compare, also, points, edges,\n // confidence, groups) lives on child elements and is observed via\n // MutationObserver in connectedCallback().\n return [\n 'width', 'height', 'for',\n 'scale-points', 'point-scale', 'center',\n 'labels', 'label-nodes', 'label-means', 'label-points',\n ];\n }\n\n static style: string = `\n ${DrawableElement.style}\n\n :host {\n display: block;\n }\n\n .wrapper {\n width: 100%;\n height: 100%;\n }\n\n svg {\n width: 100%;\n height: 100%;\n aspect-ratio: 1 / 1;\n background-color: #FFF;\n }\n `;\n\n svg_element: SVGElement;\n graph: QEGraphElement;\n parent: SVGElement | null;\n zoom_level: number = 1;\n\n __data__: Graph;\n __children__: QEArray = new QEArray();\n __name__: string;\n \n\n private _vizena!: QEVisualElement;\n get vizena() {\n return this._vizena;\n }\n\n private _hasModel = false;\n private _renderPending = false;\n private _childObserver: MutationObserver | null = null;\n\n // SVG <rect> elements for per-group CI boxes, keyed by group name.\n // Managed directly (not via QELayer) so they render behind unit points.\n private _ciRects: Map<string, SVGRectElement> = new Map();\n private _outlierRects: Map<string, SVGRectElement> = new Map();\n private _ciCross: Map<string, SVGPathElement> = new Map();\n\n // Cached reference to the labels <g> layer — set once in connectedCallback()\n // after draw() so it is guaranteed to be in the SVG DOM.\n private _labelsGroup: SVGGElement | null = null;\n\n // SVG <text> label elements for nodes, mean points, and unit points.\n private _nodeLabels: Map<string, QELabel> = new Map();\n private _meanLabels: Map<string, QELabel> = new Map();\n private _pointLabels: Map<string, QELabel> = new Map();\n\n // Axes (<qe-axes>): whether to show axis lines, and resolved label text\n // (null = no label for that axis). SVG <text> nodes are cached and positioned\n // in update_axis_labels() using the freshly-computed extremes.\n private _showAxes = false;\n private _axisXText: string | null = null;\n private _axisYText: string | null = null;\n private _axisLabelEls: Map<'x' | 'y', SVGTextElement> = new Map();\n // \"(scaled 1.5x)\" label, drawn whenever <qe-edges magnify> is present.\n private _magnifyText: string | null = null;\n private _magnifyEl: SVGTextElement | null = null;\n // <qe-graph range> / plot-title / label-font-* (qe_plot(range =, title =),\n // qe_labels(font_*)); resolved each render.\n private _rangeExtent: number | null = null;\n private _rangeMode: 'network' | 'points' | 'number' | null = null;\n /** center=\"content\": centre the view on the drawn content, not the origin */\n private _centerContent = false;\n private _plotTitle: string | null = null;\n private _titleEl: SVGTextElement | null = null;\n private _resizeObs: ResizeObserver | null = null;\n _labelFont: { size: number | null; family: string | null; color: string | null } =\n { size: null, family: null, color: null };\n\n /** SVG user units per CSS pixel at the current size / zoom. */\n unitsPerPixel(): number {\n const extent = this.__data__.extremes.x_max || 1;\n const rect = this.svg_element?.getBoundingClientRect?.();\n const zoom = (this as any).zoom_level || 1;\n return rect && rect.width > 0 ? (2 * extent / rect.width) / zoom : extent * 0.004;\n }\n\n constructor() {\n super();\n\n this.graph = this;\n this.parent = null;\n\n this.__data__ = new Graph(DefaultGraphOptions);\n this.__name__ = this.__data__.name || \"unnamed-graph\";\n this.svg_element = this.create();\n\n console.log(\"Created ena-graph svg element: \", this.svg_element);\n\n // Listen for the model-updated CustomEvent dispatched by VisualQEElement.\n // The Model object is carried in event.detail, so ena-graph works whether it\n // is a child, sibling, or anywhere else relative to ena-visual.\n document.addEventListener('model-updated', (e: Event) => {\n // When multiple qe-visual elements exist on the page, each qe-graph must\n // only react to events from its own associated visual. _vizena is resolved\n // in connectedCallback(); before that point we accept all events (initial\n // load), but once the association is known we filter strictly.\n // composedPath()[0]: inside a shadow root (e.g. a qe-visual in another\n // component), e.target is retargeted to the shadow host\n const origin = e.composedPath?.()[0] ?? e.target;\n if (this._vizena && origin !== this._vizena) return;\n\n const model = (e as CustomEvent).detail;\n if (!model) return;\n\n // Tweening (opt-in via `animate`): snapshot current mark/edge positions\n // BEFORE the rebuild so we can animate old→new after this.update().\n this._animateMs = this.hasAttribute('animate')\n ? (parseInt(this.getAttribute('animate') || '', 10) || 300)\n : 0;\n const tweenFrom = (this._animateMs > 0 && this._hasModel) ? this._captureTween() : null;\n\n this._hasModel = true;\n\n const dims = model.dimensions as string[];\n\n // Resolved column names from setModelData (auto-detected or caller-supplied)\n const unitIdCol = model.unit_id_col;\n const nodeIdCol = model.node_id_col;\n const groupColName = model.group_col;\n\n // ── Layer config (read once from child elements) ─────────────────────────\n const config = this._readLayerConfig();\n\n // ── Axes (<qe-axes>) ─────────────────────────────────────────────────────\n // Resolve label text now that dims are known: empty x/y attribute falls\n // back to the dimension name; a value is used verbatim; null = no label.\n this._showAxes = config.showAxes;\n this._axisXText = config.axisXLabel === null ? null : (config.axisXLabel || String(dims?.[0] ?? 'x'));\n // Present on any <qe-edges magnify>, including \"1\" — as webENA labels\n // its side plots \"(scaled 1.0x)\" so an exported set says which plot was\n // magnified.\n this._magnifyText = config.edgeMagnify == null ? null\n : `(scaled ${config.edgeMagnify.toFixed(1)}x)`;\n this._axisYText = config.axisYLabel === null ? null : (config.axisYLabel || String(dims?.[1] ?? 'y'));\n\n // ── Group color map ──────────────────────────────────────────────────────\n // Priority: (1) points groupCol, (2) groups frame row names, (3) empty.\n const groupColorMap: Record<string, string> = {};\n // Model palette (qe_plot(palette =)) or the default Tol \"bright\" scheme.\n const PALETTE: string[] = (model as any).palette?.length ? (model as any).palette : GROUP_PALETTE;\n if (groupColName && model.points?.names) {\n const groupCol = model.points.col(groupColName);\n if (groupCol) {\n const uniqueGroups: string[] = [...new Set([...groupCol].map(String))];\n uniqueGroups.forEach((g, i) => {\n groupColorMap[g] = PALETTE[i % PALETTE.length];\n });\n }\n }\n // Groups-frame rows: a `color` column overrides the palette, and rows that\n // are not groups of the points (e.g. the mean of an arbitrary subset,\n // qe_group(points =)) still get a colour so they count as known groups.\n if (model.groups?.rows && model.groups.rows().length > 0) {\n model.groups.rows().forEach((row: DataFrameRow) => {\n const g = row.rowName ?? String(row[0]);\n const ci = row.names.indexOf('color');\n const c = ci >= 0 ? row[ci] : null;\n if (c && String(c) !== 'NA') groupColorMap[g] = String(c);\n else if (!groupColorMap[g]) {\n groupColorMap[g] = PALETTE[Object.keys(groupColorMap).length % PALETTE.length];\n }\n });\n }\n\n // ── Active groups for MEANS display ─────────────────────────────────────\n // `groups` attribute: comma-separated list of group names whose means and\n // CI boxes should be rendered. Default (attribute absent or empty): show\n // means for ALL groups present in the model.\n //\n // Means display is intentionally independent of edge selection. The edge\n // section below reads `group` / `compare` / `also` to determine which\n // network(s) to draw; those attributes have no effect here.\n const _allGroupNames_ = Object.keys(groupColorMap);\n const activeMeanGroups: Set<string> = (config.activeMeanGroups && config.activeMeanGroups.trim())\n ? new Set(\n config.activeMeanGroups.split(',')\n .map(s => s.trim())\n .filter(g => groupColorMap[g]) // silently drop names not in model\n )\n : new Set(_allGroupNames_); // default: every group\n\n // ── Point-to-node coordinate scaling ────────────────────────────────────\n // Unit point coordinates are in a different (typically much smaller) range\n // Unit/mean point coordinates are rescaled by default so the outermost point\n // aligns with the outermost code node — matching the ENA Web Tool default.\n // Set scale-points=\"false\" on <qe-graph> to show raw SVD coordinates\n // (points cluster near origin relative to code nodes).\n const scalePointsEnabled = config.scalePoints;\n\n const getExtent = (rows: DataFrameRow[]): number => {\n let max = 0;\n rows.forEach(row => {\n const xIdx = row.names.indexOf(dims[0]);\n const yIdx = dims.length > 1 ? row.names.indexOf(dims[1]) : -1;\n if (xIdx >= 0) max = Math.max(max, Math.abs(Number(row[xIdx])));\n if (yIdx >= 0) max = Math.max(max, Math.abs(Number(row[yIdx])));\n });\n return max;\n };\n\n const maxNodeExtent = model.nodes?.rows ? getExtent(model.nodes.rows()) : 0;\n const maxPointExtent = model.points?.rows ? getExtent(model.points.rows()) : 0;\n const maxTrajExtent = model.trajectories?.rows ? getExtent(model.trajectories.rows()) : 0;\n const effectivePointExtent = maxPointExtent > 0 ? maxPointExtent : maxTrajExtent;\n // point-scale=\"N\" (optional, unset by default): an explicit factor, e.g.\n // 1 for raw coordinates or another tool's rescaling, instead of fitting\n // the outermost point to the outermost node\n const pointScale = config.pointScale !== null ? config.pointScale\n : (scalePointsEnabled && effectivePointExtent > 0 && maxNodeExtent > 0)\n ? maxNodeExtent / effectivePointExtent\n : 1;\n\n // <qe-graph range>: a symmetric axis range, as rENA's scale.to —\n // \"network\" = ±max |node| × 1.2, \"points\" = ±max |drawn point| × 1.2, or\n // a number. Absent → qeviz's default (1.3 × the largest drawn mark).\n this._rangeExtent =\n config.range === 'network' ? maxNodeExtent * 1.2\n : config.range === 'points' ? effectivePointExtent * pointScale * 1.2\n : typeof config.range === 'number' ? config.range\n : null;\n this._rangeMode = config.range === 'network' || config.range === 'points' ? config.range\n : typeof config.range === 'number' ? 'number' : null;\n this._centerContent = config.centerContent;\n this._plotTitle = config.plotTitle;\n this._labelFont = config.labelFont;\n\n // ── Label display modes — sourced from config (child elements or shorthand) ──\n const labelNodes = config.labelNodes;\n const labelMeans = config.labelMeans;\n const labelPoints = config.labelPoints;\n\n // Use the cached labels <g> reference (set once in connectedCallback).\n const labelSvg = this._labelsGroup;\n\n // ── Helper: build a Point from a DataFrame row ───────────────────────────\n // Looks up dimension values by column name so it works with any data format.\n // Y is negated because SVG y-axis points down while ENA convention is y-up.\n // `scale` multiplies x/y — use pointScale for unit/mean points, 1 for nodes.\n const rowToPoint = (row: DataFrameRow, idCol: string, colorStr?: string, scale = 1): Point => {\n const idIdx = row.names.indexOf(idCol);\n const xIdx = row.names.indexOf(dims[0]);\n const yIdx = dims.length > 1 ? row.names.indexOf(dims[1]) : -1;\n const pt = new Point({\n ID: idIdx >= 0 ? String(row[idIdx]) : (row.rowName || `pt-${Math.random().toString(36).slice(2)}`),\n dimensions: [\n xIdx >= 0 ? Number(row[xIdx]) * scale : 0,\n yIdx >= 0 ? -Number(row[yIdx]) * scale : 0, // negate Y: SVG y-down vs ENA y-up\n ],\n meta: {},\n });\n if (colorStr) pt.color = new Color(colorStr);\n return pt;\n };\n\n // ── Unit points + group means ────────────────────────────────────────────\n // groupSums is used later for mean edges and CI ellipses.\n // x2/y2/xy accumulate Σ(raw²) for variance computation.\n const groupSums: Record<string, {\n x: number; y: number; x2: number; y2: number; xy: number;\n n: number; color: string;\n }> = {};\n\n // <qe-points> presence controls unit-dot visibility.\n // <qe-means> presence controls mean markers and CI boxes.\n const showUnitPoints = config.showPoints;\n\n // ── Explicit point sets (qe_points(units =, points =)) ─────────────────\n // Each <qe-points set=\"…\"> draws that set's rows of model.pointsets, on\n // the same point scale as the unit points.\n const pointSetFrame = (model as any).pointsets;\n if (config.pointSets.length && pointSetFrame?.rows) {\n const psLayer = this.__children__.search('__children__', 'points') as QELayer;\n const col = (r: DataFrameRow, k: string) => { const i = r.names.indexOf(k); return i >= 0 ? r[i] : null; };\n config.pointSets.forEach((ps, si) => {\n pointSetFrame.rows().forEach((row: DataFrameRow) => {\n if (String(col(row, 'set')) !== ps.set) return;\n const id = String(col(row, 'id'));\n const group = col(row, 'group') != null && String(col(row, 'group')) !== 'NA' ? String(col(row, 'group')) : null;\n const color = col(row, 'color') && String(col(row, 'color')) !== 'NA' ? String(col(row, 'color'))\n : group && groupColorMap[group] ? groupColorMap[group]\n : PALETTE[si % PALETTE.length];\n const pt = rowToPoint(row, 'id', color, pointScale);\n pt.ID = `${ps.set}::${id}`;\n pt.size = ps.size ?? config.pointSize ?? 2.5;\n const shape = col(row, 'shape');\n if (shape && String(shape) !== 'NA') pt.shape = String(shape);\n const label = col(row, 'label');\n (pt as any).meta = {\n stroke: '#ffffff', kind: 'point',\n name: label != null && String(label) !== 'NA' ? String(label) : id,\n group: group ?? undefined, unit: id, set: ps.set,\n fixedSize: ps.fixedSize,\n };\n this.__data__.points.set(pt.ID, pt);\n psLayer?.__data__.objects.set(pt.ID, pt);\n });\n });\n }\n\n if (model.points?.rows) {\n const pointsLayer = this.__children__.search('__children__', 'points') as QELayer;\n if (pointsLayer) {\n model.points.rows().forEach((row: DataFrameRow) => {\n // Determine this point's group color\n const groupColIdx = groupColName ? row.names.indexOf(groupColName) : -1;\n const group = groupColIdx >= 0 ? String(row[groupColIdx]) : null;\n const colorStr = group ? (groupColorMap[group] ?? '#888888') : '#888888';\n\n // Only add unit dots to the layer when 'points' attribute is present.\n if (showUnitPoints) {\n const pt = rowToPoint(row, unitIdCol, colorStr, pointScale);\n // Unit-point size: <qe-points size=…> overrides the default 2.5.\n // (Point() defaults to 1, which renders smaller than code nodes.)\n pt.size = config.pointSize ?? 2.5;\n // White halo separates overlapping dots in dense clusters.\n // meta.kind/name/group feed the qe-node-* interaction events.\n (pt as any).meta = {\n ...((pt as any).meta ?? {}),\n stroke: '#ffffff', kind: 'point', name: pt.ID,\n group: group ?? undefined, unit: pt.ID,\n fixedSize: config.pointFixedSize,\n };\n this.__data__.points.set(pt.ID, pt);\n pointsLayer.__data__.objects.set(pt.ID, pt);\n }\n\n // Always accumulate for mean + variance (needed for Path B even without dots)\n if (group) {\n const xIdx = row.names.indexOf(dims[0]);\n const yIdx = dims.length > 1 ? row.names.indexOf(dims[1]) : -1;\n if (!groupSums[group]) groupSums[group] = { x: 0, y: 0, x2: 0, y2: 0, xy: 0, n: 0, color: colorStr };\n const rx = xIdx >= 0 ? Number(row[xIdx]) : 0;\n const ry = yIdx >= 0 ? Number(row[yIdx]) : 0;\n groupSums[group].x += rx;\n groupSums[group].y += ry;\n groupSums[group].x2 += rx * rx;\n groupSums[group].y2 += ry * ry;\n groupSums[group].xy += rx * ry;\n groupSums[group].n += 1;\n }\n });\n\n // ── Group means + bounds ──────────────────────────────────────────────\n // Two paths:\n // A) model.groups frame present → use pre-computed means + bounds.\n // This is the Phase 3+ preferred path. qeviz renders; adapters compute.\n // B) No groups frame → compute means from unit-point accumulations\n // (legacy fallback; also used when only points are provided).\n //\n // Deprecated frames (model.confidence, model.outlier) are still respected\n // in path B for backward compatibility with rENA adapters not yet updated.\n //\n // Means rendering is guarded by config.showMeans (<qe-means> presence).\n // When absent, activeGroupRows is kept empty so the labels section below\n // also skips mean labels cleanly.\n\n const hasGroupsFrame = !!(model.groups?.rows && model.groups.rows().length > 0);\n\n // Rows from the groups frame that are active in the current view.\n // Empty when <qe-means> is absent so downstream label logic is consistent.\n const activeGroupRows: DataFrameRow[] = (config.showMeans && hasGroupsFrame)\n ? model.groups.rows().filter((r: DataFrameRow) => {\n const g = r.rowName ?? String(r[0]);\n return activeMeanGroups.size === 0 || activeMeanGroups.has(g);\n })\n : [];\n\n if (config.showMeans) {\n const pointsLayerSvg = pointsLayer.svg_element as SVGGElement | null;\n // Interval stroke scales with the displayed range, so a plot zoomed to\n // its points (range=\"points\", or a number) keeps thin lines; with\n // range=\"network\" (= maxNodeExtent × 1.2) this is maxNodeExtent.\n const ciExtent = this._rangeExtent ? this._rangeExtent / 1.2 : maxNodeExtent;\n const sw = (ciExtent > 0 ? ciExtent : 1) * 0.008;\n\n if (hasGroupsFrame) {\n // ── Path A: groups frame ─────────────────────────────────────────\n // Remove CI/outlier rects for groups no longer active.\n const activeNames = new Set(activeGroupRows.map((r: DataFrameRow) => r.rowName ?? String(r[0])));\n this._ciRects.forEach((el, g) => { if (!activeNames.has(g)) { el.remove(); this._ciRects.delete(g); } });\n this._outlierRects.forEach((el, g) => { if (!activeNames.has(g)) { el.remove(); this._outlierRects.delete(g); } });\n this._ciCross.forEach((el, k) => { if (!activeNames.has(k.slice(2))) { el.remove(); this._ciCross.delete(k); } });\n\n activeGroupRows.forEach((row: DataFrameRow) => {\n const group = row.rowName ?? String(row[0]);\n const color = groupColorMap[group] ?? '#888888';\n const xIdx = row.names.indexOf(dims[0]);\n const yIdx = dims.length > 1 ? row.names.indexOf(dims[1]) : -1;\n const mx = xIdx >= 0 ? Number(row[xIdx]) * pointScale : 0;\n const my = yIdx >= 0 ? -Number(row[yIdx]) * pointScale : 0;\n\n // Mean marker — square, larger than unit points\n const meanPt = new Point({\n ID: `mean-${group}`,\n dimensions: [mx, my],\n meta: { kind: 'mean', name: group, group, fixedSize: config.meanFixedSize },\n });\n meanPt.color = new Color(color);\n meanPt.size = 4; // radius = extent × 0.006 × 4 ≈ 0.024 for a unit extent\n const shapeIdx = row.names.indexOf('shape');\n const rowShape = shapeIdx >= 0 ? row[shapeIdx] : null;\n meanPt.shape = rowShape && String(rowShape) !== 'NA' ? String(rowShape) : 'rect';\n this.__data__.points.set(meanPt.ID, meanPt);\n pointsLayer.__data__.objects.set(meanPt.ID, meanPt);\n\n // Per-mean overrides (explicit means, as rENA's ena.plot.group\n // sets them per call): groups-frame `intervals` / `outlier`\n // columns win over the <qe-means> attributes when present.\n const cell = (name: string): any => {\n const i = row.names.indexOf(name);\n const v = i >= 0 ? row[i] : null;\n return v == null || String(v) === 'NA' || String(v) === '' ? null : v;\n };\n const rowIv = cell('intervals');\n const iv: 'box' | 'crosshairs' | 'none' =\n rowIv === 'box' || rowIv === 'crosshairs' || rowIv === 'none' ? rowIv : config.intervals;\n const rowOut = cell('outlier');\n const showOut = rowOut == null ? config.showOutlier : (rowOut === true || String(rowOut) === 'true');\n\n // Outlier interval (qe_group(outlier = TRUE)): {dim}.olow / .ohigh.\n const ob = showOut\n ? readIntervalBounds(row, dims[0] as string, dims[1] as string, 'o')\n : null;\n if (!ob) {\n this._outlierRects.get(group)?.remove(); this._outlierRects.delete(group);\n } else {\n let oel = this._outlierRects.get(group);\n if (!oel) {\n oel = document.createElementNS('http://www.w3.org/2000/svg', 'rect') as SVGRectElement;\n oel.setAttribute('data-outlier-group', group);\n this._outlierRects.set(group, oel);\n }\n oel.setAttribute('x', (ob.x_low * pointScale).toString());\n oel.setAttribute('y', (-ob.y_high * pointScale).toString());\n oel.setAttribute('width', ((ob.x_high - ob.x_low) * pointScale).toString());\n oel.setAttribute('height', ((ob.y_high - ob.y_low) * pointScale).toString());\n oel.setAttribute('fill', 'none');\n oel.setAttribute('stroke', color);\n oel.setAttribute('stroke-width', sw.toString());\n oel.setAttribute('stroke-opacity', '0.5');\n oel.setAttribute('stroke-dasharray', `${sw * 2} ${sw * 2}`);\n if (pointsLayerSvg && !oel.parentElement) pointsLayerSvg.insertBefore(oel, pointsLayerSvg.firstChild);\n }\n\n // CI (<qe-means intervals=\"box|crosshairs|none\">, or the legacy\n // `confidence` flag = box). Gated so qe_group(intervals = \"none\")\n // draws nothing.\n const bounds = iv !== 'none'\n ? readIntervalBounds(row, dims[0] as string, dims[1] as string)\n : null;\n const crossKey = `x:${group}`;\n if (!bounds || iv !== 'crosshairs') {\n this._ciCross.get(crossKey)?.remove(); this._ciCross.delete(crossKey);\n }\n if (bounds && iv === 'crosshairs') {\n this._ciRects.get(group)?.remove(); this._ciRects.delete(group);\n // Two arms through the mean: x_lo..x_hi at the mean's y, and\n // y_lo..y_hi at the mean's x.\n const x0 = bounds.x_low * pointScale, x1 = bounds.x_high * pointScale;\n const y0 = -bounds.y_high * pointScale, y1 = -bounds.y_low * pointScale;\n capMeanToInterval(meanPt, (x1 - x0) / 2, (y1 - y0) / 2);\n let cel = this._ciCross.get(crossKey);\n if (!cel) {\n cel = document.createElementNS('http://www.w3.org/2000/svg', 'path') as SVGPathElement;\n cel.setAttribute('data-ci-group', group);\n cel.setAttribute('data-ci-kind', 'crosshairs');\n this._ciCross.set(crossKey, cel);\n }\n cel.setAttribute('d', `M${x0} ${my} L${x1} ${my} M${mx} ${y0} L${mx} ${y1}`);\n cel.setAttribute('fill', 'none');\n cel.setAttribute('stroke', color);\n cel.setAttribute('stroke-width', (sw * 1.25).toString());\n cel.setAttribute('stroke-opacity', '0.8');\n if (pointsLayerSvg && !cel.parentElement) pointsLayerSvg.insertBefore(cel, pointsLayerSvg.firstChild);\n } else if (!bounds) {\n const stale = this._ciRects.get(group);\n if (stale) { stale.remove(); this._ciRects.delete(group); }\n } else {\n const rect_x = bounds.x_low * pointScale;\n const rect_y = -bounds.y_high * pointScale;\n const rect_width = (bounds.x_high - bounds.x_low) * pointScale;\n const rect_height = (bounds.y_high - bounds.y_low) * pointScale;\n capMeanToInterval(meanPt, rect_width / 2, rect_height / 2);\n\n let el = this._ciRects.get(group);\n if (!el) {\n el = document.createElementNS('http://www.w3.org/2000/svg', 'rect') as SVGRectElement;\n el.setAttribute('data-ci-group', group);\n this._ciRects.set(group, el);\n }\n el.setAttribute('x', rect_x.toString());\n el.setAttribute('y', rect_y.toString());\n el.setAttribute('width', rect_width.toString());\n el.setAttribute('height', rect_height.toString());\n el.setAttribute('fill', 'none');\n el.setAttribute('stroke', color);\n el.setAttribute('stroke-width', sw.toString());\n el.setAttribute('stroke-opacity', '0.8');\n el.setAttribute('stroke-dasharray', `${sw * 4} ${sw * 3}`);\n if (pointsLayerSvg && !el.parentElement) {\n pointsLayerSvg.insertBefore(el, pointsLayerSvg.firstChild);\n }\n }\n });\n\n } else {\n // ── Path B: legacy — compute means from groupSums ────────────────\n // Add one mean point per group — larger (size=1.5) and same group color\n Object.entries(groupSums).forEach(([group, { x, y, n, color }]) => {\n const meanPt = new Point({\n ID: `mean-${group}`,\n dimensions: [x / n * pointScale, -(y / n) * pointScale],\n meta: { kind: 'mean', name: group, group, fixedSize: config.meanFixedSize },\n });\n meanPt.color = new Color(color);\n meanPt.size = 4; // radius = extent × 0.006 × 4 ≈ 0.024 for a unit extent\n meanPt.shape = 'rect';\n this.__data__.points.set(meanPt.ID, meanPt);\n pointsLayer.__data__.objects.set(meanPt.ID, meanPt);\n });\n\n // ── CI boxes (deprecated confidence frame or JS fallback) ────────\n const showCI = config.showCI;\n if (showCI) {\n this._ciRects.forEach((el, g) => {\n if (!groupSums[g]) { el.remove(); this._ciRects.delete(g); }\n });\n\n if (model.confidence?.rows) {\n // Pre-computed path: deprecated model.confidence frame\n model.confidence.rows().forEach((row: DataFrameRow) => {\n const groupIdx = row.names.indexOf(groupColName ?? 'group');\n const group = groupIdx >= 0 ? String(row[groupIdx]) : (row.rowName ?? null);\n if (!group) return;\n const color = groupColorMap[group] ?? '#888888';\n const bounds = readIntervalBounds(row, dims[0] as string, dims[1] as string);\n if (!bounds) return;\n const rect_x = bounds.x_low * pointScale;\n const rect_y = -bounds.y_high * pointScale;\n const rect_width = (bounds.x_high - bounds.x_low) * pointScale;\n const rect_height = (bounds.y_high - bounds.y_low) * pointScale;\n capMeanToInterval(this.__data__.points.get(`mean-${group}`) as Point | undefined,\n rect_width / 2, rect_height / 2);\n let el = this._ciRects.get(group);\n if (!el) {\n el = document.createElementNS('http://www.w3.org/2000/svg', 'rect') as SVGRectElement;\n el.setAttribute('data-ci-group', group);\n this._ciRects.set(group, el);\n }\n el.setAttribute('x', rect_x.toString());\n el.setAttribute('y', rect_y.toString());\n el.setAttribute('width', rect_width.toString());\n el.setAttribute('height', rect_height.toString());\n el.setAttribute('fill', 'none');\n el.setAttribute('stroke', color);\n el.setAttribute('stroke-width', sw.toString());\n el.setAttribute('stroke-opacity', '0.8');\n el.setAttribute('stroke-dasharray', `${sw * 4} ${sw * 3}`);\n if (pointsLayerSvg && !el.parentElement) {\n pointsLayerSvg.insertBefore(el, pointsLayerSvg.firstChild);\n }\n });\n } else {\n // JS fallback: compute CI from accumulated variance\n Object.entries(groupSums).forEach(([group, { x, y, x2, y2, n, color }]) => {\n if (n < 2) return;\n const μx = x / n, μy = y / n;\n const rawVarX = x2 / n - μx * μx;\n const rawVarY = y2 / n - μy * μy;\n const { halfW, halfH } = computeCIRect(rawVarX, rawVarY, n, pointScale);\n const cx = μx * pointScale, cy = -(μy) * pointScale;\n capMeanToInterval(this.__data__.points.get(`mean-${group}`) as Point | undefined,\n halfW, halfH);\n let el = this._ciRects.get(group);\n if (!el) {\n el = document.createElementNS('http://www.w3.org/2000/svg', 'rect') as SVGRectElement;\n el.setAttribute('data-ci-group', group);\n this._ciRects.set(group, el);\n }\n el.setAttribute('x', (cx - halfW).toString());\n el.setAttribute('y', (cy - halfH).toString());\n el.setAttribute('width', (halfW * 2).toString());\n el.setAttribute('height', (halfH * 2).toString());\n el.setAttribute('fill', 'none');\n el.setAttribute('stroke', color);\n el.setAttribute('stroke-width', sw.toString());\n el.setAttribute('stroke-opacity', '0.8');\n el.setAttribute('stroke-dasharray', `${sw * 4} ${sw * 3}`);\n if (pointsLayerSvg && !el.parentElement) {\n pointsLayerSvg.insertBefore(el, pointsLayerSvg.firstChild);\n }\n });\n }\n }\n\n // ── Outlier boxes (deprecated model.outlier frame) ───────────────\n const showOutlier = true; // legacy frame; presence of model.outlier guards rendering\n if (showOutlier && model.outlier?.rows) {\n this._outlierRects.forEach((el, g) => {\n if (!groupColorMap[g]) { el.remove(); this._outlierRects.delete(g); }\n });\n model.outlier.rows().forEach((row: DataFrameRow) => {\n const groupIdx = row.names.indexOf(groupColName ?? 'group');\n const group = groupIdx >= 0 ? String(row[groupIdx]) : (row.rowName ?? null);\n if (!group) return;\n const color = groupColorMap[group] ?? '#888888';\n const bounds = readIntervalBounds(row, dims[0] as string, dims[1] as string);\n if (!bounds) return;\n const rect_x = bounds.x_low * pointScale;\n const rect_y = -bounds.y_high * pointScale;\n const rect_width = (bounds.x_high - bounds.x_low) * pointScale;\n const rect_height = (bounds.y_high - bounds.y_low) * pointScale;\n let el = this._outlierRects.get(group);\n if (!el) {\n el = document.createElementNS('http://www.w3.org/2000/svg', 'rect') as SVGRectElement;\n el.setAttribute('data-outlier-group', group);\n this._outlierRects.set(group, el);\n }\n el.setAttribute('x', rect_x.toString());\n el.setAttribute('y', rect_y.toString());\n el.setAttribute('width', rect_width.toString());\n el.setAttribute('height', rect_height.toString());\n el.setAttribute('fill', 'none');\n el.setAttribute('stroke', color);\n el.setAttribute('stroke-width', sw.toString());\n el.setAttribute('stroke-opacity', '0.5');\n el.setAttribute('stroke-dasharray', `${sw * 2} ${sw * 2}`);\n if (pointsLayerSvg && !el.parentElement) {\n pointsLayerSvg.insertBefore(el, pointsLayerSvg.firstChild);\n }\n });\n }\n } // end Path B\n } // end config.showMeans\n\n // ── Labels ──────────────────────────────────────────────────────────\n if (labelSvg) {\n // Remove labels for objects that no longer exist\n this._pointLabels.forEach((lbl, id) => {\n if (!pointsLayer.__data__.objects.get(id)) { lbl.remove(); this._pointLabels.delete(id); }\n });\n this._meanLabels.forEach((lbl, id) => {\n if (!pointsLayer.__data__.objects.get(`mean-${id}`)) { lbl.remove(); this._meanLabels.delete(id); }\n });\n\n // Unit point labels\n if (labelPoints !== 0) {\n model.points.rows().forEach((row: DataFrameRow) => {\n const qIdx = row.names.indexOf(unitIdCol);\n const unitId = qIdx >= 0 ? String(row[qIdx]) : null;\n if (!unitId) return;\n const pt = pointsLayer.__data__.objects.get(unitId) as Point | undefined;\n if (!pt) return;\n // Use the raw unit ID as the label text.\n // TODO: support a label-format attribute or callback so callers\n // can supply a custom display string (e.g. strip a prefix,\n // extract a sub-field from a compound ID, etc.)\n const displayText = unitId;\n let lbl = this._pointLabels.get(unitId);\n if (!lbl) {\n lbl = new QELabel(displayText, pt, labelSvg, this, labelPoints);\n this._pointLabels.set(unitId, lbl);\n } else {\n labelPoints === Label.DISPLAY_TYPES.ON ? lbl.show() : lbl.hide();\n }\n });\n }\n\n // Mean labels — use active groups frame rows if available, else groupSums keys\n if (labelMeans !== 0) {\n const meanGroupNames: string[] = hasGroupsFrame\n ? activeGroupRows.map((r: DataFrameRow) => r.rowName ?? String(r[0]))\n : Object.keys(groupSums);\n\n meanGroupNames.forEach((group: string) => {\n const meanId = `mean-${group}`;\n const pt = pointsLayer.__data__.objects.get(meanId) as Point | undefined;\n if (!pt) return;\n let lbl = this._meanLabels.get(group);\n if (!lbl) {\n lbl = new QELabel(group, pt, labelSvg, this, labelMeans);\n this._meanLabels.set(group, lbl);\n } else {\n labelMeans === Label.DISPLAY_TYPES.ON ? lbl.show() : lbl.hide();\n }\n });\n }\n }\n\n pointsLayer.__data__.__state__.setVariable('layer_updated', pointsLayer.__data__);\n }\n }\n\n // ── Cognitive Trajectories Layer ──────────────────────────────────────────\n const trajectoriesLayer = this.__children__.search('__children__', 'trajectories') as QELayer;\n const trajectoriesEnabled = config.showTrajectories;\n if (trajectoriesEnabled && trajectoriesLayer) {\n trajectoriesLayer.__data__.objects.clear();\n this.__data__.trajectories.clear();\n\n const trajSource = model.trajectories?.rows ? model.trajectories : model.points;\n if (trajSource?.rows) {\n const unitRows: Record<string, Array<{ x: number; y: number; time: number }>> = {};\n const selectedUnits = config.trajectoryUnits ? config.trajectoryUnits.split(',').map(s => s.trim()) : null;\n\n trajSource.rows().forEach((row: DataFrameRow) => {\n const uIdx = row.names.indexOf(unitIdCol) >= 0 ? row.names.indexOf(unitIdCol) : (row.names.indexOf('unit') >= 0 ? row.names.indexOf('unit') : (row.names.indexOf('ENA_UNIT') >= 0 ? row.names.indexOf('ENA_UNIT') : -1));\n const unit = uIdx >= 0 ? String(row[uIdx]) : (row.rowName || 'unit-1');\n\n if (selectedUnits && !selectedUnits.includes(unit)) return;\n\n const xIdx = row.names.indexOf(dims[0]);\n const yIdx = dims.length > 1 ? row.names.indexOf(dims[1]) : -1;\n const tIdx = row.names.indexOf('time') >= 0 ? row.names.indexOf('time') : (row.names.indexOf('ActivityNumber') >= 0 ? row.names.indexOf('ActivityNumber') : (row.names.indexOf('RowID') >= 0 ? row.names.indexOf('RowID') : -1));\n\n const time = tIdx >= 0 ? Number(row[tIdx]) : (unitRows[unit] ? unitRows[unit].length + 1 : 1);\n // Keep every row: the playhead is applied inside Trajectory via\n // currentTime so degree selection can run on the full trajectory\n // while only the visible prefix is fit and drawn.\n\n if (xIdx >= 0 && yIdx >= 0) {\n if (!unitRows[unit]) unitRows[unit] = [];\n unitRows[unit].push({\n x: Number(row[xIdx]) * pointScale,\n y: -Number(row[yIdx]) * pointScale,\n time\n });\n }\n });\n\n const unitKeys = Object.keys(unitRows);\n unitKeys.forEach((unitKey, uIdx) => {\n const rawPts = unitRows[unitKey];\n if (rawPts.length === 0) return;\n\n const colorStr = PALETTE[uIdx % PALETTE.length];\n\n const trajObj = new Trajectory({\n ID: `traj-${unitKey}`,\n unitId: unitKey,\n color: new Color(colorStr),\n lineStyle: config.trajectoryLineStyle,\n strokeWidth: config.trajectoryStrokeWidth,\n strokeWidthRange: config.trajectoryStrokeWidthRange,\n opacityRange: config.trajectoryOpacityRange,\n smooth: config.trajectorySmooth,\n maxDegree: config.trajectoryMaxDegree,\n degreeSelection: config.trajectoryDegreeSelection,\n currentTime: config.trajectoryPlayhead ?? Infinity,\n showPoints: config.trajectoryShowPoints,\n showTips: config.trajectoryShowTips,\n points: rawPts.map(p => ({ x: p.x, y: p.y, time: p.time }))\n });\n\n this.__data__.trajectories.set(unitKey, trajObj);\n trajectoriesLayer.__data__.objects.set(trajObj.ID, trajObj);\n });\n }\n trajectoriesLayer.__data__.__state__.setVariable('layer_updated', trajectoriesLayer.__data__);\n }\n\n // ── Mean network edges ───────────────────────────────────────────────────\n // For each group, compute the mean weight of every edge column across its\n // unit rows, then draw a Line for pairs whose mean weight is non-zero.\n const networkLayer = this.__children__.search('__children__', 'network') as QELayer;\n const edgeLayer = networkLayer?.__children__.search('__children__', 'edges') as QELayer;\n const nodeLayer = networkLayer?.__children__.search('__children__', 'nodes') as QELayer;\n // edgenodes sits above `nodes` in the layer tree — self-connections (NodeEdge)\n // must be drawn here so the dot is visible on top of the code node.\n const edgenodeLayer = networkLayer?.__children__.search('__children__', 'edgenodes') as QELayer;\n\n const edgesEnabled = config.showEdges;\n if (model.nodes?.rows && nodeLayer) {\n // ── Step 1: Populate node positions first ─────────────────────────────\n // Nodes are always placed so they anchor the coordinate space (extremes).\n // Sizes will be overwritten after edge weights are computed; when edges\n // are hidden the default size is used instead.\n model.nodes.rows().forEach((row: DataFrameRow) => {\n const pt = rowToPoint(row, nodeIdCol, '#444444');\n pt.size = 2; // default when no edge weights available\n // Display text: the nodes frame's optional `label` column\n // (qe_nodes(labels =)); the code id stays the node's identity.\n const li = row.names.indexOf('label');\n const lv = li >= 0 ? row[li] : null;\n (pt as any).meta = { ...((pt as any).meta ?? {}), kind: 'node',\n name: lv != null && String(lv) !== 'NA' && String(lv) !== '' ? String(lv) : pt.ID };\n nodeLayer.__data__.objects.set(pt.ID, pt);\n });\n\n if (edgesEnabled && edgeLayer && model.edges?.rows) {\n // ── Step 2: Build unit→group lookup from points data ─────────────────\n const unitGroupMap: Record<string, string> = {};\n if (groupColName && model.points?.rows) {\n model.points.rows().forEach((row: DataFrameRow) => {\n const qIdx = row.names.indexOf(unitIdCol);\n const gIdx = row.names.indexOf(groupColName!);\n if (qIdx >= 0 && gIdx >= 0) unitGroupMap[String(row[qIdx])] = String(row[gIdx]);\n });\n }\n\n // ── Step 3: Collect valid edge-column → code-pair mappings ───────────\n const codeNames: string[] = model.nodes.rows().map((r: DataFrameRow) => {\n const idx = r.names.indexOf(nodeIdCol);\n return idx >= 0 ? String(r[idx]) : '';\n }).filter(Boolean);\n\n const edgePairs: Array<{ col: string; pair: [string, string] }> = [];\n (model.edges.names ?? []).forEach((col: string) => {\n const pair = parseEdgePair(col, codeNames);\n if (pair) edgePairs.push({ col, pair });\n });\n\n // ── Step 4: Edge-weight helpers ───────────────────────────────────────\n type EdgeWeights = Record<string, number>;\n\n /** Raw weights for a single unit row. */\n const getUnitEdges = (unitId: string): EdgeWeights => {\n const result: EdgeWeights = {};\n model.edges.rows().forEach((row: DataFrameRow) => {\n const qIdx = row.names.indexOf(unitIdCol);\n if (qIdx < 0 || String(row[qIdx]) !== unitId) return;\n edgePairs.forEach(({ col }) => {\n const colIdx = row.names.indexOf(col);\n if (colIdx >= 0) result[col] = Number(row[colIdx]) || 0;\n });\n });\n return result;\n };\n\n /** Mean weights across all units in a group. */\n const getGroupEdges = (groupName: string): EdgeWeights => {\n const sums: EdgeWeights = {};\n let count = 0;\n model.edges.rows().forEach((row: DataFrameRow) => {\n const qIdx = row.names.indexOf(unitIdCol);\n const unitId = qIdx >= 0 ? String(row[qIdx]) : null;\n const gColIdx = groupColName ? row.names.indexOf(groupColName) : -1;\n const group = gColIdx >= 0 ? String(row[gColIdx]) : (unitId ? unitGroupMap[unitId] : null);\n if (group !== groupName) return;\n count++;\n edgePairs.forEach(({ col }) => {\n const colIdx = row.names.indexOf(col);\n if (colIdx >= 0) { const v = Number(row[colIdx]); if (!isNaN(v)) sums[col] = (sums[col] ?? 0) + v; }\n });\n });\n if (count === 0) return {};\n const result: EdgeWeights = {};\n edgePairs.forEach(({ col }) => { result[col] = (sums[col] ?? 0) / count; });\n return result;\n };\n\n /** Resolve an identifier to edge weights + color.\n * Checks group names first, then treats the value as a unit ID. */\n const resolve = (id: string): { weights: EdgeWeights; color: string; label: string } => {\n if (groupColorMap[id]) {\n return { weights: getGroupEdges(id), color: groupColorMap[id], label: id };\n }\n // Unit: color from its group, or neutral grey\n const groupOfUnit = unitGroupMap[id] ?? null;\n const color = groupOfUnit ? (groupColorMap[groupOfUnit] ?? '#888888') : '#888888';\n return { weights: getUnitEdges(id), color, label: id };\n };\n\n // ── Steps 5–6: Build the edges to draw, one <qe-edges> layer at a time ─\n //\n // Named layers (as before):\n // group=\"A\" — group mean\n // unit=\"u\" — one unit's network\n // group=\"A\" compare=\"B\" — subtraction A − B (sign → colour)\n // group=\"A\" also=\"B\" — two groups overlaid\n // Explicit layers (0.5):\n // network=\"n1\" — a row of model.networks (signed)\n // Per layer: colors=\"pos,neg\" overrides the palette; threshold=\"min,max\"\n // drops |w| < min and caps |w| > max (rENA semantics).\n // Each entry's weight is ≥ 0; the sign is carried by its colour.\n type DrawEdge = { col: string; pair: [string, string]; weight: number; color: string;\n layer: number; name?: string; group?: string; unit?: string };\n const drawEdges: DrawEdge[] = [];\n\n const networkRow = (name: string): EdgeWeights | null => {\n const frame = (model as any).networks;\n const row = frame?.rows?.().find((r: DataFrameRow) => r.rowName === name);\n if (!row) return null;\n const w: EdgeWeights = {};\n edgePairs.forEach(({ col }) => {\n const i = row.names.indexOf(col);\n if (i >= 0) { const v = Number(row[i]); if (Number.isFinite(v)) w[col] = v; }\n });\n return w;\n };\n const thresholded = (w: number, thr: [number, number] | null): number => {\n if (!thr) return w;\n const a = Math.abs(w);\n if (a < thr[0]) return 0;\n return a > thr[1] ? Math.sign(w) * thr[1] : w;\n };\n\n config.edgeLayers.forEach((L, li) => {\n const push = (col: string, pair: [string, string], w: number, color: string,\n meta: { name?: string; group?: string; unit?: string }) => {\n w = thresholded(w, L.threshold);\n if (Math.abs(w) < 1e-6) return;\n drawEdges.push({ col: `${li}:${col}`, pair, weight: Math.abs(w), color, layer: li, ...meta });\n };\n const signColors = (pos: string, neg: string): [string, string] => {\n if (!L.colors) return [pos, neg];\n return [L.colors[0], L.colors[1] ?? complementColor(L.colors[0])];\n };\n\n if (L.network) {\n // Explicit network: signed weights from model.networks.\n const w = networkRow(L.network);\n if (!w) return;\n const [pos, neg] = signColors(PALETTE[0], PALETTE[1]);\n const meta = { name: L.name ?? L.network };\n edgePairs.forEach(({ col, pair }) => {\n const v = w[col] ?? 0;\n push(col, pair, v, v >= 0 ? pos : neg, meta);\n });\n return;\n }\n\n // Named layer — unit overrides group; no default to the first group.\n const primaryId = L.unit ?? L.group ?? null;\n if (!primaryId) return;\n const primary = resolve(primaryId);\n const secondaryId = L.compare ?? L.also ?? null;\n const secondary = secondaryId ? resolve(secondaryId) : null;\n const meta = { name: L.name ?? primaryId, group: L.group ?? undefined, unit: L.unit ?? undefined };\n const [pos, neg] = signColors(primary.color, secondary?.color ?? primary.color);\n\n if (secondary && L.compare) {\n // A − B: positive → primary colour, negative → secondary colour\n edgePairs.forEach(({ col, pair }) => {\n const d = (primary.weights[col] ?? 0) - (secondary.weights[col] ?? 0);\n push(col, pair, d, d > 0 ? pos : neg, meta);\n });\n } else if (secondary && L.also) {\n // Overlay: both networks, each in its own colour\n edgePairs.forEach(({ col, pair }) => {\n const wA = primary.weights[col] ?? 0, wB = secondary.weights[col] ?? 0;\n if (wA > 0) push(col + '-a', pair, wA, pos, meta);\n if (wB > 0) push(col + '-b', pair, wB, neg, { ...meta, name: L.also ?? undefined, group: L.also ?? undefined });\n });\n } else {\n edgePairs.forEach(({ col, pair }) => {\n const w = primary.weights[col] ?? 0;\n if (w > 0) push(col, pair, w, pos, meta);\n });\n }\n });\n\n // Thin edges on top (rENA's thin.lines.in.front): later objects draw\n // over earlier ones, so add the heaviest first.\n drawEdges.sort((a, b) => b.weight - a.weight);\n\n // ── Step 7: Mark sizes and colour ────────────────────────────────────\n // Width is absolute (webENA): raw weight × one width-per-weight set by\n // <qe-graph edge-width>, shared by edges, directed wide ends,\n // self-connection dots and nodes (diameter = Σ edge widths).\n const isDirected = !!(model as any).directed;\n // <qe-edges magnify> scales this plot's widths and node sizes (not\n // colour) — e.g. to read a faint subtraction — and is always\n // labelled \"(scaled Nx)\" so it is never mistaken for the shared scale.\n const widthFrac = widthPerWeight(config.edgeWidth) * (config.edgeMagnify ?? 1);\n\n // Colour (webENA ramps): each class (lines vs self-loops) rescales\n // |weight| from [min, max] onto saturation 0.25–1 / opacity 0.3–1.\n // The range comes from the whole model — every non-zero weight in\n // the edges frame — so plots of one model share a colour scale;\n // webENA takes it from each plotted network (\"plot\").\n const rangeOf = (ws: number[]): [number, number] => {\n const nz = ws.map(Math.abs).filter(v => v > 0);\n return nz.length ? [Math.min(...nz), Math.max(...nz)] : [0, 0];\n };\n const modelRange = (self: boolean): [number, number] => {\n const vals: number[] = [];\n edgePairs.forEach(({ col, pair }) => {\n if ((pair[0] === pair[1]) !== self) return;\n const column = model.edges.col(col);\n if (column) for (const v of column) vals.push(Number(v));\n });\n return rangeOf(vals);\n };\n const plotRange = (self: boolean): [number, number] =>\n rangeOf(drawEdges.filter(e => (e.pair[0] === e.pair[1]) === self).map(e => e.weight));\n const cscale = config.edgeColorScale;\n const colourRange = (self: boolean): [number, number] =>\n cscale === 'plot' ? plotRange(self) : modelRange(self);\n const lineRange = colourRange(false), selfRange = colourRange(true);\n const colourOf = (w: number, self: boolean) => {\n if (cscale === 'absolute') { const a = Math.min(1, Math.abs(w)); return { saturation: a, opacity: a }; }\n const [lo, hi] = self ? selfRange : lineRange;\n return { saturation: rampFor(w, lo, hi, SATURATION_RANGE), opacity: rampFor(w, lo, hi, OPACITY_RANGE) };\n };\n\n // Weight accumulated at each node:\n // Undirected: every edge touching the node (both endpoints).\n // Directed: only edges directed *at* the node (pair[1] is the\n // target; its wide end is drawn there), including the\n // node's self-connection.\n const nodeWeightSum: Record<string, number> = {};\n drawEdges.forEach(({ pair, weight }) => {\n const isSelf = pair[0] === pair[1];\n if (isSelf && !isDirected) return; // skip illegal undirected diagonals\n const add = (id: string) => { nodeWeightSum[id] = (nodeWeightSum[id] ?? 0) + Math.abs(weight); };\n if (isDirected) { add(pair[1]); return; }\n add(pair[0]); add(pair[1]);\n });\n\n // Node sizes: diameter = Σ widths of the edges counted above. Nodes\n // with nothing counted get a tiny dot, or are hidden with\n // <qe-nodes unconnected=\"hide\">.\n model.nodes.rows().forEach((row: DataFrameRow) => {\n const codeIdx = row.names.indexOf(nodeIdCol);\n const id = codeIdx >= 0 ? String(row[codeIdx]) : '';\n if (!id) return;\n const pt = nodeLayer.__data__.objects.get(id) as Point | undefined;\n if (!pt) return;\n const w = nodeWeightSum[id] ?? 0;\n const unconnected = !(w > 0);\n pt.size = unconnected ? (config.hideUnconnectedNodes ? 0 : UNCONNECTED_NODE_SIZE)\n : nodeSizeForEdges(w, widthFrac);\n (pt as any).meta = { ...((pt as any).meta ?? {}),\n hidden: unconnected && config.hideUnconnectedNodes };\n });\n\n // ── Step 8: Create edge objects ───────────────────────────────────────\n // For directed models, TaperedWeightedMidpointEdge needs the combined\n // weight of both directions (A→B + B→A) so the apex can be positioned\n // proportionally along the edge. Build a lookup keyed by \"A.B\" per\n // drawn network: an `also` overlay draws two networks in one layer,\n // and pooling them left every triangle short of its counterpart.\n const totalWeightByPair: Record<string, number> = {};\n const pairKey = (layer: number, net: string | undefined, a: string, b: string) =>\n `${layer}:${net ?? ''}:${a}.${b}`;\n if (isDirected) {\n drawEdges.forEach(({ pair, weight, layer, name }) => {\n const key = pairKey(layer, name, pair[0], pair[1]);\n totalWeightByPair[key] = (totalWeightByPair[key] ?? 0) + weight;\n });\n }\n\n drawEdges.forEach(({ col, pair, weight, color, layer, name, group, unit }) => {\n const fromNode = nodeLayer.__data__.objects.get(pair[0]);\n const toNode = nodeLayer.__data__.objects.get(pair[1]);\n if (!fromNode || !toNode) return;\n\n const isSelf = pair[0] === pair[1];\n if (isSelf && !isDirected) return; // undirected ENA has zero diagonal\n\n // Colour ramps rescale within each visual class (lines vs\n // self-loops), since self-weights are typically smaller.\n const { saturation, opacity } = colourOf(weight, isSelf);\n const fromPt = new Point({ ID: `${pair[0]}-src`, dimensions: [fromNode.x, fromNode.y], meta: {} });\n const toPt = new Point({ ID: `${pair[1]}-dst`, dimensions: [toNode.x, toNode.y], meta: {} });\n // Pick the edge class by topology:\n // • self-connection (A→A) → NodeEdge (filled circle at the node)\n // • directed (A→B) → TaperedWeightedMidpointEdge (triangle\n // whose apex is placed proportionally\n // to weight(A→B) / (weight(A→B) + weight(B→A)))\n // • undirected → Line (straight stroke)\n let edgeLine: Line;\n if (isSelf) {\n edgeLine = new NodeEdge({}, fromPt as any, toPt as any);\n // Actual display size is deferred to QELine.update() so it uses\n // the live extremes.x_max (which is not yet computed here).\n // Set a placeholder weight; update() will overwrite it.\n (edgeLine as any).weight = 0;\n } else if (isDirected) {\n const fwd = totalWeightByPair[pairKey(layer, name, pair[0], pair[1])] ?? weight;\n const bwd = totalWeightByPair[pairKey(layer, name, pair[1], pair[0])] ?? 0;\n const totalweight = fwd + bwd;\n edgeLine = new TaperedWeightedMidpointEdge(\n { weight, totalweight },\n fromPt as any,\n toPt as any\n );\n } else {\n edgeLine = new Line({}, fromPt, toPt);\n }\n edgeLine.ID = `edge-${col}`;\n edgeLine.color = new Color(color);\n (edgeLine as any).meta = {\n isMeanEdge: true,\n weight,\n // Width per unit weight (extent units), shared by all marks.\n widthFrac,\n saturation,\n opacity,\n isDirected,\n isSelf,\n // Identity for the qe-edge-* interaction events.\n source: pair[0],\n target: pair[1],\n group,\n unit,\n layer: name,\n };\n // Self-connections go in the `edgenodes` layer (above `nodes` in\n // draw order) so the dot is visible on top of the code node.\n const targetLayer = isSelf ? (edgenodeLayer ?? edgeLayer) : edgeLayer;\n targetLayer.__data__.objects.set(edgeLine.ID, edgeLine);\n });\n\n edgeLayer.__data__.__state__.setVariable('layer_updated', edgeLayer.__data__);\n if (edgenodeLayer) edgenodeLayer.__data__.__state__.setVariable('layer_updated', edgenodeLayer.__data__);\n }\n\n // ── Node visibility ──────────────────────────────────────────────────\n // Node positions come from the model and stay in the layer either way,\n // so they keep anchoring the extent (the plot does not rescale when\n // nodes are toggled); <qe-nodes> presence only controls the drawing,\n // as <qe-axes> does for the axis sub-tree.\n const nodesVisible = config.showNodes;\n if (nodeLayer.svg_element) {\n (nodeLayer.svg_element as SVGElement).style.display = nodesVisible ? '' : 'none';\n }\n if (!nodesVisible) {\n this._nodeLabels.forEach(lbl => lbl.remove());\n this._nodeLabels.clear();\n }\n\n // ── Node labels ──────────────────────────────────────────────────────\n if (labelSvg && labelNodes !== 0 && nodesVisible) {\n // Clean up stale node labels\n this._nodeLabels.forEach((lbl, id) => {\n if (!nodeLayer.__data__.objects.get(id)) { lbl.remove(); this._nodeLabels.delete(id); }\n });\n model.nodes.rows().forEach((row: DataFrameRow) => {\n const codeIdx = row.names.indexOf(nodeIdCol);\n const id = codeIdx >= 0 ? String(row[codeIdx]) : '';\n if (!id) return;\n const pt = nodeLayer.__data__.objects.get(id) as Point | undefined;\n if (!pt) return;\n if ((pt as any).meta?.hidden) {\n this._nodeLabels.get(id)?.remove();\n this._nodeLabels.delete(id);\n return;\n }\n const text = String((pt as any).meta?.name ?? id);\n let lbl = this._nodeLabels.get(id);\n if (lbl && lbl.text !== text) { lbl.remove(); this._nodeLabels.delete(id); lbl = undefined; }\n if (!lbl) {\n lbl = new QELabel(text, pt, labelSvg, this, labelNodes);\n this._nodeLabels.set(id, lbl);\n } else {\n labelNodes === Label.DISPLAY_TYPES.ON ? lbl.show() : lbl.hide();\n }\n });\n }\n\n // Fire after both positions and sizes are set\n nodeLayer.__data__.__state__.setVariable('layer_updated', nodeLayer.__data__);\n }\n\n // ── Axis lines / points ──────────────────────────────────────────────────\n const axisPointsLayer = this.__children__.search('__children__', 'axis_points');\n const axisLinesLayer = this.__children__.search('__children__', 'axis_lines');\n if (axisPointsLayer) this.__data__.__state__.setVariable('graph_updated_axis_points', axisPointsLayer.__data__.objects);\n if (axisLinesLayer) this.__data__.__state__.setVariable('graph_updated_axis_lines', axisLinesLayer.__data__.objects);\n\n this.update();\n\n // Animate marks/edges from their pre-rebuild positions to the new ones.\n if (tweenFrom) this._runTween(tweenFrom);\n });\n }\n\n // ── Shared re-render scheduler ───────────────────────────────────────────────\n // Batches synchronous attribute / child-list changes into a single microtask\n // so that e.g. adding <qe-edges> and setting its attributes in the same tick\n // only triggers one render cycle.\n private _scheduleRerender(): void {\n if (!this._vizena || !this._hasModel) return;\n if (this._renderPending) return;\n this._renderPending = true;\n queueMicrotask(() => {\n this._renderPending = false;\n this._vizena?.dispatchEvent(new CustomEvent('model-updated', {\n detail: this._vizena.model,\n bubbles: true,\n composed: true,\n }));\n });\n }\n\n // ── Layer configuration reader ────────────────────────────────────────────────\n // Reads child element presence / attributes to determine what each layer\n // should render. Called once at the top of every model-updated handler so\n // all rendering decisions are derived from a single snapshot.\n private _readLayerConfig(): {\n // Nodes\n labelNodes: number;\n showNodes: boolean;\n edgeWidth: number;\n range: 'network' | 'points' | number | null;\n centerContent: boolean;\n plotTitle: string | null;\n labelFont: { size: number | null; family: string | null; color: string | null };\n hideUnconnectedNodes: boolean;\n scalePoints: boolean;\n pointScale: number | null;\n // Means\n showMeans: boolean;\n activeMeanGroups: string | null;\n showCI: boolean;\n intervals: 'box' | 'crosshairs' | 'none';\n showOutlier: boolean;\n labelMeans: number;\n meanFixedSize: boolean;\n // Points\n showPoints: boolean;\n pointSets: Array<{ set: string; size: number | null; fixedSize: boolean }>;\n labelPoints: number;\n pointSize: number | null;\n pointFixedSize: boolean;\n // Edges\n showEdges: boolean;\n edgeLayers: EdgeLayerSpec[];\n edgeColorScale: ColorScale;\n edgeMagnify: number | null;\n\n showTrajectories: boolean;\n trajectoryUnits: string | null;\n trajectorySmooth: 'none' | 'poly';\n trajectoryMaxDegree: number;\n trajectoryDegreeSelection: 'loocv_2d' | 'fixed';\n trajectoryShowPoints: boolean;\n trajectoryShowTips: boolean;\n trajectoryPlayhead: number | null;\n trajectoryLineStyle: 'uniform' | 'tapered';\n trajectoryStrokeWidth: number;\n trajectoryStrokeWidthRange: [number, number];\n trajectoryOpacityRange: [number, number];\n // Axes\n showAxes: boolean;\n axisXLabel: string | null;\n axisYLabel: string | null;\n } {\n const nodesEl = this.querySelector('qe-nodes');\n const meansEl = this.querySelector('qe-means');\n // <qe-points> without `set` = all unit points; with `set` = an explicit set.\n const allPointsEls = [...this.querySelectorAll('qe-points')];\n const pointsEl = allPointsEls.find(e => !e.hasAttribute('set')) ?? null;\n const setEls = allPointsEls.filter(e => e.hasAttribute('set'));\n // Every <qe-edges> child is one layer (0.5): a named network (group / unit\n // / compare / also) or an explicit one (network=\"name\" → model.networks).\n const edgeEls = [...this.querySelectorAll('qe-edges')];\n const firstAttr = (a: string) => edgeEls.find(e => e.hasAttribute(a))?.getAttribute(a) ?? null;\n const magnifyEl = edgeEls.find(e => e.hasAttribute('magnify'));\n const trajectoriesEl = this.querySelector('qe-trajectories');\n const axesEl = this.querySelector('qe-axes');\n const labelsShorthand = this.getAttribute('labels');\n\n return {\n // Nodes — always placed from the model (they anchor the coordinate\n // space); <qe-nodes> presence draws them, like every other layer.\n labelNodes: parseLabelMode(\n nodesEl?.getAttribute('label') ?? this.getAttribute('label-nodes') ?? labelsShorthand,\n Label.DISPLAY_TYPES.ON\n ),\n showNodes: !!nodesEl,\n range: (() => {\n const v = this.getAttribute('range');\n if (v === 'network' || v === 'points') return v;\n const n = Number(v);\n return v != null && Number.isFinite(n) && n > 0 ? n : null;\n })(),\n plotTitle: this.getAttribute('plot-title') || null,\n labelFont: {\n size: (() => { const n = Number(this.getAttribute('label-font-size'));\n return Number.isFinite(n) && n > 0 ? n : null; })(),\n family: this.getAttribute('label-font-family') || null,\n color: this.getAttribute('label-font-color') || null,\n },\n edgeWidth: (() => {\n const v = Number(this.getAttribute('edge-width'));\n return Number.isFinite(v) && v > 0 && v <= 1 ? v : DEFAULT_EDGE_WIDTH;\n })(),\n hideUnconnectedNodes: nodesEl?.getAttribute('unconnected')?.toLowerCase() === 'hide',\n scalePoints: this.getAttribute('scale-points') !== 'false',\n pointScale: (() => {\n const v = Number(this.getAttribute('point-scale'));\n return this.hasAttribute('point-scale') && Number.isFinite(v) && v > 0 ? v : null;\n })(),\n centerContent: this.getAttribute('center') === 'content',\n\n // Means — presence of <qe-means> = show; absence = hide.\n showMeans: !!meansEl,\n activeMeanGroups: meansEl?.getAttribute('groups') ?? null,\n showCI: !!meansEl && meansEl.hasAttribute('confidence'),\n // intervals=\"box|crosshairs|none\"; absent → the legacy `confidence` flag.\n intervals: (() => {\n const v = meansEl?.getAttribute('intervals');\n if (v === 'box' || v === 'crosshairs' || v === 'none') return v;\n return meansEl?.hasAttribute('confidence') ? 'box' : 'none';\n })() as 'box' | 'crosshairs' | 'none',\n showOutlier: !!meansEl && meansEl.hasAttribute('outlier'),\n labelMeans: parseLabelMode(\n meansEl?.getAttribute('label') ?? this.getAttribute('label-means') ?? labelsShorthand,\n Label.DISPLAY_TYPES.ON\n ),\n // fixed-size keeps mean markers a constant on-screen px size (webENA parity).\n meanFixedSize: !!meansEl && meansEl.hasAttribute('fixed-size'),\n\n // Points — presence of <qe-points> = show unit dots.\n showPoints: !!pointsEl,\n pointSets: setEls.map(e => ({\n set: e.getAttribute('set')!,\n size: e.getAttribute('size') ? parseFloat(e.getAttribute('size')!) : null,\n fixedSize: e.hasAttribute('fixed-size'),\n })),\n labelPoints: parseLabelMode(\n pointsEl?.getAttribute('label') ?? this.getAttribute('label-points') ?? labelsShorthand,\n Label.DISPLAY_TYPES.OFF\n ),\n pointSize: pointsEl?.getAttribute('size') ? parseFloat(pointsEl.getAttribute('size')!) : null,\n // fixed-size keeps unit dots a constant on-screen px size (webENA parity).\n pointFixedSize: !!pointsEl && pointsEl.hasAttribute('fixed-size'),\n\n // Edges — presence of <qe-edges> = draw a network.\n showEdges: edgeEls.length > 0,\n edgeLayers: edgeEls.map(parseEdgeLayer),\n // Plot-wide edge settings: the first <qe-edges> that sets them.\n edgeColorScale: parseColorScale(firstAttr('color-scale')),\n edgeMagnify: magnifyEl ? (() => {\n const v = Number(magnifyEl.getAttribute('magnify'));\n return Number.isFinite(v) && v > 0 ? v : 1;\n })() : null,\n\n // Trajectories — presence of <qe-trajectories> = draw cognitive trajectories\n showTrajectories: !!trajectoriesEl,\n trajectoryUnits: trajectoriesEl?.getAttribute('units') ?? null,\n trajectorySmooth: (trajectoriesEl?.getAttribute('smooth') as 'none' | 'poly') ?? 'none',\n trajectoryMaxDegree: trajectoriesEl?.getAttribute('max-degree') ? parseInt(trajectoriesEl.getAttribute('max-degree')!, 10) : 3,\n trajectoryDegreeSelection: (trajectoriesEl?.getAttribute('degree-selection') as 'loocv_2d' | 'fixed') ?? 'loocv_2d',\n trajectoryShowPoints: trajectoriesEl?.getAttribute('points') !== 'false',\n trajectoryShowTips: trajectoriesEl?.getAttribute('tips') !== 'false',\n trajectoryPlayhead: trajectoriesEl?.getAttribute('playhead') ? parseFloat(trajectoriesEl.getAttribute('playhead')!) : null,\n trajectoryLineStyle: (trajectoriesEl?.getAttribute('line-style') as 'uniform' | 'tapered') ?? 'uniform',\n trajectoryStrokeWidth: trajectoriesEl?.getAttribute('stroke-width') ? parseFloat(trajectoriesEl.getAttribute('stroke-width')!) : 2,\n trajectoryStrokeWidthRange: this._parseNumberPair(trajectoriesEl?.getAttribute('stroke-width-range'), [1, 6]),\n trajectoryOpacityRange: this._parseNumberPair(trajectoriesEl?.getAttribute('opacity-range'), [0.3, 1]),\n\n // Axes — presence of <qe-axes> = draw axis lines. The x / y attributes add\n // a per-axis label: a value is used verbatim, an empty attribute falls back\n // to the dimension name (resolved later, where dims are known). null = no\n // label for that axis.\n showAxes: !!axesEl,\n axisXLabel: axesEl?.hasAttribute('x') ? (axesEl.getAttribute('x') ?? '') : null,\n axisYLabel: axesEl?.hasAttribute('y') ? (axesEl.getAttribute('y') ?? '') : null,\n };\n }\n\n private _parseNumberPair(value: string | null | undefined, fallback: [number, number]): [number, number] {\n if (!value) return fallback;\n const parts = value.split(',').map(part => Number(part.trim()));\n if (parts.length < 2 || !parts.every(Number.isFinite)) return fallback;\n return [parts[0], parts[1]];\n }\n\n attributeChangedCallback(_name: string, oldValue: string | null, newValue: string | null): void {\n if (oldValue === newValue) return;\n this._scheduleRerender();\n }\n\n connectedCallback(): void {\n // Apply width/height HTML attributes as CSS dimensions on the host element\n // so the shadow-DOM wrapper's height:100% resolves to a real pixel value.\n const w = this.getAttribute('width');\n const h = this.getAttribute('height');\n this.style.display = 'block'; // custom elements are inline by default\n if (w) this.style.width = isNaN(Number(w)) ? w : `${w}px`;\n if (h) this.style.height = isNaN(Number(h)) ? h : `${h}px`;\n\n this.appendChild(this.svg_element);\n QEGraphElement._instances.add(this); // registry for getGraph()/instances()\n\n // Watch for child layer element additions/removals and attribute changes.\n // Any mutation schedules a re-render via the same microtask batch used by\n // attributeChangedCallback, so synchronous DOM mutations collapse to one pass.\n this._childObserver = new MutationObserver(() => this._scheduleRerender());\n this._childObserver.observe(this, {\n childList: true,\n attributes: true,\n subtree: true,\n attributeFilter: [\n 'group', 'unit', 'compare', 'also', 'color-scale', 'magnify',\n 'network', 'colors', 'threshold', 'name',\n 'groups', 'confidence', 'label', 'intervals', 'outlier', 'set', 'unconnected',\n 'scale-points', 'point-scale', 'edge-width', 'labels', 'range', 'center', 'plot-title',\n 'label-font-size', 'label-font-family', 'label-font-color', 'label-nodes', 'label-means', 'label-points',\n 'units', 'smooth', 'degree', 'points', 'tips', 'playhead',\n 'line-style', 'stroke-width', 'stroke-width-range', 'opacity-range',\n 'x', 'y', 'size', 'fixed-size',\n ],\n });\n // Find the associated ena-visual: check 'for' attribute first, then nearest\n // ancestor, then first one on the page. This lets ena-graph work as a child,\n // a sibling, or anywhere else in the document.\n const forId = this.getAttribute('for');\n this._vizena = (\n (forId ? document.getElementById(forId) : null) ??\n this.closest('qe-visual') ??\n this.parentElement?.closest('qe-visual') ??\n document.querySelector('qe-visual')\n ) as QEVisualElement;\n this.draw();\n\n // Cache the labels <g> after draw() has connected all layer elements to\n // the SVG DOM. We do this once here rather than searching on every\n // model-updated event to guarantee we always have a valid reference.\n const labelsLayer = this.__children__.search('__children__', 'labels') as QELayer;\n if (labelsLayer?.svg_element) {\n this._labelsGroup = labelsLayer.svg_element as SVGGElement;\n } else {\n // Fallback: create a new <g> directly inside the outermost graph layer.\n console.warn('[ena-graph] labels layer not found in layer tree; creating fallback <g>');\n const graphLayer = this.__children__[0] as QELayer;\n if (graphLayer?.svg_element) {\n this._labelsGroup = document.createElementNS('http://www.w3.org/2000/svg', 'g') as SVGGElement;\n this._labelsGroup.setAttribute('data-layer-name', 'labels-fallback');\n graphLayer.svg_element.appendChild(this._labelsGroup);\n }\n }\n }\n\n disconnectedCallback(): void {\n this._childObserver?.disconnect();\n this._childObserver = null;\n this._resizeObs?.disconnect();\n this._resizeObs = null;\n QEGraphElement._instances.delete(this);\n // Remove the body-level tooltip node so it doesn't outlive the graph.\n this._tooltipEl?.remove();\n this._tooltipEl = null;\n }\n\n // ── Instance registry + read APIs (webENA integration) ──────────────────────\n private static _instances: Set<QEGraphElement> = new Set();\n\n /** All connected <qe-graph> instances (newest membership order). */\n static instances(): QEGraphElement[] { return [...QEGraphElement._instances]; }\n\n /** Look up a graph by its `id` or `plot-group` attribute. */\n static getGraph(key: string): QEGraphElement | null {\n for (const g of QEGraphElement._instances) {\n if (g.id === key || g.getAttribute('plot-group') === key) return g;\n }\n return null;\n }\n\n /** Resolved code nodes with their current graph-space coordinates. */\n getNodes(): Array<{ id: string; name: string; x: number; y: number }> {\n const layer = this.__children__.search('__children__', 'nodes') as QELayer | undefined;\n if (!layer) return [];\n return [...layer.__data__.objects.values()].map((o: any) => ({\n id: o.ID, name: o.meta?.name ?? o.ID, x: o.x, y: o.y,\n }));\n }\n\n /** Resolved edges of the current network with weights and direction. */\n getEdges(): Array<{ source: string; target: string; weight: number; directed: boolean; self: boolean }> {\n const collect = (name: string) => {\n const l = this.__children__.search('__children__', name) as QELayer | undefined;\n return l ? [...l.__data__.objects.values()] : [];\n };\n return [...collect('edges'), ...collect('edgenodes')]\n .map((o: any) => {\n const m = o.meta ?? {};\n return { source: m.source, target: m.target, weight: m.weight ?? 0,\n directed: !!m.isDirected, self: !!m.isSelf };\n })\n .filter(e => e.source != null && e.target != null);\n }\n\n // ── Transition tweening (opt-in via the `animate` attribute; webENA P2.1) ───\n private _animateMs = 0;\n private _tweenRaf: number | null = null;\n\n /** Matches every numeric token in an SVG path `d` string (ints, decimals,\n * scientific notation, leading sign) while leaving command letters intact. */\n private static _PATH_NUM_RE = /-?\\d*\\.?\\d+(?:e[-+]?\\d+)?/gi;\n\n /** Marks (circles/rects), undirected edge lines, and directed / self-edge\n * triangle paths all participate in tweening. */\n private _tweenTargets(): SVGElement[] {\n return [...this.svg_element.querySelectorAll(\n 'circle[data-point-id], rect[data-point-id], line[data-edge-source], path[data-edge-source]'\n )] as SVGElement[];\n }\n\n private _readCoords(el: SVGElement): any {\n const tag = el.tagName.toLowerCase();\n const n = (a: string) => parseFloat(el.getAttribute(a) || '0');\n if (tag === 'circle') return { t: 'c', cx: n('cx'), cy: n('cy') };\n if (tag === 'rect') return { t: 'r', x: n('x'), y: n('y') };\n if (tag === 'line') return { t: 'l', x1: n('x1'), y1: n('y1'), x2: n('x2'), y2: n('y2') };\n if (tag === 'path') {\n const d = el.getAttribute('d') || '';\n return { t: 'p', d, nums: (d.match(QEGraphElement._PATH_NUM_RE) || []).map(Number) };\n }\n return null;\n }\n\n /** Snapshot current tween-target positions keyed by element. */\n private _captureTween(): Map<SVGElement, any> {\n const m = new Map<SVGElement, any>();\n this._tweenTargets().forEach(el => { const c = this._readCoords(el); if (c) m.set(el, c); });\n return m;\n }\n\n /** Animate each still-present element from its snapshot to its new position. */\n private _runTween(from: Map<SVGElement, any>): void {\n if (this._tweenRaf !== null) { cancelAnimationFrame(this._tweenRaf); this._tweenRaf = null; }\n const to = new Map<SVGElement, any>();\n this._tweenTargets().forEach(el => { if (from.has(el)) { const c = this._readCoords(el); if (c) to.set(el, c); } });\n if (!to.size) return;\n\n const dur = this._animateMs;\n const t0 = performance.now();\n const ease = (t: number) => (t < 0.5 ? 2 * t * t : 1 - Math.pow(-2 * t + 2, 2) / 2);\n const lerp = (a: number, b: number, k: number) => a + (b - a) * k;\n\n const step = (now: number) => {\n const t = Math.min(1, (now - t0) / dur);\n const k = ease(t);\n to.forEach((nc, el) => {\n const oc = from.get(el);\n if (!oc || oc.t !== nc.t) return;\n if (nc.t === 'c') {\n el.setAttribute('cx', String(lerp(oc.cx, nc.cx, k)));\n el.setAttribute('cy', String(lerp(oc.cy, nc.cy, k)));\n } else if (nc.t === 'r') {\n el.setAttribute('x', String(lerp(oc.x, nc.x, k)));\n el.setAttribute('y', String(lerp(oc.y, nc.y, k)));\n } else if (nc.t === 'l') {\n el.setAttribute('x1', String(lerp(oc.x1, nc.x1, k)));\n el.setAttribute('y1', String(lerp(oc.y1, nc.y1, k)));\n el.setAttribute('x2', String(lerp(oc.x2, nc.x2, k)));\n el.setAttribute('y2', String(lerp(oc.y2, nc.y2, k)));\n } else {\n // Directed / self-edge triangle path: interpolate the numeric tokens\n // in `d` when the command structure is stable (equal token count).\n // Otherwise leave the freshly-built `d` in place (graceful snap).\n if (!oc.nums || oc.nums.length !== nc.nums.length) return;\n let i = 0;\n const d = nc.d.replace(QEGraphElement._PATH_NUM_RE,\n () => String(lerp(oc.nums[i], nc.nums[i++], k)));\n el.setAttribute('d', d);\n }\n });\n this._tweenRaf = t < 1 ? requestAnimationFrame(step) : null;\n };\n this._tweenRaf = requestAnimationFrame(step);\n }\n\n /** Serialize the current plot as a standalone SVG string (webENA P2.3). */\n toSVG(): string {\n const svg = this.svg_element.cloneNode(true) as SVGSVGElement;\n svg.setAttribute('xmlns', 'http://www.w3.org/2000/svg');\n svg.setAttribute('xmlns:xlink', 'http://www.w3.org/1999/xlink');\n const rect = this.svg_element.getBoundingClientRect();\n if (rect.width) svg.setAttribute('width', String(Math.round(rect.width)));\n if (rect.height) svg.setAttribute('height', String(Math.round(rect.height)));\n return new XMLSerializer().serializeToString(svg);\n }\n\n /** Rasterize the current plot to a PNG data URL (webENA P2.3). `scale`\n * multiplies the pixel dimensions for a higher-resolution image. */\n toPNG(scale = 2): Promise<string> {\n const svgStr = this.toSVG();\n const rect = this.svg_element.getBoundingClientRect();\n const w = Math.max(1, Math.round(rect.width));\n const h = Math.max(1, Math.round(rect.height));\n return new Promise((resolve, reject) => {\n const blob = new Blob([svgStr], { type: 'image/svg+xml;charset=utf-8' });\n const url = URL.createObjectURL(blob);\n const img = new Image();\n img.onload = () => {\n try {\n const canvas = document.createElement('canvas');\n canvas.width = w * scale;\n canvas.height = h * scale;\n const ctx = canvas.getContext('2d');\n if (!ctx) { URL.revokeObjectURL(url); reject(new Error('no 2d context')); return; }\n ctx.scale(scale, scale);\n ctx.drawImage(img, 0, 0, w, h);\n URL.revokeObjectURL(url);\n resolve(canvas.toDataURL('image/png'));\n } catch (err) { URL.revokeObjectURL(url); reject(err); }\n };\n img.onerror = (e) => { URL.revokeObjectURL(url); reject(e); };\n img.src = url;\n });\n }\n\n /** Unit points with their current graph-space coordinates. */\n getPoints(): Array<{ id: string; group?: string; set?: string; x: number; y: number }> {\n const layer = this.__children__.search('__children__', 'points') as QELayer | undefined;\n if (!layer) return [];\n return [...layer.__data__.objects.values()]\n .filter((o: any) => o.meta?.kind === 'point')\n .map((o: any) => ({ id: o.meta?.unit ?? o.ID, group: o.meta?.group, set: o.meta?.set,\n x: o.x, y: o.y }));\n }\n\n /** Ids of unit points inside a graph-space rectangle (for drag/lasso select). */\n pointsInRect(rect: { x: number; y: number; w: number; h: number }): string[] {\n return this.getPoints()\n .filter(p => p.x >= rect.x && p.x <= rect.x + rect.w &&\n p.y >= rect.y && p.y <= rect.y + rect.h)\n .map(p => p.id);\n }\n\n // ── Host-driven highlight / selection (webENA P1.1) ─────────────────────────\n // Rendered as an overlay group so it never mutates the marks themselves, and\n // is re-applied after every render so selection survives model updates.\n private _highlight: { edges: Set<string>; nodes: Set<string> } = { edges: new Set(), nodes: new Set() };\n private _highlightGroup: SVGGElement | null = null;\n\n /** Order-independent key so an undirected pair matches either direction. */\n private _edgeKey(a: string, b: string): string {\n return a <= b ? `${a}\u0000${b}` : `${b}\u0000${a}`;\n }\n\n /** Mark edges/nodes as highlighted. Replaces the previous selection. */\n setHighlight(sel: { edges?: Array<{ source: string; target: string }>; nodes?: Array<string> }): void {\n this._highlight.edges = new Set((sel.edges ?? []).map(e => this._edgeKey(e.source, e.target)));\n this._highlight.nodes = new Set((sel.nodes ?? []).map(String));\n this._applyHighlights();\n }\n\n /** Clear all highlighting. */\n clearHighlight(): void {\n this._highlight.edges.clear();\n this._highlight.nodes.clear();\n this._applyHighlights();\n }\n\n private _applyHighlights(): void {\n if (!this.svg_element) return;\n if (!this._highlightGroup) {\n this._highlightGroup = document.createElementNS('http://www.w3.org/2000/svg', 'g') as SVGGElement;\n this._highlightGroup.setAttribute('data-layer-name', 'highlight');\n this._highlightGroup.setAttribute('pointer-events', 'none');\n }\n // Keep the overlay on top.\n this.svg_element.appendChild(this._highlightGroup);\n const g = this._highlightGroup;\n g.textContent = '';\n\n const extent = (this.__data__ as Graph).extremes.x_max || 1;\n const HL = '#f5a623';\n const mk = (tag: string, attrs: Record<string, string | number>) => {\n const el = document.createElementNS('http://www.w3.org/2000/svg', tag);\n for (const k in attrs) el.setAttribute(k, String(attrs[k]));\n return el;\n };\n\n // Edges — a translucent glow line between the two code-node centres.\n if (this._highlight.edges.size) {\n const xy: Record<string, { x: number; y: number }> = {};\n this.getNodes().forEach(n => { xy[n.id] = { x: n.x, y: n.y }; });\n this._highlight.edges.forEach(key => {\n const [a, b] = key.split('\u0000');\n const A = xy[a], B = xy[b];\n if (!A || !B) return;\n g.appendChild(mk('line', {\n x1: A.x, y1: A.y, x2: B.x, y2: B.y,\n stroke: HL, 'stroke-width': extent * 0.02, 'stroke-opacity': 0.6, 'stroke-linecap': 'round',\n }));\n });\n }\n\n // Nodes / means / points — a ring around the mark.\n this._highlight.nodes.forEach(id => {\n const el = this.svg_element.querySelector(`[data-point-id=\"${(window as any).CSS?.escape ? CSS.escape(id) : id}\"]`) as SVGElement | null;\n if (!el) return;\n const tag = el.tagName.toLowerCase();\n let cx: number, cy: number, r: number;\n if (tag === 'rect') {\n const w = parseFloat(el.getAttribute('width') || '0');\n cx = parseFloat(el.getAttribute('x') || '0') + w / 2;\n cy = parseFloat(el.getAttribute('y') || '0') + parseFloat(el.getAttribute('height') || '0') / 2;\n r = w / 2;\n } else {\n cx = parseFloat(el.getAttribute('cx') || '0');\n cy = parseFloat(el.getAttribute('cy') || '0');\n r = parseFloat(el.getAttribute('r') || '0');\n }\n g.appendChild(mk('circle', {\n cx, cy, r: r * 1.7 + extent * 0.004, fill: 'none', stroke: HL, 'stroke-width': extent * 0.006,\n }));\n });\n }\n\n create(): SVGElement {\n const\n svg = document.createElementNS(\"http://www.w3.org/2000/svg\", \"svg\")\n ;\n svg.classList.add(\"graph\");\n // Fill the host and keep the square ENA drawing centered (equal x/y scaling\n // preserves distances). Without this the SVG collapses to an intrinsic size\n // and pins to the left, leaving dead space in the container.\n svg.style.display = 'block';\n svg.style.width = '100%';\n svg.style.height = '100%';\n svg.setAttribute(\"preserveAspectRatio\", \"xMidYMid meet\");\n svg.setAttribute(\"viewBox\", (this.__data__ as Graph).extremes.as_viewBox());\n svg.setAttribute(\"transform\", (this.__data__ as Graph).transform.toString());\n svg.setAttribute(\"role\", \"figure\");\n svg.setAttribute(\"data-graph-size\", `${Math.min((this.__data__ as Graph).extremes.width, (this.__data__ as Graph).extremes.height)}`);\n this.svg_element = svg;\n\n // Pre-generate one arrowhead marker per palette color. Per-color markers are\n // the most reliable approach: `context-stroke` and `currentColor` inheritance\n // through SVG markers is inconsistent across browsers and shadow-DOM contexts.\n // Reference as url(#qe-arrow-RRGGBB) where RRGGBB is the hex without '#'.\n const defs = document.createElementNS('http://www.w3.org/2000/svg', 'defs');\n // Arrow dimensions in SVG user-space units (viewBox is ~4.8×4.8).\n // AW must be large enough so the body of the arrowhead is visible before it\n // disappears behind the target node circle. ~5% of the viewport (0.24 units)\n // works well. markerUnits=\"userSpaceOnUse\" keeps the size fixed regardless\n // of stroke-width, so even thin edges get a readable direction indicator.\n const AW = 0.22, AH = 0.15; // arrow length (along edge) and base width (perp)\n const makeArrow = (id: string, fill: string) => {\n const m = document.createElementNS('http://www.w3.org/2000/svg', 'marker');\n m.setAttribute('id', id);\n m.setAttribute('markerWidth', String(AW));\n m.setAttribute('markerHeight',String(AH));\n m.setAttribute('refX', String(AW)); // tip at reference point\n m.setAttribute('refY', String(AH / 2));\n m.setAttribute('orient', 'auto');\n m.setAttribute('markerUnits', 'userSpaceOnUse');\n const p = document.createElementNS('http://www.w3.org/2000/svg', 'path');\n p.setAttribute('d', `M0,0 L0,${AH} L${AW},${AH/2} z`);\n p.setAttribute('fill', fill);\n m.appendChild(p);\n defs.appendChild(m);\n };\n // One marker per GROUP_PALETTE entry (covers all possible edge colors)\n GROUP_PALETTE.forEach(color => makeArrow(`qe-arrow-${color.slice(1)}`, color));\n svg.appendChild(defs);\n\n this.__data__.layers.forEach((layer: LayerLike) => {\n const layer_g: QELayer = new QELayer(layer as any, this.svg_element, this);\n this.__children__.push(layer_g);\n });\n\n this.__data__.__state__.setVariable(\"graph_updated\", this.__data__ );\n\n this.attach_events();\n\n return svg;\n }\n\n attach_events() {\n // Attach event for zooming\n this.svg_element.addEventListener(\"wheel\", (ev: WheelEvent) => {\n console.log(\"Wheel event: \", ev);\n ev.preventDefault();\n const delta = Math.sign(ev.deltaY);\n if (delta < 0) {\n this.zoom_level *= 1.1;\n } else {\n this.zoom_level /= 1.1;\n }\n this.__data__.transform.zoom(this.zoom_level);\n this.update();\n });\n\n // Attach event for panning\n let isPanning = false;\n let startX: number, startY: number;\n\n this.svg_element.addEventListener(\"mousedown\", (ev: MouseEvent) => {\n isPanning = true;\n startX = ev.clientX;\n startY = ev.clientY;\n });\n let panAnimationFrame: number | null = null;\n let pendingPan: { dx: number, dy: number } | null = null;\n\n const panUpdate = () => {\n if (pendingPan) {\n this.__data__.transform.pan(pendingPan.dx, pendingPan.dy);\n this.__children__[0].svg_element.setAttribute(\"transform\", this.__data__.transform.toString());\n pendingPan = null;\n }\n panAnimationFrame = null;\n };\n\n this.svg_element.addEventListener(\"mousemove\", (ev: MouseEvent) => {\n if (!isPanning) return;\n const \n dx = ev.clientX - startX,\n dy = ev.clientY - startY\n ;\n pendingPan = { dx: dx / 100, dy: dy / 100 };\n startX = ev.clientX;\n startY = ev.clientY;\n \n if (panAnimationFrame === null) {\n panAnimationFrame = requestAnimationFrame(panUpdate);\n }\n });\n\n this.svg_element.addEventListener(\"mouseup\", (ev: MouseEvent) => {\n isPanning = false;\n });\n\n // ── Label interactions ───────────────────────────────────────────────────\n // CLICK mode: toggle label on point-clicked event\n this.svg_element.addEventListener('point-clicked', ((ev: CustomEvent) => {\n const id = ev.detail?.pointData?.ID;\n if (!id) return;\n const lbl = this._pointLabels.get(id)\n ?? this._meanLabels.get(id.replace('mean-', ''))\n ?? this._nodeLabels.get(id);\n if (lbl && lbl.displayMode === Label.DISPLAY_TYPES.CLICK) lbl.toggle();\n }) as EventListener);\n\n // AUTO mode: show/hide labels via event delegation on the SVG.\n // We look for the nearest ancestor (or the target itself) that has\n // data-point-id so the hit-area works even on complex shapes.\n const findPointId = (el: SVGElement | null): string | null => {\n while (el && el !== this.svg_element) {\n const id = el.getAttribute?.('data-point-id');\n if (id) return id;\n el = el.parentElement as SVGElement | null;\n }\n return null;\n };\n\n const getAutoLabel = (id: string): QELabel | undefined => {\n return this._pointLabels.get(id)\n ?? this._meanLabels.get(id.replace(/^mean-/, ''))\n ?? this._nodeLabels.get(id);\n };\n\n this.svg_element.addEventListener('mouseover', (ev: MouseEvent) => {\n const id = findPointId(ev.target as SVGElement);\n if (!id) return;\n const lbl = getAutoLabel(id);\n if (lbl?.displayMode === Label.DISPLAY_TYPES.AUTO) lbl.show();\n });\n\n this.svg_element.addEventListener('mouseout', (ev: MouseEvent) => {\n // Only hide when the mouse leaves the point element entirely,\n // not when it enters a child (e.g., a nested SVG element).\n const id = findPointId(ev.target as SVGElement);\n if (!id) return;\n // relatedTarget is where the mouse went — if it's still inside\n // the same point element, don't hide.\n const related = ev.relatedTarget as SVGElement | null;\n const relatedId = findPointId(related);\n if (relatedId === id) return; // still inside the same point\n const lbl = getAutoLabel(id);\n if (lbl?.displayMode === Label.DISPLAY_TYPES.AUTO) lbl.hide();\n });\n\n // ── Public interaction events (webENA integration surface) ────────────────\n // Dispatched on the public <qe-graph> element with bubbles+composed so a\n // host app can subscribe regardless of shadow DOM. See README \"Events\".\n this._attachInteractionEvents();\n }\n\n /** Emit a namespaced CustomEvent on the public element (bubbles + composed). */\n private _emit(name: string, detail: Record<string, any>): void {\n this.dispatchEvent(new CustomEvent(name, { detail, bubbles: true, composed: true }));\n }\n\n /** Walk up from a hit element to the nearest ancestor carrying `attr`. */\n private _closestWith(el: SVGElement | null, attr: string): SVGElement | null {\n while (el && el !== this.svg_element) {\n if (el.getAttribute?.(attr) != null && el.hasAttribute?.(attr)) return el;\n el = el.parentElement as SVGElement | null;\n }\n return null;\n }\n\n /** Resolve an edge hit element to a qe-edge-* detail, or null. */\n private _edgeDetail(el: SVGElement | null): Record<string, any> | null {\n const e = this._closestWith(el, 'data-edge-source');\n if (!e) return null;\n const d: Record<string, any> = {\n source: e.getAttribute('data-edge-source'),\n target: e.getAttribute('data-edge-target'),\n weight: parseFloat(e.getAttribute('data-edge-weight') || '0'),\n directed: e.getAttribute('data-edge-directed') === 'true',\n self: e.getAttribute('data-edge-self') === 'true',\n };\n if (e.hasAttribute('data-edge-group')) d.group = e.getAttribute('data-edge-group');\n if (e.hasAttribute('data-edge-unit')) d.unit = e.getAttribute('data-edge-unit');\n return d;\n }\n\n /** Resolve a node/mean/point hit element to a qe-node-* detail, or null. */\n private _nodeDetail(el: SVGElement | null): Record<string, any> | null {\n const n = this._closestWith(el, 'data-point-id');\n if (!n) return null;\n const tag = n.tagName.toLowerCase();\n let x: number, y: number;\n if (tag === 'rect') {\n x = parseFloat(n.getAttribute('x') || '0') + parseFloat(n.getAttribute('width') || '0') / 2;\n y = parseFloat(n.getAttribute('y') || '0') + parseFloat(n.getAttribute('height') || '0') / 2;\n } else {\n x = parseFloat(n.getAttribute('cx') || '0');\n y = parseFloat(n.getAttribute('cy') || '0');\n }\n const id = n.getAttribute('data-point-id')!;\n const d: Record<string, any> = {\n id,\n kind: n.getAttribute('data-kind') || 'point',\n name: n.getAttribute('data-name') || id,\n x, y,\n };\n if (n.hasAttribute('data-group')) d.group = n.getAttribute('data-group');\n if (n.hasAttribute('data-unit')) d.unit = n.getAttribute('data-unit');\n return d;\n }\n\n private _attachInteractionEvents(): void {\n const svg = this.svg_element;\n\n svg.addEventListener('click', (ev: MouseEvent) => {\n const target = ev.target as SVGElement;\n const edge = this._edgeDetail(target);\n if (edge) { this._emit('qe-edge-click', { ...edge, originalEvent: ev }); return; }\n const node = this._nodeDetail(target);\n if (node) this._emit('qe-node-click', { ...node, originalEvent: ev });\n });\n\n // Hover enter/leave, tracked so we emit one unhover→hover pair per change.\n let hovered: { type: 'edge' | 'node'; key: string } | null = null;\n const keyOf = (t: 'edge' | 'node', d: Record<string, any>) =>\n t === 'edge' ? `${d.source}\u0000${d.target}` : String(d.id);\n\n svg.addEventListener('mousemove', (ev: MouseEvent) => {\n const target = ev.target as SVGElement;\n const edge = this._edgeDetail(target);\n const node = edge ? null : this._nodeDetail(target);\n const next = edge ? { type: 'edge' as const, detail: edge }\n : node ? { type: 'node' as const, detail: node }\n : null;\n const nextKey = next ? keyOf(next.type, next.detail) : null;\n if (hovered && (!next || hovered.key !== nextKey)) {\n this._emit(hovered.type === 'edge' ? 'qe-edge-unhover' : 'qe-node-unhover', { key: hovered.key });\n hovered = null;\n }\n if (next && (!hovered || hovered.key !== nextKey)) {\n this._emit(next.type === 'edge' ? 'qe-edge-hover' : 'qe-node-hover', { ...next.detail, originalEvent: ev });\n hovered = { type: next.type, key: nextKey! };\n }\n // Opt-in built-in tooltip (P1.3 bonus): shown only when <qe-graph tooltip>.\n // The host is free to build its own from the hover events instead.\n if (this.hasAttribute('tooltip') && next) {\n this._showTooltip(this._tooltipText(next.type, next.detail), ev.clientX, ev.clientY);\n } else {\n this._hideTooltip();\n }\n });\n\n svg.addEventListener('mouseleave', () => {\n if (hovered) {\n this._emit(hovered.type === 'edge' ? 'qe-edge-unhover' : 'qe-node-unhover', { key: hovered.key });\n hovered = null;\n }\n this._hideTooltip();\n });\n }\n\n // ── Opt-in built-in tooltip ─────────────────────────────────────────────────\n private _tooltipEl: HTMLDivElement | null = null;\n\n /** \"source – target (weight)\" for edges; the mark name for nodes/means/points. */\n private _tooltipText(type: 'edge' | 'node', d: Record<string, any>): string {\n if (type === 'edge') {\n const w = Number(d.weight);\n const wStr = Number.isFinite(w) ? ` (${(+w.toFixed(3))})` : '';\n return `${d.source} – ${d.target}${wStr}`;\n }\n return String(d.name ?? d.id);\n }\n\n private _showTooltip(text: string, clientX: number, clientY: number): void {\n if (!this._tooltipEl) {\n const el = document.createElement('div');\n el.setAttribute('data-qe-tooltip', '');\n Object.assign(el.style, {\n position: 'fixed', zIndex: '2147483647', pointerEvents: 'none',\n background: 'rgba(20,20,20,0.92)', color: '#fff',\n font: '12px/1.4 system-ui, sans-serif', padding: '3px 7px',\n borderRadius: '4px', whiteSpace: 'nowrap',\n transform: 'translate(-50%, calc(-100% - 8px))',\n } as CSSStyleDeclaration);\n document.body.appendChild(el);\n this._tooltipEl = el;\n }\n this._tooltipEl.textContent = text;\n this._tooltipEl.style.left = `${clientX}px`;\n this._tooltipEl.style.top = `${clientY}px`;\n this._tooltipEl.style.display = 'block';\n }\n\n private _hideTooltip(): void {\n if (this._tooltipEl) this._tooltipEl.style.display = 'none';\n }\n\n draw() {\n if(!this.svg_element) {\n console.error(\"No element to draw to: \", this);\n return;\n }\n \n this.wrapper?.appendChild(this.svg_element);\n\n (this.__children__ as QELayer[]).forEach((enaLayer: QELayer) => {\n enaLayer.draw();\n });\n\n // Pixel-sized text (label-font-size, the plot title) is converted to model\n // units at the current width, so re-lay it out when the plot is resized.\n if (!this._resizeObs && typeof ResizeObserver !== 'undefined' && this.svg_element) {\n let lastW = 0;\n this._resizeObs = new ResizeObserver(entries => {\n const w = entries[0]?.contentRect.width ?? 0;\n if (w > 0 && Math.abs(w - lastW) > 0.5) {\n lastW = w;\n this.update_labels();\n this.update_axes();\n }\n });\n this._resizeObs.observe(this.svg_element);\n }\n }\n\n update() {\n // Two-pass update: first pass lays out elements and computes extremes;\n // second pass re-syncs the viewBox now that all element positions are final.\n this.update_extremes();\n this.update_layers();\n this.update_labels(); // positions labels using the freshly-computed extent\n this.update_extremes(); // re-apply viewBox after label/layer repositioning\n this.update_axes(); // axis line visibility + labels (uses final extent)\n this._applyHighlights(); // re-apply host highlight over the fresh render\n }\n\n /**\n * Axes (<qe-axes>): toggle the axis-line cross by presence, and draw/position\n * per-axis labels at the positive ends using the current extent. Labels are\n * cached SVG <text> nodes in the labels group; null text removes them.\n */\n update_axes(): void {\n // Show or hide the whole axis sub-tree (lines + origin) by <qe-axes> presence.\n const axesLayer = this.__children__.search('__children__', 'axes') as QELayer | undefined;\n if (axesLayer?.svg_element) {\n (axesLayer.svg_element as SVGElement).style.display = this._showAxes ? '' : 'none';\n }\n\n const parent = this._labelsGroup;\n const extent = this.__data__.extremes.x_max;\n const { cx, cy } = this.__data__.extremes;\n if (!parent || extent <= 0) return;\n\n const fontSize = extent * 0.06;\n const gap = fontSize * 0.6;\n\n const place = (axis: 'x' | 'y', text: string | null) => {\n let el = this._axisLabelEls.get(axis);\n if (!this._showAxes || text == null) { // remove when hidden / no label\n if (el) { el.remove(); this._axisLabelEls.delete(axis); }\n return;\n }\n if (!el) {\n el = document.createElementNS('http://www.w3.org/2000/svg', 'text') as SVGTextElement;\n el.setAttribute('data-axis-label', axis);\n el.setAttribute('pointer-events', 'none');\n parent.appendChild(el);\n this._axisLabelEls.set(axis, el);\n }\n el.textContent = text;\n el.setAttribute('font-size', fontSize.toString());\n el.setAttribute('font-family', 'system-ui, sans-serif');\n el.setAttribute('font-weight', '600');\n el.setAttribute('fill', '#556');\n if (axis === 'x') {\n // At the right (+x) tip, anchored end so any-length text grows inward\n // and never clips past the viewBox edge; nudged just above the axis.\n el.setAttribute('x', (cx + extent - gap).toString());\n el.setAttribute('y', (-gap).toString());\n el.setAttribute('text-anchor', 'end');\n } else {\n // Just below the top (−y) tip, centered on the y-axis, inside the box.\n el.setAttribute('x', (gap).toString());\n el.setAttribute('y', (cy - extent + fontSize + gap).toString());\n el.setAttribute('text-anchor', 'start');\n }\n };\n\n place('x', this._axisXText);\n place('y', this._axisYText);\n\n // Magnification label, top-left inside the plot; independent of axes.\n if (this._magnifyText == null) {\n this._magnifyEl?.remove();\n this._magnifyEl = null;\n } else {\n if (!this._magnifyEl) {\n this._magnifyEl = document.createElementNS('http://www.w3.org/2000/svg', 'text') as SVGTextElement;\n this._magnifyEl.setAttribute('data-magnify-label', '');\n this._magnifyEl.setAttribute('pointer-events', 'none');\n }\n if (!this._magnifyEl.parentElement) parent.appendChild(this._magnifyEl);\n const el = this._magnifyEl;\n el.textContent = this._magnifyText;\n el.setAttribute('font-size', (fontSize * 0.85).toString());\n el.setAttribute('font-family', 'system-ui, sans-serif');\n el.setAttribute('font-style', 'italic');\n el.setAttribute('fill', '#556');\n el.setAttribute('x', (cx - extent + gap).toString());\n el.setAttribute('y', (cy - extent + fontSize + gap).toString());\n el.setAttribute('text-anchor', 'start');\n }\n\n // Plot title (qe_plot(title =)), top centre, drawn into the SVG so it is\n // part of toSVG() / toPNG() exports.\n if (!this._plotTitle) {\n this._titleEl?.remove(); this._titleEl = null;\n } else {\n if (!this._titleEl) {\n this._titleEl = document.createElementNS('http://www.w3.org/2000/svg', 'text') as SVGTextElement;\n this._titleEl.setAttribute('data-plot-title', '');\n this._titleEl.setAttribute('pointer-events', 'none');\n }\n if (!this._titleEl.parentElement) parent.appendChild(this._titleEl);\n const px = (this._labelFont.size ?? 12) * 1.35;\n const ts = px * this.unitsPerPixel();\n const t = this._titleEl;\n t.textContent = this._plotTitle;\n t.setAttribute('font-size', ts.toString());\n t.setAttribute('font-family', this._labelFont.family ?? 'system-ui, sans-serif');\n t.setAttribute('font-weight', '600');\n t.setAttribute('fill', this._labelFont.color ?? '#223');\n t.setAttribute('x', cx.toString());\n t.setAttribute('y', (cy - extent + ts * 1.1).toString());\n t.setAttribute('text-anchor', 'middle');\n }\n }\n\n update_labels(): void {\n this._nodeLabels.forEach(lbl => lbl.update());\n this._meanLabels.forEach(lbl => lbl.update());\n this._pointLabels.forEach(lbl => lbl.update());\n }\n\n update_extremes() {\n const graph = this.__data__ as Graph;\n graph.update_extremes(this._centerContent);\n if (this._rangeExtent && this._rangeExtent > 0) {\n // A centred view measures range=\"network\" from its centre, not the origin\n const { cx, cy } = graph.extremes;\n const r = this._centerContent && this._rangeMode === 'network'\n ? graph.nodeExtentFrom(cx, cy) * 1.2\n : this._rangeExtent;\n graph.extremes = new Extremes(r, r, cx, cy);\n }\n\n const svgRect = this.svg_element?.getBoundingClientRect();\n if(this.svg_element && svgRect) {\n console.log(\"SVG rect: \", svgRect);\n let w, h;\n if(svgRect.width === 0 || svgRect.height === 0) {\n w = 1;\n h = 1;\n }\n else {\n w = svgRect.width;\n h = svgRect.height;\n }\n this.__data__.scale_x = 1 / (w / (4 * this.__data__.extremes.x_max));\n this.__data__.scale_y = 1 / (h / (4 * this.__data__.extremes.y_max));\n\n // this.svg_element.setAttribute(\"transform\", this.__data__.transform.toString());\n this.__children__[0].svg_element.setAttribute(\"transform\", this.__data__.transform.toString());\n\n this.svg_element.setAttribute(\"viewBox\", (this.__data__ as Graph).extremes.as_viewBox());\n\n let axisLineLayer: LayerLike | undefined = this.__data__.layers.search(\"layers\", \"axis_lines\");\n if (axisLineLayer) {\n let \n axis_x = axisLineLayer.objects.get(\"axis-x\") as Line,\n axis_y = axisLineLayer.objects.get(\"axis-y\") as Line\n ;\n if (axis_x && axis_y) {\n const ex = this.__data__.extremes;\n axis_x.from = new Point({ ID: \"axis-x-start\", dimensions: [ex.cx - ex.x_max, 0], classes: [\"ena.dimension\", \"ena.dimension\"] });\n axis_x.to = new Point({ ID: \"axis-x-end\", dimensions: [ex.cx + ex.x_max, 0], classes: [\"ena.dimension\", \"ena.dimension\"] });\n axis_y.from = new Point({ ID: \"axis-y-start\", dimensions: [0, ex.cy - ex.y_max], classes: [\"ena.dimension\", \"ena.dimension\"] });\n axis_y.to = new Point({ ID: \"axis-y-end\", dimensions: [0, ex.cy + ex.y_max], classes: [\"ena.dimension\", \"ena.dimension\"] });\n }\n }\n }\n }\n\n update_layers() {\n (this.__children__ as QELayer[]).forEach((enaLayer: QELayer) => {\n enaLayer.update();\n });\n }\n}\ncustomElements.define(QEGraphElement.tagName, QEGraphElement);\n","// QEViz standalone entry point — no arbor/webr dependency.\n// Import this bundle directly from rENA or any non-arbor context.\n\nexport { QEVisualElement, vizENA } from './elements/QEVisual.js';\nexport { QEGraphElement } from './elements/QEGraph.js';\nimport { QEGraphElement as _QEGraph } from './elements/QEGraph.js';\n/** Look up a connected <qe-graph> by its `id` or `plot-group` attribute. */\nexport const getGraph = (key: string) => _QEGraph.getGraph(key);\n/** All connected <qe-graph> instances. */\nexport const getGraphs = () => _QEGraph.instances();\nexport { QENodesElement, QEMeansElement, QEPointsElement, QEEdgesElement, QETrajectoriesElement, QEAxesElement } from './elements/QEChildElements.js';\nexport { QELayer } from './elements/QELayer.js';\nexport { QEPoint } from './elements/QEPoint.js';\nexport { QELine } from './elements/QELine.js';\nexport { QETrajectory } from './elements/QETrajectory.js';\n\nexport type { ModelData, QEFrame, ONAModelData, ENAModelData, ENADataFrame } from './types/ModelData.js';\n\nexport { Graph } from './objects/Graph.js';\nexport { Edge } from './objects/Edges.js';\nexport { Trajectory } from './objects/Trajectory.js';\nexport { fitTrajectory, selectDegree, sampleCurve, nearOriginFilter, TRAJECTORY_ZERO_EPS } from './objects/polyfit.js';\nexport type { XY, DegreeSelection, TrajectoryFit } from './objects/polyfit.js';\nexport { Color, WeightedColor } from './objects/Color.js';\n\nexport { DataFrame, DataFrameRow, DataFrameColumn, DataFrameColumnType } from './types/DataFrame.js'\n"],"names":["_DataFrameRow","names","values","rowName","parent","index","__privateAdd","_rowNumber","_rowName","_names","_parent","_classes","__privateSet","__privateGet","wh","predicate","__name","DataFrameRow","DataFrameColumnType","_DataFrameColumn","name","column","rowNames","_name","_type","_rowNames","i","v","DataFrameColumn","_DataFrame","colValues","classes","c","l","transposed","col","j","idx","result_vals","_a","selectors","selectedRows","selectedRowNames","numRows","_","item","r","row","selectedCols","selectedNames","rows","cols","DataFrame","_Model","o","id","key","value","Model","DEBUG","dbg","args","vizENA","n","elements","_QEVisualElement","shadow","style","val","pts","p","edges","data","raw","types","colNames","idCol","removalCol","nodesDF","pointsDF","_b","unitId","_c","_d","nodeId","xColOvr","yColOvr","numCols","QEVisualElement","_Color","base","target","prop","g","b","color","m","resolved","out","ctx","a","Color","_WeightedColor","weight","alpha","hex","rn","gn","bn","max","min","d","s","h","x","w","WeightedColor","_Transform","vals","k","z","y","Transform","Tools","Matrix","matrixString","matrix","Geometry","Point","translate","point","angle","distance","Angle","rotate","origin","rotatePoint","p0","Line","slope","p1","p2","intercept","slopeIntercept","point_along","line","ratio","Xt","Yt","midpoint","length","by","translated","rotated","rotated_reflection","untranslated","untranslated2","rotate2","fixed","P","Q","xx","yy","x_fixed","y_fixed","angle_rad","xx_new","yy_new","intersection","lineA","lineB","x1","y1","x2","y2","x3","y3","x4","y4","D","num1","num2","intersect_circle","circle_xy","circle_r","int","interpolate","t","toRad","toDeg","ArrayTools","unique","arr","divide","isArray","obj","Mathematics","sum","mean","round","decimals","factor","Events","createEvent","element","Hash","parts","exists","Objects","proxy","handler","deep","property","get","current","part","set","URL","parse","location","Query","keys","has","_EventBus","options","oldValue","type","listener","typeMap","newValue","EventBus","_LayerArray","found","fn","recurse","callback","depth","results","layer","result","LayerArray","_Layer","ID","StateManager","Layer","_DimensionVector","_flipped","vec","DimensionVector","_PlottedObject","dimensions","x_","y_","PlottedObject","_Line","from","to","_Point","meta","_Label","txt","object","Label","_Extremes","cx","cy","Extremes","_AxisPoint","AxisPoint","DefaultGraphOptions","_Graph","layer_id","buildLayerTree","layerData","graph","new_layer","child","axisPointLayer","axisLineLayer","extremes","axis_x","axis_y","e","ps","g_","ns","new_node","nodesLayer","es","added","edgesLayer","centerContent","search_layers","minX","maxX","minY","maxY","content_max","found_max","nodes","scale","minDim","Graph","_DrawableElement","wrapper","DrawableElement","TRAJECTORY_ZERO_EPS","nearOriginFilter","eps","normalizedT","design","degree","ti","qr","A","R","norm","dot","qtY","backSolve","leverages","fitCoeffs","X","evalPoly","coeffs","loocv2d","press","denom","ex","ey","selectDegree","fitPts","maxDegree","mode","cap","best","bestVal","deg","fitTrajectory","activePts","opts","selBasis","basis","coeffsX","coeffsY","sampleCurve","fit","steps","TRAJECTORY_CURVE_STEPS","_Trajectory","defaultColor","pt","acc","Trajectory","zoom_level","_Edge","Edge","_EdgeArrow","edge","_edge","_this","T","B0","B1","L","W","u","halfW","at","dh","dm","dn","EdgeArrow","_TaperedEdge","_with_arrow","_arrow","edg","top","bx","tx","ty","dx","dy","wt","px","py","TaperedEdge","_TaperedWeightedMidpointEdge","TaperedWeightedMidpointEdge","_NodeEdge","CX","R2","NodeEdge","_Drawable","__data__","__children__","QEArray","elem","animate","attr","duration","start","now","Drawable","DEFAULT_EDGE_WIDTH","SATURATION_RANGE","OPACITY_RANGE","rampFor","lo","hi","range","EDGE_WIDTH_PER_EXTENT","TAPERED_OUTLINE_PX","CHEVRON_DARKEN","CHEVRON_HALO_PX","POINT_RADIUS_PER_EXTENT","UNCONNECTED_NODE_SIZE","widthPerWeight","edgeWidth","nodeSizeForEdges","weightSum","widthFrac","flattenOnWhite","f","darkenRgba","_QELine","el","path","extent","maxW","opacity","ext","sw","baseColor","saturation","edgeColor","arrowPath","QELine","_QEPoint","sizeScale","rect","zoom","pxPerUnit","stroke","pointEvent","QEPoint","_QETrajectory","pixels","width","group","segmentsGroup","pointsGroup","tip","dStr","pathPts","nSegments","minWidth","maxWidth","minOpacity","maxOpacity","end","progress","segment","lastPt","QETrajectory","_QEArray","QEElementConstructors","_QELayer","childId","removing","updating","obj_name","constructor","ena_element","newData","sublayer","layer_g","QELayer","_QELabel","text","displayMode","position","customX","customY","ev","svg","toUser","baseX","baseY","onMove","onUp","font","fontSize","offset","anchor","dist","QELabel","_QENodesElement","QENodesElement","_QEMeansElement","QEMeansElement","_QEPointsElement","QEPointsElement","_QEEdgesElement","QEEdgesElement","_QETrajectoriesElement","QETrajectoriesElement","_QEAxesElement","QEAxesElement","GROUP_PALETTE","parseEdgePair","colName","codes","c1","c2","computeCIRect","varX","varY","pointScale","df","t95","seX","seY","MEAN_MAX_FRACTION_OF_INTERVAL","capMeanToInterval","meanPt","halfH","half","readIntervalBounds","dim0","dim1","prefix","xLow","xHigh","yLow","yHigh","parseEdgeLayer","thr","complementColor","mx","mn","parseColorScale","parseLabelMode","defaultMode","_QEGraphElement","model","tweenFrom","dims","unitIdCol","nodeIdCol","groupColName","config","groupColorMap","PALETTE","groupCol","ci","_allGroupNames_","activeMeanGroups","scalePointsEnabled","getExtent","xIdx","yIdx","maxNodeExtent","_e","maxPointExtent","_f","maxTrajExtent","_g","effectivePointExtent","labelNodes","labelMeans","labelPoints","labelSvg","rowToPoint","colorStr","idIdx","groupSums","showUnitPoints","pointSetFrame","psLayer","si","shape","label","_h","pointsLayer","groupColIdx","rx","ry","hasGroupsFrame","_i","activeGroupRows","pointsLayerSvg","ciExtent","activeNames","my","shapeIdx","rowShape","cell","rowIv","iv","rowOut","ob","oel","bounds","crossKey","x0","y0","cel","rect_x","rect_y","rect_width","rect_height","stale","_j","groupIdx","μx","μy","rawVarX","rawVarY","_k","lbl","qIdx","displayText","meanId","trajectoriesLayer","trajSource","_l","unitRows","selectedUnits","uIdx","unit","tIdx","time","unitKey","rawPts","trajObj","networkLayer","edgeLayer","nodeLayer","edgenodeLayer","edgesEnabled","_m","li","lv","_n","unitGroupMap","_o","gIdx","codeNames","edgePairs","pair","getUnitEdges","colIdx","getGroupEdges","groupName","sums","count","gColIdx","resolve","groupOfUnit","drawEdges","networkRow","frame","thresholded","push","signColors","pos","neg","primaryId","primary","secondaryId","secondary","wA","wB","isDirected","rangeOf","ws","nz","modelRange","self","plotRange","cscale","colourRange","lineRange","selfRange","colourOf","nodeWeightSum","add","codeIdx","unconnected","totalWeightByPair","pairKey","net","fromNode","toNode","isSelf","fromPt","toPt","edgeLine","fwd","bwd","totalweight","nodesVisible","axisPointsLayer","axisLinesLayer","nodesEl","meansEl","allPointsEls","pointsEl","setEls","edgeEls","firstAttr","magnifyEl","trajectoriesEl","axesEl","labelsShorthand","fallback","forId","labelsLayer","graphLayer","collect","tag","dur","t0","ease","lerp","step","nc","oc","svgStr","reject","blob","url","img","canvas","err","sel","HL","mk","attrs","xy","B","defs","AW","AH","makeArrow","fill","isPanning","startX","startY","panAnimationFrame","pendingPan","panUpdate","findPointId","getAutoLabel","related","detail","node","hovered","keyOf","next","nextKey","wStr","clientX","clientY","enaLayer","lastW","entries","axesLayer","gap","place","axis","ts","svgRect","QEGraphElement","getGraph","_QEGraph","getGraphs"],"mappings":"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"}
|